{"owner":"Leonxlnx","repo":"taste-skill","hasSkills":true,"totalSkillsCount":26,"totalTokensCount":189413,"categories":["marketplace","plugin-manifest","anthropic-skill"],"hasMcp":false,"mcpConfig":null,"found":[".agents/plugins/marketplace.json",".claude-plugin/marketplace.json",".codex-plugin/plugin.json","skills/taste-skill/README.md","skills/taste-skill/SKILL.md","skills/taste-skill/evals/evals.json","skills/taste-skill/library/app.json","skills/taste-skill/library/directions.json","skills/taste-skill/library/heroes.json","skills/taste-skill/library/motions.json","skills/taste-skill/library/palettes.json","skills/taste-skill/library/photos.json","skills/taste-skill/library/sections.json","skills/taste-skill/library/sites.json","skills/taste-skill/library/type.json","skills/taste-skill/references/app-screens.md","skills/taste-skill/references/colour.md","skills/taste-skill/references/copy.md","skills/taste-skill/references/critique.md","skills/taste-skill/references/imagery.md","skills/taste-skill/references/layout.md","skills/taste-skill/references/motion.md","skills/taste-skill/references/research.md","skills/taste-skill/references/scenes.md","skills/taste-skill/references/tells.md","skills/taste-skill/references/type.md"],"skills":{".agents/plugins/marketplace.json":"{\n  \"name\": \"taste-skill\",\n  \"interface\": {\n    \"displayName\": \"Taste Skill\"\n  },\n  \"plugins\": [\n    {\n      \"name\": \"taste-skill\",\n      \"source\": {\n        \"source\": \"url\",\n        \"url\": \"https://github.com/Leonxlnx/taste-skill.git\",\n        \"ref\": \"main\"\n      },\n      \"policy\": {\n        \"installation\": \"AVAILABLE\",\n        \"authentication\": \"ON_INSTALL\"\n      },\n      \"category\": \"Design\"\n    }\n  ]\n}\n",".claude-plugin/marketplace.json":"{\n  \"name\": \"taste-skill\",\n  \"description\": \"tasteskill: art direction for coding agents, for websites, product pages, dashboards and app screens, checked in a real browser.\",\n  \"owner\": {\n    \"name\": \"leonxlnx\",\n    \"email\": \"hello@tasteskill.dev\"\n  },\n  \"plugins\": [\n    {\n      \"name\": \"taste-skill\",\n      \"description\": \"tasteskill v2: art direction for websites, product pages, dashboards and app screens, with a library of researched directions, real pictures from open collections and a real-browser inspector.\",\n      \"version\": \"2.1.4\",\n      \"source\": \"./\",\n      \"skills\": [\"./skills/taste-skill\"],\n      \"author\": {\n        \"name\": \"leonxlnx\",\n        \"email\": \"hello@tasteskill.dev\"\n      },\n      \"homepage\": \"https://github.com/Leonxlnx/taste-skill\",\n      \"repository\": \"https://github.com/Leonxlnx/taste-skill\",\n      \"license\": \"MIT\",\n      \"keywords\": [\"skills\", \"frontend\", \"design\", \"taste\", \"ui\", \"dashboard\"]\n    }\n  ]\n}\n",".codex-plugin/plugin.json":"{\n  \"name\": \"taste-skill\",\n  \"version\": \"2.1.4\",\n  \"description\": \"tasteskill v2: art direction for websites, product pages, dashboards and app screens, checked in a real browser.\",\n  \"author\": {\n    \"name\": \"leonxlnx\",\n    \"url\": \"https://github.com/Leonxlnx\"\n  },\n  \"homepage\": \"https://github.com/Leonxlnx/taste-skill\",\n  \"repository\": \"https://github.com/Leonxlnx/taste-skill\",\n  \"license\": \"MIT\",\n  \"keywords\": [\n    \"skills\",\n    \"frontend\",\n    \"design\",\n    \"taste\",\n    \"ui\"\n  ],\n  \"skills\": \"./skills/\",\n  \"interface\": {\n    \"displayName\": \"Taste Skill\",\n    \"shortDescription\": \"Art direction for websites, dashboards and app screens.\",\n    \"longDescription\": \"tasteskill v2 from Leonxlnx/taste-skill: researched directions, real pictures and a real-browser inspector for websites, product pages, dashboards and app screens.\",\n    \"developerName\": \"leonxlnx\",\n    \"category\": \"Design\",\n    \"capabilities\": [],\n    \"websiteURL\": \"https://github.com/Leonxlnx/taste-skill\",\n    \"defaultPrompt\": [\n      \"Design a distinctive frontend without generic AI patterns.\",\n      \"Redesign this interface while preserving its brand.\",\n      \"Build the dashboard for this product with real data and charts.\"\n    ]\n  }\n}\n","skills/taste-skill/README.md":"# tasteskill v2 (`design-taste-frontend`)\n\nA design skill for coding agents, built from a study of 247 curated sites (One Page Love and Awwwards\nSites of the Day, October 2026). It gives an agent an art direction instead of letting it fall back on\nthe average landing page, holds it to a strict no-ornament house style, and makes it look at its own\nrender before calling the work done.\n\n## How it works\n\n1. **Inventory.** The agent lists what only this client has: the name and what it means, the street,\n   the numbers, the one constraint, the materials, the hours.\n2. **Draw.** `scripts/draw.mjs` deals three of 20 directions (each an idea engine seen on the\n   strongest studied sites); the agent picks the one that can carry something from the inventory, and\n   the script deals the rest: a hero composition, section compositions, a type system of real free\n   fonts, a palette, photographs, a motion, studied references, and under every blueprint a list of\n   where it disagrees with the house rules. Recent draws are remembered so projects do not repeat.\n3. **Idea and live thing.** One sentence tying the client's own material to the direction's device,\n   checked against the nearest competitor, and one thing the visitor can do on the page.\n4. **Build** from the sheet, words first, full content. When the project has no photographs of its\n   own, `scripts/assets.mjs` finds real pictures of the subject's world in open collections (its\n   street in old postcards, old maps, its materials, engravings of its trade, museum objects of its\n   kind), downloads them into the project and records their credits; the subject is drawn in code\n   only where no honest picture exists.\n5. **Gate.** `scripts/lint.mjs` (source) and `scripts/inspect.mjs` (real browser, 1440 / 768 / 390)\n   measure the house rules: headlines of two lines or fewer, no eyebrow labels, no monospace, no\n   01/02/03, no thin rules, no gradients, no resting shadows, no cream-and-terracotta, no violet, and\n   the faults blind jurors punished: no focal point, empty screens, text covered or cut, long pins,\n   sideways rows, faded text.\n6. **Look.** The inspector saves screenshots; the agent critiques them with an Awwwards-weighted\n   rubric, fixes the top three problems and repeats, at most three rounds.\n\nFive rounds of blind tests against a no-skill baseline and another design skill are recorded in\n`references/research.md` §11.\n\n## Contents\n\n```\nSKILL.md                 the run, the house rules, the laws\nreferences/              copy, type, colour, layout, imagery, motion, critique, tells, research\nscripts/draw.mjs         deal options / a direction / reprint / redraw; --alternatives, --photos, --site\nscripts/assets.mjs       search open image collections (Openverse, Wikimedia Commons, Art Institute of\n                         Chicago, the Met) and, with --video, real footage (Wikimedia Commons, Internet\n                         Archive, NASA); --get downloads with the credit, --credits prints them\nscripts/lint.mjs         static scan for banned patterns and stock phrases\nscripts/inspect.mjs      render, measure, photograph\nscripts/lib/             zero-dependency Chrome DevTools client, the in-page probe, the rules\nlibrary/                 directions (20), heroes, sections, type systems, palettes, photographs,\n                         studied sites, motions\nassets/base.css, base.js an optional neutral foundation\nevals/evals.json         six briefs for testing the skill against a no-skill baseline\n```\n\n## Requirements\n\nNode 22 or newer and an installed Chrome, Edge or Chromium for `inspect.mjs` (it drives the browser\nover the DevTools protocol with Node's built-in WebSocket; nothing is installed). `draw.mjs`,\n`lint.mjs` and `assets.mjs` run on Node 18+; `assets.mjs` needs network access and no API keys. Set\n`CHROME_PATH` if the browser is somewhere unusual.\n\n## Install\n\nCopy this folder to your skills directory, for example `~/.claude/skills/design-taste-frontend/`, or keep it in\na repository under `.claude/skills/`.\n\n## Notes\n\n- Photographs in the library are served by Lorem Picsum from Unsplash, under the Unsplash licence.\n  They are placeholders for atmosphere; replace them with the project's own pictures.\n- Pictures found with `assets.mjs` keep their own licences. By default it offers only CC0, public\n  domain, CC BY and CC BY-SA, and `--get` records the title, creator, licence and source of every\n  download in `assets/credits.json`. The page must carry the credits (`--credits` prints them).\n- `assets.mjs --video` finds short clips of the subject's world, takes a 720p-or-smaller rendition,\n  refuses files over 25 MB unless `--max-mb` is passed, and saves a poster frame with each clip; how\n  to use one on a page (muted loop, poster, stopped under reduced motion) is in\n  `references/imagery.md` §11.\n- Fonts are loaded from Google Fonts and Fontshare. Check each face's licence for your use.\n- The scores in `references/research.md` are model judgements from screenshots, not Awwwards scores.\n- The draw history lives in `~/.taste-skill/history.json` (set `TASTE_SKILL_HISTORY` to move it).\n  Delete it to reset.\n- A build takes an agent roughly 30–45 minutes and a few hundred thousand tokens with the full\n  look-and-fix loop; most of that is finding or drawing pictures when a project has no photographs.\n","skills/taste-skill/SKILL.md":"---\nname: design-taste-frontend\ndescription: >-\n  tasteskill v2, the anti-slop frontend skill. Art direction for websites, distilled from a study of\n  247 curated gallery sites (One Page Love, Awwwards Sites of the Day). Deals researched directions\n  (idea, composition, type, palette, photographs, section blueprints) from a library, enforces a strict\n  no-slop house style with a real-browser inspector, and runs a look-and-fix loop on screenshots. Use\n  this whenever you build, design, redesign, restyle, polish or review a landing page, marketing site,\n  portfolio, product page, one-pager, hero or any public-facing web page, in any stack (HTML/CSS, React,\n  Next.js, Vue, Svelte, Astro, Tailwind) — also when the user says a page looks generic, templated,\n  \"AI-made\", sloppy, or asks to make it look designed, premium, award-level or less like every other\n  site. Also for app screens: dashboards, admin and analytics views, settings, inboxes and other screens\n  people work in, with their own run and rules.\n---\n\n# tasteskill v2\n\nA page built by a model usually looks like the average of every page the model has seen: a centred\nheadline over three lines, a little label above it, a row of icon cards, a soft gradient, a few thin\nrules and a monospace caption. Nothing in it is wrong and nothing in it was decided.\n\nThis skill replaces those defaults with decisions, in four ways:\n\n1. **A script deals the directions, you choose among them.** Asked to invent a look, a model picks\n   the category default every time. `scripts/draw.mjs` deals three of twenty researched directions;\n   you choose the one that carries the subject's idea, and the script then deals its type system,\n   palette, hero and section compositions from a library distilled from 247 real sites.\n2. **The idea comes from the subject.** In the study, what separated the best sites from the forgettable\n   ones was a concept taken from the thing itself, not the styling.\n3. **A house style with no ornaments,** measured in a real browser by `scripts/inspect.mjs`, so the\n   rules are checked rather than hoped for.\n4. **You look at what you made.** Screenshots at three widths, a juror's rubric, fix, look again.\n\nOne warning learned in testing. Taking the ornaments away is only half the job; a page that has lost its\nlabels, rules and cards and gained nothing in their place reads as thin, and blind jurors rightly prefer\na richer page with tells over an empty page without them. The other half is substance: type set\nlarger, whole fields of colour, real pictures of this subject's world (found or drawn), and every\nsection carrying its full content. The skill is built to give you that; do not trade it for restraint.\n\nIn the commands below `<skill>` is this skill's folder. Run them from the project's root, so the\nworking files land in `.taste-skill/` there. The scripts need Node 22+ and an installed Chrome, Edge\nor Chromium, and install nothing. `assets.mjs` also needs network access; it uses no API keys.\n\n## Page or app screen\n\nDecide first which of two kinds of work this is.\n\n- **A page** is read and scrolled: a landing page, a marketing or product site, a portfolio, an\n  event, a restaurant, a one-pager. It follows **the run** below.\n- **An app screen** is worked in: a dashboard, an admin or analytics view, settings, billing, an inbox\n  or queue to work through, a wallet, a list with filters, an editor or builder. It follows\n  **`references/app-screens.md`**: its own run, its own draw (`draw.mjs --app`), its own house rules\n  (quiet borders, small labels and repeated panels are normal there; gradients, glows, icons in tinted\n  squares, rainbow charts and invented vanity numbers are not) and `inspect.mjs --app`. Read that file\n  whole before you start; the page run below does not apply.\n\nA product site that shows its app is a page; the interface fragments on it follow the app-screen\nrules for their insides. Deal the product's app style once, in its own folder, with the page's colours\nand type kept:\n\n```bash\nnode <skill>/scripts/draw.mjs --app --kind <kind> --brief \"<the product>\" --keep palette,type --out .taste-skill/app\n```\n\nand build every fragment the page shows (the hero's live screen, a feature's crop, a chart) as a real\npiece of that app: `assets/app.css` for its panels, tables and controls, `assets/charts.js` for its\ncharts, real data that adds up, one finding stated, cropped and scaled the way the page's blueprint\ntreats a picture. A fragment that looks like a working product is the strongest picture a software page\nhas; grey bars and lorem numbers are the weakest. When a request mixes both (a landing page and the\ndashboard behind it), build each with its own run and one shared palette and typeface.\n\n## The run\n\nDo these in order. Steps 1–5 take a few minutes and decide whether the page is any good.\n\n### 1. Read the brief and the project\n\nFind out what is real: the subject, the audience, the one thing the page must get someone to do, the\nstack, any existing brand (colours, fonts, logo), and above all **what imagery truly exists**: the\nproject's own photographs or product shots, a real interface that can be shown, an image generation\ntool you can call, or nothing. Do not plan around pictures you do not have. Nothing of its own is\nrarely nothing at all: the subject's city, street, materials and history are in open archives and\nmuseums, free to use with a credit (step 6, `scripts/assets.mjs`).\n\nIf the request is vague, decide and state your reading in one line instead of asking. Ask only when a\nmissing fact blocks the work (for example, no product name).\n\nThen **inventory the subject** in your notes: eight to twelve things that belong to this client and to\nno competitor. Look for its name and what the name means; its address, door number, street and\nneighbourhood, and what that place looks like (its tiles, signs, paint colours, typefaces on its shop\nfronts, its light, its weather); the numbers in the brief (seats, rooms, minutes to the sea, the\nprice, the year); the constraint it lives with (only one batch a month, closed in winter, by\nappointment); its materials and colours; its rituals and hours (the oven lit at five, the ferry at\nseven); the printed things of its world (a timetable, a label, a ticket, a sign). This list is where\nthe idea comes from in step 4. In blind tests, the page that won each brief was built from an item on\nsuch a list (the client's name and what it means, the street it stands in, the one constraint that\nmakes it what it is), and the pages that lost had a good composition with a category idea. The list\nis also your picture search: each place, material and printed thing on it is a query for step 6.\n\n### 2. Write the argument\n\nBefore any design, list the page as claims with their proof, one line per section, the way\n`references/copy.md` §1 shows. The claims decide which sections exist and in what order. Delete any\nsection that has no claim. This is how you avoid the stock sequence of hero, logos, three features,\ntestimonial, pricing, call to action.\n\n### 3. Draw the direction\n\n```bash\nnode <skill>/scripts/draw.mjs --sector <sector> --brief \"<one line about the subject>\" \\\n  --sections <roles in the order of your argument> [--tone <tone>] [--have <assets>] [--keep palette,type] \\\n  --options 3\n```\n\nThis deals three directions and prints a short summary of each. Hold each one against your inventory:\nwhich way of composing can carry something only this client has? Choose that one, not the most\nfamiliar, and write one line in your notes on why. In testing, a single random direction that did not\nsuit the subject was the commonest cause of a weak page. Then deal the full sheet:\n\n```bash\nnode <skill>/scripts/draw.mjs <the same arguments, without --options> --direction <chosen id>\n```\n\n- `--sector`: `node <skill>/scripts/draw.mjs --list sectors`. Pick the closest.\n- `--sections`: roles from `--list roles` (features, showcase, how-it-works, testimonial, proof, stats,\n  pricing, faq, cta, footer, intro, about, work, gallery, list, contact). The hero is implied.\n- `--tone` (optional): quiet, bold, warm, technical, playful, luxury, editorial. Only pass it when the\n  brief clearly asks for one.\n- `--have`: assets that really exist, comma-separated: `photography` (the project's own photographs of\n  the place, people or work), `product-photo` (photographs of the specific product, or an image tool\n  that can make them), `product-ui` (real screenshots), `illustration`, `video`. Leave it out if you\n  have none: the draw then avoids compositions that depend on them and the sheet says how to fill\n  picture slots honestly (software shows its own interface built in HTML; a product with no photographs\n  is drawn and set among real pictures of its world, never a fake product shot). Pictures you will\n  find in the open collections are not the project's own; leave them out of `--have`.\n- `--keep palette,type`: when the brand already fixes colours or typefaces. The draw then deals only\n  the composition, and you map the brand's values onto the roles.\n\nThe command prints a **direction sheet**. It is the art direction for this build:\n\n- **Adopt it.** Do not blend it with the layout you would have made anyway. If it feels unfamiliar,\n  good: the familiar layout is the one this skill exists to prevent.\n- Redraw one slot (`--redraw hero | type | palette | photos | scenes | section:<role> | direction`) only for a\n  reason you can state: it contradicts a stated brand constraint, or needs an asset that does not\n  exist. Never redraw to get something more comfortable. Record every redraw in your report.\n- When a dealt section cannot hold the real content (it compares three plans and there is one price;\n  it wants five quotations and there are none), do not bend the content to fit. List the others with\n  `--alternatives <role>`, pick the one whose assumptions match the content, and take it with\n  `--redraw section:<role>=<id>`.\n- **Check the palette against the subject.** A dealt palette is a set of proportions (one ground, one\n  ink, one accent, fields) as much as a set of colours. If its colours fight the subject's own material\n  (candy pastels for a peat whisky, neon for a mountain hut), redraw the palette once; if the subject\n  has unmistakable colours of its own (its material, the paint of its street, the landscape outside\n  its windows), keep the dealt proportions and take the colours from the subject instead, and say so\n  in the report.\n- Reprint it any time with `node <skill>/scripts/draw.mjs --show`. In a long session, re-read it before each\n  section you build.\n\n### 4. Find the idea\n\nThe direction is a way of composing. The idea is what makes the page belong to this subject and no\nother. Write this sentence in your notes and do not start building until both blanks are filled from\nthe subject itself:\n\n> On this page, **[something that belongs to the subject]** becomes **[the device the direction calls for]**.\n\nPlaces to look for the first blank:\n\n- **Its output.** What does the thing produce? Put the real output on the page as material. (A camera\n  that prints poems delivered its copy as paper slips.)\n- **Its object or shape.** What does it physically look like, in cross-section, in silhouette?\n  Enlarge it, crop it, make it the frame or the one motif.\n- **Its name.** Can the letters hold a photograph, stack into a wall, split to two corners?\n- **Its place.** Is there one view that makes someone want to be there?\n- **Its ritual.** Is there a sequence the page can perform as it scrolls?\n- **Its artefact.** What printed thing already exists in its world: ticket, menu, label, receipt,\n  invitation, folder, manual?\n- **Its opposite.** Which other category owns the feeling this one lacks?\n\nFill the first blank from your inventory (step 1), not from the category. **The competitor test:** put\nthe nearest real competitor in the sentence (the bakery two streets away, another oak furniture maker,\nanother hut on the same mountain). If the sentence still works, the idea belongs to the category: a\nloaf of bread is every bakery; the seven doors of the street this one is named after are only this one.\n\"Clean and modern\" is not an idea. The sites the study's panel scored lowest were the ones whose idea\nwas recorded as \"none beyond the standard formula\".\n\n**One live thing.** Give the page one thing the visitor can do, or that is different for each visit,\nmade from the idea: pick a wood and see the chair in it; type your name and see it cut in the\nfoundry's letters; set the loan and read the real monthly figure; see whether the hut's stove is lit\nright now and how long until the last ferry; choose a size and see it against the room. In blind tests every winning page had one and the jurors named it first. Rules: it uses the subject's real content, it works on a phone with a thumb, it has a plain\nfallback without script, it never blocks reading, and it is one thing, not a playground. It is\nbuilt in step 6 as part of the page, not added as motion in step 9.\n\n**The scenes carry the idea too.** The scroll scenes on the sheet are devices waiting for a subject.\nDecide what each one shows from your inventory before building: the fly-through passes through this\nstudio's own title cards, the route is the road this shipment really takes, the picture that opens to\nthe whole screen is the room the guest will wake up in. A scene filled with pictures that could belong\nto anyone is a screensaver.\n\n### 5. Write the words\n\nWrite the whole page as a copy deck (plain text) before markup, following `references/copy.md`:\n\n- **Every headline fits in two lines or fewer at every width.** Do the arithmetic in copy.md §2 before\n  committing to a sentence: about 32 characters is safe everywhere at a confident size. The studied\n  gallery heroes have a median of 5 words and 32 characters.\n- One supporting sentence, directly under the headline (32–48px below it) and shown with it, never\n  docked at the foot of the first screen or held back by an animation. When the headline is a name or\n  a figure of speech, this sentence says plainly what the thing is. One primary action, named for what\n  it does, as a real button on the first screen.\n- **The first screen answers the visitor's first question in large type.** For an event: what it is,\n  when and where (the dates belong in the headline or at the second size, never only in small text).\n  For a product: what it is and what it costs or does. For a person: who and what they do. Every\n  section the visitor came for (the line-up, the menu, the rooms, the price) has its own heading and\n  its own place in the navigation.\n- **Write the full content.** Every section the brief asks for delivers its information completely:\n  the whole menu with prices, each room with its own details, every speaker and talk, the price with\n  what it includes, an answer for each real question. Thin sections are the commonest reason a clean\n  page loses to a busier one.\n- Sample details are expected where the brief leaves gaps (dish names, room names and rates, project\n  titles) so the design is seen at full density; list them in the report for the client to confirm.\n  Proof is never invented: no customers, quotes, reviews, press, logos or business statistics.\n\n### 6. Build it, still\n\nBuild the page with motion switched off in your head; a page that needs animation to look finished is\nnot finished. Order of work:\n\n1. **Tokens.** Colour and type roles from the sheet as CSS custom properties. Everything downstream\n   references tokens only. `<skill>/assets/base.css` is a neutral foundation you may start from (reset, token\n   names, fluid type steps, grid, focus and selection styles, the motion helpers); it has no look of\n   its own.\n2. **The hero, exactly as the blueprint describes it,** at desktop and at phone width. Get the big\n   thing big and the small things small before anything else exists.\n3. **Each section from its blueprint,** with this project's content. Keep the geometry, change the\n   subject. Neighbouring sections must not share a layout. **Carry the idea into every section,**\n   pricing, FAQ and footer included: the commonest failure in the study, even among good sites, is a\n   distinctive first screen followed by stock blocks.\n4. **Imagery,** in this order of preference:\n   1. the project's own;\n   2. generated, if you have an image tool;\n   3. **real pictures of the subject's world from the open collections,** whenever an honest one\n      exists. Search them with `node <skill>/scripts/assets.mjs \"<query>\"` (Openverse, Wikimedia\n      Commons, the Art Institute of Chicago and the Met; only licences that allow commercial use, by\n      default). Search the inventory, not the category: its street in old postcards, an old map of the\n      neighbourhood, its material up close, its trade in engravings, a museum object of its kind, a\n      botanical plate, a star chart. Use them large and with intent: one archival photograph as the\n      hero, an engraving enlarged into the page's motif, the real map of the street as the contact\n      section. Look at each before choosing; `--get <ref>` downloads it into `assets/` and records\n      its source and licence, and `--credits` prints the credit line for the footer. A found picture\n      shows the world around the client and is never presented as the client's own product, room,\n      dish, person or team;\n   4. **drawn in code from the subject itself,** for what no honest picture exists of (its objects,\n      its tiles, its windows, its product's interface, made as one consistent flat graphic language in\n      the palette's real colours);\n   5. the photographs dealt on the sheet, only where an honestly generic picture fits (the sea for a\n      sea house), never as a stand-in for the subject;\n   6. type and colour alone.\n\n   When the project has footage or a real picture of its own process or product, the first screen\n   shows it, large (about 40% of the screen or more). Never write a sentence on the page about where\n   the pictures come from or what they are not (\"none of these shows our bar\"): a caption says what\n   the picture is, and the credit line sits small in the footer. A portfolio whose work is invented\n   for the brief draws each piece as a finished still of that work (its title card with its own type,\n   an end frame, a poster), with real detail, never as a pictogram of the client's product.\n\n   **The floor, which the inspector checks:** at least four real pictures on the page, usually six to\n   twelve (photographs, archival images, maps, engravings, footage, raster artwork; for software, its\n   cropped interface fragments count too). SVG drawings do not count toward the floor: draw what no\n   picture exists of, and still carry real pictures. Add one moving picture wherever an honest clip\n   exists: search it with `assets.mjs --video \"<query>\"` and use it as a muted loop with a poster\n   frame. Models skip pictures and footage because finding them is work; the page fails without them.\n\n   `references/imagery.md` covers searching, licences and credits, video, drawing, crops and treatments.\n5. **The live thing** from step 4, built into the section where it proves the claim (often the hero\n   or the booking), with real content, a thumb-sized phone version and a plain fallback.\n6. **The scroll scenes,** when the sheet deals them (section 9), each with the section it carries: the page's big\n   moments, the camera that flies through the work, the picture that opens to the whole screen, the\n   word that buckles under the scroll. Copy the shared stage and the scene's files from\n   `<skill>/assets/scenes/`, fill the scene with this project's own pictures and words, and set the\n   page's tokens so it takes the page's look. A scene is composition: it decides how long the page is\n   and what each screen shows, so it is built now and seen in every look round, not added at the end.\n   `references/scenes.md` says how to put one on a page, fill it, fit it and check it;\n   `assets/scenes/demo/<id>.html` is a working example of each.\n7. **Fullness.** Look at each desktop screen as a poster: one dominant thing and the content it\n   carries. A screen that is mostly empty ground is an underbuilt section, not a rest; one deliberate\n   rest per page is the limit, and the inspector fails a page with two or more near-empty screens.\n   Running text is in the full ink at 16px or more; grey is for secondary notes.\n8. **The frame.** The page has one pair of equal outer margins at every width, and every section uses\n   the width the page has set up: when its text sits in the left half, the right half holds its\n   picture, its second column, its list or its figure, never nothing. Asymmetry lives inside the grid,\n   never in the frame: a void is placed only when something closes it on the far side. No stretch of\n   the page taller than about half a screen holds nothing at all; sections are 120–240px apart on\n   desktop. Every section the visitor came for opens with a heading that names it, and the first\n   screen carries the page's title in an `h1`. These are what readers name first when a page looks\n   wrong (\"no clear title\", \"random empty space\", \"everything is pushed to one side\"), and the\n   inspector measures each of them.\n9. **States and semantics.** Real links and buttons, visible focus, alt text, a phone layout that is\n   its own composition.\n\nRead `references/type.md`, `references/colour.md` and `references/layout.md` when you need the detail\nbehind a decision; the laws below are the short form.\n\n### 7. Gate\n\n```bash\nnode <skill>/scripts/lint.mjs <source files or folder>\nnode <skill>/scripts/inspect.mjs <url or path/to/index.html>\nnode <skill>/scripts/scenes.mjs <url or path/to/index.html>     # when the page has scroll scenes\n```\n\n`scenes.mjs` photographs every scroll scene at 0, 10 … 100% of its hold, on desktop and on a phone,\nand the reduced-motion page; with scenes on the sheet, `inspect.mjs` also films the whole scroll\n(`desktop-film-NN.jpg`). A scene that never started or rests on desktop is a `FAIL`.\n\n`lint.mjs` scans source for banned patterns and stock phrases. `inspect.mjs` opens the page in a real\nbrowser at 1440, 768 and 390 pixels, measures it (headline line counts, type sizes, fonts actually\nloaded, colours, rules, shadows, gradients, contrast, overflow, and the frame: equal margins, sections\nhuddled on one side, blank stretches, the title, untitled sections, text against the screen edge) and\nsaves screenshots to `.taste-skill/inspect/`. Fix every `FAIL`. Treat each `WARN` as wrong unless you can defend it to a\ndesigner in one sentence. Re-run until there are no `FAIL`s. Do not argue with the meter and do not\nhide things from it. The inspector serves local files over a throwaway local server; if the page must\nalso open straight from the file system, open `index.html` that way once before you finish.\n\n### 8. Look\n\nPassing the gate means nothing banned was measured. It does not mean the page is good. Open the\nscreenshots the inspector lists (every viewport, with your image viewer or Read tool) and critique them\nwith `references/critique.md`: the fourteen passes, the Awwwards-weighted score, the caps. Write the critique\ndown in its format, fix the top three problems, run the inspector again, look again. Three rounds at\nmost.\n\nJudge only the pictures. If a problem is visible in a screenshot, it is real, whatever the code says.\n\n### 9. Move\n\nNow build the motion layer. It is required, and it is more than one fade: the inspector counts the\nelements that really move while the page loads and is scrolled, and fails a page under eight (it warns\nunder sixteen). Any scroll scenes are already built (step 6); around them the layer has four parts:\n\n1. **The signature move** named on the sheet: one, done well (a dealt scene can be it).\n2. **An entrance for the parts of every section:** the heading, then the text, then the picture,\n   staggered by 60–90ms, rising 16–32px with opacity, triggered once as the section enters. Not one\n   fade for the whole block, and never content that stays hidden if the script fails.\n3. **Feedback on every control:** press, hover and focus on buttons, links, cards and the live thing.\n4. **One moving picture:** a found clip as a muted loop, a slow scale or drift on a photograph, or a\n   scroll-linked move on the hero picture.\n\nTransform and opacity only; every move has a `prefers-reduced-motion` fallback that keeps the content\nand drops the travel. A move that changes the colour or the layout of whole screens (colour by\nchapter, a pinned story) is part of the composition, so build it in step 6 and let every look round see\nit. `references/motion.md` has the tokens and tested recipes. Then run the inspector once more and check\nevery screenshot for content that failed to appear.\n\n### 10. Report\n\nDo not report until all of these are true; each one was skipped in a test run that came out badly:\n\n- `inspect.mjs` shows **0 FAIL** at 1440, 768 and 390, on the final version of the page.\n- You opened every screenshot it listed after the last change, not only the first screen.\n- With scroll scenes: `scenes.mjs` ran on the final page with no problems, and you read every sheet\n  (desktop, phone, reduced motion).\n- A stranger reading the first screen for five seconds can say what this is and what to do.\n- Every section has a heading; the margins match on both sides; no stretch of the page is empty.\n- The critique of your last round is written down in the shape of `references/critique.md` §4.\n\nTell the user, briefly: the direction dealt (name and seed) and any redraws with reasons; the idea\nsentence and the live thing; the final scores from your last critique round and what still falls short;\nevery found picture and clip with its title, creator, licence and source page (`assets.mjs --credits` prints\nthe list) and where its credit sits on the page; which bundled photographs and which drawings stand in\nfor photography (so they can be replaced); and any sample content that must be swapped before launch.\nDo not claim a check you did not run.\n\n## House rules\n\nThese hold on every build, whatever the direction. `inspect.mjs` measures them.\n\n| Rule | Instead |\n| --- | --- |\n| **Headlines: two lines or fewer, at every width.** Every `h1`–`h6`, and the main line of the first screen whatever its tag. | Cut words. Then widen the measure. Size last. |\n| **A clear title on the first screen**, in the page's one `h1`, and a heading on every section. | Say what this is: the name with what it does, the product with what it is for, the event with its date and place. |\n| **Equal outer margins; no section huddled on one side** with the other half of the screen empty. | Close every void with something on its far side: the section's picture, a second column, a list, a figure. |\n| **No blank stretches** taller than about half a screen. | The normal section gap. A deliberate rest is a placed picture or a field of colour, once per page. |\n| **Statements are paragraphs.** An intro sentence or a quotation set large is marked up as `<p>` or `<blockquote>`, stays at statement size (36px or less on desktop, 24px on a phone) and runs to about 25 words, three lines. | Larger than that it is a headline and the two-line rule applies. In blind tests jurors read a 42px sentence over four lines as a four-line headline. |\n| **No eyebrows.** No small label above a heading, no pill badge above the headline, no \"New ·\" chip. | Put the information in the heading or the first sentence, or drop it. |\n| **No monospace** outside real code blocks. | The text face. Tabular figures where numbers align. |\n| **No index numbering.** No 01 / 02 / 03, no (001), no \"Step 2\". | Order shown by position, size, or the words. A real `<ol>` if order matters. |\n| **No thin rules.** No hairline dividers, no 1px outlined boxes, no grid lines, crosshairs or crop marks. | Space. A step in background tone. A change of scale. A filled shape. |\n| **No gradients.** Not as backgrounds, not on buttons, not in text. | Flat colour, or a real photograph. A neutral scrim under text on a photo is the one exception. |\n| **No shadows on things at rest.** No glows. | A tone step between surfaces. Shadows only on what truly floats: a menu, a dialog. |\n| **No assistant palette.** No yellow-cream ground with terracotta or rust; no violet or indigo. | The dealt palette. |\n| **No tiny uppercase letter-spaced labels.** | Sentence case at a readable size. |\n| **No icon-topped feature cards, no rows of identical cards.** | The dealt section blueprint. |\n| **No glass.** No backdrop blur panels, no floating pill navigation. | A plain bar: wordmark, a few links, one action. |\n| **No emoji, no gradient blobs, no decorative shapes, no fake dashboards of grey bars.** | A real picture, a real interface fragment, or nothing. |\n| **No styled accent word** in a headline (italic, serif, coloured, underlined). | One face, one colour. The words carry the emphasis. |\n| **Two typefaces at most,** usually one. | The dealt type system. |\n\nThree places keep their own conventions and are left alone by the inspector: real code in\n`<pre>`/`<code>` (monospace is correct there), real tables and form fields (they may have lines), and\na real interface fragment whose root carries the attribute `data-ui` (the product's own borders and\nmenus; see `references/imagery.md` §7).\n\nWhy these, honestly. Some are what the study measured: among the 247 sites, those the panel scored\n7.5 or higher used icon feature cards 1% of the time against 28% for sites under 6.5, pill badges 14%\nagainst 34%, gradients 22% against 52%, shadows 24% against 48%, tiny tracked caps 16% against 57%.\nOthers are the owner's taste and go against current gallery fashion: monospace labels, index numbers\nand hairline grids are actually *more* common on award sites than on weak ones, which is exactly why\ngenerators imitate them and why they now read as costume. They are banned here without exception.\n`references/tells.md` keeps the dated registry.\n\nRemoving ornament leaves space. Never fill it with another ornament. Fill it with scale (make the main\nthing larger), with the full content, with a picture made for this subject, or with a field of flat\ncolour. Leave it empty on purpose once per page at most.\n\n## Laws of the craft\n\nShort form. Numbers are from the study unless marked as house style.\n\n**Type**\n- Two or three sizes do the visible work: one very large, one small, nothing in between. Median\n  headline-to-body ratio on the studied sites is 4.3; the best go far beyond (largest type: median\n  8.4vw on the top sites against 5.0vw on the weak ones).\n- Display type: tracking -0.02 to -0.05em, leading 0.85–1.05. Text: 16–20px, leading 1.45–1.6,\n  45–75 characters per line.\n- Five sizes on a page is the ceiling. One family is normal (a third of the studied sites); two is the\n  limit.\n- Left-aligned by default. Centre at most one moment.\n\n**Space**\n- One grid, one pair of tight margins (16–32px), used everywhere; large things run to the edges. Text\n  blocks share two or three left edges on the whole page.\n- Asymmetry inside the grid, never in the frame: the two outer margins are equal, and an off-centre\n  heading is answered by something at the far side of the grid.\n- The gap between sections is clearly larger than any gap inside one: 120–240px on desktop (the study's median is about 240).\n- Each section has a different composition from its neighbours; none is a card grid.\n\n**Colour**\n- One ground, one ink, one accent. The accent appears on the action and perhaps one other thing.\n- Running text in the full ink. A page set in soft grey reads unfinished.\n- Surfaces are separated by a small step in tone, never by a line or a shadow.\n- A section may change the whole field colour. Nothing fades into anything.\n\n**Imagery**\n- One dominant image beats six small ones. On the top-scored sites the hero media covers at least half\n  the first screen 68% of the time.\n- Same crop ratios, same treatment, square corners unless the direction says otherwise (73% of the\n  studied sites leave media square).\n- No image is better than a placeholder, an icon, or an abstract shape. A picture drawn for this\n  subject, in its colours and with care, is better than either. A real picture of its world, found\n  and credited, is better still.\n- Every found picture is downloaded into the project, credited on the page and listed in the report.\n  None is presented as the client's own.\n- Nothing ever lies on top of a headline or a statement (the inspector fails it).\n\n**Components**\n- Buttons: flat, one fill colour, either square-cornered or fully round, decided once (top sites: 52%\n  square, 23% pill; the 9–16px \"soft\" radius is the weak-site default). Most strong heroes have no\n  button at all, or one.\n- Navigation: wordmark, three to five plain links, one action. No bar chrome.\n- The footer is a designed close, not a sitemap: on most strong sites the name returns at full width.\n\n## Special cases\n\n**An existing brand or design system.** Pass `--keep palette,type`, map the brand's colours and faces\nonto the roles, and take only composition from the draw. The house rules still apply; if the brand\nitself requires a banned device (its logo sits in a gradient, its accent is violet), keep the brand\nasset, say so in the report, and pass `--allow <rule>` to the inspector for that rule only.\n\n**Redesign, restyle or review of an existing page or app screen.**\n\n1. **Record the before.** Run the project as it is and inspect it into its own folder\n   (`inspect.mjs <url> --out .taste-skill/before`, with `--app` for an app screen) and lint its\n   source. Read the code: the framework, the styling method (Tailwind v3 or v4, CSS modules,\n   styled-components, plain CSS), the components, and what must survive: routes, forms, data,\n   behaviour, the brand's own assets.\n2. **A review stops here.** Critique the before screenshots with `references/critique.md`, list the\n   findings with the inspector's measurements, and name the three changes that would move the page\n   most.\n3. **Keep the stack, the content and what works.** No framework or styling-library migration; check the\n   dependency file before adding anything. A restyle keeps the layout and takes type, colour and\n   components from a dealt direction (`--keep` whatever the brand fixes); a redesign deals a full\n   direction and rebuilds the sections from its blueprints inside the existing components. Either way\n   proceed from step 2 of the run with the page's real content.\n4. **Order of work, biggest effect for least risk:** type (faces and scale), colour (one ground, one\n   ink, one accent), the frame (margins, section rhythm, a title on the first screen and a heading on\n   every section), states (hover, focus, loading, empty, error), then the stock components (icon\n   cards, pill badges, gradient blobs, card grids) replaced by the dealt blueprints.\n5. **Prove it.** Inspect again into `.taste-skill/after`, compare before and after at every width,\n   click through every link, form and menu that worked before, and report the before and after\n   measurements side by side.\n\n**A component or a single section, not a page.** Skip the draw unless there is no direction to follow.\nMatch the surrounding design, apply the house rules and the laws, and still inspect the result.\n\n**No checkout, no form backend.** The primary button goes to the real destination when the brief names\none. Otherwise it opens an email with a written subject and body (`mailto:` with the visitor's choices\nfilled in), or, for a shop, it points at `#checkout` and the report says it must be wired before\nlaunch. Never fake a payment form.\n\n**No Chrome or Node 22.** Run `lint.mjs` (Node 18+), take screenshots with whatever browser tool you\nhave, and critique those. Say in the report that the inspector could not run.\n\n**No network.** If `assets.mjs` reaches no source, draw the pictures and say in the report that the\nopen collections could not be searched.\n\n## Files\n\n| File | Read it when |\n| --- | --- |\n| `references/app-screens.md` | Any dashboard, admin, settings or other app screen: its own run, rules, tokens and checks. |\n| `references/copy.md` | Writing the argument and the copy deck (steps 2 and 5). The two-line arithmetic. |\n| `references/type.md` | Setting type: scales, tracking, measure, loading fonts, pairing. |\n| `references/colour.md` | Applying the palette: roles, proportions, tone steps, dark pages, contrast. |\n| `references/layout.md` | Grid, margins, rhythm, section variety, navigation, footer, the phone composition. |\n| `references/imagery.md` | Choosing, finding, crediting, cropping and treating pictures; what to do with none. |\n| `references/motion.md` | Step 9. Budget, tokens, recipes, reduced motion. |\n| `references/scenes.md` | Step 6, when the sheet deals scroll scenes: putting one on a page, filling, fitting, the phone, checking, the catalogue. |\n| `references/critique.md` | Step 8. How to look, how to score, what to fix first. |\n| `references/tells.md` | The dated registry of generated-page tells and what each is replaced by. |\n| `references/research.md` | The study: method, numbers, what the best and worst sites do. Cite it, do not guess. |\n| `scripts/draw.mjs` | Deals and reprints the direction; `--photos`, `--site <id>` for more references; `--app` deals an app style instead. |\n| `scripts/assets.mjs` | Step 6: searches open collections for real pictures of the subject's world; `--get` downloads with the credit, `--credits` prints them. |\n| `scripts/lint.mjs` · `scripts/inspect.mjs` | The gate. |\n| `scripts/scenes.mjs` | The gate for scroll scenes: each scene at 0-100% of its hold, desktop, phone, reduced motion. |\n| `assets/base.css` · `assets/base.js` | An optional neutral foundation to build on. |\n| `assets/scenes/` | The scroll scenes: the shared stage (`stage.js`, `stage.css`) and, for each scene in the library, its `.js`, `.css` and a working demo page in `demo/`. |\n| `assets/app.css` · `assets/charts.js` | For app screens: a neutral shell, panels, tables and controls, and small SVG charts drawn to the app rules. |\n| `library/` | The data the draw reads: directions, heroes, sections, type systems, palettes, photographs, studied sites, motions, scroll scenes (`scenes.json`), and the app styles, shells and screen patterns (`app.json`). Do not read it whole; use the script. |\n","skills/taste-skill/evals/evals.json":"{\n  \"skill_name\": \"design-taste-frontend\",\n  \"how_to_run\": \"For each eval, give the prompt to a fresh agent that has this skill, and to a second fresh agent without it (the baseline). Render both with scripts/inspect.mjs and have a judge who does not know which is which score the screenshots with references/critique.md. Record inspector FAIL counts for both. Evals 7 to 10 are app screens: inspect them with --app (a sheet dealt by draw.mjs --app switches it on by itself) and judge them with the app-screen passes in references/critique.md.\",\n  \"evals\": [\n    {\n      \"id\": 1,\n      \"name\": \"saas-invoicing\",\n      \"prompt\": \"Build a landing page for Ledgerly, an invoicing tool for freelance designers. What it does: you write an invoice in under a minute, the client pays by card or bank transfer, and it sends polite reminders by itself when an invoice is overdue. It costs 9 euros a month flat, with a 14-day free trial and no card needed. Include pricing and a short FAQ. There is no existing brand and no screenshots; the product name is all we have. Plain static HTML, CSS and JS in one folder.\",\n      \"expected_output\": \"A static landing page with a clear idea drawn from invoicing itself, headlines of two lines or fewer at 1440/768/390, no eyebrow labels, no monospace, no index numbering, no thin rules, no gradients or shadows, a non-default palette and type system, a pricing section that is not three cards, and no invented customers or statistics.\",\n      \"files\": []\n    },\n    {\n      \"id\": 2,\n      \"name\": \"restaurant-osteria\",\n      \"prompt\": \"Make a one-page website for Osteria Nove, a 38-seat Italian restaurant in Alfama, Lisbon. Handmade pasta, a short natural wine list, dinner only, Tuesday to Saturday from 19:00. Address: Rua dos Remédios 9. Reservations by phone (+351 21 000 0009) or email (mesa@osterianove.pt). The page needs the menu (invent a believable short one: antipasti, pasta, dolci, with prices in euros), hours, address and how to book. We have no photographs yet. Static HTML/CSS/JS.\",\n      \"expected_output\": \"A one-page restaurant site with a specific idea (for example the page as the menu itself), the menu set typographically without divider lines, practical information easy to find, bundled photographs used only as atmosphere and listed for replacement, and all house rules met.\",\n      \"files\": []\n    },\n    {\n      \"id\": 3,\n      \"name\": \"portfolio-designer\",\n      \"prompt\": \"I'm Mara Lindqvist, a product designer in Stockholm with eight years in fintech and health apps. I need a portfolio homepage: six selected projects (make up plausible names, clients, years and one-line descriptions), a short about paragraph, and a way to contact me (mara@lindqvist.studio). I don't have project images ready, so design it so it still looks finished without them, or use placeholders that I can swap. Static HTML/CSS/JS.\",\n      \"expected_output\": \"A portfolio page that looks finished without project imagery (a typographic index, a name-led hero, or atmosphere photographs clearly marked for replacement), with a designed footer, a phone layout that is its own composition, and all house rules met.\",\n      \"files\": []\n    },\n    {\n      \"id\": 4,\n      \"name\": \"product-ceramics\",\n      \"prompt\": \"Launch page for Kiln, a ceramic pour-over coffee set (dripper, carafe and two cups) that is hand-glazed in small batches in Porto. It costs 84 euros and ships across the EU within a week. The glaze is mixed by hand so no two sets are identical. We have not shot product photos yet, so there are no images of the set. One page, with a way to buy (a button is enough). Static HTML/CSS/JS.\",\n      \"expected_output\": \"A product page that does not fake product photography: it either commits to type and colour, uses one shape from the object as a motif, or uses atmosphere photographs honestly, with the price and purchase action clear, and all house rules met.\",\n      \"files\": []\n    },\n    {\n      \"id\": 5,\n      \"name\": \"guesthouse-ericeira\",\n      \"prompt\": \"Website for Casa Mirante, a six-room guesthouse on the cliffs above Ericeira, Portugal. Rooms from 140 euros a night with breakfast included; ten minutes' walk to the surf at Ribeira d'Ilhas; open March to November. One page: what it is, the rooms, what's nearby, and how to book (email reservas@casamirante.pt). We have no photographs yet. Static HTML/CSS/JS.\",\n      \"expected_output\": \"A calm, photograph-led or type-led one-pager whose hero is one clear thing, with rooms and booking information easy to find, bundled coast photographs used as atmosphere and listed for replacement, and all house rules met.\",\n      \"files\": []\n    },\n    {\n      \"id\": 6,\n      \"name\": \"conference-format\",\n      \"prompt\": \"Landing page for Format, a two-day design conference in Rotterdam on 14 and 15 May 2027. Twelve speakers (invent plausible names and talk titles), 400 seats, tickets at 390 euros, venue: Maassilo. Sections: what it is, the line-up, the schedule in brief, tickets, and a short FAQ. No brand exists yet beyond the name. Static HTML/CSS/JS.\",\n      \"expected_output\": \"An event page with a strong typographic or colour idea, the line-up and schedule set as structured text without divider lines or index numbers, a ticket section that is not three cards, and all house rules met.\",\n      \"files\": []\n    },\n    {\n      \"id\": 7,\n      \"name\": \"app-budget-overview\",\n      \"prompt\": \"Build the main screen of Ledgerly, a budgeting app for couples who share money: the October overview with their accounts and balances, the spending plan (planned against spent by category), bills due in the next 14 days and recent transactions. Two people use it, Mia and Tom. Desktop first, and it must work on a phone. Static HTML/CSS/JS.\",\n      \"expected_output\": \"An app screen, not a landing page: a quiet shell (sidebar or rail), a clear screen title, numbers that add up and are right-aligned with tabular figures, one chart per question, colour spent on data and status only, no icons in tinted squares, no gradients or glows, no placeholder names, and a phone layout where the navigation folds away. inspect.mjs --app passes.\",\n      \"files\": []\n    },\n    {\n      \"id\": 8,\n      \"name\": \"app-deploy-dashboard\",\n      \"prompt\": \"Dashboard for Relay, an edge deployment platform for web teams: one project's overview with recent deployments (status, branch, commit message, author, duration, region), requests and p95 latency over the last 24 hours, the error rate, and usage against the plan's limits. Dark theme. Static HTML/CSS/JS.\",\n      \"expected_output\": \"A dense, readable dark screen on a neutral (not navy) ground: one surface step or one hairline between regions, a deployments table with honest statuses and aligned numbers, charts with few gridlines and one series each, IDs in monospace at most, no rainbow series, no glow, and app inspector checks passing.\",\n      \"files\": []\n    },\n    {\n      \"id\": 9,\n      \"name\": \"app-settings-billing\",\n      \"prompt\": \"Workspace settings for Proofline, a design-review tool: general settings, members and roles (a members table with an invite form), billing (current plan, seats, invoices) and notifications. Static HTML/CSS/JS, desktop and phone.\",\n      \"expected_output\": \"A settings screen with a label column beside its fields (or stacked fields on a phone), labels above inputs, one control height, quiet borders, honest disabled states, a members table with right-aligned figures and one status pill per row, and no decorative icons or gradients.\",\n      \"files\": []\n    },\n    {\n      \"id\": 10,\n      \"name\": \"app-support-queue\",\n      \"prompt\": \"The queue screen of Hearth, a support inbox for a six-person SaaS team: the list of conversations with assignee, priority, channel and time to the SLA, the open conversation with the customer's details beside it, plus filters and saved views. Static HTML/CSS/JS.\",\n      \"expected_output\": \"A three-region work screen (navigation, list, conversation) that stays readable at 1440 and folds to one region at a time on a phone, with status shown once per row, times in words, no tinted icon squares or emoji, and app inspector checks passing.\",\n      \"files\": []\n    }\n  ]\n}\n","skills/taste-skill/library/app.json":"{\n  \"version\": 1,\n  \"about\": \"App-screen library for tasteskill: styles (directions), shells and screen patterns, distilled from the study of 23 desktop product screens (17 light, 6 dark, 17 products) chosen by the owner. Every number is a measurement from the study or a median over it, except where a note says a value was moved for contrast or for the house palette bans. Reference products are not named; the screenshots stay private.\",\n  \"styles\": [\n    {\n      \"id\": \"achromatic-ledger\",\n      \"name\": \"Achromatic ledger\",\n      \"theme\": \"light\",\n      \"basis\": \"4 screens: a seller home, a per-agent insights page, a generated report, a settings page with usage numbers\",\n      \"suits\": [\n        \"finance\",\n        \"commerce\",\n        \"devtools\",\n        \"support\",\n        \"report\",\n        \"workspace\",\n        \"builder\"\n      ],\n      \"idea\": \"The chrome holds no colour at all; money and counts are set in ink, the one chart hue marks the screen's main data element, and the only other hue is a small signal where a figure changed.\",\n      \"colourBudget\": \"under 1% coloured pixels; the chrome is ink, the one chart hue goes on the main data element, and the only other hue is a small change signal\",\n      \"tokens\": {\n        \"ground\": \"#f8f8f8\",\n        \"surface\": \"#ffffff\",\n        \"raised\": \"#eeeeee\",\n        \"border\": \"#e6e6e6\",\n        \"rule\": \"#f0f0f0\",\n        \"control\": \"#d4d4d4\",\n        \"text\": \"#0a0a0a\",\n        \"muted\": \"#6b6b6b\",\n        \"accent\": \"#141414\",\n        \"positive\": \"#2e7d32\",\n        \"negative\": \"#c4242a\",\n        \"warning\": \"#92400e\",\n        \"chart\": [\n          \"#141414\",\n          \"#8a8a8a\",\n          \"#1d5fbf\"\n        ],\n        \"pills\": {\n          \"positive\": [\n            \"#dcfae5\",\n            \"#04250e\"\n          ],\n          \"negative\": [\n            \"#ffedea\",\n            \"#831c1e\"\n          ],\n          \"warning\": [\n            \"#fffbeb\",\n            \"#92400e\"\n          ],\n          \"neutral\": [\n            \"#eeeeee\",\n            \"#3d3d3d\"\n          ]\n        },\n        \"radius\": {\n          \"card\": 8,\n          \"control\": 6\n        },\n        \"font\": {\n          \"family\": \"Geist\",\n          \"second\": \"Geist Mono, for IDs and keys only\",\n          \"fallback\": \"Inter, system-ui, sans-serif\",\n          \"sizes\": {\n            \"title\": 24,\n            \"section\": 16,\n            \"kpi\": 30,\n            \"body\": 14,\n            \"small\": 12\n          },\n          \"weights\": [\n            400,\n            500,\n            700\n          ],\n          \"note\": \"700 is for money figures only; every other number is 400-500.\"\n        },\n        \"density\": \"sparse\",\n        \"rowHeight\": 44,\n        \"sidebarWidth\": 256,\n        \"gap\": 12,\n        \"pad\": 24,\n        \"controlHeight\": 36\n      },\n      \"shell\": \"open-plane\",\n      \"shellAlternatives\": [\n        \"icon-rail\",\n        \"no-sidebar\"\n      ],\n      \"signature\": \"No brand colour anywhere in the chrome: the one primary action is near-black (a grey pill, #e5e5e5, is the secondary), the main data element (today's series, the booked bars, the current period) takes the one chart hue, #1d5fbf, and everything else is drawn in ink with the comparison or the part after the cursor in grey, zero balances are set in grey, and the only hue on the screen is a small triangle or a short coloured number where a figure changed.\",\n      \"identity\": [\n        \"A ground from the product's world in place of #f8f8f8, one level off white and low in chroma: a stone (#f4f3f1) for a bakery or a shop, a sage (#f2f5f2) for a garden or a greenhouse, a blue-grey (#f2f4f7) for a ledger or a meter. Cards stay white; a warm tint stays under the cream check (saturation under about 15%).\",\n        \"The one chart hue (#1d5fbf, or the brand's own hue at 3:1 or more on white) on the screen's main data element: today's line, the booked bars, the current period's column, the margin that breaks. The chrome stays ink and the hue stays under 1% of the screen.\",\n        \"Every figure in Geist Mono, as the style's decision, so money and counts read as a ledger's columns while the text stays Geist. Lint and the inspector flag mono; give the reason in the report.\"\n      ],\n      \"avoid\": [\n        \"a brand-coloured primary button\",\n        \"tinted cards or tinted KPI tiles\",\n        \"a coloured chart where one series in ink says it\",\n        \"bold on anything but money\",\n        \"a chart with no y-scale (the study's one example of this look hid magnitude behind hover and was flagged)\",\n        \"a grey pill as the only button for the screen's main job: in testing an Approve repeated in grey on every row left the screen without a primary\"\n      ],\n      \"notes\": \"The studied screens of this kind used 11-12px card radii, which §9.4 counts among the rare middle values; the library sets the tight pair (8 and 6) so the style lands on the bimodal rule. After testing, the chart hue moved from an unused third series colour onto the main data element: a screen whose only hue was a delta read as a kit.\"\n    },\n    {\n      \"id\": \"framed-sheet\",\n      \"name\": \"Framed sheet\",\n      \"theme\": \"light\",\n      \"basis\": \"6 screens: a developer platform overview, an analytics overview, an events analytics tab, a list detail, a reports dashboard, a flow builder\",\n      \"suits\": [\n        \"analytics\",\n        \"devtools\",\n        \"builder\",\n        \"smb-admin\",\n        \"support\",\n        \"commerce\",\n        \"report\"\n      ],\n      \"idea\": \"The app chrome is one tinted L-shaped frame; the work sits on a white sheet with a hairline edge and soft corners, so depth comes from a single tone step and no shadow.\",\n      \"colourBudget\": \"under 3%; the brand shrinks to the logo and a 2px tab underline, the data carries the chroma\",\n      \"tokens\": {\n        \"ground\": \"#f9fbfc\",\n        \"surface\": \"#ffffff\",\n        \"raised\": \"#f4f6f8\",\n        \"active\": \"#ebedee\",\n        \"border\": \"#e8eaec\",\n        \"rule\": \"#f0f1f2\",\n        \"control\": \"#cdced1\",\n        \"text\": \"#131416\",\n        \"muted\": \"#5d5f60\",\n        \"accent\": \"#1b6c80\",\n        \"positive\": \"#1e7b4f\",\n        \"negative\": \"#c4242a\",\n        \"warning\": \"#92400e\",\n        \"chart\": [\n          \"#1b6c80\",\n          \"#2f70bb\",\n          \"#a86f0c\"\n        ],\n        \"pills\": {\n          \"positive\": [\n            \"#dcfae5\",\n            \"#04250e\"\n          ],\n          \"negative\": [\n            \"#ffedea\",\n            \"#831c1e\"\n          ],\n          \"warning\": [\n            \"#fffbeb\",\n            \"#92400e\"\n          ],\n          \"neutral\": [\n            \"#ebedee\",\n            \"#353736\"\n          ]\n        },\n        \"radius\": {\n          \"card\": 8,\n          \"control\": 6,\n          \"sheet\": 16\n        },\n        \"sheetInset\": 8,\n        \"font\": {\n          \"family\": \"IBM Plex Sans\",\n          \"second\": \"IBM Plex Mono, for IDs and keys only\",\n          \"fallback\": \"Inter, system-ui, sans-serif\",\n          \"sizes\": {\n            \"title\": 22,\n            \"section\": 16,\n            \"kpi\": 28,\n            \"body\": 14,\n            \"small\": 12\n          },\n          \"weights\": [\n            400,\n            500,\n            600\n          ],\n          \"note\": \"KPI values at 400; the semibold goes on the label and the active tab.\"\n        },\n        \"density\": \"medium\",\n        \"rowHeight\": 48,\n        \"sidebarWidth\": 228,\n        \"gap\": 24,\n        \"pad\": 24,\n        \"controlHeight\": 32\n      },\n      \"shell\": \"framed-sheet\",\n      \"shellAlternatives\": [],\n      \"signature\": \"One tinted frame holds the sidebar and the 48px top bar with no rule between them; the page is a white sheet inset 8px from the window's right and bottom edges, with a 1px edge, 16px corners and no shadow. The active tab is a 2px underline in ink or the accent; everything else in the chrome is grey.\",\n      \"identity\": [\n        \"The frame tinted from the product's colour in place of #f9fbfc: one low-chroma step of its hue (a green-grey for a climate or farm tool, a blue-grey for an observability tool, a stone for a print shop). The sheet stays white.\",\n        \"The brand's own hue from the brief as --chart-1 in place of the dealt teal, on the main series and the one selected state, at 3:1 or more on white, never violet or indigo.\",\n        \"IBM Plex Mono for IDs, keys and the figures in tables (one job): its figures have their own drawing, and a developer reads them as the product's.\"\n      ],\n      \"avoid\": [\n        \"a border between the sidebar and the top bar\",\n        \"a shadow under the sheet\",\n        \"cards whose border is heavier than the sheet's (#cdcfcf on cards read as heavy in the study)\",\n        \"a fourth nesting level: frame, sheet and card are enough\",\n        \"different gutters for the KPI row and the chart row (20 against 24 was flagged)\"\n      ],\n      \"notes\": \"The study's second data hue in this style was an orange (#e88e46) that falls inside the house terracotta range; the third chart colour here is an amber moved out of that range and darkened to 3:1 on white.\"\n    },\n    {\n      \"id\": \"accent-ladder\",\n      \"name\": \"Accent ladder\",\n      \"theme\": \"light\",\n      \"basis\": \"3 screens: a newsletter home, a network analytics overview, a cap-table company home\",\n      \"suits\": [\n        \"creator\",\n        \"smb-admin\",\n        \"community\",\n        \"analytics\"\n      ],\n      \"idea\": \"One brand hue at full strength only on small marks, and its pale tints doing all the area work: the active nav row, a plan card, badges and progress tracks.\",\n      \"colourBudget\": \"3-10%, nearly all of it as pale tints of the one hue\",\n      \"tokens\": {\n        \"ground\": \"#f9fafb\",\n        \"surface\": \"#ffffff\",\n        \"raised\": \"#f3f4f6\",\n        \"border\": \"#e5e7eb\",\n        \"rule\": \"#f2f2f2\",\n        \"control\": \"#d1d5db\",\n        \"text\": \"#111827\",\n        \"muted\": \"#5f6672\",\n        \"accent\": \"#b8336a\",\n        \"accentSoft\": \"#fdf2f7\",\n        \"accentTrack\": \"#f8dbe8\",\n        \"accentInk\": \"#6b1d3e\",\n        \"positive\": \"#247b50\",\n        \"negative\": \"#c4242a\",\n        \"warning\": \"#92400e\",\n        \"chart\": [\n          \"#b8336a\",\n          \"#6b7280\",\n          \"#d4618f\"\n        ],\n        \"pills\": {\n          \"positive\": [\n            \"#dcfce7\",\n            \"#14532d\"\n          ],\n          \"negative\": [\n            \"#ffedea\",\n            \"#831c1e\"\n          ],\n          \"warning\": [\n            \"#fffbeb\",\n            \"#92400e\"\n          ],\n          \"neutral\": [\n            \"#f3f4f6\",\n            \"#374151\"\n          ],\n          \"accent\": [\n            \"#fdf2f7\",\n            \"#6b1d3e\"\n          ]\n        },\n        \"radius\": {\n          \"card\": 8,\n          \"control\": 6\n        },\n        \"font\": {\n          \"family\": \"DM Sans\",\n          \"second\": null,\n          \"fallback\": \"Inter, system-ui, sans-serif\",\n          \"sizes\": {\n            \"title\": 32,\n            \"section\": 18,\n            \"kpi\": 24,\n            \"body\": 14,\n            \"small\": 12\n          },\n          \"weights\": [\n            400,\n            500,\n            600,\n            700\n          ],\n          \"note\": \"700 for the page title only.\"\n        },\n        \"density\": \"sparse\",\n        \"rowHeight\": 45,\n        \"sidebarWidth\": 230,\n        \"gap\": 24,\n        \"pad\": 24,\n        \"controlHeight\": 32\n      },\n      \"shell\": \"open-plane\",\n      \"shellAlternatives\": [\n        \"ruled-t-frame\"\n      ],\n      \"signature\": \"The full hue goes only on small marks: the one filled-button style, the data series and the active nav icon. Its 50-200 tints carry every area: the active nav row (tint fill with the dark ink of the hue), the plan or trial card, badges and progress tracks. The primary action may instead be near-black, as on the study's newsletter home.\",\n      \"identity\": [\n        \"The ladder built from the brand's own hue (its logo, the brief's object) in place of the dealt raspberry: the full hue on small marks, its pale tints on areas, never violet or indigo.\",\n        \"The product's objects in the lead block: the newsletter's latest issue as its cover, the shop's products as 40px thumbnails, the course's lessons with their own art.\",\n        \"A ground one level toward the hue's palest tint (#fbf7f8 for the raspberry) in place of #f9fafb, so the page and the tints read as one family.\"\n      ],\n      \"avoid\": [\n        \"the full hue on large areas\",\n        \"a second accent family (four families on one screen was flagged in the study)\",\n        \"a gradient on the trial chip or upgrade button\",\n        \"a left accent bar on the active nav row on top of the tint (seen once in 23 screens)\",\n        \"violet or indigo\"\n      ],\n      \"notes\": \"All three studied screens of this kind used violet, purple or pink as the one hue. The move does not depend on the hue, so the house's violet and indigo ban holds and the library deals a raspberry instead.\"\n    },\n    {\n      \"id\": \"editorial-greeting\",\n      \"name\": \"Editorial greeting\",\n      \"theme\": \"light\",\n      \"basis\": \"2 screens: a team workspace home and a personal insights home\",\n      \"suits\": [\n        \"workspace\",\n        \"creator\"\n      ],\n      \"idea\": \"A personal or team home that opens with a typeset greeting in a centred column; every number below it is set at regular weight on tonal panels.\",\n      \"colourBudget\": \"under 2% for the accent; tonal panels carry the structure\",\n      \"tokens\": {\n        \"ground\": \"#ffffff\",\n        \"surface\": \"#f9f9f9\",\n        \"raised\": \"#ffffff\",\n        \"border\": \"#eaeaea\",\n        \"rule\": \"#f3f3f3\",\n        \"control\": \"#d9d9d6\",\n        \"text\": \"#1f201d\",\n        \"muted\": \"#636361\",\n        \"accent\": \"#1b6e66\",\n        \"positive\": \"#2e7d32\",\n        \"negative\": \"#b42318\",\n        \"warning\": \"#92400e\",\n        \"chart\": [\n          \"#1f201d\",\n          \"#1b6e66\",\n          \"#8c8c88\"\n        ],\n        \"pills\": {\n          \"positive\": [\n            \"#dcfae5\",\n            \"#04250e\"\n          ],\n          \"negative\": [\n            \"#fdecea\",\n            \"#7a1d14\"\n          ],\n          \"warning\": [\n            \"#fffbeb\",\n            \"#92400e\"\n          ],\n          \"neutral\": [\n            \"#f3f3f3\",\n            \"#3d3d3a\"\n          ]\n        },\n        \"radius\": {\n          \"card\": 22,\n          \"control\": 999\n        },\n        \"font\": {\n          \"family\": \"Instrument Sans\",\n          \"second\": \"Instrument Serif, for the greeting only\",\n          \"fallback\": \"Inter, system-ui, sans-serif\",\n          \"sizes\": {\n            \"title\": 48,\n            \"section\": 14,\n            \"kpi\": 32,\n            \"body\": 14,\n            \"small\": 12\n          },\n          \"weights\": [\n            400,\n            500,\n            600\n          ],\n          \"note\": \"The 48px title is the serif greeting; set in the sans it is 24/400. Every figure is 400.\"\n        },\n        \"density\": \"sparse\",\n        \"rowHeight\": 63,\n        \"sidebarWidth\": 224,\n        \"gap\": 16,\n        \"pad\": 20,\n        \"controlHeight\": 38\n      },\n      \"shell\": \"open-plane\",\n      \"shellAlternatives\": [\n        \"framed-sheet\"\n      ],\n      \"signature\": \"The greeting is the h1, in a centred 1100px column on a real 12-column grid (77px columns, 16px gutters), with spans that change by row but share column lines (3/3/3/3, then 9/3, then 6/6, so every internal edge meets one above it). Every figure below is set at regular weight on tonal panels, one layer each: a panel one step off white holds its title and its content directly; a white inner card is used once, for the main chart.\",\n      \"identity\": [\n        \"The greeting names this team or household and today's one fact, set from the data (\\\"Morning, Okoro house. The car is ready by 06:10.\\\"), never \\\"Welcome back\\\".\",\n        \"Each person's stable hue as a pale tint on their avatar and their own lane or column (a couple and their joint account as three lanes): identity, not data, so it stays out of the chart legends.\",\n        \"A surface from the product's world in place of #f9f9f9, one level toward its material (a sage for a garden, a stone for a kitchen, a blue-grey for a studio), with the page white kept.\"\n      ],\n      \"avoid\": [\n        \"an emoji in the greeting\",\n        \"a tracked uppercase date above the greeting (put the date after it or in the grey line below)\",\n        \"a 624-864px column on a desktop screen (both were flagged as wasted width)\",\n        \"a tray around every card (a grey panel with a white card 6px inside it, on every block, read as a bento template in testing)\",\n        \"red as the accent: in testing red marked a record week of upgrades and read as an alarm; red is for the failing fact only\"\n      ],\n      \"notes\": \"One studied screen set its greeting in a serif at 48/700 and its counts in a mono; the other set the greeting at 24/400 in the sans. The red is the second screen's chart red moved two degrees of hue out of the house terracotta range. After testing, the studied red accent was replaced by a deep teal: red on good news read as an alarm.\"\n    },\n    {\n      \"id\": \"pastel-consumer\",\n      \"name\": \"Pastel consumer\",\n      \"theme\": \"light\",\n      \"basis\": \"2 screens: a wallet home and a personal finance home\",\n      \"suits\": [\n        \"wallet\",\n        \"finance\"\n      ],\n      \"idea\": \"Categories are coded by pale tints whose ink is the dark of the same hue, all under one large radius, and each headline sum sits inside the card that explains it.\",\n      \"colourBudget\": \"5-8%, as pale tiles and data marks\",\n      \"tokens\": {\n        \"ground\": \"#f3f5f7\",\n        \"surface\": \"#ffffff\",\n        \"raised\": \"#f2f8fd\",\n        \"border\": \"#e6e6e6\",\n        \"rule\": \"#f4f4f4\",\n        \"control\": \"#d6d9dd\",\n        \"text\": \"#1b1d1f\",\n        \"muted\": \"#5c6064\",\n        \"accent\": \"#1d5fd6\",\n        \"accentSoft\": \"#dcf1ff\",\n        \"accentInk\": \"#0a3a80\",\n        \"positive\": \"#2f7a45\",\n        \"negative\": \"#c41c29\",\n        \"warning\": \"#92400e\",\n        \"chart\": [\n          \"#1d5fd6\",\n          \"#b45309\",\n          \"#2a8798\"\n        ],\n        \"pills\": {\n          \"positive\": [\n            \"#dcfae5\",\n            \"#04250e\"\n          ],\n          \"negative\": [\n            \"#ffedea\",\n            \"#831c1e\"\n          ],\n          \"warning\": [\n            \"#fffbeb\",\n            \"#92400e\"\n          ],\n          \"neutral\": [\n            \"#eef1f4\",\n            \"#3a3d40\"\n          ],\n          \"accent\": [\n            \"#dcf1ff\",\n            \"#0a3a80\"\n          ]\n        },\n        \"radius\": {\n          \"card\": 20,\n          \"control\": 10\n        },\n        \"font\": {\n          \"family\": \"Manrope\",\n          \"second\": null,\n          \"fallback\": \"Inter, system-ui, sans-serif\",\n          \"sizes\": {\n            \"title\": 28,\n            \"section\": 20,\n            \"kpi\": 32,\n            \"body\": 16,\n            \"small\": 14\n          },\n          \"weights\": [\n            400,\n            500,\n            600\n          ],\n          \"note\": \"Money at 24-32px; card titles regular; semibold for net worth, bill amounts and actions.\"\n        },\n        \"density\": \"medium\",\n        \"rowHeight\": 72,\n        \"sidebarWidth\": 240,\n        \"gap\": 24,\n        \"pad\": 24,\n        \"controlHeight\": 40\n      },\n      \"shell\": \"open-plane\",\n      \"shellAlternatives\": [\n        \"icon-rail\"\n      ],\n      \"signature\": \"Pale category tiles with the dark of their own hue as ink (#dcf1ff with #0a3a80), one large radius (20px on cards, stepping down to 10, 8 and 5 inside), and quiet money polarity: income green with a plus sign, spending in ink, no red on ordinary outgoings. Tints go on small tiles, avatars and chips; a panel that holds a list stays white. When the product has people (two partners, a family), each gets one hue, at least 60 degrees from the next.\",\n      \"identity\": [\n        \"The tile hues from the account's own colours (the card's colour, each pot's colour in the app) in place of the dealt cobalt, each tile pale with the dark of its own hue as ink.\",\n        \"The money's own objects: the card art at its real ratio, merchant marks at 24px in the rows, the goal's picture on its pot.\",\n        \"Manrope's figures carry the balance: 30-36px at 600 with tabular figures and the pence in a smaller grey, so the number itself is the face.\"\n      ],\n      \"avoid\": [\n        \"a gradient balance card\",\n        \"two data palettes on one page (flagged in the study)\",\n        \"red on every outgoing amount\",\n        \"a 624px phone-width column on a desktop screen (flagged as a stretched phone screen)\",\n        \"a KPI strip on top: the sums belong in their cards\",\n        \"whole panels tinted per person or category beside white cards (two surface languages on one screen)\"\n      ],\n      \"notes\": \"The two studied screens used a pure #0000ff and an indigo #4723f5 as their brand colour, and pastels such as #7cbecf that fall under 3:1 on white. The library uses a cobalt that reads as blue rather than indigo, and data colours darkened to at least 3:1 on the card.\"\n    },\n    {\n      \"id\": \"true-black-flat\",\n      \"name\": \"True-black flat\",\n      \"theme\": \"dark\",\n      \"basis\": \"5 screens: an events back office, an event analytics tab, a community overview, an artist studio home, an artist insights page\",\n      \"suits\": [\n        \"community\",\n        \"creator\",\n        \"markets\"\n      ],\n      \"idea\": \"Night mode on true black: sidebar, top bar and page share one ground, elevation is a lightness step alone, and colour is confined to data marks.\",\n      \"colourBudget\": \"at or under 3%; the accent never touches buttons, tabs or nav\",\n      \"tokens\": {\n        \"ground\": \"#000000\",\n        \"surface\": \"#111111\",\n        \"raised\": \"#2a2a2a\",\n        \"border\": \"#1a1a1a\",\n        \"rule\": \"#161616\",\n        \"control\": \"#444444\",\n        \"text\": \"#ffffff\",\n        \"muted\": \"#b4b4b4\",\n        \"faint\": \"#949494\",\n        \"accent\": \"#c6f24e\",\n        \"positive\": \"#c6f24e\",\n        \"negative\": \"#e5484d\",\n        \"warning\": \"#e5a93b\",\n        \"chart\": [\n          \"#c6f24e\",\n          \"#e6e6e6\",\n          \"#6b6b6b\"\n        ],\n        \"pills\": {\n          \"positive\": [\n            \"#222a10\",\n            \"#c6f24e\"\n          ],\n          \"negative\": [\n            \"#2c1a20\",\n            \"#e5566f\"\n          ],\n          \"warning\": [\n            \"#2b2414\",\n            \"#e5a93b\"\n          ],\n          \"neutral\": [\n            \"#222222\",\n            \"#ffffff\"\n          ]\n        },\n        \"radius\": {\n          \"card\": 20,\n          \"control\": 999\n        },\n        \"font\": {\n          \"family\": \"Inter\",\n          \"second\": null,\n          \"fallback\": \"system-ui, sans-serif\",\n          \"sizes\": {\n            \"title\": 20,\n            \"section\": 16,\n            \"kpi\": 24,\n            \"body\": 14,\n            \"small\": 12\n          },\n          \"weights\": [\n            400,\n            500,\n            600\n          ],\n          \"note\": \"Nothing above 600; inactive nav labels #bbb, active #fff.\"\n        },\n        \"density\": \"medium\",\n        \"rowHeight\": 80,\n        \"sidebarWidth\": 210,\n        \"gap\": 14,\n        \"pad\": 22,\n        \"controlHeight\": 36\n      },\n      \"shell\": \"ruled-t-frame\",\n      \"shellAlternatives\": [\n        \"no-sidebar\"\n      ],\n      \"signature\": \"Elevation by lightness alone (#000 ground, #111 card, #2a2a2a nested panel) with no borders or shadows on cards; the active nav item is marked only by its label going from #bbb to #fff; the primary control is made primary by inversion, a white 36px pill with black text.\",\n      \"identity\": [\n        \"The one data hue from the product's world in place of the dealt lime: a solar amber (#f2b33d) for an energy home, a sky blue (#4cb3f0) for water or weather, a lime only for sport. It is still the only hue on data and never touches buttons, tabs or nav. A green or yellow-green hue is also --positive; an amber that sits beside --warning leaves the warning to its pill pair.\",\n        \"A ground with the product's temperature: the studied #000 for media and events, a warm near-black (#0e0d0c) for a home, a cool one (#0c0d0f) for a monitor, with cards one lightness step above it (#181716, #15171a). Never navy or slate.\",\n        \"A signature element from the product's world as the lead: the energy home's power flow (sun, house, battery and grid with their live kW), an event's doors against capacity, an artist's release with its cover.\"\n      ],\n      \"avoid\": [\n        \"a navy or slate dark theme\",\n        \"glow, neon borders or shadows\",\n        \"a hue per chart (five hues across four charts was flagged)\",\n        \"the accent on buttons, tabs or nav\",\n        \"a 64px top bar left empty across most of its width (flagged twice)\"\n      ],\n      \"notes\": \"The studied screens of this kind used a violet-magenta (#dd6cff) and an orange (#ff5500) as their one data hue. The library deals a lime, which keeps the move and stays clear of the violet ban; because the lime is a yellow-green, it is also the positive colour (a second, mint green beside it read as two greens). The greys are #b4b4b4 for secondary text and #949494 for meta, 32 levels apart rather than the 20 of the measured #aaa and #969696, which read as one grey; #949494 still holds 4.5:1 on the #2a2a2a nested panel.\"\n    },\n    {\n      \"id\": \"data-terminal\",\n      \"name\": \"Data terminal\",\n      \"theme\": \"dark\",\n      \"basis\": \"1 screen: a stock research view. Keep it narrow.\",\n      \"suits\": [\n        \"markets\",\n        \"devtools\"\n      ],\n      \"idea\": \"A research or monitoring screen read in long sessions: cards darker than the ground, tabular digits that stack, signs instead of colour, and every selection marked by the same 1px accent line.\",\n      \"colourBudget\": \"under 3%; the accent is never more than a 1px line\",\n      \"tokens\": {\n        \"ground\": \"#171719\",\n        \"surface\": \"#131217\",\n        \"raised\": \"#212023\",\n        \"border\": \"#222224\",\n        \"rule\": \"#1b1a1f\",\n        \"control\": \"#3a3a3e\",\n        \"text\": \"#ffffff\",\n        \"muted\": \"#8a8c92\",\n        \"accent\": \"#4a8ad6\",\n        \"positive\": \"#44a282\",\n        \"negative\": \"#e5566f\",\n        \"warning\": \"#d9a441\",\n        \"chart\": [\n          \"#f2f2f3\",\n          \"#e5566f\",\n          \"#4a8ad6\"\n        ],\n        \"pills\": {\n          \"positive\": [\n            \"#1b2828\",\n            \"#5fc39c\"\n          ],\n          \"negative\": [\n            \"#2c1a20\",\n            \"#e5566f\"\n          ],\n          \"warning\": [\n            \"#2a2416\",\n            \"#d9a441\"\n          ],\n          \"neutral\": [\n            \"#212023\",\n            \"#bdbdc0\"\n          ]\n        },\n        \"shadow\": \"0 12px 28px rgba(0,0,0,.2)\",\n        \"radius\": {\n          \"card\": 6,\n          \"control\": 999\n        },\n        \"font\": {\n          \"family\": \"Public Sans\",\n          \"second\": null,\n          \"fallback\": \"Inter, system-ui, sans-serif\",\n          \"sizes\": {\n            \"title\": 26,\n            \"section\": 20,\n            \"kpi\": 20,\n            \"body\": 13,\n            \"small\": 12\n          },\n          \"weights\": [\n            400,\n            500,\n            600,\n            700\n          ],\n          \"note\": \"Section titles 20/400 in the muted grey; card titles 16/600; tabular figures everywhere.\"\n        },\n        \"density\": \"dense\",\n        \"rowHeight\": 42,\n        \"sidebarWidth\": 50,\n        \"gap\": 24,\n        \"pad\": 32,\n        \"controlHeight\": 34\n      },\n      \"shell\": \"icon-rail\",\n      \"shellAlternatives\": [],\n      \"signature\": \"Every selection (tab, toggle, range, nav item) is a 1px accent line exactly as wide as its label, placed on the nearest existing edge; numbers stay white or grey and carry their sign in the text ('+$24,000,000').\",\n      \"identity\": [\n        \"Every figure in a monospace as the style's decision (IBM Plex Mono or JetBrains Mono for each price, count and time, digits that stack), with the text in Public Sans. Lint and the inspector flag mono; give the reason in the report.\",\n        \"The one accent line from the product's world in place of the dealt blue (the exchange's or the team's hue): still the only selection mark, never violet or indigo.\",\n        \"A signature of the market or the system as the lead: an order book's depth as two mirrored bar lists, an incident as a minute-by-minute strip, a region map with the list beside it.\"\n      ],\n      \"avoid\": [\n        \"filled pill tabs or a coloured segmented control\",\n        \"a chart with no scale and no dates (the studied screen had none and was flagged)\",\n        \"tertiary text under 4.5:1 (#4c4c4f read at about 2:1 in the study)\",\n        \"lighter cards with borders and a glow\",\n        \"green and red on every number; the one column whose job is \\\"what moved today\\\" and a negative headline figure may carry the polarity colours\"\n      ],\n      \"notes\": \"The studied screen's muted grey #82848a and red #d4405d were lifted to #8a8c92 and #e5566f so text passes 4.5:1 on the card. Its card list rows sit on a 28px pitch and its table rows on 42px.\"\n    }\n  ],\n  \"shells\": [\n    {\n      \"id\": \"open-plane\",\n      \"name\": \"Open plane\",\n      \"basis\": \"5 of 23 screens\",\n      \"suits\": [\n        \"finance\",\n        \"wallet\",\n        \"workspace\",\n        \"creator\",\n        \"analytics\"\n      ],\n      \"numbers\": {\n        \"sidebarWidth\": \"230-256 (230, 240, 256 in the study; 280 and 292 with a built-in icon rail)\",\n        \"separation\": \"none, or one 1px hairline; the sidebar sits on the page ground or within 1-2% of it\",\n        \"navPitch\": 34,\n        \"navRowHeight\": 32,\n        \"navIcon\": \"16px outline, about 1.5px stroke\",\n        \"navLabel\": \"14px, 400, grey or ink\",\n        \"activeItem\": \"neutral grey pill, radius 6-12, inset 8-12px from the sidebar edges (#e9e9e9-#ededed)\",\n        \"topBar\": \"none\",\n        \"canvas\": \"fluid with a 24-64px gutter, or a centred 1100px column\"\n      },\n      \"blueprint\": \"The labelled sidebar sits on the page ground with nothing or one hairline between it and the canvas; there is no top bar, and the page header and cards sit straight on the ground about 32-36px from the top. Workspace or account switcher at the top of the sidebar, primary nav on a 34px pitch, groups under 12-13px sentence-case grey labels with 22-56px of air above, utilities and the user row pushed to the bottom. Cards are white on the off-white ground (or the sidebar is white with a 1px border on a #f9fafb canvas). The canvas is fluid with one gutter value, or a centred column for personal homes.\",\n      \"phone\": \"The sidebar folds into a 48px top bar holding the screen's name, a menu button that opens a full-screen sheet with the nav and the switcher, and at most one action. Content takes the full width with 16px margins.\"\n    },\n    {\n      \"id\": \"framed-sheet\",\n      \"name\": \"Tinted frame, white sheet\",\n      \"basis\": \"8 of 23 screens, in three variants\",\n      \"suits\": [\n        \"analytics\",\n        \"devtools\",\n        \"builder\",\n        \"smb-admin\",\n        \"support\"\n      ],\n      \"numbers\": {\n        \"chrome\": \"#f6f6f6-#f9fbfc (a warm #f7f6f2 once)\",\n        \"sheetInset\": \"8px from the window's right and bottom edges (12 and 16 once each)\",\n        \"sheetRadius\": \"10-16, median 16\",\n        \"sheetEdge\": \"1px #eaeaea-#ededed, no shadow\",\n        \"sidebarWidth\": \"220-263 (228 on two screens)\",\n        \"topBar\": \"48px on the chrome ground with no rule; search 548x32 centred on the window with a shortcut hint\",\n        \"contentPadding\": 24,\n        \"floatingVariant\": \"both panels inset 12px with a 12px gutter, radius 10\"\n      },\n      \"blueprint\": \"Sidebar and top bar share one tinted ground with no rule between them, forming an L; the page lives on a white sheet. Variant one: the sheet butts against the sidebar and the top bar and is inset 8px from the right and bottom edges, 16px radius, 1px edge. Variant two: a flush L-frame with no inset, the frame marked by one rule. Variant three: sidebar and content are two floating panels inset 12px from every edge with a 12px gutter. The top bar, when present, is 48px and holds a centred search, the account button and a help or AI icon. Inside the sheet the content has 24px padding and starts with the breadcrumb or title row.\",\n      \"phone\": \"The frame disappears: the sheet becomes the screen, with a 48px top bar (menu button, title, one action) on the chrome tint. The search moves into the menu sheet or behind an icon.\"\n    },\n    {\n      \"id\": \"ruled-t-frame\",\n      \"name\": \"Ruled T-frame\",\n      \"basis\": \"4 of 23 screens (3 dark, 1 light)\",\n      \"suits\": [\n        \"community\",\n        \"creator\",\n        \"smb-admin\"\n      ],\n      \"numbers\": {\n        \"sidebarWidth\": \"210-240\",\n        \"topBar\": \"64px with a 1px bottom rule\",\n        \"rules\": \"1px; #1a1a1a on #000, #f2f2f2 on white\",\n        \"navPitch\": \"34 (dark) or 40 (light)\",\n        \"switcher\": \"at the top bar's right end, behind a full-height 1px divider\",\n        \"contentGutter\": \"29px from the sidebar rule and the window edge\"\n      },\n      \"blueprint\": \"A 210-240px sidebar and a 64px top bar share one ground, divided only by 1px rules. The workspace or community switcher sits at the right end of the top bar behind a full-height divider; the sidebar holds the wordmark and the nav on a 34px pitch with sentence-case group labels. On dark, the active item is its label going from #bbb to #fff. The top bar must carry something real (search, the back link and object name, the switcher): two studied screens left about 1070px of it blank and were flagged.\",\n      \"phone\": \"The top bar stays at 48-56px with the switcher reduced to its mark; the sidebar becomes a full-screen menu sheet or a bottom bar of four or five destinations.\"\n    },\n    {\n      \"id\": \"icon-rail\",\n      \"name\": \"Icon rail\",\n      \"basis\": \"3 of 23 screens\",\n      \"suits\": [\n        \"markets\",\n        \"devtools\",\n        \"finance\",\n        \"wallet\"\n      ],\n      \"numbers\": {\n        \"railWidth\": \"50-60, median 55\",\n        \"icon\": \"15-18px outline\",\n        \"pitch\": \"34-49\",\n        \"active\": \"icon colour alone, or a full-bleed 50px band at a 2% tint, or a 1px accent bar on the rail's border\",\n        \"groups\": \"short 20px hairlines, no labels\",\n        \"utilities\": \"pushed to the bottom after a gap of about 200px\"\n      },\n      \"blueprint\": \"An unlabelled rail of 50-60px carries the brand mark at the top and 15-18px outline icons on a 34-49px pitch; groups are split by 20px hairlines, utilities sit at the bottom. The rail sits on the page ground with a 1px edge, or is white with a faint 4px shadow on a grey ground. It saves about 180px of width against a labelled sidebar, so it suits products with few destinations and screens that need the width. Icons need tooltips and an accessible name.\",\n      \"phone\": \"The rail becomes a bottom bar with the same four or five icons, each with a short label under it.\"\n    },\n    {\n      \"id\": \"no-sidebar\",\n      \"name\": \"No sidebar\",\n      \"basis\": \"3 of 23 screens\",\n      \"suits\": [\n        \"report\",\n        \"creator\",\n        \"community\"\n      ],\n      \"numbers\": {\n        \"topBar\": \"46-48px on the page ground, no border\",\n        \"column\": \"centred, 1088-1208px\",\n        \"gutters\": \"152-212px at a 1512px window\",\n        \"logo\": \"on the column's left edge\",\n        \"links\": \"14-15px semibold grey\"\n      },\n      \"blueprint\": \"A 46-48px top bar on the page ground over a centred 1088-1208px column; the logo sits exactly on the column's left edge and the bar's right cluster ends near its right edge, so header and content share one column. Three to five text links, a 36px search, the account. Use it for generated reports, viewers and products with few destinations; with a sticky bar on the same ground, give it a 1px rule when content scrolls under it (the studied bar without one sliced content off).\",\n      \"phone\": \"The bar keeps the logo, a search icon and a menu button; the links move into the menu sheet. The column becomes the full width with 16px margins.\"\n    }\n  ],\n  \"patterns\": [\n    {\n      \"id\": \"kpi-strip-chart-rail\",\n      \"name\": \"KPI strip, main chart and a side rail\",\n      \"screen\": \"overview\",\n      \"kinds\": [\n        \"creator\",\n        \"smb-admin\",\n        \"community\",\n        \"analytics\"\n      ],\n      \"basis\": \"a newsletter home; a community overview\",\n      \"blueprint\": \"Title row: a 24px noun or the product's name at 600-700, an optional 14-16px grey line under it, and the one primary action on the right, bottom-aligned with that line. 16-24px below, the scope row: section tabs and the date range in one row of 32-36px controls, or a 48px segmented track with the range select inside its right end. Then a grid of 1fr and a fixed 384px rail with a 24px gap. Main column: one KPI container split by 1px dividers into 3-5 equal cells (14px grey label, 24px value at 400-600, a 12px caption naming the baseline and window), then the main chart card, which is the largest thing on the screen, then the next card, all 16px apart. Rail: 16px headings outside their cards, 8px above each and 16px after the previous card; a recent-items list of 3-5 rows on a 45px pitch with 1px rules, closed by a 30px outlined 'View all' button instead of pagination. The rail starts level with the first card, not with the title.\",\n      \"phone\": \"The rail moves below the main column; the KPI container becomes a 2-column grid; tabs scroll inside their own row.\"\n    },\n    {\n      \"id\": \"kpi-tabs-chart\",\n      \"name\": \"KPIs as the chart's tabs\",\n      \"screen\": \"overview\",\n      \"kinds\": [\n        \"finance\",\n        \"commerce\"\n      ],\n      \"basis\": \"a seller home\",\n      \"blueprint\": \"One card per subject, 8-16px apart: the main chart card runs full width, and any card holding a table of five columns or fewer, or a short list, pairs with its neighbour in two columns, the page header indented by the card padding so the title, the card titles, the numbers and the plot share one left edge. Balances that do not change during the day go first, in one container split by 1px dividers into equal columns; a zero balance is grey and its caption becomes the next step. In the main card, 2-4 KPIs sit in a row and act as the chart's series tabs: the selected one carries a 2px rule and an ink label, the others keep a grey label and their value in ink at a lighter weight (a grey value reads as disabled); when the tabs are the per-entity breakdown the brief asks for (takings by shop), nothing is greyed and the rule alone marks the selection. Choosing one swaps the series. Under them, one line chart as wide as the card's content (about 1136x220 in the study): 3-4 solid 1px gridlines, 4-6 round y ticks at 12px, a 2-3px line in ink with straight segments and no fill, an 8px hover dot with a 1px dashed guide and the line after the cursor in pale grey. Close with a 2-3 row comparison table on a 36px pitch, value and change columns right-aligned under a 14px grey header such as 'vs prior Monday'.\",\n      \"phone\": \"KPI tabs become a 2-up grid above the chart, with the selected cell marked by a fill (never an underline floating inside the grid) or a row of tabs that scrolls sideways; the chart is full width, 160-200px tall, with 4 x labels; the comparison table keeps its two right-aligned columns.\"\n    },\n    {\n      \"id\": \"chart-pairs\",\n      \"name\": \"Per-period and running-total pairs\",\n      \"screen\": \"analytics\",\n      \"kinds\": [\n        \"community\",\n        \"smb-admin\",\n        \"analytics\"\n      ],\n      \"basis\": \"a network analytics overview\",\n      \"blueprint\": \"Title at 24-32px with one sentence under it saying what the filters do, then one filter row of 36-38px controls (one filled or near-black, the rest borderless or text, a reset link last) and 16-24px to the KPIs. KPI row: 3 equal cards in the content column (3 x 372 + 2 x 17 = 1152 in the study) or one divided container; a 16px label over the value with the change written as a phrase on the value's baseline ('+8 in the last 90 days'), grey when it is zero. Then one row per metric: the per-period column chart on the left and its cumulative line on the right, at equal width (2 x 568 + 16 = 1152) and with the same x ticks; square bars, a 2px straight line, integer ticks from zero, no legend because each chart has one series. One gap value horizontally and vertically.\",\n      \"phone\": \"Pairs stack, the cumulative chart directly under its per-period chart; KPI cards become a single column of label-value rows.\"\n    },\n    {\n      \"id\": \"insights-share-tables\",\n      \"name\": \"Insights with share tables\",\n      \"screen\": \"analytics\",\n      \"kinds\": [\n        \"analytics\",\n        \"devtools\",\n        \"builder\"\n      ],\n      \"basis\": \"a per-agent insights page\",\n      \"blueprint\": \"No cards: sections are carried by whitespace and a 16/500 heading with one 14px grey sentence under it saying what the section shows. A row of up to 6 KPIs on a fixed pitch (12px grey label over a 30px tabular value, no boxes, no dividers), then one full-width time chart (about 218px plot, 5 hairline gridlines, 11-12px grey ticks, a dot legend under the title, a 'Compare to previous period' text button on the right). Then a 2 x 2 grid of small tables with a 24px gutter whose rows align across the two columns. Each table: a header of 12px grey labels with no fill and no rule, 44px rows with 2px gaps whose rounded fill (#f5f7f9, radius 8) is the data bar, its width the row's share divided by the largest share; Share in 12px grey and Count in 14px ink, both right-aligned. An empty table keeps its header and shows one dashed 1px box about 38px tall with one sentence ('No Slack channel usage in this range.').\",\n      \"phone\": \"KPIs become a 2 x 3 grid; the chart is full width; the share tables stack in one column and keep their row bars.\"\n    },\n    {\n      \"id\": \"table-filter-bar\",\n      \"name\": \"Table with tabs and a filter bar\",\n      \"screen\": \"list\",\n      \"kinds\": [\n        \"community\",\n        \"devtools\",\n        \"commerce\",\n        \"support\",\n        \"smb-admin\"\n      ],\n      \"basis\": \"an events back office, a tracks studio, a sessions overview\",\n      \"blueprint\": \"Title row: an 18-24px title on the left, at most an outlined secondary and the one primary (36px) on the right. Underline tabs for the list's states on a full-width 1px rule with a 2px indicator as wide as the label; 22-32px below, the toolbar: a search of about 252-316 x 32-36 on the left, the count ('7 events') and the sort on the right. The table sits on the panel or page ground with no card around it: a header of 12-13px grey sentence-case labels with no fill and no rule, rows on a 48-56px pitch for one line or 72-92px with a thumbnail (media height plus 24-32px), 1px rules 3-7% darker than the ground or no rules at all, the identity column given the most width, numbers right-aligned in tabular figures with the unit muted ('5 /10'), one status mark per row and one kebab at the far right. Drop a column that is empty in every row (a blank co-host column left a 300px dead band). On an overview, cap the rows and link to the full list; on the full list, state the total and load more at the end.\",\n      \"phone\": \"Rows become two-line items: identity and the key number on line 1, the secondary fields in 13px grey on line 2, the kebab at the right. Tabs scroll in their own row; the search becomes a full-width field.\"\n    },\n    {\n      \"id\": \"count-cards-filter\",\n      \"name\": \"Count cards that filter\",\n      \"screen\": \"list\",\n      \"kinds\": [\n        \"community\",\n        \"commerce\",\n        \"support\"\n      ],\n      \"basis\": \"an events back office\",\n      \"blueprint\": \"Above a list, 3-5 equal count cards (61px tall, 12px padding, a 13px grey label over a 16/600 value, 8px gap) are the type filter: the selected card gets a 1.5px accent border and a pale accent fill, and the list below shows that type only. Zero counts print as '0' in the same style; no deltas, no icons. This is one place where a row of identical small cards is right: the cards are peers and each one does work.\",\n      \"phone\": \"The count cards become a horizontally scrolling row of chips with the count inside each, or a select above the list.\"\n    },\n    {\n      \"id\": \"settings-two-column\",\n      \"name\": \"Settings in two columns\",\n      \"screen\": \"settings\",\n      \"kinds\": [\n        \"devtools\",\n        \"smb-admin\",\n        \"support\",\n        \"workspace\",\n        \"commerce\",\n        \"analytics\",\n        \"finance\",\n        \"wallet\",\n        \"creator\",\n        \"community\",\n        \"builder\",\n        \"markets\",\n        \"report\"\n      ],\n      \"basis\": \"one settings page; stacking from a narrow rail card. The basis is thin.\",\n      \"blueprint\": \"A centred column of about 1152px. Each section is one row: a label column of about 450px (16/500 title, 14px grey description; the title's cap top 6-8px below the panel top, level with the panel's first line) beside a panel of about 700px with a #fafafa fill, 16px radius, 16px padding, no border and no shadow. Sections are split by a full-width 1px rule with 32px above and below. Inside a panel: field labels 14/500 above 40px white inputs (1px #e8e8e8, radius 10), 8px from label to field, 16px between fields, 24px from the description to the first label, 16px to the Save button; switch rows with a 14/500 title, a 20px status badge 8px after it, a 14px grey description and a 28x16 toggle 16px from the right edge, centred on the title line. A plan-gated feature shows a 48px tinted strip with a 32px button directly above its panel, and the panel stays readable. When a panel runs much taller than its label, put the section's help or a summary of the current values in the label column rather than 250px of nothing.\",\n      \"phone\": \"Each section stacks: title and description, then the panel at full width. Inside, label, 8-10px, field, 16-26px to the next pair; toggles stay on the right of their title.\"\n    },\n    {\n      \"id\": \"settings-with-usage\",\n      \"name\": \"Settings with usage on top\",\n      \"screen\": \"settings\",\n      \"kinds\": [\n        \"devtools\",\n        \"smb-admin\",\n        \"support\"\n      ],\n      \"basis\": \"one settings page\",\n      \"blueprint\": \"Use this only when usage is the question of the view (a plan, billing or quota view), and show only numbers no section below repeats, at a size below the h1. When a settings screen also reports usage, put 3-4 usage numbers in one row on top (a 14px grey label, a 30px regular value, a 12px change pinned to the card bottom with its window in words, a grey dash where there is no comparison) and link out to the analytics screen ('View more') instead of drawing a chart. Below, the two-column settings rows. One dark primary per screen. Keep upsell to one surface: the studied settings page carried three nags (a top banner, a setup button and a gated strip) and was flagged for it.\",\n      \"phone\": \"The usage row becomes a 2-column grid of label-value pairs; settings rows stack.\"\n    },\n    {\n      \"id\": \"wallet-balance-actions-assets\",\n      \"name\": \"Balance, actions and assets\",\n      \"screen\": \"wallet\",\n      \"kinds\": [\n        \"wallet\",\n        \"finance\"\n      ],\n      \"basis\": \"a wallet home\",\n      \"blueprint\": \"One column whose every element snaps to its two edges. A balance card (1px border, 16px radius, about 134px tall) holding one 32px figure and one line under it in which only the change is coloured ('-$0.09 in the last 30 days'); the title says what the figure is, so it needs no label. 32px below, 4 equal action tiles in a pale tint with dark same-hue icon and 12-14px label (4 x 144 + 3 x 16 = 624 in the study; scale the column and keep the arithmetic). 32-40px below, text tabs for the asset kinds on a 1px rule with a 2px ink indicator as wide as the word, a network or account select on the right of the same row. Then the asset table: 72px rows (48px round icon plus 24px), no dividers, two-line cells pairing a 16px value with a 14px grey unit amount, numeric columns right-aligned to shared edges, change as a small solid triangle and a coloured percentage, zero change grey, a missing share a grey em dash. On a desktop do not leave the column at phone width: the study's 624px column was flagged as a stretched phone screen; widen it to 864-1100 or give it a second column.\",\n      \"phone\": \"This pattern is phone-first: the same column at full width with 16px margins, the 4 tiles in one row, the table as two-line rows with the value right-aligned.\"\n    },\n    {\n      \"id\": \"finance-home-pinned-rail\",\n      \"name\": \"Finance home with a pinned accounts column\",\n      \"screen\": \"overview\",\n      \"kinds\": [\n        \"finance\",\n        \"wallet\"\n      ],\n      \"basis\": \"a personal finance home\",\n      \"blueprint\": \"No page header and no KPI strip: cards start 36px from the top and each headline sum sits in the card that explains it. On the left, a 306px accounts card pinned at the viewport height minus the 36px margins opens with net worth (16/600 label left, value right) and holds the account tree with no dividers: groups 16px ink, categories 14px ink, leaves 14px grey indented 8px, values right-aligned, a 30px pitch and about 45px between groups; an empty group is a bordered box with an '+ Add account' link instead of $0.00. On the right, a 2-column grid with 24px gaps of cards that answer this month's questions, each with its own period caption: the plan (spanning both columns; a ring with an empty hole, a dot legend, the available figure beside it with a per-day line), recent spending as 61px two-line rows (payee over category, amount over date, right-aligned) and upcoming bills. Income is green with a plus sign; spending stays in ink.\",\n      \"phone\": \"Net worth becomes the first card; the account tree collapses to its groups with totals; the month cards stack.\"\n    },\n    {\n      \"id\": \"builder-canvas\",\n      \"name\": \"Builder canvas\",\n      \"screen\": \"builder\",\n      \"kinds\": [\n        \"builder\"\n      ],\n      \"basis\": \"a flow builder in analytics mode\",\n      \"blueprint\": \"No global navigation: a 44px top bar on the window ground with no rule (an exit arrow, the object's name at 16/600 with a status pill, and on the right 16px icon buttons on a 40px pitch, a secondary and a near-black primary, split by 1px dividers). Below, two panels on the ground with 8px outer margins and a 12px gap, both wi\n\n<!-- [TRUNCATED AT 50KB] -->","skills/taste-skill/library/directions.json":"[\n {\n  \"id\": \"name-as-monument\",\n  \"name\": \"The name as a monument\",\n  \"sectors\": [\n   \"agency\",\n   \"studio-portfolio\",\n   \"personal-portfolio\",\n   \"hospitality\",\n   \"restaurant\",\n   \"music\",\n   \"culture\",\n   \"fashion\",\n   \"event\",\n   \"architecture\",\n   \"real-estate\",\n   \"physical-product\",\n   \"consumer-app\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"bold\",\n   \"editorial\",\n   \"luxury\"\n  ],\n  \"needs\": [],\n  \"idea\": \"The name is the headline. Set it so large that it becomes architecture: as wide as the viewport, cropped by an edge, or stacked to fill the screen. Nothing else on the first screen competes; the description of what this is drops to a single small sentence. The idea comes from treating the name's letters as material. Ask what the subject can do to its own name: a photograph of the work sits inside a counter or replaces a letter, the name repeats down the page like a reel, the letters are split to opposite corners and the page happens between them. In the study this was the single most common device among sites scoring 7.5 or more.\",\n  \"composition\": \"First screen: the wordmark spans 88–100% of the viewport width (font-size 16–24vw, set with a clamp so it never wraps), anchored either to the bottom edge with its descenders nearly touching it, or dead centre with everything else pushed to the corners. One line of supporting text at 16–20px sits in a corner on a shared margin; navigation is three or four words in the opposite corner. After the hero the page is deliberately small and calm: a narrow text column or a simple two-column grid, so the contrast with the monument holds. The name returns once more at full width as the footer, in the inverse colours. Margins are tight (20–32px) so the type reaches the edges. Two type sizes do nearly all the work: the monument and a small text size, with one mid size for section headings.\",\n  \"typography\": \"One family. The display cut must survive enormous sizes: tight tracking (-0.04 to -0.07em), leading 0.8–0.9, optical kerning on. Section headings are modest (28–40px) on purpose.\",\n  \"typeClasses\": [\n   \"grotesk-tight\",\n   \"condensed-heavy\",\n   \"extended-heavy\",\n   \"heavy-black\",\n   \"serif-display\"\n  ],\n  \"colour\": \"Two values carry the page (ground and ink). The accent, if used at all, appears on one thing only: the single action or the inset image frame. The footer inverts ground and ink.\",\n  \"paletteTags\": [\n   \"light-neutral\",\n   \"dark-neutral\",\n   \"two-tone\",\n   \"mono-accent\"\n  ],\n  \"imagery\": \"Few images, used as inserts in the typography rather than as illustrations beside it: one photograph inside or behind the name (a 4:5 or 1:1 frame replacing a letter, or tucked between two words), then a short run of large full-width or half-width photographs further down. Square corners. No collage of small thumbnails.\",\n  \"sectionTags\": [\n   \"type-led\",\n   \"quiet\",\n   \"poster\"\n  ],\n  \"motion\": \"scaling-wordmark\",\n  \"richness\": \"Scale. The size of the name against the smallness of everything else is the entire visual event, so protect both ends: do not shrink the name to make room, and do not let body text creep above 20px.\",\n  \"pitfalls\": \"A long name set small is just a logo. If the name has more than about 12 characters, stack it on two lines or crop it with the viewport edge; never drop below 12vw. Do not add a second big headline under the name. Do not decorate the letters.\",\n  \"seenIn\": [\n   \"aww-nothin\",\n   \"opl-kereliott\",\n   \"aww-paul-kalkbrenner\",\n   \"opl-nia-creative\",\n   \"aww-house-of-honey-1\",\n   \"aww-produx-design\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"sentence-as-layout\",\n  \"name\": \"The sentence is the layout\",\n  \"sectors\": [\n   \"agency\",\n   \"saas\",\n   \"ai-product\",\n   \"dev-tool\",\n   \"nonprofit\",\n   \"culture\",\n   \"education\",\n   \"physical-product\",\n   \"consumer-app\",\n   \"finance\",\n   \"health\",\n   \"event\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"bold\",\n   \"editorial\"\n  ],\n  \"needs\": [],\n  \"idea\": \"One short sentence, set at poster scale, is the composition. The trick that makes it an idea rather than a big headline: something from the subject sits inside the sentence where a word would be. A strip of photograph fills the gap between two words; a small live fragment of the product replaces the noun; the object the sentence names is pictured at the size of a letter. Write the sentence first, find the word that can be shown instead of said, and put the showing in its place. The reader completes the sentence with their eyes.\",\n  \"composition\": \"The sentence is four to seven words and runs as one or two full-width lines at 9–13vw. Inline with the type, on the baseline, sits one media slot: a rounded-rectangle or square frame exactly one line-height tall and two to three ems wide, holding a photograph or a looping crop. Above and below the sentence the screen is empty except for a small navigation line and one supporting sentence set small, both on the same left margin. Later sections repeat the grammar at smaller scale: each is a short statement on the left six columns with its proof (image, figure, list) on the right, so the page reads as a series of sentences with evidence. Generous vertical space (160px or more) between sections.\",\n  \"typography\": \"Display weight with real presence (medium to bold), tracking -0.03 to -0.05em, leading 0.95–1.0 so two lines sit close. The inline frame aligns to cap height and baseline exactly; set it with em units so it scales with the type.\",\n  \"typeClasses\": [\n   \"grotesk-tight\",\n   \"serif-display\",\n   \"condensed-heavy\",\n   \"serif-light-large\"\n  ],\n  \"colour\": \"A calm ground with ink at full contrast. The only colour comes from the photograph inside the sentence; if the palette has an accent, use it once, on the action.\",\n  \"paletteTags\": [\n   \"two-tone\",\n   \"light-neutral\",\n   \"single-field\",\n   \"mono-accent\"\n  ],\n  \"imagery\": \"One strong, simple photograph that reads at small size (a face, an object, a texture, a horizon), cropped to a wide strip inside the sentence. The same image may open to full width in the next section, so the small slot feels like a window onto something larger.\",\n  \"sectionTags\": [\n   \"type-led\",\n   \"poster\",\n   \"quiet\"\n  ],\n  \"motion\": \"masked-headline\",\n  \"richness\": \"The collision of big type and one live image inside it. Because there is only one image on the first screen, choose it with care and give it perfect alignment to the letters.\",\n  \"pitfalls\": \"The sentence must be short enough for two lines on a phone, where the inline frame drops to its own line between the two halves. Do not style one word differently to fake the device. Do not use more than one slot per sentence.\",\n  \"seenIn\": [\n   \"aww-colonia-zacamil\",\n   \"aww-bleibtgleich26\",\n   \"opl-spatial\",\n   \"aww-coffeetech-r\",\n   \"opl-midnight-2\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"pinned-poster\",\n  \"name\": \"The pinned poster\",\n  \"sectors\": [\n   \"culture\",\n   \"music\",\n   \"event\",\n   \"fashion\",\n   \"personal-portfolio\",\n   \"studio-portfolio\",\n   \"physical-product\",\n   \"ecommerce\",\n   \"hospitality\",\n   \"consumer-app\"\n  ],\n  \"tones\": [\n   \"bold\",\n   \"editorial\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Something stays put while everything else changes. A title holds its place across the viewport and the images beneath it swap; the name is split to two opposite corners and the page passes between the halves; a single frame stays centred while its contents change. Every scroll step is a new cover of the same magazine. The idea suits subjects that are a series (a book of portraits, a line-up, a collection, a set of projects): the fixed element says what the series is, the changing element shows its members.\",\n  \"composition\": \"A sticky layer holds the fixed element for the height of two to three viewports: usually the title at 10–14vw across the middle or top of the screen, or two words pinned to the top-left and bottom-right corners. Under it, a stack of full-height panels scrolls by, each a single large photograph (portrait 4:5, centred, 40–50% of the viewport wide) with one line of caption at the same small size everywhere. The title sits above the images in the stacking order and uses `mix-blend-mode: difference` or a solid colour that reads on every panel. When the pinned run ends, the page releases into ordinary flowing sections with a narrow measure. Build with `position: sticky`; never hijack the scroll.\",\n  \"typography\": \"The pinned title is the only large type on the page. Captions and body share one small size (15–17px). Tight tracking and solid weight so the title reads over photographs.\",\n  \"typeClasses\": [\n   \"grotesk-tight\",\n   \"condensed-heavy\",\n   \"heavy-black\",\n   \"extended-heavy\"\n  ],\n  \"colour\": \"One strong title colour against a pale or dark ground. Each panel may take its own flat ground colour sampled from its photograph.\",\n  \"paletteTags\": [\n   \"two-tone\",\n   \"photographic-neutral\",\n   \"single-field\"\n  ],\n  \"imagery\": \"A series of photographs with the same crop ratio and the same framing (all portraits, all objects, all rooms), so that swapping them reads as one image changing. Five to eight in the pinned run.\",\n  \"sectionTags\": [\n   \"photo-led\",\n   \"poster\",\n   \"type-led\"\n  ],\n  \"motion\": \"pinned-story\",\n  \"richness\": \"Repetition with change. The fixed title makes each new photograph feel like an event, so the photographs must be good and consistent.\",\n  \"pitfalls\": \"If the title is not legible over every panel, the idea fails: test each one. Keep the pinned run under six viewports or it feels like a trap. On a phone the title shrinks to 16–18vw and stays pinned at the top; panels become full-width. A pin longer than three screens, or one where the screens under it are nearly empty, read in blind tests as a stuck page. Every screen under the pin needs its own content, and nothing may pass over the pinned words.\",\n  \"seenIn\": [\n   \"opl-city-of-angels\",\n   \"aww-normal-is-boring\",\n   \"aww-glitch-grit\",\n   \"aww-revelatio-studio\"\n  ],\n  \"allow\": [],\n  \"needsPictures\": true\n },\n {\n  \"id\": \"colour-chapters\",\n  \"name\": \"Colour chapters\",\n  \"sectors\": [\n   \"agency\",\n   \"music\",\n   \"event\",\n   \"education\",\n   \"nonprofit\",\n   \"saas\",\n   \"consumer-app\",\n   \"culture\",\n   \"physical-product\",\n   \"health\",\n   \"finance\",\n   \"ai-product\"\n  ],\n  \"tones\": [\n   \"bold\",\n   \"playful\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Every section is a chapter with its own flat colour, floor to ceiling. The page reads like a set of posters hung in a row, held together by one typeface and one grid. The colours are not decoration: they come from the subject (the brand's packaging, the artist's record sleeves, the product's own colour ways, the categories of the content) and each chapter's colour means that chapter. Decide the sequence like a designer orders a book: a strong opener, a quiet second, a surprise in the middle, a dark or very light closer.\",\n  \"composition\": \"Sections are full-bleed fields, each at least 90svh tall, butted directly against each other with no gap and no divider. Inside every field the same 12-column grid and the same margins apply, and each field holds one thing: a huge heading (8–12vw) with a small paragraph, or one photograph with a caption, or one list. Text colour is chosen per field for strong contrast (ink or paper, never grey). Headings start on the same left edge in every chapter, so the eye feels the system as colours change. The navigation and the footer take the colours of the first and last chapter.\",\n  \"typography\": \"One typeface in two weights. Headings very large and tight; body 18–20px. Because colour is loud, the type stays plain: no italics, no second face.\",\n  \"typeClasses\": [\n   \"grotesk-tight\",\n   \"heavy-black\",\n   \"geometric\",\n   \"rounded-friendly\"\n  ],\n  \"colour\": \"Four to six flat fields used at full strength, one per section, each with its assigned text colour. No tints, no gradients between them: the hard edge where two fields meet is the look.\",\n  \"paletteTags\": [\n   \"flat-loud\",\n   \"pastel-fields\"\n  ],\n  \"imagery\": \"Sparing. One photograph or object per chapter at most, either cut out and sitting directly on the colour, or a plain rectangle with generous colour around it. Photographs should be simple enough not to fight the field.\",\n  \"sectionTags\": [\n   \"colour-field\",\n   \"type-led\",\n   \"poster\"\n  ],\n  \"motion\": \"colour-on-scroll\",\n  \"richness\": \"Colour at scale. A whole screen of one saturated colour is rich on its own, so a chapter needs few elements; it still needs its content at full size, because a coloured screen with one small line on it reads as empty.\",\n  \"pitfalls\": \"Check contrast on every field with the palette's assigned ink. Do not put cards on the fields. Do not use more than six colours. Two neighbouring fields should differ clearly in lightness as well as hue.\",\n  \"seenIn\": [\n   \"aww-warm-fuzzy\",\n   \"aww-paul-kalkbrenner\",\n   \"opl-anidachi\",\n   \"aww-aardvark-book-club\",\n   \"aww-ai-in-design-report-2026\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"place-carries-it\",\n  \"name\": \"The place carries it\",\n  \"sectors\": [\n   \"hospitality\",\n   \"restaurant\",\n   \"real-estate\",\n   \"architecture\",\n   \"event\",\n   \"health\",\n   \"culture\",\n   \"nonprofit\"\n  ],\n  \"tones\": [\n   \"quiet\",\n   \"luxury\",\n   \"warm\"\n  ],\n  \"needs\": [],\n  \"idea\": \"For a place, the photograph is the argument. One full-bleed image of where you would be standing fills the first screen, and the design steps back: the name sits along the bottom edge like a film title, or small in a corner, and nothing else interrupts the view. The page that follows keeps that restraint: few words, large pictures, long pauses. The designer's work here is editing: choosing the one frame that makes someone want to be there, and then not covering it.\",\n  \"composition\": \"First screen: a single photograph at 100vw by 100svh, focal point kept clear of text. The name is set either very large (14–20vw) hugging the bottom edge with 16–24px of margin, or small (20–28px) top-left with a one-line description bottom-left. Navigation is two to four words in the top corners in the same small size. If text sits on the image, a soft neutral scrim under the text area only. Below, sections alternate between a short centred or left-set paragraph in a narrow column (max 52ch) with wide empty margins, and photographs shown large: one full-bleed, then a pair at different sizes, then one portrait offset to the right. Practical information (hours, address, rates, booking) is gathered once near the end in a plain two-column block.\",\n  \"typography\": \"A face with some grace for the name; small, calm, well-spaced text everywhere else. Sentence case. Body 17–19px with leading around 1.55.\",\n  \"typeClasses\": [\n   \"serif-display\",\n   \"serif-light-large\",\n   \"condensed-heavy\",\n   \"grotesk-light\"\n  ],\n  \"colour\": \"Neutral paper or deep neutral ground chosen to flatter the photographs; text ink drawn from the darkest tone in the imagery. Colour lives in the pictures.\",\n  \"paletteTags\": [\n   \"photographic-neutral\",\n   \"dark-neutral\",\n   \"earth\"\n  ],\n  \"imagery\": \"The dealt set is the palette. Choose four to six photographs with the same light. The hero image must have a calm area for the name. Full-bleed or large with square corners; never thumbnails, never a carousel of ten.\",\n  \"photoTreatment\": \"Leave photographs ungraded. If text overlays one, darken only the area behind the text with a neutral scrim.\",\n  \"sectionTags\": [\n   \"photo-led\",\n   \"quiet\"\n  ],\n  \"motion\": \"slow-crossfade\",\n  \"richness\": \"The photographs, at full size, uninterrupted. Empty paper around short text makes the next image land harder.\",\n  \"pitfalls\": \"A weak hero photograph cannot be fixed by typography; pick again. Do not stack a headline, a paragraph and two buttons on the image. Do not use a booking bar that covers the bottom of the view; one small action is enough.\",\n  \"seenIn\": [\n   \"aww-white-desert\",\n   \"opl-eagles-nest\",\n   \"aww-tengile-malamala-collection\",\n   \"aww-izanami\",\n   \"aww-seasats\"\n  ],\n  \"allow\": [],\n  \"needsPictures\": true\n },\n {\n  \"id\": \"page-is-the-object\",\n  \"name\": \"The page is the object\",\n  \"sectors\": [\n   \"restaurant\",\n   \"event\",\n   \"hospitality\",\n   \"culture\",\n   \"music\",\n   \"physical-product\",\n   \"ecommerce\",\n   \"nonprofit\",\n   \"education\",\n   \"personal-portfolio\",\n   \"consumer-app\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"warm\",\n   \"playful\",\n   \"editorial\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Find the printed or physical artefact that already exists in the subject's world and build the page as that thing. A wedding site is the invitation card. A restaurant is its menu. A conference is the ticket; a record is its sleeve; a shop is the receipt or the swing tag; an archive is a stack of tabbed folders; a course is the syllabus sheet. The artefact supplies everything a template would otherwise invent: its proportions, its typographic manners, its way of grouping information. Visitors recognise the object instantly, which is why these pages feel specific.\",\n  \"composition\": \"The first screen shows the artefact as a single filled panel (paper colour on a contrasting ground) centred or offset, with believable proportions: a card at 5:7, a ticket at about 2.2:1 with a notch cut by `clip-path`, a menu as a tall sheet. All primary content lives on it, set the way that object is set: centred and symmetrical for an invitation, in tidy aligned columns for a menu or ticket. The ground behind is a flat colour or one full-bleed photograph. As the page continues, each section is another piece of the same stationery: a second card, a tear-off stub, a folded panel, always filled shapes with real edges (straight, notched, scalloped, perforated by a dotted `border` of round dots at 4px or more), never outlined boxes. The footer is the back of the object.\",\n  \"typography\": \"Take the manners of the artefact: a bookish serif with small caps avoided, or a blunt condensed face for tickets and posters. Sizes stay within what print would use relative to the panel; the name is large on the panel, details are small and exact.\",\n  \"typeClasses\": [\n   \"serif-text\",\n   \"serif-display\",\n   \"slab\",\n   \"condensed-heavy\",\n   \"grotesk-tight\"\n  ],\n  \"colour\": \"Paper and ink plus the ground the paper sits on. Two or three flat colours in total, like a two-colour print job.\",\n  \"paletteTags\": [\n   \"two-tone\",\n   \"earth\",\n   \"light-neutral\"\n  ],\n  \"imagery\": \"Optional. One photograph behind the object, or small photographs placed on it like tipped-in plates. The object itself is the image.\",\n  \"sectionTags\": [\n   \"object-led\",\n   \"type-led\",\n   \"colour-field\"\n  ],\n  \"motion\": \"curtain-footer\",\n  \"richness\": \"Recognition. The shaped edges, the print-like alignment and the limited inks make a familiar object out of plain HTML.\",\n  \"pitfalls\": \"Choose an artefact that truly belongs to the subject, or it becomes costume. Shape the edges with fills and `clip-path`; an outlined rectangle with a thin border is not an object. Keep text sizes readable on a phone, where the object becomes full width with its shaped edge kept at top and bottom.\",\n  \"seenIn\": [\n   \"opl-sarah-matt-wedding\",\n   \"aww-mosbys-files\",\n   \"opl-the-deep-end\",\n   \"opl-weeksync\",\n   \"opl-le-petit-bleu\",\n   \"opl-archiv\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"one-motif\",\n  \"name\": \"One motif\",\n  \"sectors\": [\n   \"saas\",\n   \"finance\",\n   \"consumer-app\",\n   \"ai-product\",\n   \"dev-tool\",\n   \"health\",\n   \"physical-product\",\n   \"restaurant\",\n   \"education\",\n   \"nonprofit\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"playful\",\n   \"technical\",\n   \"warm\",\n   \"bold\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Take one shape from the subject and let it run the whole system. A drilling tool's octagonal cross-section becomes the buttons, the image masks and the loader. A two-account money app becomes two circles that recur as icon, inline dot and section colour. A café's striped awning becomes every band on the page. Look at the product, the logo, the object or the word in the headline and find the simplest geometry in it (a circle, an arc, a chamfer, a stripe, a notch, a ring). Then use only that shape, at three or four very different scales, everywhere a designer would normally reach for a generic rounded rectangle.\",\n  \"composition\": \"Hero: the motif appears once at enormous scale as a flat filled shape, cropped by the viewport (a circle 120vh across entering from the right, a chamfered block filling the lower half), with a short headline at 6–8vw and one supporting sentence set on the remaining ground, left-aligned on a shared margin. Through the page the motif returns as: the mask for every photograph (via `clip-path` or `border-radius` made from the same geometry), the shape of the primary button, the bullet beside list items at text size, and one full-width band that separates the two halves of the page. Sections use simple two-column or single-column layouts so the shape is the only thing with character.\",\n  \"typography\": \"A clean geometric or grotesk face that echoes the shape (round bowls for circles, squared terminals for chamfers). Medium weight; headings 6–8vw in the hero and 3–4vw after.\",\n  \"typeClasses\": [\n   \"geometric\",\n   \"grotesk-tight\",\n   \"rounded-friendly\"\n  ],\n  \"colour\": \"The motif carries the accent colour at large scale, flat. Everything else is ground and ink. A second motif colour is allowed only if the subject has a real pair (two accounts, two modes).\",\n  \"paletteTags\": [\n   \"mono-accent\",\n   \"two-tone\",\n   \"pastel-fields\"\n  ],\n  \"imagery\": \"Photographs appear inside the motif's shape. If there is product interface to show, it sits on a flat colour stage shaped by the motif. Draw the shape with CSS or a simple inline SVG path; do not draw illustrations.\",\n  \"sectionTags\": [\n   \"colour-field\",\n   \"object-led\",\n   \"type-led\"\n  ],\n  \"motion\": \"shutter-image\",\n  \"richness\": \"One shape at many sizes. The giant cropped shape gives the hero mass and colour without a single image.\",\n  \"pitfalls\": \"One motif means one. A circle here, a hexagon there and a blob behind is the generated look this replaces. The motif must come from the subject and you must be able to say from where in one clause.\",\n  \"seenIn\": [\n   \"aww-sstr-friction-reduction\",\n   \"opl-tara\",\n   \"opl-boaxt\",\n   \"opl-midnight-2\",\n   \"opl-superlocal-2026\",\n   \"opl-billow\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"product-performs\",\n  \"name\": \"The product performs\",\n  \"sectors\": [\n   \"saas\",\n   \"dev-tool\",\n   \"ai-product\",\n   \"consumer-app\",\n   \"finance\"\n  ],\n  \"tones\": [\n   \"technical\",\n   \"quiet\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Software is most convincing when it is doing its job in front of you. Instead of describing features, put small, true, working fragments of the product on the page: the actual control, with real content, responding to the pointer. A colour picker's loupe reads the page's own background and prints its value. A list tool lets you tick an item right there. A type-scale plugin sets the page's own headings. Find the one interaction that is the product and make the hero that interaction; then show each further capability as another fragment at real size. No dashboard collage, no browser frame, no screenshots shrunk until unreadable.\",\n  \"composition\": \"Hero: a short plain headline (4–6vw, left-aligned, upper-left third) and one sentence; the rest of the first screen is the main fragment at actual interface size, sitting directly on the page or on one flat stage colour, large enough to read every label. The fragment is built in HTML and works. Below, capabilities are a single-column sequence, each a row of two parts on a 5/7 split: a two-line statement on one side and the relevant fragment on the other, with the fragments varying in size and shape so the column never becomes a zigzag of equal blocks. Fragments are cropped pieces of interface (a menu, a row, a control, a panel edge), not whole windows. One section pins a fragment while three short statements change it.\",\n  \"typography\": \"The marketing type matches the product's interface type so the fragments and the page feel like one thing. Headline modest; interface text at its true size (13–15px) inside fragments.\",\n  \"typeClasses\": [\n   \"grotesk-tight\",\n   \"grotesk-light\",\n   \"geometric\"\n  ],\n  \"colour\": \"Neutral ground. The product's own interface colours provide the colour. At most one flat stage colour behind fragments.\",\n  \"paletteTags\": [\n   \"light-neutral\",\n   \"dark-neutral\",\n   \"mono-accent\"\n  ],\n  \"imagery\": \"The interface fragments are the main imagery: build them carefully with real labels, real numbers and sensible states (one hovered, one selected). Around them, two or three real pictures of the customer's world (found with scripts/assets.mjs), never stock of people at laptops.\",\n  \"sectionTags\": [\n   \"ui-led\",\n   \"quiet\"\n  ],\n  \"motion\": \"pinned-story\",\n  \"richness\": \"Fidelity. A fragment with believable content and a real hover state is more interesting than any illustration. Spend the effort there.\",\n  \"pitfalls\": \"A fake interface made of grey bars and circles is the worst outcome; if you cannot build a believable fragment, change direction. Mark each fragment's root element with the attribute data-ui: inside it the product's own conventions apply (1px control borders, small radii, a shadow on its open menu) and the inspector leaves them alone; outside it the house rules hold as usual. data-ui is for cropped fragments only, never for a page wrapper. Do not put the fragment in a browser or laptop frame.\",\n  \"seenIn\": [\n   \"opl-dabbit\",\n   \"opl-rows\",\n   \"opl-typewave\",\n   \"opl-shelf\",\n   \"opl-uni\",\n   \"opl-kontu\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"quiet-instrument\",\n  \"name\": \"The quiet instrument\",\n  \"sectors\": [\n   \"saas\",\n   \"dev-tool\",\n   \"ai-product\",\n   \"personal-portfolio\",\n   \"consumer-app\",\n   \"finance\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"quiet\",\n   \"technical\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Radical understatement. Where every competitor shouts, this page almost whispers: a headline barely larger than body text, a narrow column, small exact demonstrations, and a great deal of untouched space. The restraint is the claim. It says the thing is simple, finished and sure of itself. This only works when it is carried through completely; one loud element breaks it. In the study, a tool for simple lists sold itself with a 27px headline and 12–14px copy and was one of the most confident pages in the set.\",\n  \"composition\": \"A single column 440–560px wide, placed left of centre (starting at about 22% of the viewport width) or dead centre, running the whole page. The headline is the one large thing on the first screen: two lines at display size (5–7vw), medium weight, starting on the column's left edge and allowed to run wider than the column. The supporting paragraph follows at body size (17–19px) in the full ink. One small primary button and one text link. Below, each point is a short paragraph followed by a compact demonstration or image no wider than the column. Sections are separated only by space (96–140px). Nothing spans the full width until the footer, which is a single quiet line. The first screen is mostly empty and that emptiness is composed: the column's top edge sits at about 30% of the viewport height.\",\n  \"typography\": \"One family, two weights. A display size for the headline (5–7vw), one heading size for section titles (about 32–40px), body at 17–19px, a small size for captions (14–15px). Leading 1.5 for text. Letter-spacing near zero. The typeface must be handsome at small sizes.\",\n  \"typeClasses\": [\n   \"grotesk-light\",\n   \"serif-text\",\n   \"geometric\"\n  ],\n  \"colour\": \"Paper and two inks (full and soft). One accent used on exactly one element per screen.\",\n  \"paletteTags\": [\n   \"light-neutral\",\n   \"mono-accent\"\n  ],\n  \"imagery\": \"Precise rather than loud: cropped interface details at true size, and real photographs of the customer's world held to the column width, each doing one job. One short looping clip can sit at column width too. Never a large stock hero image.\",\n  \"sectionTags\": [\n   \"quiet\",\n   \"ui-led\",\n   \"type-led\"\n  ],\n  \"motion\": \"stillness\",\n  \"richness\": \"Precision. With so little on the page, alignment, spacing and the exact size relationships are the design. Every element shares the column's left edge.\",\n  \"pitfalls\": \"This is the one direction where a small headline is right; the inspector will not object, but do not mix it with a large display line. Emptiness must look decided: keep the column edges exact and the vertical rhythm even. Not suitable when the subject needs emotion or photography to sell. Quiet is not thin: the column must still deliver every piece of content the brief asks for, in full, at 16px or more in the full ink. In blind tests the quiet version lost every time it was quiet everywhere: a small headline beside an empty panel read as unfinished. Quiet means few things, not small things: the headline and the demonstration are large, and every screen holds content.\",\n  \"seenIn\": [\n   \"opl-rows\",\n   \"opl-compile\",\n   \"opl-plastic\",\n   \"opl-bueno-fyi\",\n   \"aww-gil-huybrecht\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"hero-object\",\n  \"name\": \"The object, large\",\n  \"sectors\": [\n   \"physical-product\",\n   \"ecommerce\",\n   \"consumer-app\",\n   \"fashion\",\n   \"finance\",\n   \"health\",\n   \"restaurant\",\n   \"music\"\n  ],\n  \"tones\": [\n   \"bold\",\n   \"luxury\",\n   \"quiet\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"idea\": \"Show the thing, bigger than seems reasonable. One photographed object fills the first screen, scaled until the viewport crops it, with the text small and tucked beside or behind it. The crop is the idea: a record whose edge leaves the top-right corner, a bottle whose shoulder runs off the bottom, a chair seen so close you read its grain. Being that close reads as confidence in the object. Everything else on the page serves it: details as tight close-ups, facts as short lines, one way to buy.\",\n  \"composition\": \"First screen: the object occupies 55–75% of the viewport and breaks at least one edge. It sits on a flat field (ground colour or one bold colour), never in a box. The headline is short and either very large and partly hidden behind the object (10–13vw, the object overlapping two or three letters) or small (28–36px) in the opposite corner with a one-line description. No navigation bar beyond a wordmark and one action. Following sections: a row of three or four close-up details at different crop ratios (not equal tiles), a single wide photograph of the object in use, a plain list of facts set large (materials, size, price) aligned to one edge, then the purchase action. The object returns once at the end from a different angle.\",\n  \"typography\": \"Either very large and structural or very small and precise; pick one for the headline and hold it. Facts are set in the text face at 22–28px, not in a table.\",\n  \"typeClasses\": [\n   \"grotesk-light\",\n   \"grotesk-tight\",\n   \"extended-heavy\",\n   \"serif-light-large\"\n  ],\n  \"colour\": \"A flat field chosen to make the object's own colour sing (its complement, or a tone darker than its shadow side). One field for the whole page, or a second for the facts section.\",\n  \"paletteTags\": [\n   \"single-field\",\n   \"light-neutral\",\n   \"pastel-fields\",\n   \"dark-neutral\"\n  ],\n  \"imagery\": \"Use the product's own photographs if they exist. Otherwise use a still-life from the dealt set as a stand-in and say so. Prefer images with a plain background; use `mix-blend-mode: multiply` on light fields so a white studio background disappears into the page colour.\",\n  \"photoTreatment\": \"Scale the main image well past its container (`width: 120–160%`) and let `overflow: hidden` on the section do the cropping.\",\n  \"sectionTags\": [\n   \"object-led\",\n   \"photo-led\",\n   \"colour-field\"\n  ],\n  \"motion\": \"shutter-image\",\n  \"richness\": \"The object's surface at close range, and the tension of the crop.\",\n  \"pitfalls\": \"A small centred product shot with space all round is a catalogue thumbnail, not this direction. If the image has a busy background it cannot sit on a field; crop tighter or change image. Keep text off the object's focal area.\",\n  \"seenIn\": [\n   \"opl-when-you-wish-upon-a-starboy\",\n   \"opl-plastic\",\n   \"opl-archiv\",\n   \"aww-moto-finance\",\n   \"aww-the-watch\",\n   \"opl-aevion\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"specimen-catalogue\",\n  \"name\": \"The specimen catalogue\",\n  \"sectors\": [\n   \"ecommerce\",\n   \"physical-product\",\n   \"restaurant\",\n   \"fashion\",\n   \"culture\",\n   \"education\",\n   \"health\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"playful\",\n   \"warm\",\n   \"editorial\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"idea\": \"Present what is on offer the way a field guide presents birds: each item alone on a flat colour, same scale, same angle, named plainly. A bakery's pastries become specimens and the specimens become the menu. A furniture maker's chairs each get their own colour tile. The format flatters ordinary objects because it treats each as worth looking at, and it replaces both the feature grid and the product-card grid with something that has a point of view.\",\n  \"composition\": \"Hero: a left-aligned statement of what this is (5–7vw, upper-left) beside or above a tight cluster of four to seven specimen tiles of different sizes arranged as a loose mosaic that runs off the right edge. Each tile is a flat colour square or 4:5 rectangle with one photograph centred on it, no border, 8–12px gaps. The main section is the catalogue itself: a grid of tiles in which each item has its name and one fact set beneath the tile in the text face, aligned left to the tile edge. Tile colours rotate through three or four fields from the palette. One tile in every six or seven is double size. Supporting sections (about, how to order) are plain text on the ground colour, kept short.\",\n  \"typography\": \"Friendly and plain. Item names at 18–22px in medium weight, facts beneath in the soft ink. One big statement in the hero; no other display type.\",\n  \"typeClasses\": [\n   \"grotesk-tight\",\n   \"serif-text\",\n   \"slab\",\n   \"rounded-friendly\"\n  ],\n  \"colour\": \"The tiles are the colour: three or four flat fields from the palette, repeated in a steady rotation. Ground stays neutral.\",\n  \"paletteTags\": [\n   \"pastel-fields\",\n   \"flat-loud\",\n   \"light-neutral\"\n  ],\n  \"imagery\": \"Photographs of single items on plain backgrounds, all cropped to sit at the same apparent size within their tile. On light tiles, `mix-blend-mode: multiply` removes white studio backgrounds. If the subject's own item photographs are missing, use the dealt set and say so.\",\n  \"sectionTags\": [\n   \"object-led\",\n   \"colour-field\",\n   \"photo-led\"\n  ],\n  \"motion\": \"drag-row\",\n  \"richness\": \"Rhythm of colour tiles and the pleasure of comparing like with like.\",\n  \"pitfalls\": \"It needs at least six items that can be shown as objects; with three it is a feature row. Keep labels outside the tiles. No shadows under the objects, no hover lift.\",\n  \"seenIn\": [\n   \"aww-noho\",\n   \"opl-madie\",\n   \"opl-humanoid-index\",\n   \"opl-smallbits\",\n   \"aww-butter\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"borrowed-category\",\n  \"name\": \"Dressed as something else\",\n  \"sectors\": [\n   \"finance\",\n   \"saas\",\n   \"consumer-app\",\n   \"physical-product\",\n   \"health\",\n   \"dev-tool\",\n   \"ai-product\",\n   \"education\",\n   \"nonprofit\",\n   \"real-estate\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"bold\",\n   \"playful\",\n   \"luxury\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Art-direct the subject as if it belonged to a different, more vivid category. A money app is sold like a streetwear drop. An industrial roaster is presented like a design object. Drilling hardware gets the calm of a watch brand. A parcel-locker service becomes a fairground of stickers. Choose the borrowed category by asking what feeling the audience is missing from this kind of product (swagger, calm, glamour, play) and which category owns that feeling. Then take its manners completely: its type, its pacing, its way of photographing things. The contrast between dull subject and vivid dress is what people remember.\",\n  \"composition\": \"Depends on the borrowed category, so decide it explicitly and write it in your notes. Fashion drop: one shouted condensed headline across the full width, a single cropped image under it, then product facts as a blunt list. Watch or perfume: a centred object on a dark field, a small serif name, very few words, long vertical pauses. Poster or zine: flat colour blocks, heavy type, tilted cut-out images. Museum: one item per screen on a plinth-like band of colour with a short label beside it. Whichever you choose, the page structure stays simple (four to six sections) and every section uses the borrowed manners, including pricing and the footer.\",\n  \"typography\": \"The borrowed category's type, fully committed: condensed and loud, or refined and small. No halfway.\",\n  \"typeClasses\": [\n   \"condensed-heavy\",\n   \"serif-display\",\n   \"extended-heavy\",\n   \"heavy-black\"\n  ],\n  \"colour\": \"The borrowed category's palette, which will be unlike the subject's sector norm. That mismatch is intended.\",\n  \"paletteTags\": [\n   \"flat-loud\",\n   \"two-tone\",\n   \"dark-neutral\",\n   \"single-field\"\n  ],\n  \"imagery\": \"Photograph the subject the way the borrowed category would be photographed. With the dealt set, choose images for attitude, not literal relevance, and crop them hard.\",\n  \"sectionTags\": [\n   \"poster\",\n   \"type-led\",\n   \"photo-led\",\n   \"colour-field\"\n  ],\n  \"motion\": \"edge-marquee\",\n  \"richness\": \"Attitude. The page has a recognisable voice from another world, applied to a subject nobody expected it for.\",\n  \"pitfalls\": \"Name the borrowed category in one word before you start, or the result is merely loud. The content must still be clear: what it is, what it costs, how to get it. Avoid borrowing from 'tech startup', which is the default you are escaping.\",\n  \"seenIn\": [\n   \"opl-uglycash\",\n   \"aww-coffeetech-r\",\n   \"aww-sstr-friction-reduction\",\n   \"opl-locker-land\",\n   \"aww-moto-finance\",\n   \"aww-vero-new-york\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"contact-sheet\",\n  \"name\": \"The contact sheet\",\n  \"sectors\": [\n   \"personal-portfolio\",\n   \"studio-portfolio\",\n   \"agency\",\n   \"fashion\",\n   \"culture\",\n   \"architecture\",\n   \"music\",\n   \"ecommerce\"\n  ],\n  \"tones\": [\n   \"quiet\",\n   \"technical\",\n   \"editorial\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Show everything at once, small, in order. The work is laid out like a photographer's contact sheet or an archive drawer: dozens of small frames in strict rows, with all text set at one small size. Nothing is featured, which is the point: the volume and consistency of the body of work is the statement, and the visitor does the choosing. It suits people and studios whose strength is range and output.\",\n  \"composition\": \"The name, or one sentence about the work, sits at display size (6–9vw) across the top of the first screen, and the sheet begins directly under it, still inside the first screen. The first screen opens with three or four short blocks of small text across the top on a 12-column grid (who, what, where to reach them), all at 14–16px, and immediately below, the sheet begins: rows of thumbnails at a fixed height (90–140px) with their natural widths, 6–10px gaps, each project forming a run of four to eight frames preceded by its title in the same small text. The sheet fills the whole page width edge to edge with 16–20px margins. Hovering a run dims the others and shows that project's one-line description in a fixed position. A single enlarged frame may interrupt the sheet once per screen at four times the size.\",\n  \"typography\": \"One face. The name at display size on the first screen; everything else at one text size and one small size; hierarchy below the name comes from position and from a single brighter ink for titles.\",\n  \"typeClasses\": [\n   \"grotesk-light\",\n   \"grotesk-tight\"\n  ],\n  \"colour\": \"Black or white ground, so the thumbnails are the only colour.\",\n  \"paletteTags\": [\n   \"dark-neutral\",\n   \"light-neutral\"\n  ],\n  \"imagery\": \"Many images: at least 24 frames to make a sheet. They can be project photographs from the dealt set cropped to mixed ratios, or page captures of the work. Square corners, no captions on the frames.\",\n  \"sectionTags\": [\n   \"dense\",\n   \"photo-led\",\n   \"quiet\"\n  ],\n  \"motion\": \"index-preview\",\n  \"richness\": \"Density and order. The mass of small images forms a texture; the strict rows keep it calm.\",\n  \"pitfalls\": \"With fewer than about 20 images it looks unfinished; choose another direction. Do not add a big headline above the sheet. On a phone the frames become two per row at a fixed height and each run scrolls sideways. Rows that run past the right edge read as clipped in screenshots and to most visitors: wrap the frames onto the next line, or end each row inside the grid.\",\n  \"seenIn\": [\n   \"aww-gil-huybrecht\",\n   \"opl-smallbits\",\n   \"opl-gunes-atakan-peksen\",\n   \"opl-proooof\",\n   \"aww-oimachi\"\n  ],\n  \"allow\": [],\n  \"needsPictures\": true\n },\n {\n  \"id\": \"editorial-report\",\n  \"name\": \"The printed annual\",\n  \"sectors\": [\n   \"culture\",\n   \"nonprofit\",\n   \"education\",\n   \"finance\",\n   \"saas\",\n   \"ai-product\",\n   \"health\",\n   \"agency\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"editorial\",\n   \"bold\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Lay the page out like a well-designed printed report or magazine feature: a masthead image, a tight oversized title, text held to a strict column line, and colour used in solid blocks the way a two-colour print job would. It gives weight and authority to subjects that are really about content: findings, a manifesto, a programme, a serious product. The reader should feel that someone edited this.\",\n  \"composition\": \"A fixed vertical axis at about 42% of the viewport width organises everything: headings begin on it, body columns hang from it, and the 0–42% zone holds small side notes, figures or stays empty. Masthead: a wide image band (photographic mosaic or a single crop) across the top 45% of the first screen; below it the title at 7–9vw starting on the axis, with a two-sentence standfirst at 20–24px. Sections alternate between text pages (title on the axis, body in one or two columns of 34–40ch to its right) and full-bleed colour pages carrying one large figure, quotation or image mosaic. Mosaics are gutterless: photographs and flat colour tiles butted together in a 4- or 6-cell grid. Page numbers, running heads and other print furniture are left out.\",\n  \"typography\": \"A tight heavy grotesk or a sharp serif for titles; an excellent text face for reading at 18–20px with leading near 1.5. Headings in sentence case, tracked tight.\",\n  \"typeClasses\": [\n   \"grotesk-tight\",\n   \"serif-display\",\n   \"serif-text\"\n  ],\n  \"colour\": \"Paper, ink and two or three solid block colours. A colour page is a whole section in one flat colour.\",\n  \"paletteTags\": [\n   \"flat-loud\",\n   \"two-tone\",\n   \"mono-accent\"\n  ],\n  \"imagery\": \"Photographs used as blocks in mosaics alongside flat colour tiles; mixed subjects are fine if cropped tight and converted to one treatment.\",\n  \"photoTreatment\": \"Give all photographs in a mosaic one treatment: greyscale via `filter: grayscale(1) contrast(1.05)`, or all full colour. Do not mix.\",\n  \"sectionTags\": [\n   \"type-led\",\n   \"colour-field\",\n   \"dense\",\n   \"poster\"\n  ],\n  \"motion\": \"masked-headline\",\n  \"richness\": \"The column line, the mosaics and whole pages of colour give structure and variety without ornaments.\",\n  \"pitfalls\": \"The axis must be exact and reused everywhere or it reads as random indentation. Keep paragraphs to a real reading measure. On a phone the axis collapses to the left margin and side notes move inline above their paragraph.\",\n  \"seenIn\": [\n   \"aww-ai-in-design-report-2026\",\n   \"opl-applied-imagination\",\n   \"opl-the-queue\",\n   \"opl-artem-taradash\",\n   \"opl-belgrade-architecture\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"loud-flat-poster\",\n  \"name\": \"Loud and flat\",\n  \"sectors\": [\n   \"agency\",\n   \"consumer-app\",\n   \"music\",\n   \"event\",\n   \"education\",\n   \"nonprofit\",\n   \"physical-product\",\n   \"saas\",\n   \"culture\"\n  ],\n  \"tones\": [\n   \"bold\",\n   \"playful\"\n  ],\n  \"needs\": [],\n  \"idea\": \"A page with the directness of a street poster: flat saturated colour, the heaviest type you can find, short blunt statements, and photographs cut out and stuck on. It is for subjects with a voice. Write the page as things a person would actually say out loud, and let the design say them at full volume. The craft is in the control beneath the noise: a strict grid, two or three colours, and exact alignment keep it from becoming a mess.\",\n  \"composition\": \"Hero: a statement of three to six words in ultra-heavy type at 11–15vw, filling the width, lines stacked tight (leading 0.85), flush left with 20–28px margins, on a flat saturated ground. One cut-out or hard-cropped photograph overlaps the type from the right or bottom, tilted 3–6 degrees. A single chunky button in the contrasting flat colour. Sections are solid panels in alternating palette colours: one is a row of short statements each on its own panel of unequal width; one is a single photograph bleeding off two edges with a caption block set over a solid colour bar; one is a large plain list. Panels meet edge to edge. Corners are square or use one large radius (28–40px) consistently.\",\n  \"typography\": \"The heaviest weight available, set tight, mostly lowercase or mostly uppercase (choose one). Body text is a plain grotesk at 18–20px.\",\n  \"typeClasses\": [\n   \"heavy-black\",\n   \"condensed-heavy\",\n   \"extended-heavy\",\n   \"rounded-friendly\"\n  ],\n  \"colour\": \"Three or four flat colours at full strength including black or white. Each panel is one colour; text on it is one other.\",\n  \"paletteTags\": [\n   \"flat-loud\"\n  ],\n  \"imagery\": \"Photographs with attitude, cropped hard or cut to a simple shape with `clip-path` (circle, arch, blunt polygon), slightly rotated, overlapping the type. Two or three on the page.\",\n  \"sectionTags\": [\n   \"poster\",\n   \"colour-field\",\n   \"type-led\"\n  ],\n  \"motion\": \"edge-marquee\",\n  \"richness\": \"Colour mass, type mass, and overlap.\",\n  \"pitfalls\": \"Headlines still obey the two-line rule: at 13vw that means very few words, which is correct for this voice. No outlines, no offset shadows, no sticker confetti. Rotation is for two or three images only, never for text blocks.\",\n  \"seenIn\": [\n   \"aww-warm-fuzzy\",\n   \"aww-aardvark-book-club\",\n   \"opl-uglycash\",\n   \"opl-depo-budget-app\",\n   \"aww-trevor-noah\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"split-stage\",\n  \"name\": \"The split stage\",\n  \"sectors\": [\n   \"restaurant\",\n   \"hospitality\",\n   \"personal-portfolio\",\n   \"physical-product\",\n   \"fashion\",\n   \"real-estate\",\n   \"health\",\n   \"culture\",\n   \"ecommerce\",\n   \"saas\",\n   \"consumer-app\"\n  ],\n  \"tones\": [\n   \"warm\",\n   \"quiet\",\n   \"editorial\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Half the screen never moves. One side is a fixed photograph (or object, or product view) that stays in place for the whole visit; the other side is a calm scrolling column with everything you need to read. The fixed half keeps the feeling present while the reader gets on with the facts, like sitting in the room while reading the menu. As sections pass, the fixed image may quietly change to the one that matches.\",\n  \"composition\": \"Desktop: a two-column page, 50/50 or 45/55. One column is `position: sticky; top: 0; height: 100svh` and holds a single photograph filling it edge to edge, or the object centred on a flat field. The other column scrolls and holds all content in a single narrow measure (max 46ch) with comfortable padding (48–72px): name and one-line description first, then sections separated by generous space, then contact and footer. Headings in the scrolling column are modest (32–44px). The column grounds differ: photograph on one side, flat paper colour on the other, meeting at a clean vertical edge. On a phone the fixed half becomes a 60svh image at the top that stays sticky behind the first section, then releases.\",\n  \"typography\": \"A text-first setting: a readable serif or a calm sans at 17–19px, with one display size for the name. Left-aligned throughout.\",\n  \"typeClasses\": [\n   \"serif-text\",\n   \"serif-display\",\n   \"grotesk-light\",\n   \"slab\"\n  ],\n  \"colour\": \"The paper colour of the reading column is chosen against the photograph: a tone taken from its shadows or its lightest area. One ink, optionally one accent ink for links and the action.\",\n  \"paletteTags\": [\n   \"two-tone\",\n   \"earth\",\n   \"light-neutral\",\n   \"photographic-neutral\"\n  ],\n  \"imagery\": \"One excellent portrait-orientation photograph for the fixed half, plus three or four more that crossfade in as their sections arrive. Small inline photographs in the reading column are optional and should be few.\",\n  \"sectionTags\": [\n   \"quiet\",\n   \"photo-led\",\n   \"type-led\"\n  ],\n  \"motion\": \"slow-crossfade\",\n  \"richness\": \"A full-height photograph always in view, against a quiet, well-set column of text.\",\n  \"pitfalls\": \"The reading column must be genuinely well typeset, since it is half the page. Do not put cards or grids in it. Check that the fixed image crops well at short viewport heights. In blind tests the commonest complaint was monotony: several screens of the same split with only the text changing. Change what the reading half holds from section to section (a list, a large figure, a table, a full-colour panel, a drawing) and let at least one section break the split and run full width.\",\n  \"seenIn\": [\n   \"opl-le-petit-bleu\",\n   \"opl-rafael-derolez-2026\",\n   \"opl-flowjam-2\",\n   \"opl-devonshire\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"dense-tiles\",\n  \"name\": \"The well-kept board\",\n  \"sectors\": [\n   \"agency\",\n   \"studio-portfolio\",\n   \"saas\",\n   \"dev-tool\",\n   \"ai-product\",\n   \"culture\",\n   \"music\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"technical\",\n   \"bold\"\n  ],\n  \"needs\": [],\n  \"idea\": \"The whole page is a board of tiles fitted edge to edge with narrow gaps, like a tidy desk seen from above. Each tile is one thing: the name, a statement, a photograph, a number, a link, a short list. There is no hero and no sequence of bands; the page is one continuous composition that the eye roams. It suits subjects with many small true things to show (a studio with work, writing, clients and news; a product with several distinct capabilities) and it replaces the gen\n\n<!-- [TRUNCATED AT 50KB] -->","skills/taste-skill/library/heroes.json":"[\n {\n  \"id\": \"name-under-photograph\",\n  \"name\": \"Name under a photograph\",\n  \"archetype\": \"giant-wordmark\",\n  \"directions\": [\n   \"name-as-monument\",\n   \"place-carries-it\",\n   \"dark-room\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A full-bleed photograph fills the top 58% of the 1440×900 viewport, touching the top, left and right edges, `object-fit: cover`, with its focal point in the upper two-thirds. The lower 42% is a flat ground colour that butts against the photograph with no gap. The name runs across this band on one line, spanning all 12 columns between 24px margins, at clamp(120px, 19vw, 300px), tracking -0.05em, line-height 0.85, its baseline 28px above the bottom edge so descenders nearly touch it. Fit the size to the length of the name so it never wraps. In the strip of ground between photograph and name, 24px under the photograph's edge, sits one row at 17px: the supporting sentence on columns 1–5 at the left margin, and the single action as a small solid rectangular button flush to the right margin. Navigation is four text links at 15px laid over the photograph's top-right corner, 24px in, with a neutral scrim behind that row only if the image is light there. No logo is repeated: the name is the logo. Nothing else is on the screen.\",\n  \"mobile\": \"The photograph takes the top 50svh at full width, re-cropped around its focal point. The name sits under it at 23vw on one line; a name longer than seven characters breaks onto two lines at 21vw, line-height 0.85, and fills the band down to a 16px bottom margin. The supporting sentence at 16px and the action button stack above the name on the left margin. The links collapse to one 'Menu' word over the photograph, top-right.\",\n  \"headline\": \"The name itself on one line, up to about 12 characters at 19vw (drop towards 13vw for longer names), and at most two lines on a phone.\",\n  \"motion\": \"scaling-wordmark\",\n  \"seenIn\": [\n   \"aww-house-of-honey-1\",\n   \"opl-kereliott\",\n   \"aww-lxl-creative\"\n  ]\n },\n {\n  \"id\": \"stacked-name-two-inks\",\n  \"name\": \"Stacked name, two inks\",\n  \"archetype\": \"type-poster\",\n  \"directions\": [\n   \"name-as-monument\",\n   \"colour-chapters\",\n   \"type-only-statement\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One saturated flat field covers the whole 1440×900 viewport and there is no image. The name is broken into two lines and set flush left from a 40px margin at clamp(110px, 15vw, 230px), heavy weight, tracking -0.04em, line-height 0.82 so the lines almost touch. The block starts 14% down and fills the top 58% of the screen; the longer line reaches at least column 11. Line one is set in the light ink and line two in the dark ink, so the break reads as a change of voice: split a two-word name between the lines, or break one long name with a hyphen at a syllable. The top edge carries only small text at 15px, 24px in: a monogram top-left, and two or three text links plus the single action as an underlined link top-right. The supporting sentence, 18px in the light ink and max 30ch, is right-aligned in the bottom-right corner on columns 9–12, its last line 40px above the bottom edge. The bottom-left corner stays empty. The next section begins as a different flat field exactly at the fold.\",\n  \"mobile\": \"The field fills 100svh. The name keeps its two lines and two inks at 21vw, flush left at a 16px margin, starting 18% down; a long name hyphenates rather than dropping below 18vw. The supporting sentence moves to the bottom-left at 16px across the full width, with the action as an underlined link beneath it, 24px above the bottom edge. The top-right links reduce to one word.\",\n  \"headline\": \"The name on exactly two lines, one per ink, each line up to about 8 characters at 15vw on desktop and 21vw on a phone.\",\n  \"motion\": \"masked-headline\",\n  \"seenIn\": [\n   \"opl-marina-rachello\",\n   \"opl-anidachi\"\n  ]\n },\n {\n  \"id\": \"photograph-for-a-letter\",\n  \"name\": \"Photograph for a letter\",\n  \"archetype\": \"giant-wordmark\",\n  \"directions\": [\n   \"name-as-monument\",\n   \"sentence-as-layout\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A flat white or pale ground, about 85% empty. The name sits on one line at the exact vertical centre, bold, at clamp(96px, 10.5vw, 168px), tracking -0.04em, spanning 78–88% of the width with equal side margins. One photograph is set into the line as if it were a glyph. Either it fills the word space between first and last name (a landscape frame one x-height tall and about 1.6em wide, resting on the baseline), or it replaces one round letter of a short name (a square frame exactly one cap-height tall). Build the line as an inline-flex row with `align-items: baseline` and size the frame in em so it scales with the type; square corners, `object-fit: cover`. Navigation is small and pushed to the edges: a 15px wordmark or monogram top-left at a 24px margin and up to five text links at 14px spread evenly across the right half of the top edge. Along the bottom edge, on the same margin: one supporting sentence at 16px starting at column 6, and the single action as an underlined text link flush right.\",\n  \"mobile\": \"The name stacks on two centred lines at 19vw with line-height 0.9. The photograph leaves the line and becomes a 3:2 frame at full width minus 16px margins between the two lines, so the screen reads word, picture, word. A single short name keeps the square frame inline at cap height instead. The supporting sentence and action sit under the block at 16px; the links collapse to one word top-right.\",\n  \"headline\": \"The name on one line with a photograph in its word space or in place of one letter, up to about 16 characters at 10.5vw, splitting into two lines on a phone.\",\n  \"motion\": \"shutter-image\",\n  \"seenIn\": [\n   \"aww-paul-kalkbrenner\",\n   \"opl-nia-creative\"\n  ]\n },\n {\n  \"id\": \"name-split-to-corners\",\n  \"name\": \"Name split to corners\",\n  \"archetype\": \"pinned-stage\",\n  \"directions\": [\n   \"pinned-poster\",\n   \"name-as-monument\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"The name is cut into two halves that stay pinned to opposite corners while the page passes between them. A layer with `position: sticky; top: 0; height: 100svh` and `pointer-events: none` holds both: the first word top-left, 28px from the top and left edges; the second word bottom-right, 28px from the bottom and right edges. Both are set at clamp(72px, 9vw, 140px), line-height 0.85, in white with `mix-blend-mode: difference` so they read on every panel beneath. On the first screen the stage between them is a paper-white panel on columns 1–9 and one full-height photograph on columns 10–12 touching the top, right and bottom edges. The supporting sentence, 20px and max 34ch, starts at column 3 at 44% of the height; the single action is a text link with an arrow directly under it. Three text links are stacked at 15px along the right edge of the white panel at mid-height. The rest of the panel is empty. Later panels, full-height photographs and text panels of different widths, scroll under the pinned halves for three to five viewports; then the layer releases into ordinary sections.\",\n  \"mobile\": \"Both halves stay pinned: the first word top-left and the second bottom-right, each at 15vw with 16px margins. Between them every panel is a full-width photograph 56svh tall followed by its sentence at 17px. On the first screen the photograph crosses the middle band with the supporting sentence and the action link beneath it. The stacked links collapse to one word at the top-right corner.\",\n  \"headline\": \"The name in two halves (two words, or one word cut at a syllable), each up to about 9 characters at 9vw, one per corner, with no other headline.\",\n  \"motion\": \"pinned-story\",\n  \"seenIn\": [\n   \"aww-normal-is-boring\",\n   \"aww-the-state-of-the-gallery\",\n   \"aww-milledollars\"\n  ]\n },\n {\n  \"id\": \"pinned-title-over-portraits\",\n  \"name\": \"Pinned title over portraits\",\n  \"archetype\": \"pinned-stage\",\n  \"directions\": [\n   \"pinned-poster\",\n   \"name-as-monument\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A pale flat ground. The title runs on one line of extra-bold uppercase at clamp(90px, 10vw, 160px), centred, spanning about 82% of the width, its cap line 120px from the top. It lives in a sticky layer (`position: sticky; top: 0; height: 100svh`) stacked above the images and set in one saturated ink that reads on both ground and photograph. Beneath it a single portrait photograph, 2:3, sits centred on columns 5–8 (about 37% of the width) and runs from 90px below the top edge down to the bottom edge, so the title crosses its upper quarter and the middle letters sit on the image. The wordmark sits top-left at 24px in 15px bold; one 'Menu' word sits top-right. Bottom-left on columns 1–3: the supporting sentence as a narrow column at 16px bold, max 26ch, its last line 32px above the bottom edge. Bottom-right: the single action as a solid rectangular button. As the page scrolls, further portraits of identical ratio and position replace the first, five to eight in all, each bringing its own flat ground colour sampled from the photograph, before the layer releases.\",\n  \"mobile\": \"The title stays pinned at the top at 17vw on one line, or two lines at 15vw if longer than ten characters. Each portrait becomes full width minus 16px margins at 2:3 and starts behind the lower half of the title. The supporting sentence follows the first portrait at 16px. The action button is fixed to the bottom-right corner, 16px in. The wordmark shrinks to a monogram top-left.\",\n  \"headline\": \"The title of the series, or the name: one uppercase line of up to about 14 characters at 10vw, two short lines on a phone.\",\n  \"motion\": \"pinned-story\",\n  \"seenIn\": [\n   \"opl-city-of-angels\",\n   \"aww-glitch-grit\"\n  ]\n },\n {\n  \"id\": \"sentence-with-photo-strip\",\n  \"name\": \"Sentence with a photo strip\",\n  \"archetype\": \"inline-media-sentence\",\n  \"directions\": [\n   \"sentence-as-layout\",\n   \"place-carries-it\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A warm flat ground with no navigation bar. One sentence of four or five words runs as a single line of condensed capitals at clamp(120px, 13vw, 200px), sitting on the vertical centre and reaching edge to edge inside 28px margins. Where one word of the sentence would be, a strip of photograph takes its place: a frame exactly one cap-height tall (set in em) and 45–50% of the viewport wide, ratio near 5:1, corners radiused 14px, `object-fit: cover`. Build the line as a flex row with `align-items: baseline` and give the strip `flex: 1` so words and picture always fill the width. The photograph shows the thing the sentence names: a wide view of the place, taken from above or along a horizon, so it survives the letterbox crop. The top third of the screen is empty apart from a 15px wordmark top-left and two text links top-right. About 150px under the sentence the single action sits centred as a small solid button. One supporting sentence at 22px, max 44ch, is centred 48px above the bottom edge.\",\n  \"mobile\": \"The sentence breaks into two lines at 21vw with the strip between them: the first words, then the photograph as a 2:1 frame at full width minus 16px margins with the same 14px corners, then the remaining words. The block is centred vertically. The action button sits 32px under the last line and the supporting sentence under that at 16px. The top links collapse to one word.\",\n  \"headline\": \"A sentence of four or five short words, about 14 characters of type in total, whose missing word is the photograph.\",\n  \"motion\": \"shutter-image\",\n  \"seenIn\": [\n   \"aww-colonia-zacamil\"\n  ]\n },\n {\n  \"id\": \"sentence-split-by-frame\",\n  \"name\": \"Sentence split by a frame\",\n  \"archetype\": \"inline-media-sentence\",\n  \"directions\": [\n   \"sentence-as-layout\",\n   \"pinned-poster\",\n   \"product-performs\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A white or pale ground. One short sentence is broken in two and pushed to the edges: the first half flush to the 32px left margin, the second half flush to the right margin, both on the vertical centre line at clamp(40px, 3.6vw, 60px), medium weight. Between them, dead centre on columns 5–8, sits one media frame: 35% of the viewport wide, 16:9, corners 4px, holding a photograph or a working fragment of the product. The frame belongs to a vertical reel: the bottom 60px of the previous frame shows at the top edge of the viewport and the top 60px of the next at the bottom edge, same width, 24px gaps, so the centre column reads as a strip passing through the sentence. The stage is sticky; the reel advances three or four steps while the two halves of the sentence hold their place. Wordmark top-left; three text links and the single action as a small solid button top-right, all at 15px. Bottom-left on columns 1–4: one supporting sentence at 18px, its last line 32px above the bottom edge. The other corners stay empty.\",\n  \"mobile\": \"The halves stack: the first half of the sentence at 9vw flush left under the wordmark, then the frame at full width minus 16px margins and 4:3, then the second half flush right at 9vw. The neighbouring frames show as 28px slivers above and below. The supporting sentence and the action button follow at 16px. The links collapse to one word.\",\n  \"headline\": \"One sentence of four to six words split into two halves of up to about 14 characters each; the frame between them shows what it is about.\",\n  \"motion\": \"pinned-story\",\n  \"seenIn\": [\n   \"aww-made-with-gsap-1\",\n   \"aww-artem-shcherbakov\"\n  ]\n },\n {\n  \"id\": \"headline-across-two-fields\",\n  \"name\": \"Headline across two fields\",\n  \"archetype\": \"colour-field\",\n  \"directions\": [\n   \"colour-chapters\",\n   \"sentence-as-layout\",\n   \"type-only-statement\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"The viewport is two flat fields meeting at exactly half height: paper above, one saturated colour below, with a hard edge and nothing drawn on it. A two-line headline in black-weight capitals at clamp(96px, 9.5vw, 150px), line-height 0.86, is centred across the seam and spans about 70% of the width, so line one stands on the upper field and line two is cut through its upper third by the seam. The type changes ink where it crosses: above the seam it takes the accent ink, below it a deep ink two steps darker than the lower field, as if submerged. Build it as two stacked copies of the same headline, one per ink, the first clipped with `clip-path: inset(0 0 50% 0)` and the second with `inset(50% 0 0 0)`. Wordmark top-left at 28px; up to four text links and the single action, a solid rectangular button, top-right. One supporting sentence at 20px in the paper colour is centred on the lower field, 56px above the bottom edge. The lower field continues for 30svh past the fold before the next colour begins.\",\n  \"mobile\": \"The same two fields with the seam at 46svh. The headline stays on two lines at 15vw, centred, still cut by the seam and still changing ink. Wordmark top-left and the action button top-right; the links drop into one menu word beside it. The supporting sentence sits on the lower field at 16px, centred, max 28ch, with 40px beneath it.\",\n  \"headline\": \"A statement of two to four words on two lines, up to about 10 characters per line, whose meaning the rising field acts out.\",\n  \"motion\": \"colour-on-scroll\",\n  \"seenIn\": [\n   \"opl-juggle\"\n  ]\n },\n {\n  \"id\": \"swatch-column-beside-view\",\n  \"name\": \"Swatch column beside the view\",\n  \"archetype\": \"split\",\n  \"directions\": [\n   \"colour-chapters\",\n   \"place-carries-it\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A 10px frame of paper colour surrounds the screen. Columns 1–10 are one photograph panel, full height inside the frame, corners radiused 12px, `object-fit: cover`: a wide, calm view with a low horizon and a great deal of sky. The headline is centred in the panel's upper third on two lines of light-weight serif at clamp(72px, 8.6vw, 132px), white, with a neutral scrim behind that band only if the sky is pale. The wordmark sits top-left inside the panel, 28px in. The single action, a white rectangular button, sits bottom-centre, 36px above the panel's lower edge; one supporting sentence at 18px sits bottom-left on columns 1–4, level with it. Columns 11–12 are both the navigation and a preview of the page: a full-height stack of five flat colour blocks of equal height, butted together with no gaps, each holding one text link at 16px in its top-left corner with 20px padding. The five colours are sampled from the photograph, ordered light to dark, and each is the ground colour of the section its link scrolls to. There is no other navigation.\",\n  \"mobile\": \"The photograph panel takes the top 64svh inside an 8px frame, with the headline at 12vw on two lines in its upper third and the action button at its bottom-centre. The swatch column becomes five full-width bars, each 52px tall with its link at 15px, stacked directly under the panel; the first three show above the fold. The supporting sentence moves into the first section.\",\n  \"headline\": \"A two-line statement of three to five words, up to about 14 characters per line at 8.6vw, set over the sky.\",\n  \"motion\": \"colour-on-scroll\",\n  \"seenIn\": [\n   \"aww-seasats\"\n  ]\n },\n {\n  \"id\": \"film-title-on-bottom-edge\",\n  \"name\": \"Film title, bottom edge\",\n  \"archetype\": \"bottom-anchored-type\",\n  \"directions\": [\n   \"place-carries-it\",\n   \"name-as-monument\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One photograph fills the viewport at 100vw by 100svh, `object-fit: cover`, with its subject in the upper two-thirds and a calmer, darker zone along the bottom. The name is one condensed uppercase word, or a short name in a high-contrast serif, set at clamp(150px, 17.5vw, 290px) and sized to span the full width between 32px margins. It is centred and anchored so its baseline sits 34px above the bottom edge, covering roughly the lowest quarter of the frame. A soft neutral dark scrim lies under that bottom band only, about 40% of the height; the rest of the image is untouched. Directly above the name's left end, on the same margin, sits the supporting sentence at 16px on two short lines. Directly above its right end, right-aligned, sits the single action as a small paper-coloured rectangular button. The top edge carries a small emblem or wordmark at the left margin and up to five text links at 15px grouped at the right, all in white. The central half of the screen belongs to the view.\",\n  \"mobile\": \"The photograph is re-cropped to portrait with `object-position` on its subject and fills 100svh. The name stays on the bottom edge at 22vw on one line, or two lines at 20vw beyond eight characters, 20px above the edge. The supporting sentence sits above the name's left end at 15px. The action button moves to the top-right corner and the links collapse to a menu word beside the emblem.\",\n  \"headline\": \"The name of the place: one word of up to about 12 characters at 17.5vw, or two words stacked on a phone.\",\n  \"motion\": \"slow-crossfade\",\n  \"seenIn\": [\n   \"aww-white-desert\",\n   \"opl-eagles-nest\"\n  ]\n },\n {\n  \"id\": \"small-name-open-sky\",\n  \"name\": \"Small name, open sky\",\n  \"archetype\": \"fullbleed-media\",\n  \"directions\": [\n   \"place-carries-it\",\n   \"uneven-photographs\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A single photograph fills the viewport edge to edge with no frame: choose one whose upper 45% is sky, wall or water with nothing in it and whose subject sits low and off-centre. All type is white and stays out of that empty zone. Top-left at a 24px margin, the name is stacked on two or three lines at 14px, like a letterhead. Top-right, three or four text links run in one line at 14px separated by commas, the current one marked by a 2px underline. Bottom-left, 32px from the left and bottom edges, the name repeats as the only larger type: two tight lines at clamp(44px, 4.2vw, 64px), line-height 1.0, regular weight, on columns 1–5. On the same baseline at the bottom-right margin sits the single action as an underlined text link with an arrow, and above it one supporting sentence at 15px, right-aligned, max 32ch. If a lower corner is too bright for white type, darken that corner alone with a neutral scrim. The page below opens on plain paper with one narrow paragraph and wide empty margins.\",\n  \"mobile\": \"The photograph is cropped to portrait around its subject and fills 100svh, its upper half still empty. The small stacked name stays top-left at 13px and the links collapse to one word top-right. The larger name sits bottom-left at 9.5vw on two lines, 20px in. The supporting sentence and the underlined action stack beneath it at 15px, left-aligned, 24px above the bottom edge.\",\n  \"headline\": \"The name set small on two lines of up to about 16 characters each at 4.2vw; the photograph does the work of a headline.\",\n  \"motion\": \"slow-crossfade\",\n  \"seenIn\": [\n   \"aww-kononenko-architectural-bureau\",\n   \"aww-julien-calot\",\n   \"aww-depo-luxe\"\n  ]\n },\n {\n  \"id\": \"invitation-card-cropped\",\n  \"name\": \"Invitation card, cropped\",\n  \"archetype\": \"artefact\",\n  \"directions\": [\n   \"page-is-the-object\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A flat field of one soft colour fills the viewport. Centred on it is a single portrait card in paper colour, 5:7, on columns 4–9, its top edge 190px down and its lower third cut off by the bottom of the viewport, so the page visibly continues as the rest of the card. The card is a filled shape with scalloped inner corners, made with `clip-path` or with four corner circles in the field colour, and no outline. Inside, with 56px padding, everything is centred and symmetrical like letterpress stationery. The two names, or the title, are set in a large italic serif at clamp(56px, 5.6vw, 88px) on two lines, staggered so line one sits left of centre and line two right. Between and beneath them, date, time and place appear as short lines at 15px in sentence case, separated by space and by one solid 10px diamond. The top row sits on the field above the card at 28px margins: a small monogram top-left, three text links centred, and the single action, a solid rectangular button in the ink colour, top-right.\",\n  \"mobile\": \"The card becomes full width minus 12px margins, starts 96px down and is still cropped by the bottom edge, with its scalloped top corners kept. The names stay on two lines at 12vw, centred without the stagger, and the details follow at 15px. The monogram sits top-left and the action button top-right on the field; the three links move onto the card's lower part, below the fold.\",\n  \"headline\": \"The two names or the title on two lines, up to about 12 characters per line, set as they would be printed on the card.\",\n  \"motion\": \"curtain-footer\",\n  \"seenIn\": [\n   \"opl-sarah-matt-wedding\"\n  ]\n },\n {\n  \"id\": \"card-over-dim-room\",\n  \"name\": \"Card over a dim room\",\n  \"archetype\": \"artefact\",\n  \"directions\": [\n   \"page-is-the-object\",\n   \"pinned-poster\",\n   \"dark-room\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A full-bleed, low-key photograph of the room fills the viewport, darkened with `filter: brightness(0.7)` so it reads as atmosphere. Centred over it is one square-cornered panel in a flat warm tone taken from the photograph: columns 4–10, about 55% of the width and 62% of the height, a filled programme card with 32px padding. Along its top edge the three words of the title are spread to the left, centre and right in bold condensed capitals at clamp(28px, 2.5vw, 38px); that line is the headline. Under it sit two left-aligned blocks in the same face and size, line-height 1.0: the facts (date, time, place) as three short lines, then one supporting sentence held to 30ch. Along the card's bottom edge: a credit at left in 14px, the single action as a solid rectangular button in the centre, one text link at right. There is no navigation outside the card. The card is `position: sticky`: as the page scrolls it shrinks with `transform: scale` toward the bottom-left corner and stays there as a ticket-sized stub while photographs of differing sizes pass on a flat ground.\",\n  \"mobile\": \"The photograph fills 100svh and the card sits centred at full width minus 16px margins, 70svh tall. The title words stack as a two-line heading at 9vw at the card's top-left. The facts and the supporting sentence follow at 5.2vw in the condensed face. The action button spans the card's bottom edge. On scroll the card shrinks to a 120px stub pinned bottom-left.\",\n  \"headline\": \"The event or venue name, three words at most and up to about 8 characters each, spread across the card's top edge; two lines on a phone.\",\n  \"motion\": \"pinned-story\",\n  \"seenIn\": [\n   \"opl-the-deep-end\"\n  ]\n },\n {\n  \"id\": \"tabbed-folder-stack\",\n  \"name\": \"Tabbed folder stack\",\n  \"archetype\": \"artefact\",\n  \"directions\": [\n   \"page-is-the-object\",\n   \"one-motif\",\n   \"colour-chapters\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A dark flat ground. A slim top row at 24px holds the wordmark dead centre and one text link far right at 15px. The headline is one centred line of heavy condensed capitals at clamp(96px, 10vw, 160px), spanning about 70% of the width, its cap line 110px from the top. Under it one supporting sentence in a serif at 20px, centred, max 46ch. From 51% of the height down the screen is a stack of five file folders: flat colour bands 86% of the viewport wide, centred, each offset 64px below the one behind so only a strip of the back four shows. Every folder has one trapezoid tab rising 40px from its top edge, cut with `clip-path: polygon()`, at its own horizontal position and in its own colour, holding one section name at 18px. The front folder is open and runs off the bottom edge; it carries the single action as a solid button at its top-left with 32px padding. Each folder links to its section and lends that section its ground colour. The tab shape returns as the button's top corners.\",\n  \"mobile\": \"The headline sits 96px down at 17vw on one line, or two at 15vw, centred, with the supporting sentence at 16px beneath. The folder stack starts at 48svh at full width: bands offset 52px, tabs 32px tall with names at 15px, staggered left, centre and right. The front folder runs off the bottom with the action button at full width inside it.\",\n  \"headline\": \"The name or a two-word statement on one line of up to about 12 characters at 10vw; two lines allowed on a phone.\",\n  \"motion\": \"index-preview\",\n  \"seenIn\": [\n   \"aww-mosbys-files\",\n   \"opl-medium-rare\"\n  ]\n },\n {\n  \"id\": \"striped-card-beside-room\",\n  \"name\": \"Striped card beside the room\",\n  \"archetype\": \"split\",\n  \"directions\": [\n   \"one-motif\",\n   \"page-is-the-object\",\n   \"split-stage\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"The viewport is split 50/50 with a 12px gap and 12px outer margins. The right half is one full-height photograph of the room, corners radiused 16px, `position: sticky` so it stays in view while the left half scrolls. The left half is a printed card: a flat paper-colour panel with the same 16px radius, and the subject's stripe (from its awning, label or ribbon) as the only ornament. Across the card's top runs a band 56px tall made of alternating bars of the single ink colour and paper, each bar 28px wide, built as a flex row of filled blocks. The same stripe returns as an 8px band above the footer and inside the button on hover. Under the band, centred: the wordmark about 300px wide, then a two-line headline in a light serif at clamp(40px, 3.6vw, 56px) in the ink colour, one supporting sentence at 17px held to 36ch, and the single action as a solid rectangular button. Three text links sit in one centred row at 15px, 28px above the card's bottom edge. One ink on paper; the photograph supplies every other colour.\",\n  \"mobile\": \"The photograph comes first at full width inside 12px margins, 48svh tall, with the 16px radius. The card follows and overlaps the photograph's bottom edge by 24px using a negative margin. Its striped band is 40px tall; below it the wordmark at 56% width, the headline at 8vw on two lines, the sentence and the button, all centred. The links wrap into the card's foot.\",\n  \"headline\": \"A warm two-line welcome of three to six words, up to about 18 characters per line at 3.6vw.\",\n  \"motion\": \"slow-crossfade\",\n  \"seenIn\": [\n   \"opl-le-petit-bleu\",\n   \"opl-zara-webb\"\n  ]\n },\n {\n  \"id\": \"giant-cropped-shape\",\n  \"name\": \"Giant cropped shape\",\n  \"archetype\": \"colour-field\",\n  \"directions\": [\n   \"one-motif\",\n   \"colour-chapters\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A plain ground with one flat shape at enormous scale. The shape is the simplest geometry found in the subject (a circle, a ring segment, a chamfered block, an arch), drawn in CSS or as a single inline SVG path and filled with the accent colour. It is about 120vh across and enters from the right, centred near 78% of the width and 55% of the height, so the top, right and bottom edges of the viewport crop it and its left boundary reaches column 7. If the subject has a true pair (two accounts, two modes), a second shape in a second flat colour overlaps the first by a quarter with `mix-blend-mode: multiply`. The headline sits on the bare ground on columns 1–6, vertically centred, flush left at 8% from the left edge: two lines at clamp(64px, 6.4vw, 100px), heavy weight, tracking -0.03em. Beneath it comes one supporting sentence at 19px, then the single action as a solid button cut to the same shape. A bold wordmark sits top-left at 32px; up to three text links sit top-right in the ground colour.\",\n  \"mobile\": \"The shape moves to the bottom: 130vw across, centred horizontally, its top at 56svh, cropped by the left, right and bottom edges. The headline sits above it at 11.5vw on two lines at a 16px margin, starting 15% down, with the sentence at 16px and the motif-shaped button beneath. Wordmark top-left; the links collapse to one word top-right.\",\n  \"headline\": \"Two lines of two or three words each, up to about 12 characters per line at 6.4vw.\",\n  \"motion\": \"shutter-image\",\n  \"seenIn\": [\n   \"opl-tara\",\n   \"opl-superlocal-2026\",\n   \"aww-sstr-friction-reduction\"\n  ]\n },\n {\n  \"id\": \"fragment-on-shaped-stage\",\n  \"name\": \"Fragment on a shaped stage\",\n  \"archetype\": \"split\",\n  \"directions\": [\n   \"product-performs\",\n   \"one-motif\",\n   \"colour-chapters\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A neutral ground. The headline occupies the upper-left third: two lines at clamp(52px, 5.2vw, 80px), medium weight, flush left on columns 1–6 at a 40px margin, starting 150px down. One supporting sentence at 18px, max 40ch, follows, then the single action as a small rectangular button. The rest of the screen belongs to one flat stage in a saturated colour: it spans columns 5–12, begins 42% down, and bleeds off the right and bottom edges. Its top-left corner is cut with the product's own shape using `clip-path` (a notch, a chamfer or a tab two columns wide), the only decoration on the page. On the stage, 56px in from its left and top edges, sits the main fragment of the interface at true size with labels at 13–15px, built in HTML and working: one panel or control about 620px wide, cropped by the bottom edge, never a whole window and never inside a browser or laptop frame. Mark its root with data-ui. Navigation is a plain row at 28px from the top: wordmark left and four text links right at 15px. Nothing overlaps the headline.\",\n  \"mobile\": \"The headline sits under the wordmark at 10vw on two lines, followed by the sentence at 16px and the button. The stage comes next at full width, bleeding off both sides and the bottom, its corner cut kept at 72px wide. The fragment sits 16px inside it at true size; if it is wider than the screen the right edge crops it rather than scaling it down.\",\n  \"headline\": \"A plain statement of what the product does in three to six words, two lines of up to about 16 characters each at 5.2vw.\",\n  \"motion\": \"shutter-image\",\n  \"seenIn\": [\n   \"opl-typewave\",\n   \"opl-vessa\",\n   \"opl-uni\"\n  ]\n },\n {\n  \"id\": \"control-reads-the-page\",\n  \"name\": \"Control that reads the page\",\n  \"archetype\": \"split\",\n  \"directions\": [\n   \"product-performs\",\n   \"quiet-instrument\",\n   \"dark-room\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A near-black or deep neutral ground split into two halves by tone alone: the right half is one step lighter than the left, and they meet at a clean vertical edge at 50%. Left half: a small logo mark top-left at a 40px margin, then two-thirds of empty ground, then everything else anchored bottom-left, 40px from the edges: a one-line headline at clamp(26px, 2.1vw, 32px) in medium weight, one supporting sentence at 17px in the softer ink held to 44ch, and the single action as a light rectangular button. Right half: one fragment of the product, centred, about 450px square, built in HTML and working. It is the product's defining control (a loupe, a picker, a dial, a field) and it acts on the page itself: it reads the real background colour, the real headline size or the pointer position and prints that value in its own readout at 13px. Mark its root with data-ui so the product's own radii and borders apply inside it. There is no navigation bar; one text link sits top-right at 15px.\",\n  \"mobile\": \"The halves stack as two tones. The fragment comes first: 78vw square, centred in the lighter block, which is 58svh tall, still live and reading the page under the visitor's finger. The darker block below holds the headline at 6.4vw on up to two lines, the sentence at 16px and the button, left-aligned at 20px. The logo mark sits top-left over the first block.\",\n  \"headline\": \"One plain line at 26–32px naming what the tool is, up to about 32 characters, wrapping to two lines on a phone.\",\n  \"motion\": \"masked-headline\",\n  \"seenIn\": [\n   \"opl-dabbit\"\n  ]\n },\n {\n  \"id\": \"controls-on-the-sentence\",\n  \"name\": \"Controls on the sentence\",\n  \"archetype\": \"type-poster\",\n  \"directions\": [\n   \"product-performs\",\n   \"sentence-as-layout\",\n   \"type-only-statement\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A dark flat ground with no logo bar: a 14px wordmark top-left and the single action as an underlined text link top-right, both 28px in. The headline is a two-line sentence, centred, at clamp(96px, 9vw, 150px), line-height 1.0, occupying the middle 64% of the width and sitting slightly above the midline. It is set in a variable font and it is the demonstration. Three small control chips from the product sit on top of the sentence, each about 300 by 80px with the product's true radius, a text label and a numeric readout: one above the first line near its left end, one overlapping the start of the second line, and a two-state switch at the lower right. They are tilted 2 to 4 degrees and filled solid, one step lighter than the ground. Each one works: dragging the first changes the headline's weight through `font-variation-settings`, the second changes its letter-spacing, the third toggles uppercase. Mark each chip's root with data-ui. One supporting sentence at 17px, max 40ch, is centred 72px under the headline. The bottom third of the screen stays empty.\",\n  \"mobile\": \"The sentence stays on two lines at 13.5vw, centred at 38% of the height. The three chips shrink to 200 by 60px and move off the letters: one above the sentence and two side by side beneath it, untilted and still live. The supporting sentence follows at 16px. The wordmark stays top-left and the action link top-right.\",\n  \"headline\": \"A two-line sentence of three to five words, up to about 11 characters per line at 9vw, that still reads when its weight and spacing change.\",\n  \"motion\": \"masked-headline\",\n  \"seenIn\": [\n   \"opl-dialkit\"\n  ]\n },\n {\n  \"id\": \"column-on-one-line\",\n  \"name\": \"Column on one line\",\n  \"archetype\": \"quiet-column\",\n  \"directions\": [\n   \"quiet-instrument\",\n   \"product-performs\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A warm off-white page that is more than 80% empty. Everything hangs on one vertical alignment 27% in from the left edge, the start of column 4; nothing is centred and nothing sits to its left. A small logo mark sits on that alignment 56px from the top. About 220px lower the column begins, only 380px wide: a two-line headline at 27px in medium weight, line-height 1.25; one supporting sentence at 15px in the softer ink, line-height 1.5; then, 28px below, the single action as a near-black rectangular button with 4px corners and one text link with an arrow beside it. A sign-in text link sits alone in the top-right corner at 14px; there is no navigation bar. At the bottom edge the first demonstration peeks in on the same alignment: a flat panel one step darker than the page, 368px wide, its top 90px visible, holding two real rows of the product's interface at true size with a visible pointer. Mark the panel's root with data-ui. The right half of the screen is blank on purpose, and nothing spans the full width until the footer.\",\n  \"mobile\": \"The alignment becomes the 24px left margin. The logo mark sits 32px from the top and the column starts at 30% of the height: headline at 24px on two lines, the sentence at 15px, then button and text link side by side. The demonstration panel spans the width between the margins and shows its top 120px above the fold. The sign-in link stays top-right.\",\n  \"headline\": \"A dry two-line statement at 27px, up to about 30 characters per line; it never grows larger at any width.\",\n  \"motion\": \"slow-crossfade\",\n  \"seenIn\": [\n   \"opl-rows\",\n   \"opl-lovably\"\n  ]\n },\n {\n  \"id\": \"single-object-on-plinth\",\n  \"name\": \"Single object on a plinth\",\n  \"archetype\": \"object-centre\",\n  \"directions\": [\n   \"quiet-instrument\",\n   \"hero-object\",\n   \"specimen-catalogue\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"blueprint\": \"An off-white screen that is about 80% empty and does not need to scroll. One photographed object stands dead centre: a studio shot on a plain background, shown 440px tall (about half the viewport height) whatever its width, with `mix-blend-mode: multiply` so its backdrop disappears into the page. It rests on a plinth, a rounded square 520px across filled one step lighter than the page and centred behind it, with no border. The wordmark sits top-left at a 56px margin in a heavy serif or grotesk, about 400px wide (28% of the viewport) and 80px tall; it is the only large type. Opposite it, top-right on the same margin and aligned to the wordmark's top, sits the one supporting sentence at 15px, right-aligned, max 36ch. Centred 40px under the plinth is the single action: a compact email field or button 240px wide with 8px corners. Further objects replace the first in the same position by crossfade, each scaled to the same visual mass. There is no navigation. Nothing else touches the edges, and the object never grows beyond half the viewport height.\",\n  \"mobile\": \"The wordmark sits top-left at 44vw wide with 20px margins and the supporting sentence drops beneath it at 14px. The plinth is 78vw square, centred at 54% of the height, with the object 44svh tall on it. The action sits 32px under the plinth, 40px in from each side. The screen stays mostly empty and the objects swap in place.\",\n  \"headline\": \"None beyond the name: the wordmark top-left, up to about 10 characters, is the only large type and the object is the statement.\",\n  \"motion\": \"slow-crossfade\",\n  \"seenIn\": [\n   \"opl-archiv\",\n   \"opl-humanoid-index\"\n  ]\n },\n {\n  \"id\": \"object-crops-three-edges\",\n  \"name\": \"Object cropped by three edges\",\n  \"archetype\": \"object-centre\",\n  \"directions\": [\n   \"hero-object\",\n   \"loud-flat-poster\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"blueprint\": \"A flat off-white or single bold colour field with no navigation bar: only a small wordmark top-right at 24px and the single action fixed bottom-right as a solid rectangular button. The left 60% of the screen is one object photographed on a plain background and scaled far past its container. Set the image to about 150% of the hero's height, rotate it 10 to 20 degrees and position it so the top, left and bottom edges of the viewport all crop it and only its right-hand third is fully inside; use `overflow: hidden` on the section and `mix-blend-mode: multiply` if the field is light. The headline fills the right half: two stacked lines of very bold lowercase at clamp(120px, 13vw, 210px), right-aligned 16px from the right edge, tracking -0.05em, line-height 0.86, vertically centred. It sits behind the object in the stacking order, so the object's right-hand contour tucks over the first one or two letters of each line. One supporting sentence at 18px, max 28ch, is right-aligned under the headline on columns 9–12. Nothing else is on the screen: no second image, no list.\",\n  \"mobile\": \"The object moves to the top: the image is 150vw wide, rotated, cropped by the top, left and right edges, and occupies the upper 52svh. The headline sits below it at 19vw on two lines, right-aligned at a 12px margin, its first line overlapped by the object's lower contour. The supporting sentence follows at 16px, right-aligned. The action button stays fixed bottom-right.\",\n  \"headline\": \"Two lines of one or two short words each, up to about 8 characters per line at 13vw, partly tucked behind the object.\",\n  \"motion\": \"shutter-image\",\n  \"seenIn\": [\n   \"opl-when-you-wish-upon-a-starboy\"\n  ]\n },\n {\n  \"id\": \"object-splits-the-headline\",\n  \"name\": \"Object splits the headline\",\n  \"archetype\": \"object-centre\",\n  \"directions\": [\n   \"hero-object\",\n   \"sentence-as-layout\",\n   \"dark-room\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"blueprint\": \"One deep, flat ground colour. The object, a low-key studio photograph whose background matches the ground, stands at dead centre, scaled to 66% of the viewport height and tilted about 8 degrees, with its base cropped by the bottom edge. The headline is split around it: line one is centred across the object's upper fifth and line two across its lower fifth, both at clamp(64px, 5.8vw, 92px), regular weight, spanning columns 2–11, so the object fills the gap where a paragraph would normally sit. The type lies above the object in the stacking order in the light ink, so every letter stays readable where it crosses. At the object's mid-height two small text blocks at 14px face each other: the supporting sentence far left on columns 1–2, and two short facts (size, price) far right on columns 11–12, right-aligned, each 32px from its edge. Wordmark top-left; three text links top-centre; the single action top-right as a small light rectangular tab, the only light solid on the screen. The lower corners stay dark and empty.\",\n  \"mobile\": \"The object is 54svh tall, centred, its base cropped by the bottom edge. Line one of the headline crosses its top at 11vw and line two its lower third at 11vw, both centred inside 16px margins. The side text blocks merge into one 15px sentence under the navigation. Wordmark top-left and the action tab top-right; the links collapse to one word.\",\n  \"headline\": \"A two-line statement of four to six words, up to about 16 characters per line at 5.8vw, with the object standing between the lines.\",\n  \"motion\": \"slow-crossfade\",\n  \"seenIn\": [\n   \"aww-zeroz-brand-site\",\n   \"aww-moto-finance\"\n  ]\n },\n {\n  \"id\": \"object-on-the-seam\",\n  \"name\": \"Object on the seam\",\n  \"archetype\": \"object-centre\",\n  \"directions\": [\n   \"hero-object\",\n   \"quiet-instrument\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"blueprint\": \"A white or very pale page organised by one change of tone. A square-cornered panel one step darker than the page (a flat pale blue-grey or warm grey) fills the top 44% of the viewport inside 12px margins; the page colour runs below it. The object, photographed on a plain background and blended with `mix-blend-mode: multiply`, straddles the seam between the two tones: it is about 62% of the viewport wide, starts at column 6 and runs off the right edge, with its upper half over the panel and its lower half over the page. Type is small and exact. The headline is two lines at 24px in medium weight, far left on columns 1–3 at a 32px margin, its first baseline resting exactly on the seam; the second line is set in the softer ink. One supporting sentence at 15px, max 34ch, sits 120px lower on the same margin with the single action as a small rectangular button under it. A plain top row inside the panel at 14px: wordmark left, three text links centred, one text link right.\",\n  \"mobile\": \"The tonal panel takes the top 46svh. The object is 120vw wide, centred on the seam and cropped by the right edge. The headline sits just under the seam at 22px on two lines at a 20px margin, with the sentence at 15px beneath and then the button. The wordmark sits top-left inside the panel; the links collapse to one word top-right.\",\n  \"headline\": \"Two short sentences at 24px, one per line and up to about 28 characters each, the second in the softer ink.\",\n  \"motion\": \"shutter-image\",\n  \"seenIn\": [\n   \"opl-aevion\"\n  ]\n },\n {\n  \"id\": \"statement-beside-specimen-mosaic\",\n  \"name\": \"Statement beside specimen mosaic\",\n  \"archetype\": \"mosaic\",\n  \"directions\": [\n   \"specimen-catalogue\",\n   \"split-stage\",\n   \"uneven-photographs\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"blueprint\": \"The viewport is split 50/50 by tone alone: the left half is the page ground, the right half a field one step darker, meeting at a clean vertical edge with no line. Left half: the wordmark at 22px sits top-left on a 32px margin; under it the statement at clamp(44px, 4.4vw, 68px), bold, tracking -0.04em, leading 1.0, top-left aligned and filling the upper 40% of the half. The lower part of this side stays empty except for one supporting sentence at 18px pinned bottom-left and the single action as a solid rectangle beside it. Right half: a loose mosaic of seven specimen tiles on a 4-column, 3-row grid with 14px gaps. Each tile is a flat palette colour at 3:4 holding one cut-out item, centred, object-fit: contain, mix-blend-mode: multiply. Five cells are left empty so the tiles stagger; one tile spans two columns and two rows; the rightmost column is cropped by the viewport edge. Two text links sit top-right over the darker field. The right half may be position: sticky while the left scrolls.\",\n  \"mobile\": \"The split becomes a stack. The statement comes first at 10.5vw on two lines inside 20px margins, the supporting sentence under it at 16px, then the action. Below, the darker field runs full width and the mosaic becomes two columns of tiles, the right column started 48px lower than the left; five tiles show and the last row is cropped by the bottom of the screen. Navigation is the wordmark and one link.\",\n  \"headline\": \"A 3-5 word statement of what is on offer, at most 28 characters so it holds two lines at 10.5vw on a phone.\",\n  \"motion\": \"shutter-image\",\n  \"seenIn\": [\n   \"aww-noho\"\n  ]\n },\n {\n  \"id\": \"specimen-wall-docked-panel\",\n  \"name\": \"Specimen wall, docked panel\",\n  \"archetype\": \"tiles\",\n  \"directions\": [\n   \"specimen-catalogue\",\n   \"dense-tiles\",\n   \"contact-sheet\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"blueprint\": \"There is no header and no display headline: the whole viewport is a wall of specimens. Square tiles of about 112px (7.8vw) with 8px gaps fill the screen edge to edge in eight rows; alternate rows shift half a tile sideways so the wall reads as brickwork, and tiles at every edge are cropped by the viewport (overflow: hidden on the section). Each tile is a flat fill, rotating through three palette colours, holding one cut-out item at 60% of the tile, centred, with mix-blend-mode: multiply on light fills. A solid panel in the ink colour, 800px wide (columns 4-9) and about 170px tall with square corners, is docked at the bottom centre, 24px above the bottom edge, covering the tiles behind it. Inside, on 28px padding: the sentence that says what this is at 24px semibold on the left across two lines, the single action as a filled rectangle in the paper colour on the right, and beneath them a row holding the wordmark and four text links at 15px. Nothing else overlays the wall.\",\n  \"mobile\": \"Tiles become 22vw squares with 6px gaps, four and a half per row, still offset as brickwork and cropped at both sides. The panel turns into a full-width block fixed to the bottom of the first screen, about a third of its height: the sentence at 6vw on two lines, the action full width beneath it, the wordmark and links in one wrapped row at 14px. The wall fills everything above.\",\n  \"headline\": \"No display line: one plain sentence of up to 56 characters inside the panel names what the items are.\",\n  \"motion\": \"index-preview\",\n  \"seenIn\": [\n   \"opl-smallbits\",\n   \"opl-beige-force\"\n  ]\n },\n {\n  \"id\": \"single-specimen-name-list\",\n  \"name\": \"Single specimen with name list\",\n  \"archetype\": \"object-centre\",\n  \"directions\": [\n   \"specimen-catalogue\",\n   \"borrowed-category\",\n   \"hero-object\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"blueprint\": \"Borrowed from a museum plinth. A calm light ground with roughly 70% left empty. The wordmark is set large for a logo, about 28% of the viewport wide (clamp(64px, 6vw, 92px), heavy serif or grotesk), top-left on a 56px margin; one sentence of description at 15px sits top-right on the same margin, its first line aligned to the top of the wordmark. Dead centre stands one specimen: a flat tile in a palette colour, 400px wide and 460px tall (columns 5-8) with a 16px radius, holding a single cut-out item at about 80% of the tile height, object-fit: contain. Left of the tile, in columns 2-4, a vertical list of item names is right-aligned towards it: the selected name in full ink at 20px, the names above and below stepping down in size and opacity (18, 16, 14px; 60, 35, 15%). Choosing a name swaps the item and the tile colour. Below the tile, centred: the item's one-line fact at 14px, then the single action, a filled rectangle 240px wide. Three text links sit bottom-left at 14px.\",\n  \"mobile\": \"The wordmark sits top-left at 11vw with the description sentence beneath it at 15px. The tile takes the full width inside 20px margins at 4:5, starting at 30% of the height. The name list becomes one horizontal row under the tile that scrolls sideways with scroll-snap, the selected name centred in full ink at 18px. The action sits full width at the bottom of the screen; the links move to the footer.\",\n  \"headline\": \"The name itself as an oversized wordma\n\n<!-- [TRUNCATED AT 50KB] -->","skills/taste-skill/library/motions.json":"[\n {\n  \"id\": \"masked-headline\",\n  \"name\": \"Masked headline\",\n  \"description\": \"On load, each line of the headline rises from behind its own baseline, about 900ms with a strong ease-out, the second line 110ms after the first; the supporting sentence and the action then fade up together. Nothing else on the page performs. Because headlines are two lines at most, you author the line breaks and wrap each line yourself. Recipe: 'Masked line reveal' in references/motion.md.\"\n },\n {\n  \"id\": \"shutter-image\",\n  \"name\": \"Shutter image\",\n  \"description\": \"The one hero or showcase image opens from an edge with a clip-path over about 1.1 seconds while the picture inside settles from 1.12 scale to rest. Use it once, on the image that matters most; later images simply are there. Recipe: 'Image shutter' in references/motion.md.\"\n },\n {\n  \"id\": \"scaling-wordmark\",\n  \"name\": \"Scaling wordmark\",\n  \"description\": \"The giant name responds to the scroll: as the first screen leaves, the wordmark scales down a few percent (or grows from 0.94 to 1 as the footer arrives) on a scroll-linked timeline, so the monument feels heavy. Travel stays under 8%. Static fallback where scroll timelines are unsupported. Recipe: 'Scroll-linked progress' in references/motion.md, animating `scale`.\"\n },\n {\n  \"id\": \"pinned-story\",\n  \"name\": \"Pinned story\",\n  \"description\": \"One element holds its place with `position: sticky` (a title, a frame, a product fragment) while the items that belong to it scroll past or swap inside it. The page's ordinary scrolling does the work; nothing is hijacked. Hold it for about one screen per step and three screens at most, two held stages per page at most, with a line of text on every held screen. Recipe: 'Pinned story' in references/motion.md.\"\n },\n {\n  \"id\": \"index-preview\",\n  \"name\": \"Index with preview\",\n  \"description\": \"Rows of text are the navigation through the work; pointing at a row brings up its image in one fixed frame and dims the other rows. On touch screens each row shows its image inline instead. Fast and exact (about 240ms crossfade), no lag behind the pointer. Recipe: 'Index with preview, anchored to the row' in references/motion.md.\"\n },\n {\n  \"id\": \"curtain-footer\",\n  \"name\": \"Curtain footer\",\n  \"description\": \"The page content slides up like a sheet to uncover the footer waiting beneath it, so the last screen is revealed rather than scrolled to. Build with a sticky footer at the bottom and a main element with its own background and a higher stacking order. No JavaScript.\"\n },\n {\n  \"id\": \"slow-crossfade\",\n  \"name\": \"Slow crossfade\",\n  \"description\": \"The principal photograph quietly changes: three or four images of the same framing crossfade over about 1.6 seconds, holding five to six seconds each, or the fixed image changes when its matching section arrives. It should feel like light shifting in a room. Pause when the tab is hidden; under reduced motion show only the first image.\"\n },\n {\n  \"id\": \"edge-marquee\",\n  \"name\": \"Edge-to-edge marquee\",\n  \"description\": \"One line of very large type travels sideways across the full width at a slow constant speed, as a band between two sections or as the closing statement. Linear timing, duplicated content for a seamless loop, paused on hover and under reduced motion. One marquee per page, carrying real words (the name, the claim), never a list of buzzwords.\"\n },\n {\n  \"id\": \"drag-row\",\n  \"name\": \"Drag row\",\n  \"description\": \"A row of large items wider than the screen that the visitor pulls sideways: native horizontal scrolling with scroll snapping, the first item aligned to the page margin and the last allowed to run off the edge so the row visibly continues. No carousel library, no arrows, no dots.\"\n },\n {\n  \"id\": \"colour-on-scroll\",\n  \"name\": \"Colour by chapter\",\n  \"description\": \"Each chapter is its own full-bleed field of one palette colour, so the ground changes exactly at section edges as you scroll, never as a global recolouring of the screen. The only movement: the fixed header (or the one pinned element) takes the ink of the chapter beneath it, switching with a 300ms colour transition as each edge passes under it. Do not drive the page background from an observer: in blind tests a page recoloured mid-section, with a paragraph sitting on two colours, read as broken twice.\"\n },\n {\n  \"id\": \"stillness\",\n  \"name\": \"Stillness\",\n  \"description\": \"No showpiece. The page is simply there, instantly, and the discipline is the statement. Motion is limited to exact feedback: a 140ms press on the button, a 180ms colour change on links, focus rings that appear without delay. Do not add a load animation or scroll reveals to this direction.\"\n },\n {\n  \"id\": \"opening-window\",\n  \"name\": \"Opening window\",\n  \"description\": \"A type screen hands over to the one great photograph: the picture first shows as a window about 45% of the width in the middle of a held stage and opens to full-bleed over about one screen of scroll, while the image inside settles from 1.15 scale. Scroll-linked and linear, so the reader sets the pace; it is fully open after three quarters of the hold and rests a moment before the page moves on. Use it once, for the picture that carries the subject. Where scroll timelines are unsupported, or under reduced motion, the picture is simply a full-bleed screen. Recipe: 'Opening window' in references/motion.md.\"\n },\n {\n  \"id\": \"ink-fill\",\n  \"name\": \"Ink-fill statement\",\n  \"description\": \"One statement of three to five lines at 32px or more starts at 45% ink and fills to full ink line by line as it rises from three quarters of the way down the screen to just past half way, so the reading pace follows the scroll. Every word is readable before it fills; the fill only sets the rhythm. Once per page, never on body copy, never on a headline the visitor needs at once. Full ink without scroll timelines or under reduced motion. Recipe: 'Ink fill' in references/motion.md.\"\n },\n {\n  \"id\": \"sheet-over\",\n  \"name\": \"Sheet over a held picture\",\n  \"description\": \"A full-bleed photograph holds its place for one screen and the next chapter, an opaque sheet in the page ground carrying its heading at the top edge, slides up over it like a page being turned. The chapter change is read, not just seen, and nothing is hijacked: the photograph is a 100svh figure with position: sticky; top: 0, followed by a section with its own background and a higher stacking order. Hold for one screen at most, use it at one or two chapter changes, and give each held photograph a caption so the held screen carries a line of text.\"\n },\n {\n  \"id\": \"sideways-gallery\",\n  \"name\": \"Sideways gallery\",\n  \"description\": \"A short set of pictures (eight or fewer: rooms, kitchens, pieces) moves sideways while the vertical scroll holds the stage, one pixel of scroll for one pixel of travel, and the hold ends the moment the last picture reaches the margin. Only on wide screens with motion allowed and only when the row is under three screens long; phones, reduced motion and longer rows get the native drag row with snapping. Focusing a link scrolls its picture into view, and the only copy of a call to action never sits inside the moving row. Recipe: 'Sideways gallery' in references/motion.md.\"\n },\n {\n  \"id\": \"pushed-line\",\n  \"name\": \"Pushed line\",\n  \"description\": \"One line of very large type, the name or the claim, is pushed sideways by the scroll rather than by a clock: it travels from 12% right to 12% left of its place while it crosses the screen, linear and locked to the scrollbar, and reads whole at the middle of its run. One per page, never across running text, and the words must never be cropped at the moment the line sits in the middle of the screen. Build with animation-timeline: view() on the line and a translateX keyframe; static where scroll timelines are unsupported and under reduced motion.\"\n },\n {\n  \"id\": \"rolling-figures\",\n  \"name\": \"Rolling figures\",\n  \"description\": \"For a page whose case is a handful of numbers (a report, a fund, a practice with a founding year): three or four figures at display size roll each digit up to its value once as they come into view, about 1.1 seconds on a strong ease-out, the columns 70ms apart. Tabular figures, the real number kept in the text for screen readers and search, never in running text and never for a value that changes after load. Set at its value under reduced motion. Recipe: 'Rolling figures' in references/motion.md.\"\n },\n {\n  \"id\": \"carried-picture\",\n  \"name\": \"Carried picture\",\n  \"description\": \"Between the index and a case page, the picture the visitor clicked travels into place as the new page's hero while the old page fades out in 200ms and the new one rises in, all within 480ms, using the browser's own cross-document view transitions with no library and no full-screen curtain. Give the card picture and the hero the same view-transition-name; each name appears once per page. Browsers without view transitions simply navigate; reduced motion turns it off. Recipe: 'Page to page' in references/motion.md.\"\n }\n]\n","skills/taste-skill/library/palettes.json":"[\n {\n  \"id\": \"white-link-blue\",\n  \"name\": \"Sheet and biro\",\n  \"tags\": [\n   \"light-neutral\",\n   \"mono-accent\"\n  ],\n  \"bg\": \"#ffffff\",\n  \"surface\": \"#f4f4f4\",\n  \"ink\": \"#111111\",\n  \"muted\": \"#6b6b6b\",\n  \"accent\": \"#1a4be0\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#111111\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"White holds the whole page with black type, one grey for secondary lines and a pale grey step for tiles and inputs; the footer may invert to black. Blue is the colour of text links and the one button, and nothing else is tinted.\",\n  \"seenIn\": [\n   \"opl-shawn-golden\",\n   \"opl-lovably\",\n   \"aww-bleibtgleich26\"\n  ]\n },\n {\n  \"id\": \"cool-white-slate\",\n  \"name\": \"Frost and slate\",\n  \"tags\": [\n   \"light-neutral\"\n  ],\n  \"bg\": \"#f7f9fa\",\n  \"surface\": \"#ecf0f2\",\n  \"ink\": \"#1f3038\",\n  \"muted\": \"#5d6b72\",\n  \"accent\": \"#0d7480\",\n  \"accentInk\": \"#ffffff\",\n  \"note\": \"Cool white and one paler blue-grey step hold everything, with type in dark slate instead of black. Teal appears once per screen at most, as the primary button or one small detail beside the product photograph.\",\n  \"seenIn\": [\n   \"opl-aevion\",\n   \"aww-cominvi\"\n  ]\n },\n {\n  \"id\": \"rose-grey-green\",\n  \"name\": \"Rose grey, green\",\n  \"tags\": [\n   \"light-neutral\"\n  ],\n  \"bg\": \"#ebe5e3\",\n  \"surface\": \"#e1dad7\",\n  \"ink\": \"#2b2622\",\n  \"muted\": \"#6a615d\",\n  \"accent\": \"#0f7d45\",\n  \"accentInk\": \"#ffffff\",\n  \"note\": \"A single rosy grey covers the page from top to bottom with brown-black text and grey secondary lines; images are kept greyscale. Green appears only on the current-page link and on one button in the footer.\",\n  \"seenIn\": [\n   \"opl-the-queue\"\n  ]\n },\n {\n  \"id\": \"paper-grey-brass\",\n  \"name\": \"Newsprint and brass\",\n  \"tags\": [\n   \"light-neutral\"\n  ],\n  \"bg\": \"#e8e8e3\",\n  \"surface\": \"#dcdcd6\",\n  \"ink\": \"#181715\",\n  \"muted\": \"#63625c\",\n  \"accent\": \"#bfb21a\",\n  \"accentInk\": \"#181715\",\n  \"fields\": [\n   {\n    \"bg\": \"#181715\",\n    \"ink\": \"#e8e8e3\"\n   }\n  ],\n  \"note\": \"Warm paper grey with near-black type holds the upper page, then whole sections flip to near-black with paper-grey type; no section is tinted. Brass yellow marks one small detail per screen, such as the button or a single word.\",\n  \"seenIn\": [\n   \"aww-monolog\"\n  ]\n },\n {\n  \"id\": \"stone-blueprint\",\n  \"name\": \"Stone and blueprint\",\n  \"tags\": [\n   \"light-neutral\"\n  ],\n  \"bg\": \"#dfdedb\",\n  \"surface\": \"#d3d2ce\",\n  \"ink\": \"#26251e\",\n  \"muted\": \"#5f5d55\",\n  \"accent\": \"#2456d6\",\n  \"accentInk\": \"#ffffff\",\n  \"note\": \"Stone paper carries the whole page with near-black and grey text. One image at a time is printed in the accent blue as its only ink, and the same blue fills the single button.\",\n  \"seenIn\": [\n   \"opl-compile\"\n  ]\n },\n {\n  \"id\": \"white-navy-tab\",\n  \"name\": \"Navy on white\",\n  \"tags\": [\n   \"light-neutral\",\n   \"photographic-neutral\"\n  ],\n  \"bg\": \"#ffffff\",\n  \"surface\": \"#f4f4f2\",\n  \"ink\": \"#1f2b4d\",\n  \"muted\": \"#6a7186\",\n  \"accent\": \"#f7941d\",\n  \"accentInk\": \"#1f2b4d\",\n  \"fields\": [\n   {\n    \"bg\": \"#05070a\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#e3e1dc\",\n    \"ink\": \"#1f2b4d\"\n   }\n  ],\n  \"note\": \"Pure white pages with navy type sit between full-bleed photographs, opening on near-black and closing on a warm grey footer. Tangerine is one small tab or button, never larger than a thumbnail.\",\n  \"seenIn\": [\n   \"aww-white-desert\",\n   \"aww-realevate\"\n  ]\n },\n {\n  \"id\": \"three-stones\",\n  \"name\": \"Three stones\",\n  \"tags\": [\n   \"light-neutral\",\n   \"photographic-neutral\"\n  ],\n  \"bg\": \"#eeecea\",\n  \"surface\": \"#e4e1dd\",\n  \"ink\": \"#333231\",\n  \"muted\": \"#6b6763\",\n  \"accent\": \"#5c6b54\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#cdc3b6\",\n    \"ink\": \"#333231\"\n   }\n  ],\n  \"note\": \"Three close stone tones share the interface: the lightest for the page, the middle one for panels, the darkest for a single band, all with charcoal type. Saturated colour is left to the photographs and their backdrops; the grey-green fills the button only.\",\n  \"seenIn\": [\n   \"aww-noho\",\n   \"aww-vero-new-york\"\n  ]\n },\n {\n  \"id\": \"putty-black-teal\",\n  \"name\": \"Putty and black\",\n  \"tags\": [\n   \"light-neutral\",\n   \"photographic-neutral\"\n  ],\n  \"bg\": \"#dedad3\",\n  \"surface\": \"#d3cec6\",\n  \"ink\": \"#0a0a0a\",\n  \"muted\": \"#5c5852\",\n  \"accent\": \"#256f82\",\n  \"accentInk\": \"#ffffff\",\n  \"note\": \"Warm putty covers the page and pure black handles all type and the main shapes. The only tint in the interface is teal, used for the one button or a single marker placed near the photographs.\",\n  \"seenIn\": [\n   \"aww-colonia-zacamil\",\n   \"opl-archiv\"\n  ]\n },\n {\n  \"id\": \"moss-sand\",\n  \"name\": \"Sand and moss\",\n  \"tags\": [\n   \"light-neutral\",\n   \"earth\"\n  ],\n  \"bg\": \"#ddd6c6\",\n  \"surface\": \"#d2cab8\",\n  \"ink\": \"#2a2a26\",\n  \"muted\": \"#59574e\",\n  \"accent\": \"#4f6238\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#3f5a2a\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"Sand grey holds the page with charcoal type, and one deep leaf-green band may close it. Moss green is reserved for buttons; brighter greens and blues arrive only through photographs.\",\n  \"seenIn\": [\n   \"opl-vestris\",\n   \"aww-izanami\"\n  ]\n },\n {\n  \"id\": \"green-mat-chocolate\",\n  \"name\": \"Bone, green, chocolate\",\n  \"tags\": [\n   \"light-neutral\",\n   \"earth\"\n  ],\n  \"bg\": \"#e5e1d8\",\n  \"surface\": \"#dad5ca\",\n  \"ink\": \"#2a1d17\",\n  \"muted\": \"#6b5b51\",\n  \"accent\": \"#456f3a\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#456f3a\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"Bone ground with chocolate-brown text takes most of the page. The green is spent on one large flat block, about a third of a screen, and on the button; all other colour comes from photographs.\",\n  \"seenIn\": [\n   \"opl-davesocozy\",\n   \"opl-mat\"\n  ]\n },\n {\n  \"id\": \"lunar-grey-bronze\",\n  \"name\": \"Lunar and bronze\",\n  \"tags\": [\n   \"dark-neutral\"\n  ],\n  \"bg\": \"#111111\",\n  \"surface\": \"#1c1c1c\",\n  \"ink\": \"#f2f2f2\",\n  \"muted\": \"#8f8f8f\",\n  \"accent\": \"#a08672\",\n  \"accentInk\": \"#111111\",\n  \"note\": \"Soft black holds the page with panels one step lighter, white text and grey secondary lines, so photographs supply all the colour. Muted bronze goes on small markers and the one button only.\",\n  \"seenIn\": [\n   \"aww-21-hrs-on-the-moon\",\n   \"opl-dialkit\",\n   \"opl-lorenzo-bocchi-photography\"\n  ]\n },\n {\n  \"id\": \"blue-black-cornflower\",\n  \"name\": \"Night and cornflower\",\n  \"tags\": [\n   \"dark-neutral\"\n  ],\n  \"bg\": \"#0a0d14\",\n  \"surface\": \"#131824\",\n  \"ink\": \"#e9edf3\",\n  \"muted\": \"#8891a1\",\n  \"accent\": \"#5a9bfc\",\n  \"accentInk\": \"#0a0d14\",\n  \"note\": \"Blue-black ground and slate panels with silver-white text fill the page; no section changes colour. Cornflower blue marks the buttons and at most one word in a heading.\",\n  \"seenIn\": [\n   \"opl-viewport-2\",\n   \"aww-moto-finance\",\n   \"opl-rafael-derolez-2026\"\n  ]\n },\n {\n  \"id\": \"green-black-bone\",\n  \"name\": \"Green-black and bone\",\n  \"tags\": [\n   \"dark-neutral\",\n   \"earth\"\n  ],\n  \"bg\": \"#161c1a\",\n  \"surface\": \"#1f2725\",\n  \"ink\": \"#e3e2da\",\n  \"muted\": \"#8e948d\",\n  \"accent\": \"#9fc7b8\",\n  \"accentInk\": \"#161c1a\",\n  \"note\": \"Bone type on green-black from top to bottom, with panels and drawn details barely lighter than the ground so photographs supply the colour. Pale jade is for the booking or contact button alone.\",\n  \"seenIn\": [\n   \"opl-kereliott\",\n   \"aww-lama-lama-2\"\n  ]\n },\n {\n  \"id\": \"black-crimson\",\n  \"name\": \"Black and crimson\",\n  \"tags\": [\n   \"dark-neutral\",\n   \"mono-accent\"\n  ],\n  \"bg\": \"#0a0a0a\",\n  \"surface\": \"#151515\",\n  \"ink\": \"#efefef\",\n  \"muted\": \"#8c8c8c\",\n  \"accent\": \"#b11226\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#efefef\",\n    \"ink\": \"#0a0a0a\"\n   }\n  ],\n  \"note\": \"Black with off-white text and mid-grey texture takes nearly the whole page, and the last sections may invert to off-white with black type. Deep crimson is scattered sparingly: a few characters in a heading, a slider fill, the one button.\",\n  \"seenIn\": [\n   \"opl-textmode-overlay\"\n  ]\n },\n {\n  \"id\": \"forest-pale-lime\",\n  \"name\": \"Forest and lime\",\n  \"tags\": [\n   \"dark-neutral\",\n   \"earth\"\n  ],\n  \"bg\": \"#0f1f10\",\n  \"surface\": \"#162a17\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#9aa39a\",\n  \"accent\": \"#c6f19d\",\n  \"accentInk\": \"#0f1f10\",\n  \"fields\": [\n   {\n    \"bg\": \"#000000\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#ffffff\",\n    \"ink\": \"#0f1f10\"\n   }\n  ],\n  \"note\": \"Forest green, black and white sections alternate, with forest green holding the most; photographs stay in moss greens and stone browns. Pale lime sits on small squares only, such as arrow buttons and the closing wordmark.\",\n  \"seenIn\": [\n   \"aww-alethia\"\n  ]\n },\n {\n  \"id\": \"charcoal-room-sage\",\n  \"name\": \"Charcoal and sage\",\n  \"tags\": [\n   \"dark-neutral\",\n   \"photographic-neutral\"\n  ],\n  \"bg\": \"#1c1c1c\",\n  \"surface\": \"#262626\",\n  \"ink\": \"#f1f1ef\",\n  \"muted\": \"#9a9b96\",\n  \"accent\": \"#8fa68e\",\n  \"accentInk\": \"#1c1c1c\",\n  \"fields\": [\n   {\n    \"bg\": \"#c8c5ba\",\n    \"ink\": \"#1c1c1c\"\n   }\n  ],\n  \"note\": \"Charcoal holds the page with off-white text, and one section may flip to a pale concrete tone with dark text. Colour comes from the photographs; grey sage is used for the single button and the active state of a control.\",\n  \"seenIn\": [\n   \"opl-transport\",\n   \"opl-amanda-guo-design\"\n  ]\n },\n {\n  \"id\": \"warm-black-gold\",\n  \"name\": \"Warm black, gold\",\n  \"tags\": [\n   \"dark-neutral\",\n   \"photographic-neutral\"\n  ],\n  \"bg\": \"#0c0a08\",\n  \"surface\": \"#181512\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#8f8a84\",\n  \"accent\": \"#c9a45a\",\n  \"accentInk\": \"#0c0a08\",\n  \"note\": \"Warm near-black fills the page and photographs sit bright against it, with pure white small type; panels warm to a brown-black. Gold is for one text link or small button per screen, never a field.\",\n  \"seenIn\": [\n   \"aww-cipher\",\n   \"opl-hebbia\"\n  ]\n },\n {\n  \"id\": \"graphite-safety-orange\",\n  \"name\": \"Graphite and orange\",\n  \"tags\": [\n   \"mono-accent\",\n   \"dark-neutral\"\n  ],\n  \"bg\": \"#18191b\",\n  \"surface\": \"#222427\",\n  \"ink\": \"#eff0f1\",\n  \"muted\": \"#9c9ea3\",\n  \"accent\": \"#ff4a1f\",\n  \"accentInk\": \"#18191b\",\n  \"fields\": [\n   {\n    \"bg\": \"#eff0f1\",\n    \"ink\": \"#18191b\"\n   }\n  ],\n  \"note\": \"Graphite and cool light-grey sections alternate, graphite taking about two thirds, and photographs are desaturated so nothing competes. Safety orange marks the buttons, one thick solid bar across the top of the page and the highlighted item in a list or chart.\",\n  \"seenIn\": [\n   \"aww-sstr-friction-reduction\",\n   \"aww-boc-studio\",\n   \"aww-dragonfly-redux\"\n  ]\n },\n {\n  \"id\": \"soot-pale-lime\",\n  \"name\": \"Soot and lime\",\n  \"tags\": [\n   \"mono-accent\",\n   \"dark-neutral\"\n  ],\n  \"bg\": \"#0f0f0f\",\n  \"surface\": \"#1a1a1a\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#8f8f8f\",\n  \"accent\": \"#dafa9c\",\n  \"accentInk\": \"#0f0f0f\",\n  \"fields\": [\n   {\n    \"bg\": \"#ffffff\",\n    \"ink\": \"#0f0f0f\"\n   },\n   {\n    \"bg\": \"#dafa9c\",\n    \"ink\": \"#0f0f0f\"\n   }\n  ],\n  \"note\": \"A soot-black opening and close bracket white middle sections, all in black, white and grey. Pale lime is the single action colour: every button, and at most one headline set in it on the dark ground.\",\n  \"seenIn\": [\n   \"opl-builders-table\",\n   \"aww-made-with-gsap-1\",\n   \"aww-hilden-kaira\"\n  ]\n },\n {\n  \"id\": \"plum-black-pink\",\n  \"name\": \"Plum-black and pink\",\n  \"tags\": [\n   \"mono-accent\",\n   \"dark-neutral\"\n  ],\n  \"bg\": \"#0d060b\",\n  \"surface\": \"#1b0e17\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#9a8f97\",\n  \"accent\": \"#ff488b\",\n  \"accentInk\": \"#0d060b\",\n  \"fields\": [\n   {\n    \"bg\": \"#470c35\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#ffffff\",\n    \"ink\": \"#101421\"\n   }\n  ],\n  \"note\": \"Near-black and plum at the top and bottom bracket a white middle with navy-black text. Hot pink is reserved for primary buttons, bars in charts and map markers; it never fills a section.\",\n  \"seenIn\": [\n   \"aww-cerebrium\"\n  ]\n },\n {\n  \"id\": \"white-signal-red\",\n  \"name\": \"Signal red, white\",\n  \"tags\": [\n   \"mono-accent\"\n  ],\n  \"bg\": \"#ffffff\",\n  \"surface\": \"#f2f2f2\",\n  \"ink\": \"#0a0a0a\",\n  \"muted\": \"#6b6b6b\",\n  \"accent\": \"#d92b21\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#000000\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"White ground, black text and paper grey for filled panels, with one full black band allowed. Signal red is the only colour in the interface: one word in a headline, a few solid blocks, or the button.\",\n  \"seenIn\": [\n   \"opl-rsquad\",\n   \"aww-serotoninn\",\n   \"opl-estacion-venenta\"\n  ]\n },\n {\n  \"id\": \"white-mint-tiles\",\n  \"name\": \"Greys and mint\",\n  \"tags\": [\n   \"mono-accent\"\n  ],\n  \"bg\": \"#ffffff\",\n  \"surface\": \"#f3f3f3\",\n  \"ink\": \"#232323\",\n  \"muted\": \"#6e6e6e\",\n  \"accent\": \"#a1ffcb\",\n  \"accentInk\": \"#232323\",\n  \"fields\": [\n   {\n    \"bg\": \"#a1ffcb\",\n    \"ink\": \"#232323\"\n   },\n   {\n    \"bg\": \"#232323\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"White, near-black and two greys fill a board of flat tiles. Mint floods a few whole tiles (one statement, one figure, the closing call to action) and appears nowhere else.\",\n  \"seenIn\": [\n   \"aww-aspen-search\"\n  ]\n },\n {\n  \"id\": \"cool-grey-cobalt\",\n  \"name\": \"Cool grey, cobalt\",\n  \"tags\": [\n   \"mono-accent\"\n  ],\n  \"bg\": \"#eef0f3\",\n  \"surface\": \"#e2e5ea\",\n  \"ink\": \"#0b0c0e\",\n  \"muted\": \"#5d6470\",\n  \"accent\": \"#1f2de6\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#1f2de6\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"Cool pale grey holds the page with near-black type and nothing else tinted. Cobalt starts as the button and one highlighted sentence, takes one whole section as a flat field with white text, then returns as a single button block.\",\n  \"seenIn\": [\n   \"opl-vessa\",\n   \"opl-specia1ne\",\n   \"opl-brikkenco\"\n  ]\n },\n {\n  \"id\": \"offwhite-bottle-yellow\",\n  \"name\": \"Bottle ink, yellow\",\n  \"tags\": [\n   \"mono-accent\"\n  ],\n  \"bg\": \"#f7f7f7\",\n  \"surface\": \"#ebebeb\",\n  \"ink\": \"#0d2a1c\",\n  \"muted\": \"#5f6b64\",\n  \"accent\": \"#f6e016\",\n  \"accentInk\": \"#0d2a1c\",\n  \"fields\": [\n   {\n    \"bg\": \"#f6e016\",\n    \"ink\": \"#0d2a1c\"\n   }\n  ],\n  \"note\": \"Off-white ground with all type in a near-black bottle green instead of black. Yellow is the only saturated note: the button or one small object on most screens, and one later section that turns fully yellow.\",\n  \"seenIn\": [\n   \"aww-leo-parpeix-portfolio-2026\",\n   \"opl-wild-as\"\n  ]\n },\n {\n  \"id\": \"teal-on-paper\",\n  \"name\": \"Teal on paper\",\n  \"tags\": [\n   \"two-tone\"\n  ],\n  \"bg\": \"#f7f9f8\",\n  \"surface\": \"#ebf0ee\",\n  \"ink\": \"#06525c\",\n  \"muted\": \"#2f737d\",\n  \"accent\": \"#06525c\",\n  \"accentInk\": \"#f7f9f8\",\n  \"fields\": [\n   {\n    \"bg\": \"#06525c\",\n    \"ink\": \"#f7f9f8\"\n   }\n  ],\n  \"note\": \"Cool white paper and a single teal used for every word, shape and button, with no black anywhere. The accent is that same teal filled solid, for the button and for one inverted band with paper-coloured type.\",\n  \"seenIn\": [\n   \"opl-le-petit-bleu\"\n  ]\n },\n {\n  \"id\": \"navy-pink\",\n  \"name\": \"Navy and pink\",\n  \"tags\": [\n   \"two-tone\",\n   \"single-field\"\n  ],\n  \"bg\": \"#1a2039\",\n  \"surface\": \"#212846\",\n  \"ink\": \"#f9a3c0\",\n  \"muted\": \"#b9879c\",\n  \"accent\": \"#f9a3c0\",\n  \"accentInk\": \"#1a2039\",\n  \"note\": \"One navy field runs the entire page. Pink does everything else, from the name and headings to body text, and fills one solid button.\",\n  \"seenIn\": [\n   \"aww-trevor-noah\"\n  ]\n },\n {\n  \"id\": \"blush-aubergine\",\n  \"name\": \"Blush and aubergine\",\n  \"tags\": [\n   \"two-tone\"\n  ],\n  \"bg\": \"#edccbe\",\n  \"surface\": \"#e8c2b2\",\n  \"ink\": \"#351a2b\",\n  \"muted\": \"#6c4857\",\n  \"accent\": \"#351a2b\",\n  \"accentInk\": \"#edccbe\",\n  \"fields\": [\n   {\n    \"bg\": \"#351a2b\",\n    \"ink\": \"#edccbe\"\n   }\n  ],\n  \"note\": \"Blush pink and dark aubergine alternate as full fields and serve as each other's text colour, in roughly equal shares. There is no third colour: the button is a solid block of whichever of the two is not the ground.\",\n  \"seenIn\": [\n   \"aww-house-of-honey-1\",\n   \"opl-sarah-matt-wedding\"\n  ]\n },\n {\n  \"id\": \"cobalt-on-sand\",\n  \"name\": \"Cobalt on sand\",\n  \"tags\": [\n   \"two-tone\"\n  ],\n  \"bg\": \"#e6dbc7\",\n  \"surface\": \"#ddd0b9\",\n  \"ink\": \"#062b8a\",\n  \"muted\": \"#3a5aa8\",\n  \"accent\": \"#062b8a\",\n  \"accentInk\": \"#e6dbc7\",\n  \"note\": \"Sand paper and one cobalt do everything: text, drawings and solid shapes are all the same blue. The button is a cobalt block with sand-coloured type, and no black or second hue is used.\",\n  \"seenIn\": [\n   \"aww-illoca\"\n  ]\n },\n {\n  \"id\": \"oxblood-grey\",\n  \"name\": \"Oxblood and grey\",\n  \"tags\": [\n   \"two-tone\"\n  ],\n  \"bg\": \"#e2e2e2\",\n  \"surface\": \"#d6d6d6\",\n  \"ink\": \"#7d0c14\",\n  \"muted\": \"#7a4a4e\",\n  \"accent\": \"#7d0c14\",\n  \"accentInk\": \"#e2e2e2\",\n  \"fields\": [\n   {\n    \"bg\": \"#7d0c14\",\n    \"ink\": \"#e2e2e2\"\n   }\n  ],\n  \"note\": \"Deep red text on grey paper holds most of the page, then pale grey text on a solid red field takes one long section and the footer. Photographs are desaturated so nothing breaks the pair, and the button is a solid red block.\",\n  \"seenIn\": [\n   \"opl-belgrade-architecture\"\n  ]\n },\n {\n  \"id\": \"olive-on-bone\",\n  \"name\": \"Olive on bone\",\n  \"tags\": [\n   \"two-tone\",\n   \"earth\"\n  ],\n  \"bg\": \"#ecebe7\",\n  \"surface\": \"#e1dfd9\",\n  \"ink\": \"#38450f\",\n  \"muted\": \"#5d683a\",\n  \"accent\": \"#38450f\",\n  \"accentInk\": \"#ecebe7\",\n  \"fields\": [\n   {\n    \"bg\": \"#38450f\",\n    \"ink\": \"#ecebe7\"\n   }\n  ],\n  \"note\": \"A bone page with every word, large or small, in one olive green; the footer inverts to a solid olive field with bone text. Photography supplies all other colour, and the button is the same olive, filled.\",\n  \"seenIn\": [\n   \"aww-tengile-malamala-collection\"\n  ]\n },\n {\n  \"id\": \"burgundy-bubblegum\",\n  \"name\": \"Burgundy and bubblegum\",\n  \"tags\": [\n   \"two-tone\"\n  ],\n  \"bg\": \"#3d0012\",\n  \"surface\": \"#4d0519\",\n  \"ink\": \"#ff99d3\",\n  \"muted\": \"#c77aa0\",\n  \"accent\": \"#ff99d3\",\n  \"accentInk\": \"#3d0012\",\n  \"note\": \"Deep burgundy is the ground for the whole page and bubblegum pink sets every word on it. The button and the active state of a control are solid pink with burgundy type; product photographs supply any other colour.\",\n  \"seenIn\": [\n   \"opl-madie\"\n  ]\n },\n {\n  \"id\": \"bottle-green-gold\",\n  \"name\": \"Bottle green, gold\",\n  \"tags\": [\n   \"two-tone\",\n   \"earth\"\n  ],\n  \"bg\": \"#133621\",\n  \"surface\": \"#1a4429\",\n  \"ink\": \"#f4d96c\",\n  \"muted\": \"#b3a55e\",\n  \"accent\": \"#f4d96c\",\n  \"accentInk\": \"#133621\",\n  \"note\": \"Bottle green covers the page and warm gold sets all the type, with panels one step lighter than the ground. The button is solid gold with green text, and photographs are kept dark and warm so the pair is not disturbed.\",\n  \"seenIn\": [\n   \"aww-lacoste-ace-breaker\"\n  ]\n },\n {\n  \"id\": \"cobalt-field\",\n  \"name\": \"Cobalt field\",\n  \"tags\": [\n   \"single-field\"\n  ],\n  \"bg\": \"#0034eb\",\n  \"surface\": \"#002fd6\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#c5d0ff\",\n  \"accent\": \"#e9e34a\",\n  \"accentInk\": \"#111111\",\n  \"note\": \"One electric cobalt fills everything, with white and pale-blue type; photographs are tinted into blue monotone or kept as small thumbnails. A single yellow dot or button is the only other colour on the page.\",\n  \"seenIn\": [\n   \"opl-george-wood\",\n   \"aww-studio-k95-3\"\n  ]\n },\n {\n  \"id\": \"mustard-field\",\n  \"name\": \"Mustard and black\",\n  \"tags\": [\n   \"single-field\"\n  ],\n  \"bg\": \"#e1ac10\",\n  \"surface\": \"#cd9d0f\",\n  \"ink\": \"#0b0b0b\",\n  \"muted\": \"#4d3d0a\",\n  \"accent\": \"#24338f\",\n  \"accentInk\": \"#ffffff\",\n  \"note\": \"One warm mustard field for the whole page with black ink only. Royal blue is the single interruption, kept to a sliver along one edge or one small button.\",\n  \"seenIn\": [\n   \"opl-beige-force\"\n  ]\n },\n {\n  \"id\": \"carmine-field\",\n  \"name\": \"Carmine field\",\n  \"tags\": [\n   \"single-field\"\n  ],\n  \"bg\": \"#9c1220\",\n  \"surface\": \"#8a101c\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#f0b9bd\",\n  \"accent\": \"#ffd9dc\",\n  \"accentInk\": \"#9c1220\",\n  \"fields\": [\n   {\n    \"bg\": \"#2a2a2a\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"A deep red field bookends or fills the page, with white type and pale pink secondary lines; work shown in between sits on flat charcoal so it keeps its own colours. The button is a pale pink block with red type.\",\n  \"seenIn\": [\n   \"opl-marina-rachello\",\n   \"opl-belgrade-architecture\"\n  ]\n },\n {\n  \"id\": \"pink-field-lime\",\n  \"name\": \"Bubblegum and lime\",\n  \"tags\": [\n   \"single-field\"\n  ],\n  \"bg\": \"#ff87ab\",\n  \"surface\": \"#ff739d\",\n  \"ink\": \"#0a0a0a\",\n  \"muted\": \"#6b1f3a\",\n  \"accent\": \"#def915\",\n  \"accentInk\": \"#0a0a0a\",\n  \"fields\": [\n   {\n    \"bg\": \"#0a0a0a\",\n    \"ink\": \"#ff87ab\"\n   }\n  ],\n  \"note\": \"A flat bubblegum pink field with black type from top to bottom. Fluorescent lime is the action colour only: the menu button, one highlighter swipe behind a word and the main button.\",\n  \"seenIn\": [\n   \"opl-nodeck\",\n   \"aww-decathlon-yestalgia\"\n  ]\n },\n {\n  \"id\": \"sky-field-navy\",\n  \"name\": \"Sky and navy\",\n  \"tags\": [\n   \"single-field\"\n  ],\n  \"bg\": \"#6bb4ee\",\n  \"surface\": \"#7dbdf0\",\n  \"ink\": \"#0e1822\",\n  \"muted\": \"#1b3d5c\",\n  \"accent\": \"#ff5a1f\",\n  \"accentInk\": \"#0e1822\",\n  \"fields\": [\n   {\n    \"bg\": \"#ffffff\",\n    \"ink\": \"#0e1822\"\n   },\n   {\n    \"bg\": \"#0e1822\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"Sky blue sits behind everything, white cards lie on top of it, and navy handles all text and the footer. Orange is for buttons and one highlighted word, so orange against blue is the single clash on the page.\",\n  \"seenIn\": [\n   \"opl-ohhmydesign\",\n   \"opl-anidachi\"\n  ]\n },\n {\n  \"id\": \"orange-field-black\",\n  \"name\": \"Orange and black\",\n  \"tags\": [\n   \"single-field\",\n   \"two-tone\"\n  ],\n  \"bg\": \"#ff7a1f\",\n  \"surface\": \"#ff8633\",\n  \"ink\": \"#050f16\",\n  \"muted\": \"#5a2306\",\n  \"accent\": \"#050f16\",\n  \"accentInk\": \"#ff7a1f\",\n  \"fields\": [\n   {\n    \"bg\": \"#ffffff\",\n    \"ink\": \"#050f16\"\n   }\n  ],\n  \"note\": \"Hot orange is the page: one flat field with blue-black type, flipping at a hard horizontal seam to a white section when the content needs a rest. The button is a solid block of the same blue-black with orange text, and every other colour comes from the objects shown.\",\n  \"seenIn\": [\n   \"opl-postaway\",\n   \"opl-the-new-industrials\"\n  ]\n },\n {\n  \"id\": \"tobacco-olive\",\n  \"name\": \"Tobacco and olive\",\n  \"tags\": [\n   \"single-field\",\n   \"earth\"\n  ],\n  \"bg\": \"#472913\",\n  \"surface\": \"#55321a\",\n  \"ink\": \"#e4e0cf\",\n  \"muted\": \"#b39f84\",\n  \"accent\": \"#525e1b\",\n  \"accentInk\": \"#e4e0cf\",\n  \"fields\": [\n   {\n    \"bg\": \"#c79a3e\",\n    \"ink\": \"#2b170a\"\n   },\n   {\n    \"bg\": \"#525e1b\",\n    \"ink\": \"#e4e0cf\"\n   }\n  ],\n  \"note\": \"Tobacco brown fills the page with bone type, and photographs stay in browns and ochre. One olive block holds the main text or the button, and a single ochre band may break the brown once.\",\n  \"seenIn\": [\n   \"aww-the-tuscan-journey-begins\"\n  ]\n },\n {\n  \"id\": \"poster-chapters\",\n  \"name\": \"Poster chapters\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#e6e0d2\",\n  \"surface\": \"#dcd5c5\",\n  \"ink\": \"#1a1a1a\",\n  \"muted\": \"#5f5b52\",\n  \"accent\": \"#18bc42\",\n  \"accentInk\": \"#1a1a1a\",\n  \"fields\": [\n   {\n    \"bg\": \"#ed4b44\",\n    \"ink\": \"#0f0f0f\"\n   },\n   {\n    \"bg\": \"#1a1a1a\",\n    \"ink\": \"#e6e0d2\"\n   },\n   {\n    \"bg\": \"#18bc42\",\n    \"ink\": \"#1a1a1a\"\n   },\n   {\n    \"bg\": \"#f2c21a\",\n    \"ink\": \"#1a1a1a\"\n   },\n   {\n    \"bg\": \"#e6e0d2\",\n    \"ink\": \"#1a1a1a\"\n   }\n  ],\n  \"note\": \"Each chapter takes one flat field in turn (coral red, near-black, bone, green, yellow) with black or bone type and no tints between them. Green doubles as the accent for the one button when the ground is bone or black.\",\n  \"seenIn\": [\n   \"aww-pp-neue-montreal\"\n  ]\n },\n {\n  \"id\": \"blue-red-black\",\n  \"name\": \"Blue, red, black\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#ffffff\",\n  \"surface\": \"#f3f3f3\",\n  \"ink\": \"#0a0a0a\",\n  \"muted\": \"#6b6b6b\",\n  \"accent\": \"#2436ff\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#2436ff\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#ff3b1f\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#0a0a0a\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#050a5c\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"Three flat poster colours each own whole sections: electric blue, red-orange and black, with white for the areas that show the product. No tints sit between them, and blue is the button colour on white.\",\n  \"seenIn\": [\n   \"opl-juggle\"\n  ]\n },\n {\n  \"id\": \"charcoal-primaries\",\n  \"name\": \"Charcoal and primaries\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#191919\",\n  \"surface\": \"#242424\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#9a9a9a\",\n  \"accent\": \"#0c7866\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#d71e1e\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#1e4bd7\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#0c7866\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#ffe927\",\n    \"ink\": \"#111111\"\n   }\n  ],\n  \"note\": \"A charcoal ground holds flat poster primaries assigned to whole panels: red, blue, teal green and yellow, each placed against a different one. Type is white, or black on yellow; teal green is the button colour on charcoal.\",\n  \"seenIn\": [\n   \"aww-mosbys-files\"\n  ]\n },\n {\n  \"id\": \"ultramarine-yellow\",\n  \"name\": \"Ultramarine and yellow\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#1423b8\",\n  \"surface\": \"#1220a6\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#b4bcf0\",\n  \"accent\": \"#1fc27a\",\n  \"accentInk\": \"#0a0a0a\",\n  \"fields\": [\n   {\n    \"bg\": \"#1423b8\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#000000\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#f7dd47\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#e9479f\",\n    \"ink\": \"#000000\"\n   }\n  ],\n  \"note\": \"Each section is one flat field in sequence: ultramarine, black, yellow, then ultramarine again, with white type on blue and black, and black type on yellow. Green is the only small accent and never grows larger than a button.\",\n  \"seenIn\": [\n   \"aww-warm-fuzzy\",\n   \"aww-px-push\"\n  ]\n },\n {\n  \"id\": \"candy-chapters\",\n  \"name\": \"Candy chapters\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#ffd249\",\n  \"surface\": \"#f5c63c\",\n  \"ink\": \"#0a0a0a\",\n  \"muted\": \"#5e4a0a\",\n  \"accent\": \"#f53fd6\",\n  \"accentInk\": \"#0a0a0a\",\n  \"fields\": [\n   {\n    \"bg\": \"#ffd249\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#ffffff\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#ffc4ef\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#a4f6f8\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#f9a21f\",\n    \"ink\": \"#0a0a0a\"\n   }\n  ],\n  \"note\": \"Each section owns one flat candy colour: yellow first, then white, pink, cyan and orange, with all type in black. Magenta is kept for buttons alone.\",\n  \"seenIn\": [\n   \"aww-aardvark-book-club\"\n  ]\n },\n {\n  \"id\": \"orange-sky-lime\",\n  \"name\": \"Orange, sky, lime\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#ff8126\",\n  \"surface\": \"#ff8d3a\",\n  \"ink\": \"#111111\",\n  \"muted\": \"#5c2a05\",\n  \"accent\": \"#de194b\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#ff8126\",\n    \"ink\": \"#111111\"\n   },\n   {\n    \"bg\": \"#4db3ff\",\n    \"ink\": \"#111111\"\n   },\n   {\n    \"bg\": \"#c5f53d\",\n    \"ink\": \"#111111\"\n   },\n   {\n    \"bg\": \"#161615\",\n    \"ink\": \"#f2f2f2\"\n   }\n  ],\n  \"note\": \"The page ground changes as you read: orange first, then sky blue, then acid lime at the end, with one near-black band between; type stays black on all three colours. Crimson is one small button per field.\",\n  \"seenIn\": [\n   \"opl-the-new-industrials\",\n   \"opl-anidachi\"\n  ]\n },\n {\n  \"id\": \"post-red-mustard\",\n  \"name\": \"Post red, mustard\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#e2dccf\",\n  \"surface\": \"#d7d0c1\",\n  \"ink\": \"#2a1110\",\n  \"muted\": \"#6b524c\",\n  \"accent\": \"#4a6f84\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#dc1928\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#952625\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#e0a912\",\n    \"ink\": \"#2a1110\"\n   },\n   {\n    \"bg\": \"#4a6f84\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#e2dccf\",\n    \"ink\": \"#2a1110\"\n   }\n  ],\n  \"note\": \"Post red and bone alternate as full section fields, with red holding the opening and the close. Mustard, slate blue and maroon are kept for whole card frames, and slate blue also fills the one button.\",\n  \"seenIn\": [\n   \"opl-locker-land\"\n  ]\n },\n {\n  \"id\": \"mint-orange-grey\",\n  \"name\": \"Grey, mint, orange\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#ffffff\",\n  \"surface\": \"#f5f5f5\",\n  \"ink\": \"#000000\",\n  \"muted\": \"#666666\",\n  \"accent\": \"#a7ff9c\",\n  \"accentInk\": \"#000000\",\n  \"fields\": [\n   {\n    \"bg\": \"#c5c5c5\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#a7ff9c\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#ff6831\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#000000\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"Black on white to start, then whole sections flood with flat mid-grey, acid mint and orange in turn. Photographs inside a flooded section are shown in black-and-white, and mint is also the button colour on white and black.\",\n  \"seenIn\": [\n   \"aww-paul-kalkbrenner\"\n  ]\n },\n {\n  \"id\": \"report-blocks\",\n  \"name\": \"Report blocks\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#ffffff\",\n  \"surface\": \"#f6f6f6\",\n  \"ink\": \"#000000\",\n  \"muted\": \"#5f5f5f\",\n  \"accent\": \"#fe7141\",\n  \"accentInk\": \"#000000\",\n  \"fields\": [\n   {\n    \"bg\": \"#fe7141\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#d1ddd3\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#f0ff1c\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#000000\",\n    \"ink\": \"#f4f4f4\"\n   }\n  ],\n  \"note\": \"A white base with flat blocks of orange, sage, acid yellow and black assigned to whole modules: figure tiles, quote panels and chapter bands. Text is black on every colour and off-white on black, and orange is also the button colour.\",\n  \"seenIn\": [\n   \"aww-ai-in-design-report-2026\"\n  ]\n },\n {\n  \"id\": \"card-pastels\",\n  \"name\": \"Card pastels\",\n  \"tags\": [\n   \"pastel-fields\"\n  ],\n  \"bg\": \"#f7f7f5\",\n  \"surface\": \"#ebebe8\",\n  \"ink\": \"#000000\",\n  \"muted\": \"#666662\",\n  \"accent\": \"#d0106f\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#97aaf6\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#bbf697\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#fed878\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#6ef8fb\",\n    \"ink\": \"#000000\"\n   }\n  ],\n  \"note\": \"Neutral paper ground and black type, with each card or tile given its own flat pastel (periwinkle, lime, amber or cyan), never two alike side by side. Magenta is reserved for the logo, the email address and text links.\",\n  \"seenIn\": [\n   \"opl-medium-rare\"\n  ]\n },\n {\n  \"id\": \"mint-pink-accounts\",\n  \"name\": \"Mint and pink\",\n  \"tags\": [\n   \"pastel-fields\"\n  ],\n  \"bg\": \"#f8f8f8\",\n  \"surface\": \"#eeeeee\",\n  \"ink\": \"#0a0a0a\",\n  \"muted\": \"#6a6a6a\",\n  \"accent\": \"#1f6b3a\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#c3edce\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#f8c7c9\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#ffffff\",\n    \"ink\": \"#0a0a0a\"\n   }\n  ],\n  \"note\": \"Near-white base with black type; mint and pink are the only two colours and each stands for one side of the product. They first appear as small circles, then as full-screen section fields, and deep green is used only for the button.\",\n  \"seenIn\": [\n   \"opl-tara\"\n  ]\n },\n {\n  \"id\": \"swap-pastels\",\n  \"name\": \"Swapping pastels\",\n  \"tags\": [\n   \"pastel-fields\"\n  ],\n  \"bg\": \"#c3cbe5\",\n  \"surface\": \"#d0d6eb\",\n  \"ink\": \"#141414\",\n  \"muted\": \"#4a5068\",\n  \"accent\": \"#0f5257\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#c3cbe5\",\n    \"ink\": \"#141414\"\n   },\n   {\n    \"bg\": \"#efd3da\",\n    \"ink\": \"#141414\"\n   },\n   {\n    \"bg\": \"#e6dccd\",\n    \"ink\": \"#141414\"\n   },\n   {\n    \"bg\": \"#cfd3cb\",\n    \"ink\": \"#141414\"\n   },\n   {\n    \"bg\": \"#f9cdbd\",\n    \"ink\": \"#141414\"\n   }\n  ],\n  \"note\": \"One flat pastel is the whole background and it swaps per project or chapter: periwinkle, pink, sand, sage, peach. Type and one solid box stay near-black on all five, and dark teal is only for the button.\",\n  \"seenIn\": [\n   \"opl-belen-jones\"\n  ]\n },\n {\n  \"id\": \"blush-sage-slate\",\n  \"name\": \"Blush, sage, slate\",\n  \"tags\": [\n   \"pastel-fields\",\n   \"earth\"\n  ],\n  \"bg\": \"#a6b3bc\",\n  \"surface\": \"#b2bdc5\",\n  \"ink\": \"#1c1c1c\",\n  \"muted\": \"#38424a\",\n  \"accent\": \"#2c3620\",\n  \"accentInk\": \"#e3e2da\",\n  \"fields\": [\n   {\n    \"bg\": \"#a6b3bc\",\n    \"ink\": \"#1c1c1c\"\n   },\n   {\n    \"bg\": \"#b7c8be\",\n    \"ink\": \"#1c1c1c\"\n   },\n   {\n    \"bg\": \"#d6c4b8\",\n    \"ink\": \"#1c1c1c\"\n   },\n   {\n    \"bg\": \"#2c3620\",\n    \"ink\": \"#e3e2da\"\n   }\n  ],\n  \"note\": \"Slate blue-grey, sage and blush share the page as soft flat blocks, one per chapter or menu tile, with dark type; one deep olive block anchors the close with pale type. Olive is also the button colour, and photographs of sea and sky do the rest.\",\n  \"seenIn\": [\n   \"aww-seasats\",\n   \"opl-nia-creative\"\n  ]\n },\n {\n  \"id\": \"candy-on-black\",\n  \"name\": \"Candy on black\",\n  \"tags\": [\n   \"pastel-fields\"\n  ],\n  \"bg\": \"#000000\",\n  \"surface\": \"#0d0d0d\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#999999\",\n  \"accent\": \"#93f1f7\",\n  \"accentInk\": \"#000000\",\n  \"fields\": [\n   {\n    \"bg\": \"#9ae187\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#93f1f7\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#f3ea7a\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#fbb65c\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#b9c8ff\",\n    \"ink\": \"#000000\"\n   }\n  ],\n  \"note\": \"Black ground and dark photographs take nearly all of the surface. The only flat colour is a solid block behind each title, which takes a new candy pastel per project (mint, cyan, lemon, orange, cornflower); cyan is the default for the button.\",\n  \"seenIn\": [\n   \"aww-glitch-grit\"\n  ]\n },\n {\n  \"id\": \"sky-sand\",\n  \"name\": \"Sky and sand\",\n  \"tags\": [\n   \"pastel-fields\"\n  ],\n  \"bg\": \"#cbe4f2\",\n  \"surface\": \"#bcdcee\",\n  \"ink\": \"#0a0a0a\",\n  \"muted\": \"#44606e\",\n  \"accent\": \"#b0298f\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#cbe4f2\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#f1e3b5\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#ffc013\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#0a0a0a\",\n    \"ink\": \"#f2f2f2\"\n   }\n  ],\n  \"note\": \"Sky blue and sand yellow are the constant ground, each holding whole sections, with black text throughout. Saturated colour arrives only as small solid objects, and magenta is kept for the contact card and its button.\",\n  \"seenIn\": [\n   \"opl-applied-imagination\"\n  ]\n },\n {\n  \"id\": \"studio-grey\",\n  \"name\": \"Studio grey\",\n  \"tags\": [\n   \"photographic-neutral\"\n  ],\n  \"bg\": \"#a8a8aa\",\n  \"surface\": \"#b4b4b6\",\n  \"ink\": \"#0e0e0e\",\n  \"muted\": \"#3a3a3c\",\n  \"accent\": \"#1f5c49\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#1b1b1c\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"One mid grey serves as both page and studio backdrop, so the photographed object seems to stand on the page itself; type is black and one black band comes late. Colour comes only from the product, and racing green is for the single button.\",\n  \"seenIn\": [\n   \"aww-longbow\",\n   \"aww-l-i-s-a\"\n  ]\n },\n {\n  \"id\": \"walnut-tan\",\n  \"name\": \"Walnut and tan\",\n  \"tags\": [\n   \"photographic-neutral\",\n   \"earth\"\n  ],\n  \"bg\": \"#2b2216\",\n  \"surface\": \"#382d1e\",\n  \"ink\": \"#e4e2da\",\n  \"muted\": \"#a39a8b\",\n  \"accent\": \"#bda38b\",\n  \"accentInk\": \"#2b2216\",\n  \"fields\": [\n   {\n    \"bg\": \"#bda38b\",\n    \"ink\": \"#1c150d\"\n   }\n  ],\n  \"note\": \"Dark walnut holds the opening and the close with bone type, and the middle of the page may turn to flat tan around honey-lit photographs. There is no bright accent: tan is the fill for the one button on walnut.\",\n  \"seenIn\": [\n   \"opl-the-deep-end\"\n  ]\n }\n]","skills/taste-skill/library/photos.json":"{\n \"source\": \"Lorem Picsum (https://picsum.photos): photographs from Unsplash, used under the Unsplash licence\",\n \"url\": \"https://picsum.photos/id/{id}/{width}/{height}\",\n \"sets\": {\n  \"fog-and-quiet\": {\n   \"title\": \"Fog and quiet\",\n   \"note\": \"misty, muted, minimal landscapes and empty horizons; calm areas for text\",\n   \"sectors\": [\n    \"hospitality\",\n    \"health\",\n    \"fashion\",\n    \"agency\",\n    \"studio-portfolio\",\n    \"personal-portfolio\",\n    \"saas\",\n    \"ai-product\",\n    \"finance\",\n    \"architecture\",\n    \"real-estate\",\n    \"other\",\n    \"nonprofit\",\n    \"culture\"\n   ],\n   \"keywords\": [\n    \"fog\",\n    \"mist\",\n    \"quiet\",\n    \"calm\",\n    \"minimal\",\n    \"silence\",\n    \"retreat\",\n    \"wellness\",\n    \"spa\",\n    \"meditation\",\n    \"slow\"\n   ],\n   \"primary\": [\n    \"health\"\n   ],\n   \"photos\": [\n    {\n     \"id\": 70,\n     \"alt\": \"Road lined with tall trees fading into thick fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"centre\",\n     \"quality\": 5,\n     \"ratio\": 1.51,\n     \"by\": \"Dorothy Lin\",\n     \"page\": \"https://unsplash.com/photos/OokBLPrkCNk\"\n    },\n    {\n     \"id\": 172,\n     \"alt\": \"Stone jetty stretching into still water and dense grey fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"warm grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.51,\n     \"by\": \"Aleksi Tappura\",\n     \"page\": \"https://unsplash.com/photos/TQeX8khR54I\"\n    },\n    {\n     \"id\": 194,\n     \"alt\": \"Wooden deck and a single rock disappearing into thick fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"cool grey\",\n      \"weathered brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.51,\n     \"by\": \"Aleksi Tappura\",\n     \"page\": \"https://unsplash.com/photos/hVOv8me9ue8\"\n    },\n    {\n     \"id\": 228,\n     \"alt\": \"Single round hay bale in a field under dense fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey green\",\n      \"golden tan\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.33,\n     \"by\": \"Michal Kubicek\",\n     \"page\": \"https://unsplash.com/photos/0AbVUUorULU\"\n    },\n    {\n     \"id\": 255,\n     \"alt\": \"Gravel path leading to a cluster of bare trees on a hill\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"olive green\",\n      \"pale grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Jon Ottosson\",\n     \"page\": \"https://unsplash.com/photos/Xg1e5bR_bL4\"\n    },\n    {\n     \"id\": 266,\n     \"alt\": \"Three ships on a distant horizon across a calm blue sea\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"pale blue\",\n      \"deep blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"all\",\n     \"quality\": 5,\n     \"ratio\": 1.78,\n     \"by\": \"John Maravelakis\",\n     \"page\": \"https://unsplash.com/photos/Vosp2wlY3Bs\"\n    },\n    {\n     \"id\": 269,\n     \"alt\": \"Gulls perched on a concrete wall beside a pale still sea\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"pale blue\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Jill Heyer\",\n     \"page\": \"https://unsplash.com/photos/bbV7QzDUJus\"\n    },\n    {\n     \"id\": 279,\n     \"alt\": \"Still misty water fading into a soft pink-grey sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"dusty pink\",\n      \"slate grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"all\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Taylor Leopold\",\n     \"page\": \"https://unsplash.com/photos/OHS0yA7OkrQ\"\n    },\n    {\n     \"id\": 302,\n     \"alt\": \"Lone marker post standing in still water wrapped in fog\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"all\",\n     \"quality\": 5,\n     \"ratio\": 1.6,\n     \"by\": \"Billy Lam\",\n     \"page\": \"https://unsplash.com/photos/O3rmGgNYLKo\"\n    },\n    {\n     \"id\": 353,\n     \"alt\": \"Low cloud drifting over dark green forested hills\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"deep green\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.78,\n     \"by\": \"Forrest Cavale\",\n     \"page\": \"https://unsplash.com/photos/qfmd9bu7IgA\"\n    },\n    {\n     \"id\": 465,\n     \"alt\": \"Dark rocky peak emerging from thick white cloud\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"charcoal\",\n      \"pale grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 5,\n     \"ratio\": 1.51,\n     \"by\": \"Paula Vermeulen\",\n     \"page\": \"https://unsplash.com/photos/_f2m3mEkaaU\"\n    },\n    {\n     \"id\": 510,\n     \"alt\": \"Small red-roofed church below a mountain under a blank white sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"olive brown\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.33,\n     \"by\": \"Jeff Sheldon\",\n     \"page\": \"https://unsplash.com/photos/4IPe3tnBKK0\"\n    },\n    {\n     \"id\": 544,\n     \"alt\": \"Layered hill ridges fading into warm beige mist\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"beige\",\n      \"warm brown\",\n      \"cream\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Francesco Gallarotti\",\n     \"page\": \"https://unsplash.com/photos/-HkuuUSY1pE\"\n    },\n    {\n     \"id\": 552,\n     \"alt\": \"Tiny sailboat on a calm sea with distant hills, black and white\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"white\",\n      \"black\"\n     ],\n     \"mono\": true,\n     \"calm\": \"all\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Hugo Kerr\",\n     \"page\": \"https://unsplash.com/photos/Ke96snCJ1m0\"\n    },\n    {\n     \"id\": 594,\n     \"alt\": \"Small boathouse at the end of a jetty on dark water at night\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"black\",\n      \"deep purple\",\n      \"warm white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Aurélien bellanger\",\n     \"page\": \"https://unsplash.com/photos/uoSEDUu8F-I\"\n    },\n    {\n     \"id\": 634,\n     \"alt\": \"Pine forest dissolving into fog beneath a pale pink sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"dark green\",\n      \"pale pink\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Jay Mantri\",\n     \"page\": \"https://unsplash.com/photos/TFyi0QOx08c\"\n    },\n    {\n     \"id\": 813,\n     \"alt\": \"Still blue lake with a faint distant shoreline in haze\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"slate blue\",\n      \"powder blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"all\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Roger Burkhard\",\n     \"page\": \"https://unsplash.com/photos/rlX9J28Pd9g\"\n    },\n    {\n     \"id\": 842,\n     \"alt\": \"Wooden steps with railings descending into pale pink fog\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"blush pink\",\n      \"pale grey\",\n      \"slate\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 0.75,\n     \"by\": \"Joe Beck\",\n     \"page\": \"https://unsplash.com/photos/NbUokuw0BQI\"\n    },\n    {\n     \"id\": 922,\n     \"alt\": \"Dark treeline dissolving upward into pale fog, black and white\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"charcoal\",\n      \"grey\",\n      \"white\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.8,\n     \"by\": \"Patrick Hendry\",\n     \"page\": \"https://unsplash.com/photos/37ZuGYD3JOk\"\n    },\n    {\n     \"id\": 926,\n     \"alt\": \"Lone figure standing on a hilltop in thick beige fog\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"warm beige\",\n      \"olive grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.78,\n     \"by\": \"Harman Abiwardani\",\n     \"page\": \"https://unsplash.com/photos/mU_aX6JBYmg\"\n    },\n    {\n     \"id\": 941,\n     \"alt\": \"Small island on a pale, glassy sea beneath soft clouds\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale blue\",\n      \"soft white\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Ivan Slade\",\n     \"page\": \"https://unsplash.com/photos/RdyMe8KQAV0\"\n    },\n    {\n     \"id\": 989,\n     \"alt\": \"Low cloud covering a forested lakeshore under a pale sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"dark teal\",\n      \"soft blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Paul Jarvis\",\n     \"page\": \"https://unsplash.com/photos/eBDdgbM5dSo\"\n    },\n    {\n     \"id\": 994,\n     \"alt\": \"Silky long-exposure sea beneath a blue and orange sunset sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"soft blue\",\n      \"peach\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"all\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Jonathan Bean\",\n     \"page\": \"https://unsplash.com/photos/ywnnwzcdR5o\"\n    },\n    {\n     \"id\": 11,\n     \"alt\": \"Misty river winding through a grassy valley between forested slopes\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"pale green\",\n      \"grey green\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Paul Jarvis\",\n     \"page\": \"https://unsplash.com/photos/Cm7oKel-X2Q\"\n    },\n    {\n     \"id\": 93,\n     \"alt\": \"Marshland with scattered pine trees under a soft pastel sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"moss green\",\n      \"pale blue\",\n      \"soft pink\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Caroline Sada\",\n     \"page\": \"https://unsplash.com/photos/r1XwWjI4PyE\"\n    },\n    {\n     \"id\": 130,\n     \"alt\": \"Single seagull gliding over a grey sea beneath pale clouds\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"white\"\n     ],\n     \"mono\": true,\n     \"calm\": \"all\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Ryan Jacques\",\n     \"page\": \"https://unsplash.com/photos/ywiAen4L4qA\"\n    },\n    {\n     \"id\": 131,\n     \"alt\": \"Tiny figure on a pier under a vast pale yellow sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale yellow\",\n      \"sand beige\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.48,\n     \"by\": \"Charlie Foster\",\n     \"page\": \"https://unsplash.com/photos/yPaskTQiNjA\"\n    },\n    {\n     \"id\": 135,\n     \"alt\": \"Dark choppy sea fading into dense blue-grey fog\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"indigo\",\n      \"slate blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.33,\n     \"by\": \"Yuriy Khimanin\",\n     \"page\": \"https://unsplash.com/photos/o4H20aIIAt8\"\n    },\n    {\n     \"id\": 213,\n     \"alt\": \"Soft orange sunset sky above a calm misty sea\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"peach orange\",\n      \"slate blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"all\",\n     \"quality\": 4,\n     \"ratio\": 1.51,\n     \"by\": \"Kelly Sikkema\",\n     \"page\": \"https://unsplash.com/photos/X7dy114KWs4\"\n    },\n    {\n     \"id\": 227,\n     \"alt\": \"Railway tracks curving into a misty forest of bare trees\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"dark teal\",\n      \"grey green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"centre\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Andrea Boldizsar\",\n     \"page\": \"https://unsplash.com/photos/1iP1dozVO8I\"\n    },\n    {\n     \"id\": 264,\n     \"alt\": \"Wooden post standing among stones beside still misty water\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"warm beige\",\n      \"grey\",\n      \"tan\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Jon Phillips\",\n     \"page\": \"https://unsplash.com/photos/XsPM2CBTTpI\"\n    },\n    {\n     \"id\": 282,\n     \"alt\": \"Wooden railing overlooking a pine forest covered by low fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"muted brown\",\n      \"dark green\",\n      \"warm grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Taylor Leopold\",\n     \"page\": \"https://unsplash.com/photos/9dw0xLlxw1s\"\n    },\n    {\n     \"id\": 291,\n     \"alt\": \"Two figures standing in a misty blue field at dusk\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"deep blue\",\n      \"muted rust\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Caleb George\",\n     \"page\": \"https://unsplash.com/photos/zdjOYZeJj3w\"\n    },\n    {\n     \"id\": 300,\n     \"alt\": \"Hay bales scattered across a pale field under white sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"light grey\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Pavel Voinov\",\n     \"page\": \"https://unsplash.com/photos/2f_CnEeZsVg\"\n    },\n    {\n     \"id\": 313,\n     \"alt\": \"Distant clump of trees in a foggy field at dusk\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"dusty mauve\",\n      \"slate blue\",\n      \"dark olive\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Sonja Langford\",\n     \"page\": \"https://unsplash.com/photos/4xYgBTYC2-Q\"\n    },\n    {\n     \"id\": 385,\n     \"alt\": \"Calm sea stretching to a thin glowing horizon at dusk\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"slate blue\",\n      \"teal\",\n      \"soft orange\"\n     ],\n     \"mono\": false,\n     \"calm\": \"all\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Griffin Keller\",\n     \"page\": \"https://unsplash.com/photos/7oS_26cb1Wo\"\n    },\n    {\n     \"id\": 406,\n     \"alt\": \"Low clouds drifting across steep forested mountain slopes\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"white\",\n      \"dark green\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.51,\n     \"by\": \"Roland Batke-Mutschler\",\n     \"page\": \"https://unsplash.com/photos/SmhN4FejPFs\"\n    },\n    {\n     \"id\": 443,\n     \"alt\": \"Mist and cloud hanging over dark pine-covered mountains\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"dark green\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Tim Mossholder\",\n     \"page\": \"https://unsplash.com/photos/p3kpqGBRPok\"\n    },\n    {\n     \"id\": 457,\n     \"alt\": \"Faint ships on a pale foggy sea with almost no horizon\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"pale grey\"\n     ],\n     \"mono\": true,\n     \"calm\": \"all\",\n     \"quality\": 4,\n     \"ratio\": 1.77,\n     \"by\": \"Volkan Olmez\",\n     \"page\": \"https://unsplash.com/photos/ccPpd02Spe0\"\n    },\n    {\n     \"id\": 467,\n     \"alt\": \"Dark sea fading into white fog in black and white\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"white\",\n      \"grey\",\n      \"charcoal\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Taylor Leopold\",\n     \"page\": \"https://unsplash.com/photos/COE-CIGj8VA\"\n    },\n    {\n     \"id\": 472,\n     \"alt\": \"Small wooded island wrapped in fog on a dark lake\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"dark green\",\n      \"grey\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Dustin Scarpitti\",\n     \"page\": \"https://unsplash.com/photos/gR_zHJqbtzo\"\n    },\n    {\n     \"id\": 481,\n     \"alt\": \"Still lake at dusk with mist and dark conifers along the shore\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"teal grey\",\n      \"slate\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Dustin Scarpitti\",\n     \"page\": \"https://unsplash.com/photos/RdF3apSExR0\"\n    },\n    {\n     \"id\": 722,\n     \"alt\": \"Tree silhouettes in thick golden fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"ochre\",\n      \"olive brown\",\n      \"pale gold\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 0.67,\n     \"by\": \"Sebastian Kostrubala\",\n     \"page\": \"https://unsplash.com/photos/4yDg-dDX9uM\"\n    },\n    {\n     \"id\": 727,\n     \"alt\": \"Sandy mound with dark shrubs beneath a blank foggy sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"ochre\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.33,\n     \"by\": \"Devan Freeman\",\n     \"page\": \"https://unsplash.com/photos/HrUbyeQvL_w\"\n    },\n    {\n     \"id\": 731,\n     \"alt\": \"Grassy rocky mountain ridge emerging from thick grey mist\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"mist grey\",\n      \"olive green\",\n      \"dark brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.33,\n     \"by\": \"Rob Bye\",\n     \"page\": \"https://unsplash.com/photos/61XW8CMNX6A\"\n    },\n    {\n     \"id\": 807,\n     \"alt\": \"Lone tree on a grassy slope disappearing into thick fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"moss green\",\n      \"mist grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.78,\n     \"by\": \"Tiago Aguiar\",\n     \"page\": \"https://unsplash.com/photos/FtVQIQ9rDFI\"\n    },\n    {\n     \"id\": 886,\n     \"alt\": \"Flat grassy field vanishing into pale yellow fog\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"straw yellow\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.33,\n     \"by\": \"Glen Carrie\",\n     \"page\": \"https://unsplash.com/photos/p62O--o1x-U\"\n    },\n    {\n     \"id\": 925,\n     \"alt\": \"Conifer trees fading into dense grey fog on a hillside\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"mist grey\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"right\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Patrick Fore\",\n     \"page\": \"https://unsplash.com/photos/vpAKO21abME\"\n    },\n    {\n     \"id\": 965,\n     \"alt\": \"Long bridge disappearing into thick grey fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"mist grey\",\n      \"slate\",\n      \"pale green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Liane Metzler\",\n     \"page\": \"https://unsplash.com/photos/c5uShPcKLAE\"\n    },\n    {\n     \"id\": 966,\n     \"alt\": \"Forested mountainside sloping diagonally beneath white fog\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"olive green\",\n      \"brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Alberto Restifo\",\n     \"page\": \"https://unsplash.com/photos/kKrfPaKgE1c\"\n    },\n    {\n     \"id\": 991,\n     \"alt\": \"Hazy sun above layered dark hills in sepia tones\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"sepia\",\n      \"dark brown\",\n      \"pale gold\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Fritz Bielmeier\",\n     \"page\": \"https://unsplash.com/photos/ooJi3CJQRa8\"\n    },\n    {\n     \"id\": 1028,\n     \"alt\": \"Bare dead trees standing in dry ground under sepia haze\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"sepia\",\n      \"tan\",\n      \"dark brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Dikaseva\",\n     \"page\": \"https://unsplash.com/photos/zvf7cZ0PC20\"\n    }\n   ]\n  },\n  \"coast\": {\n   \"title\": \"Coast\",\n   \"note\": \"sea, shoreline, cliffs, piers and beaches\",\n   \"sectors\": [\n    \"hospitality\",\n    \"health\",\n    \"real-estate\",\n    \"restaurant\",\n    \"event\",\n    \"fashion\",\n    \"other\"\n   ],\n   \"keywords\": [\n    \"coast\",\n    \"sea\",\n    \"ocean\",\n    \"beach\",\n    \"surf\",\n    \"island\",\n    \"harbour\",\n    \"harbor\",\n    \"seaside\",\n    \"sail\",\n    \"boat\",\n    \"fish\",\n    \"marine\",\n    \"cliff\",\n    \"guesthouse\",\n    \"shore\",\n    \"bay\",\n    \"atlantic\",\n    \"lookout\"\n   ],\n   \"primary\": [\n    \"hospitality\"\n   ],\n   \"photos\": [\n    {\n     \"id\": 77,\n     \"alt\": \"Wooden jetty leading to a small pavilion over calm sea\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"warm tan\",\n      \"pale teal\",\n      \"soft grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.48,\n     \"by\": \"May Pamintuan\",\n     \"page\": \"https://unsplash.com/photos/j9nfqTi5T5o\"\n    },\n    {\n     \"id\": 626,\n     \"alt\": \"Red and white lighthouse in turquoise sea below a chalk cliff\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"turquoise\",\n      \"white\",\n      \"grass green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Nick Diamantidis\",\n     \"page\": \"https://unsplash.com/photos/jkPKQWK1sKU\"\n    },\n    {\n     \"id\": 640,\n     \"alt\": \"Aerial view of turquoise surf breaking onto golden sand\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"sand\",\n      \"turquoise\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Sarah Bürvenich\",\n     \"page\": \"https://unsplash.com/photos/vigsqYux_-8\"\n    },\n    {\n     \"id\": 641,\n     \"alt\": \"Empty lifeguard chair on a beach at pastel dusk\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"peach\",\n      \"slate blue\",\n      \"dusty teal\"\n     ],\n     \"mono\": false,\n     \"calm\": \"right\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Fré Sonneveld\",\n     \"page\": \"https://unsplash.com/photos/2qLT_Rq-2tk\"\n    },\n    {\n     \"id\": 853,\n     \"alt\": \"Lone rock in a calm blue sea beneath a pastel sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"sea blue\",\n      \"peach\",\n      \"pale pink\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.51,\n     \"by\": \"Stephen Radford\",\n     \"page\": \"https://unsplash.com/photos/674bDNKmnIk\"\n    },\n    {\n     \"id\": 1049,\n     \"alt\": \"Rock island reflected on a wet beach under a pale sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"soft white\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.25,\n     \"by\": \"Rosan Harmens\",\n     \"page\": \"https://unsplash.com/photos/Sd8O2SgKDJA\"\n    },\n    {\n     \"id\": 1052,\n     \"alt\": \"Black sea stacks off a dark beach with white surf under a pale sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"black\",\n      \"white\",\n      \"pale grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Annie Spratt\",\n     \"page\": \"https://unsplash.com/photos/x8R2oSWZRSE\"\n    },\n    {\n     \"id\": 12,\n     \"alt\": \"Dark rocks on a sandy beach with calm sea and islands\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"sand beige\",\n      \"dark brown\",\n      \"pale grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Paul Jarvis\",\n     \"page\": \"https://unsplash.com/photos/I_9ILwtsl_k\"\n    },\n    {\n     \"id\": 14,\n     \"alt\": \"Rocky shoreline meeting a calm pale sea under hazy sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"pale blue\",\n      \"warm brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Paul Jarvis\",\n     \"page\": \"https://unsplash.com/photos/IQ1kOQTJrOQ\"\n    },\n    {\n     \"id\": 16,\n     \"alt\": \"Blue sea and distant islands seen over a rocky driftwood shore\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"sky blue\",\n      \"deep blue\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Paul Jarvis\",\n     \"page\": \"https://unsplash.com/photos/gkT4FfgHO5o\"\n    },\n    {\n     \"id\": 27,\n     \"alt\": \"Person standing on a rocky shore watching misty waves at sunset\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"warm orange\",\n      \"brown\",\n      \"pale gold\"\n     ],\n     \"mono\": false,\n     \"calm\": \"right\",\n     \"quality\": 4,\n     \"ratio\": 1.78,\n     \"by\": \"Yoni Kaplan-Nadel\",\n     \"page\": \"https://unsplash.com/photos/iJnZwLBOB1I\"\n    },\n    {\n     \"id\": 47,\n     \"alt\": \"Long wooden pier over misty surf in black and white\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"light grey\",\n      \"charcoal\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Christopher Sardegna\",\n     \"page\": \"https://unsplash.com/photos/uDUiRS8YroY\"\n    },\n    {\n     \"id\": 68,\n     \"alt\": \"Curving pier with a railing, lamp post and weather vane\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"light grey\",\n      \"charcoal\"\n     ],\n     \"mono\": true,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Cristian Moscoso\",\n     \"page\": \"https://unsplash.com/photos/2SfRAWkinpU\"\n    },\n    {\n     \"id\": 108,\n     \"alt\": \"Palm trees silhouetted against a bright washed-out sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"soft pink\",\n      \"dark brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Florian Klauer\",\n     \"page\": \"https://unsplash.com/photos/t1mqA3V3-7g\"\n    },\n    {\n     \"id\": 144,\n     \"alt\": \"Pavilion at the end of a pier over waves, monochrome\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"black\",\n      \"white\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.78,\n     \"by\": \"Mouly Kumar\",\n     \"page\": \"https://unsplash.com/photos/TuOiIpkIea8\"\n    },\n    {\n     \"id\": 154,\n     \"alt\": \"Hazy beach at dusk with distant walkers and soft surf\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"dusty pink\",\n      \"muted purple\",\n      \"pale blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Christopher Sardegna\",\n     \"page\": \"https://unsplash.com/photos/x_jTtMOOMd4\"\n    },\n    {\n     \"id\": 162,\n     \"alt\": \"Aerial view of a coastline with turquoise sea and patchwork fields\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"turquoise\",\n      \"sand brown\",\n      \"deep blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Dillon McIntosh\",\n     \"page\": \"https://unsplash.com/photos/SlGVAKyP20U\"\n    },\n    {\n     \"id\": 179,\n     \"alt\": \"Waves breaking around dark rocks on a misty shoreline\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"slate grey\",\n      \"white\",\n      \"warm brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Angelina Odemchuk\",\n     \"page\": \"https://unsplash.com/photos/lp0IFw6YqZg\"\n    },\n    {\n     \"id\": 215,\n     \"alt\": \"Wide empty sandy beach with palm trees and blue sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale sand\",\n      \"sky blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 4,\n     \"ratio\": 1.33,\n     \"by\": \"Paula Borowska\",\n     \"page\": \"https://unsplash.com/photos/04paG2PxKGs\"\n    },\n    {\n     \"id\": 218,\n     \"alt\": \"Calm turquoise bay between two limestone cliffs under storm clouds\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"turquoise\",\n      \"slate grey\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"centre\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Monika Majkowska\",\n     \"page\": \"https://unsplash.com/photos/Nq8LdWC7HnM\"\n    },\n    {\n     \"id\": 268,\n     \"alt\": \"White lifeguard chair standing in dune grass under overcast sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"straw yellow\",\n      \"green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.52,\n     \"by\": \"davide ragusa\",\n     \"page\": \"https://unsplash.com/photos/vc3ZOCf5BN8\"\n    },\n    {\n     \"id\": 317,\n     \"alt\": \"Long wooden pier with railings reaching toward a pastel horizon\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"weathered brown\",\n      \"pale peach\",\n      \"soft blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.78,\n     \"by\": \"Paula Borowska\",\n     \"page\": \"https://unsplash.com/photos/cKYgt4K0g5w\"\n    },\n    {\n     \"id\": 323,\n     \"alt\": \"Steep green headlands dropping into a deep blue bay\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"deep blue\",\n      \"olive green\",\n      \"tan\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Paweł Wojciechowski\",\n     \"page\": \"https://unsplash.com/photos/QYAojSRu82c\"\n    },\n    {\n     \"id\": 347,\n     \"alt\": \"Dune grass bending in wind beneath a wide white sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"straw gold\",\n      \"grey blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Alex Talmon\",\n     \"page\": \"https://unsplash.com/photos/umq-jgTjr28\"\n    },\n    {\n     \"id\": 356,\n     \"alt\": \"Lone surfer walking along a misty beach in black and white\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"charcoal\",\n      \"silver grey\",\n      \"white\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.33,\n     \"by\": \"Daniel Ruswick\",\n     \"page\": \"https://unsplash.com/photos/fqtOAqbbnJg\"\n    },\n    {\n     \"id\": 372,\n     \"alt\": \"Lifeguard tower on an empty sandy beach under a hazy sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale blue\",\n      \"sand\",\n      \"soft grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Gabriel Santiago\",\n     \"page\": \"https://unsplash.com/photos/KWkMiUIxcD0\"\n    },\n    {\n     \"id\": 374,\n     \"alt\": \"Coastline with green headlands, a curving beach and turquoise sea\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"turquoise\",\n      \"deep green\",\n      \"sky blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Ma. Alejandra\",\n     \"page\": \"https://unsplash.com/photos/TDahcrcPhhA\"\n    },\n    {\n     \"id\": 404,\n     \"alt\": \"Waves breaking in white foam around a rugged brown rock\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey blue\",\n      \"white\",\n      \"rust brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Cole Patrick\",\n     \"page\": \"https://unsplash.com/photos/H28ODcp4EUk\"\n    },\n    {\n     \"id\": 440,\n     \"alt\": \"Rugged coastal headlands in soft backlit haze at sunset\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"pale gold\",\n      \"warm brown\",\n      \"cream\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Artur Pokusin\",\n     \"page\": \"https://unsplash.com/photos/0nv-h04oPhM\"\n    },\n    {\n     \"id\": 483,\n     \"alt\": \"Dark sea cliffs and rocks with white surf breaking below\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"charcoal\",\n      \"teal\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.78,\n     \"by\": \"Paulo Simões Mendes\",\n     \"page\": \"https://unsplash.com/photos/hrcRtexM7M0\"\n    },\n    {\n     \"id\": 485,\n     \"alt\": \"White chalk cliffs above a curved beach in sea mist\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"turquoise\",\n      \"sand\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.51,\n     \"by\": \"David Marcu\",\n     \"page\": \"https://unsplash.com/photos/DNXWtB33WWE\"\n    },\n    {\n     \"id\": 574,\n     \"alt\": \"Grassy cliff and black sand beach with sea stacks offshore\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"green\",\n      \"charcoal\",\n      \"pale blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"right\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Julien Lavallée\",\n     \"page\": \"https://unsplash.com/photos/lVtlz3JRV6o\"\n    },\n    {\n     \"id\": 606,\n     \"alt\": \"Wooden boardwalk winding through grassy dunes toward the sea\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"sage green\",\n      \"sand\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Aleksandra Boguslawska\",\n     \"page\": \"https://unsplash.com/photos/MS7KD9Ti7FQ\"\n    },\n    {\n     \"id\": 614,\n     \"alt\": \"Aerial view of white surf washing over a dark rocky shore\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"charcoal\",\n      \"white\",\n      \"dark brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Josefa Holland-Merten\",\n     \"page\": \"https://unsplash.com/photos/GnP5Kfg5ebU\"\n    },\n    {\n     \"id\": 732,\n     \"alt\": \"Dark rocky shoreline beside a calm sea under a pale cloudy sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale blue\",\n      \"soft grey\",\n      \"charcoal\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Dominik Schröder\",\n     \"page\": \"https://unsplash.com/photos/ivieBAESVWM\"\n    },\n    {\n     \"id\": 851,\n     \"alt\": \"Aerial view of turquoise sea meeting a curved reddish coastline\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"turquoise\",\n      \"teal\",\n      \"rust brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.66,\n     \"by\": \"Tiago Aguiar\",\n     \"page\": \"https://unsplash.com/photos/uXzNVOZT5no\"\n    },\n    {\n     \"id\": 969,\n     \"alt\": \"Wet rocky shore with sea stacks under a bright sky, black and white\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"black\",\n      \"grey\",\n      \"silver\"\n     ],\n     \"mono\": true,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Lee Miller\",\n     \"page\": \"https://unsplash.com/photos/_rsGm7nob3w\"\n    },\n    {\n     \"id\": 997,\n     \"alt\": \"Aerial view of a forested headland beside deep blue sea\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"deep blue\",\n      \"forest green\",\n      \"yellow green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 0.68,\n     \"by\": \"Mickey O'neil\",\n     \"page\": \"https://unsplash.com/photos/GSzD6vGIWKM\"\n    },\n    {\n     \"id\": 1055,\n     \"alt\": \"Wide wet sand flat with a distant shoreline under a pale sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"warm brown\",\n      \"sand\",\n      \"off-white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Neil Thomas\",\n     \"page\": \"https://unsplash.com/photos/12rzbJhQ89E\"\n    }\n   ]\n  },\n  \"mountain\": {\n   \"title\": \"Mountain\",\n   \"note\": \"peaks, alpine valleys, snow and rock\",\n   \"sectors\": [\n    \"hospitality\",\n    \"health\",\n    \"event\",\n    \"physical-product\",\n    \"nonprofit\",\n    \"other\",\n    \"education\"\n   ],\n   \"keywords\": [\n    \"mountain\",\n    \"alpine\",\n    \"peak\",\n    \"summit\",\n    \"hike\",\n    \"hiking\",\n    \"climb\",\n    \"outdoor\",\n    \"lodge\",\n    \"chalet\",\n    \"trail\",\n    \"expedition\"\n   ],\n   \"photos\": [\n    {\n     \"id\": 235,\n     \"alt\": \"Snow-covered peak rising above dark forested slopes and a lake\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"slate blue\",\n      \"white\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Paul E. Harrer\",\n     \"page\": \"https://unsplash.com/photos/TI-B-TNYJMU\"\n    },\n    {\n     \"id\": 260,\n     \"alt\": \"Snowy mountain peak framed by dark pine trees in mist\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"pale grey\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"centre\",\n     \"quality\": 5,\n     \"ratio\": 0.67,\n     \"by\": \"Sylwia Bartyzel\",\n     \"page\": \"https://unsplash.com/photos/OdAqbedkfiA\"\n    },\n    {\n     \"id\": 830,\n     \"alt\": \"Layered blue mountain ridges receding into haze\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"cobalt blue\",\n      \"pale blue\",\n      \"navy\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Luca Zanon\",\n     \"page\": \"https://unsplash.com/photos/X0OoHrPvgXE\"\n    },\n    {\n     \"id\": 906,\n     \"alt\": \"Sunlit snowy pyramid peak against a clear blue sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"sky blue\",\n      \"white\",\n      \"dark slate\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.33,\n     \"by\": \"Andras Toth\",\n     \"page\": \"https://unsplash.com/photos/E9CrQou9K0Y\"\n    },\n    {\n     \"id\": 931,\n     \"alt\": \"Layered mountain slopes fading into blue haze\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"steel blue\",\n      \"pale blue\",\n      \"dark teal\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.51,\n     \"by\": \"Paul Earle\",\n     \"page\": \"https://unsplash.com/photos/xJ2tjuUHD9M\"\n    },\n    {\n     \"id\": 1018,\n     \"alt\": \"Green cliffs and a winding road under low mist\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"moss green\",\n      \"mist grey\",\n      \"dark brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.33,\n     \"by\": \"Andrew Ridley\",\n     \"page\": \"https://unsplash.com/photos/Kt5hRENuotI\"\n    },\n    {\n     \"id\": 29,\n     \"alt\": \"Rocky ridges and snow-covered peaks in a high mountain range\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"slate grey\",\n      \"white\",\n      \"blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Go Wild\",\n     \"page\": \"https://unsplash.com/photos/V0yAek6BgGk\"\n    },\n    {\n     \"id\": 66,\n     \"alt\": \"Lone mountain peak beyond open grassland under heavy grey cloud\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"olive green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.33,\n     \"by\": \"Nicholas Swanson\",\n     \"page\": \"https://unsplash.com/photos/agnhLQWqr1Q\"\n    },\n    {\n     \"id\": 121,\n     \"alt\": \"Hazy mountain gorge with steep slopes in black and white\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"black\",\n      \"white\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Radio Pink\",\n     \"page\": \"https://unsplash.com/photos/p-bkdO43shE\"\n    },\n    {\n     \"id\": 166,\n     \"alt\": \"Moody valley with a river, dark hills and a foreground boulder\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"charcoal\",\n      \"grey\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.78,\n     \"by\": \"Romain Briaux\",\n     \"page\": \"https://unsplash.com/photos/yD3PXDV7Sjc\"\n    },\n    {\n     \"id\": 296,\n     \"alt\": \"Snow-capped mountain range beneath a deep blue sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"deep blue\",\n      \"white\",\n      \"dark brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Greg Shield\",\n     \"page\": \"https://unsplash.com/photos/Du30R57aCyM\"\n    },\n    {\n     \"id\": 327,\n     \"alt\": \"Snow-covered mountain range under a clear teal sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"teal\",\n      \"white\",\n      \"rust brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Ryan Schroeder\",\n     \"page\": \"https://unsplash.com/photos/Gg7uKdHFb_c\"\n    },\n    {\n     \"id\": 368,\n     \"alt\": \"Sheer granite cliffs above a hazy valley in warm evening light\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"peach\",\n      \"warm grey\",\n      \"slate\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Tyssul Patel\",\n     \"page\": \"https://unsplash.com/photos/o-zOatT4kQw\"\n    },\n    {\n     \"id\": 377,\n     \"alt\": \"Snow-capped mountain range under a dark blue evening sky\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"navy\",\n      \"slate blue\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Martin Staněk\",\n     \"page\": \"https://unsplash.com/photos/8WClaa1CmZ0\"\n    },\n    {\n     \"id\": 393,\n     \"alt\": \"Green mountain streaked with snow rising above a dark gravel plain\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"moss green\",\n      \"charcoal\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Alex Talmon\",\n     \"page\": \"https://unsplash.com/photos/UFskvng2OMU\"\n    },\n    {\n     \"id\": 426,\n     \"alt\": \"Layered blue mountains and a hazy valley under streaked clouds\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"slate blue\",\n      \"teal\",\n      \"pale grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Ales Krivec\",\n     \"page\": \"https://unsplash.com/photos/01ZeHnK3F_4\"\n    },\n    {\n     \"id\": 450,\n     \"alt\": \"Turquoise lake in a forested valley between snow-dusted mountains\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"turquoise\",\n      \"slate grey\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.51,\n     \"by\": \"Tanvi Malik\",\n     \"page\": \"https://unsplash.com/photos/OeC1wIsKNpk\"\n    },\n    {\n     \"id\": 523,\n     \"alt\": \"Volcanic crater rising from a hazy plain beneath a teal sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"teal\",\n      \"tan\",\n      \"brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 2.21,\n     \"by\": \"Harman Abiwardani\",\n     \"page\": \"https://unsplash.com/photos/WLUHO9A_xik\"\n    },\n    {\n     \"id\": 538,\n     \"alt\": \"Bird soaring above snowy mountain ridges in black and white\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"white\",\n      \"black\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.51,\n     \"by\": \"Julia Revitt\",\n     \"page\": \"https://unsplash.com/photos/yypv2Tu-mxU\"\n    },\n    {\n     \"id\": 565,\n     \"alt\": \"Snowy peak veiled in cloud with birds crossing a white sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"pale grey\",\n      \"dark brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"René Reichelt\",\n     \"page\": \"https://unsplash.com/photos/HzaT5l4Fzqc\"\n    },\n    {\n     \"id\": 591,\n     \"alt\": \"Jagged rock pinnacle rising through swirling white cloud\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"grey\",\n      \"tan\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 0.75,\n     \"by\": \"Billy Onjea\",\n     \"page\": \"https://unsplash.com/photos/_qGq1Z2Bk6c\"\n    },\n    {\n     \"id\": 684,\n     \"alt\": \"Jagged snow-covered peaks under a dark blue sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"navy\",\n      \"white\",\n      \"slate blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.78,\n     \"by\": \"Lee Roylland\",\n     \"page\": \"https://unsplash.com/photos/dfZbts6B4yw\"\n    },\n    {\n     \"id\": 735,\n     \"alt\": \"Steep dark cliffs with fog drifting through the gap between them\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"charcoal\",\n      \"mist grey\",\n      \"deep green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"centre\",\n     \"quality\": 4,\n     \"ratio\": 0.62,\n     \"by\": \"wyman H\",\n     \"page\": \"https://unsplash.com/photos/ZQeRH1XD4Tc\"\n    },\n    {\n     \"id\": 809,\n     \"alt\": \"Rocky mountain peak breaking through thick white clouds\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"slate grey\",\n      \"blue grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Namphuong Van\",\n     \"page\": \"https://unsplash.com/photos/sP4UZnpSiN4\"\n    },\n    {\n     \"id\": 814,\n     \"alt\": \"Jagged rocky peaks under a soft pink and violet dusk sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"dusty violet\",\n      \"soft pink\",\n      \"slate grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.53,\n     \"by\": \"Ales Krivec\",\n     \"page\": \"https://unsplash.com/photos/duoMdMm3aY0\"\n    },\n    {\n     \"id\": 827,\n     \"alt\": \"Conical mountain silhouette above a still lake under a starry dusk sky\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"indigo\",\n      \"dusky violet\",\n      \"navy\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 0.67,\n     \"by\": \"kazuend\",\n     \"page\": \"https://unsplash.com/photos/2KXEb_8G5vo\"\n    },\n    {\n     \"id\": 866,\n     \"alt\": \"Snowy mountain peak behind a snow slope under pink-tinted clouds\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"dusky blue\",\n      \"soft pink\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Samuel Zeller\",\n     \"page\": \"https://unsplash.com/photos/9RqA6tnT0gA\"\n    },\n    {\n     \"id\": 873,\n     \"alt\": \"Turquoise lake between steep rocky mountains with distant snow\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"teal\",\n      \"slate grey\",\n      \"pale cream\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 0.67,\n     \"by\": \"Daniel Roe\",\n     \"page\": \"https://unsplash.com/photos/lpjb_UMOyx8\"\n    },\n    {\n     \"id\": 918,\n     \"alt\": \"Rocky peak wrapped in sunlit cloud above a forested valley\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"warm gold\",\n      \"dark green\",\n      \"grey brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.51,\n     \"by\": \"David Marcu\",\n     \"page\": \"https://unsplash.com/photos/CaQ_KITtnVY\"\n    },\n    {\n     \"id\": 929,\n     \"alt\": \"Green cliff face rising out of dense white mist\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"moss green\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Tiago Muraro\",\n     \"page\": \"https://unsplash.com/photos/1kEHpwZdmtc\"\n    }\n   ]\n  },\n  \"forest\": {\n   \"title\": \"Forest\",\n   \"note\": \"woodland, paths between trees, moss and filtered light\",\n   \"sectors\": [\n    \"hospitality\",\n    \"health\",\n    \"nonprofit\",\n    \"education\",\n    \"physical-product\",\n    \"other\"\n   ],\n   \"keywords\": [\n    \"forest\",\n    \"wood\",\n    \"tree\",\n    \"cabin\",\n    \"nature\",\n    \"green\",\n    \"organic\",\n    \"sustainable\",\n    \"timber\",\n    \"garden\"\n   ],\n   \"photos\": [\n    {\n     \"id\": 229,\n     \"alt\": \"Path through tall pine trees fading into blue-grey fog\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"blue grey\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Orlova Maria\",\n     \"page\": \"https://unsplash.com/photos/7FLh300YONc\"\n    },\n    {\n     \"id\": 10,\n     \"alt\": \"Dense evergreen forest with a blue lake and distant hills beyond\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"deep green\",\n      \"teal blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Paul Jarvis\",\n     \"page\": \"https://unsplash.com/photos/6J--NXulQCs\"\n    },\n    {\n     \"id\": 190,\n     \"alt\": \"Path winding between rows of tall pine trunks\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"dark brown\",\n      \"moss green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"James Forbes\",\n     \"page\": \"https://unsplash.com/photos/jrzvClypPq8\"\n    },\n    {\n     \"id\": 216,\n     \"alt\": \"Narrow dirt trail through mossy green woodland\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"moss green\",\n      \"brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Paul Jarvis\",\n     \"page\": \"https://unsplash.com/photos/9702xTENR-M\"\n    },\n    {\n     \"id\": 243,\n     \"alt\": \"Autumn larch forest on a foggy hillside with a footpath\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"rust brown\",\n      \"pale grey\",\n      \"olive green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Orlova Maria\",\n     \"page\": \"https://unsplash.com/photos/DYW1s0AfLwo\"\n    },\n    {\n     \"id\": 423,\n     \"alt\": \"Snow-laden fir trees fading into pale winter fog\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"pale blue\",\n      \"grey green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"centre\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Gabriel Santiago\",\n     \"page\": \"https://unsplash.com/photos/pTgTMVxQE_k\"\n    },\n    {\n     \"id\": 476,\n     \"alt\": \"Sunlight bursting between tall redwood trunks in a shaded forest\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"dark brown\",\n      \"deep green\",\n      \"gold\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Mr. Marco\",\n     \"page\": \"https://unsplash.com/photos/QP1dUyQ8WsI\"\n    },\n    {\n     \"id\": 498,\n     \"alt\": \"Upward view of towering redwood trunks converging toward the canopy\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"green\",\n      \"reddish brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Kim Daniel\",\n     \"page\": \"https://unsplash.com/photos/JsqAqevX6lg\"\n    },\n    {\n     \"id\": 559,\n     \"alt\": \"Snow-covered lane lined with bare frosted trees\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"grey brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 4,\n     \"ratio\": 1.51,\n     \"by\": \"Ali Inay\",\n     \"page\": \"https://unsplash.com/photos/yNaGxHqjOuw\"\n    },\n    {\n     \"id\": 600,\n     \"alt\": \"Sunbeams streaming through tall conifers in a dark forest\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"dark green\",\n      \"pale gold\",\n      \"black\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Dustin Scarpitti\",\n     \"page\": \"https://unsplash.com/photos/eWBseWsTEpA\"\n    },\n    {\n     \"id\": 704,\n     \"alt\": \"Upward view of tall bamboo stems converging in a green canopy\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"dark green\",\n      \"green\",\n      \"black\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Ståle Grut\",\n     \"page\": \"https://unsplash.com/photos/NUgw97CVdAk\"\n    },\n    {\n     \"id\": 730,\n     \"alt\": \"Snow-dusted conifer forest fading into pale winter fog\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"frost white\",\n      \"pale grey\",\n      \"slate green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Ryan Pohanic\",\n     \"page\": \"https://unsplash.com/photos/W3V2tQAZxPA\"\n    },\n    {\n     \"id\": 805,\n     \"alt\": \"Band of dark conifer forest between a meadow and a blank white sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"white\",\n      \"dark green\",\n      \"olive brown\"\n     ],\n     \"mono\": false,\n     \"calm\"\n\n<!-- [TRUNCATED AT 50KB] -->","skills/taste-skill/library/sections.json":"[\n {\n  \"id\": \"features-capabilities-at-poster-scale\",\n  \"role\": \"features\",\n  \"name\": \"Capabilities at poster scale\",\n  \"shape\": \"list\",\n  \"tags\": [\n   \"type-led\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"type-only-statement\",\n   \"hero-object\",\n   \"loud-flat-poster\",\n   \"borrowed-category\",\n   \"colour-chapters\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"No images. The heading, two to four words, is the first line of the list itself, set at the same size as the items but in the soft ink, so no separate title sits above. Five to eight capability names follow, one per line, at clamp(40px, 5.2vw, 84px), medium to heavy weight, leading 1.0, tight tracking, flush left on the page margin across columns 1–8 of 12. Each name's one-sentence description is set at 16–18px in columns 9–12, its first baseline aligned with the name's baseline (CSS grid, align-items: first baseline). Rows are separated by 0.35em of space and nothing else. On hover one row keeps full ink while the others fall to 35% opacity. Leave 18–22vh of empty ground above and below; nothing else shares the section.\",\n  \"mobile\": \"Names drop to 11vw and stay one per line; a name that will not fit breaks onto a second line with a hanging indent. Each description sits directly under its name at 16px, indented one margin width, with 28px before the next name. The soft-ink heading line stays as the first row. All rows at full ink.\",\n  \"seenIn\": [\n   \"aww-cominvi\",\n   \"aww-cerebrium\",\n   \"opl-specia1ne\"\n  ]\n },\n {\n  \"id\": \"features-pinned-heading-passing-rows\",\n  \"role\": \"features\",\n  \"name\": \"Pinned heading, passing rows\",\n  \"shape\": \"pinned\",\n  \"tags\": [\n   \"colour-field\",\n   \"type-led\"\n  ],\n  \"directions\": [\n   \"pinned-poster\",\n   \"loud-flat-poster\",\n   \"colour-chapters\",\n   \"split-stage\",\n   \"editorial-report\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One flat saturated field, full-bleed, as tall as its content. Columns 1–5: the heading, two or three words, at clamp(56px, 6.6vw, 104px) in the heaviest weight, position: sticky; top: 32px, so it holds while the right side travels. Columns 7–12: four to six capability blocks stacked with 120px between them. Each block is a title at 28px bold, then a two-part row: a portrait photograph at 3:4, 180–220px wide with square corners, and beside it, top-aligned, a plain list of four to six short lines at 18px with 14px between lines. Photographs alternate between the left and the right of their list, so the column does not read as a ladder. One ink colour, chosen for contrast on the field. The heading releases when the bottom of the last block reaches it.\",\n  \"mobile\": \"The heading becomes a sticky bar at the top of the section: one line at 9vw on the field colour with 12px padding, holding while blocks pass under it. Each block stacks its title, a full-width 4:3 photograph, then the list at 17px. 72px between blocks.\",\n  \"seenIn\": [\n   \"opl-protip-marketing\",\n   \"aww-cerebrium\",\n   \"aww-sharplink\"\n  ]\n },\n {\n  \"id\": \"features-one-scene-stepping-statements\",\n  \"role\": \"features\",\n  \"name\": \"One scene, stepping statements\",\n  \"shape\": \"full-bleed\",\n  \"tags\": [\n   \"photo-led\"\n  ],\n  \"directions\": [\n   \"place-carries-it\",\n   \"pinned-poster\",\n   \"dark-room\",\n   \"hero-object\",\n   \"uneven-photographs\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A wrapper 350–450vh tall holds a sticky full-bleed photograph (100vw by 100svh) with a calm, symmetrical subject and a clear upper third; a neutral dark scrim covers only that upper third. At top centre, five or six short statements of two to five words are stacked at 18–20px with 10px between them; the first of them is the section's heading. One statement is at full white and the rest at 45% opacity; the active line steps down the stack as the reader scrolls (IntersectionObserver on invisible 70vh markers). For each statement, two small photographs with square corners, 160–240px wide and of different ratios, fade in left and right of the centre line at different heights, then leave when the next pair arrives. No other text. A low-key image on a deep ground works equally well.\",\n  \"mobile\": \"The photograph stays sticky at 100svh, cropped to its centre. The statement stack moves to the bottom third over a scrim, at 17px, left-aligned on the margin. Each statement brings one small photograph only, 44vw wide, placed in the top-right corner with a 16px margin.\",\n  \"seenIn\": [\n   \"aww-seasats\",\n   \"opl-eagles-nest\"\n  ]\n },\n {\n  \"id\": \"features-stacking-colour-sheets\",\n  \"role\": \"features\",\n  \"name\": \"Stacking colour sheets\",\n  \"shape\": \"stack\",\n  \"tags\": [\n   \"colour-field\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"colour-chapters\",\n   \"page-is-the-object\",\n   \"pinned-poster\",\n   \"loud-flat-poster\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Three to five capabilities, each a full-width flat colour sheet about 86svh tall with only its top corners rounded at 28px. Every sheet is position: sticky, with top offsets rising by 72px from one sheet to the next, so each new sheet slides up over the last and leaves the previous sheet's title band showing, like tabbed folders in a drawer. Inside a sheet: the capability name top-left at clamp(28px, 3vw, 44px), sitting within that 72px band; a paragraph of up to 40ch at 18px bottom-left; and in columns 7–12 one photograph filling the sheet from below the band to the bottom edge, square corners, no inset. Sheet colours follow the palette in a fixed order, with ink chosen per sheet. The heading, two to four words at clamp(40px, 5vw, 80px), sits on the ground above the stack with 48px beneath and scrolls away normally.\",\n  \"mobile\": \"Sheets stay sticky but the offset shrinks to 52px and the name drops to 22px so it fits the visible band. Inside each sheet the photograph comes first at 4:3 and full width, then the paragraph at 17px with 20px padding. Sheets are as tall as their content, 70svh at least.\",\n  \"seenIn\": [\n   \"aww-hilden-kaira\",\n   \"opl-nia-creative\",\n   \"opl-april-leihuanani-evangelista\",\n   \"aww-mosbys-files\"\n  ]\n },\n {\n  \"id\": \"features-mosaic-of-unlike-tiles\",\n  \"role\": \"features\",\n  \"name\": \"Mosaic of unlike tiles\",\n  \"shape\": \"mosaic\",\n  \"tags\": [\n   \"dense\",\n   \"colour-field\"\n  ],\n  \"directions\": [\n   \"dense-tiles\",\n   \"editorial-report\",\n   \"colour-chapters\",\n   \"specimen-catalogue\",\n   \"loud-flat-poster\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A 12-column grid with 8px gaps and rows of 96px, filled with no empty cells and no outlines. Six to eight filled tiles in four sizes only: 6×5, 6×3, 3×3 and 3×2 (columns × rows). The rule that keeps it from being a card grid: no two neighbouring tiles hold the same kind of thing. One tile is the heading alone, two to four words at 4vw, top-left. One is a photograph covering its tile. One is a single figure at 6vw with a caption. One is a short list of four lines at 20px. The others are a single sentence each at 28–32px. Text sits top-left with 24px padding; tiles holding one sentence leave their lower half empty. Tile fills: the ground one tone darker, two palette colours, and photographs. One corner radius everywhere, either 0 or 8px.\",\n  \"mobile\": \"Two columns with 6px gaps. The heading tile and the photograph tile span both columns; sentence tiles span both at their natural height; the figure and list tiles sit side by side as a pair of squares. Order: heading, photograph, pair, sentence, sentence.\",\n  \"seenIn\": [\n   \"opl-sand-studio\",\n   \"opl-builders-table\",\n   \"aww-cominvi\",\n   \"opl-uglycash\"\n  ]\n },\n {\n  \"id\": \"features-statement-cell-dark-rows\",\n  \"role\": \"features\",\n  \"name\": \"Statement cell, dark rows\",\n  \"shape\": \"split\",\n  \"tags\": [\n   \"type-led\",\n   \"dense\"\n  ],\n  \"directions\": [\n   \"dense-tiles\",\n   \"editorial-report\",\n   \"type-only-statement\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Two halves butted together, each 50vw wide and at least 90svh tall, with no gap. Left half, in a pale tone: the heading in three short lines at clamp(36px, 4.2vw, 68px), its middle line pushed flush right while the first and third stay flush left (text-align set per line), so the block zigzags inside the cell. A two-sentence paragraph of 30ch sits at the bottom-left and the single action at the bottom-right on the same baseline. Right half, in the darkest tone: four or five rows of equal height filling it, told apart by alternating two near-black tones, not by lines. Each row is a three-part grid: a title at 28px (5 parts), a short paragraph at 16px (4 parts) and a plain list of three terms at 15px (3 parts), all top-aligned with 28px padding. No images anywhere in the section.\",\n  \"mobile\": \"The halves stack. The light cell comes first at 70svh with the zigzag heading at 10vw and the paragraph at its foot. The dark rows follow at full width; each row stacks its title and paragraph, and its three terms run inline as one sentence separated by commas. Rows keep the alternating tones.\",\n  \"seenIn\": [\n   \"aww-aspen-search\"\n  ]\n },\n {\n  \"id\": \"features-staggered-fragment-cells\",\n  \"role\": \"features\",\n  \"name\": \"Staggered fragment cells\",\n  \"shape\": \"grid\",\n  \"tags\": [\n   \"ui-led\",\n   \"dense\"\n  ],\n  \"directions\": [\n   \"product-performs\",\n   \"dense-tiles\",\n   \"quiet-instrument\"\n  ],\n  \"needs\": [\n   \"product-ui\"\n  ],\n  \"blueprint\": \"A three-column grid of six filled cells with 8px gaps, each cell 420–460px tall and filled one tone off the ground, no outlines. Every cell has two parts: a text part (a title at 17px medium and three lines at 15px in the soft ink, 24px padding) and a real fragment of the interface at true size (a control, a menu, a table slice, a swatch strip) docked flush against the opposite edge of the cell and cropped by it. The stagger is the idea: across the first row cells run text-top, fragment-top, text-top; the second row runs the reverse, so fragments form a checkerboard. Fragments differ in shape and size on purpose. The heading, two to four words at 32–40px, sits left-aligned above the grid with 56px beneath it and no supporting line.\",\n  \"mobile\": \"One column of cells at their natural height with 6px gaps. Every cell runs text first, fragment second, but fragments alternate between docking to the left edge and the right edge, and they are allowed to run off the side of the cell at true size instead of shrinking.\",\n  \"seenIn\": [\n   \"opl-dabbit\",\n   \"opl-woblo\"\n  ]\n },\n {\n  \"id\": \"features-small-proof-beside-text\",\n  \"role\": \"features\",\n  \"name\": \"Small proof beside text\",\n  \"shape\": \"list\",\n  \"tags\": [\n   \"quiet\",\n   \"ui-led\"\n  ],\n  \"directions\": [\n   \"quiet-instrument\",\n   \"product-performs\",\n   \"split-stage\",\n   \"name-as-monument\",\n   \"contact-sheet\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One narrow module repeated four to six times down the page, never alternating sides. Each module is 640px wide at most and starts on the page's text margin (at about 22% of the viewport on an understated page). Left part: a flat panel 360px wide and 120 to 200px tall, one tone off the ground, radius 8px, holding one small exact demonstration: a cropped interface fragment at true size, or a tightly cropped photograph covering the panel. Right part, 20px away and top-aligned: a heading of one or two lines at 18px medium and two short paragraphs at 15px in the soft ink, in a column 250px wide. Panel heights vary with their content; text always hangs from the panel's top edge. 96–120px of empty ground between modules. The section heading is 24–28px, on the same left edge, 64px above the first module. In a column under 600px the text moves beneath its panel.\",\n  \"mobile\": \"Each module stacks: the panel at full width and natural height, then heading and paragraphs 16px below on the same left edge, at 17px and 15px. 64px between modules. Panels keep their true-size contents and crop from the right instead of scaling down.\",\n  \"seenIn\": [\n   \"opl-rows\"\n  ]\n },\n {\n  \"id\": \"features-comparison-set-as-text\",\n  \"role\": \"features\",\n  \"name\": \"Comparison set as text\",\n  \"shape\": \"table\",\n  \"tags\": [\n   \"type-led\",\n   \"quiet\"\n  ],\n  \"directions\": [\n   \"type-only-statement\",\n   \"editorial-report\",\n   \"product-performs\",\n   \"quiet-instrument\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A comparison table with no lines and no tick marks. A CSS grid: capability names in columns 1–5 of 12 at 22–24px medium, then three answer columns of equal width (plans, methods, or this against the usual way). Every cell answers in words at 17px: 'Yes, unlimited', 'Up to five', 'Not yet', never a symbol. Seven to ten rows, each 64–72px tall, with every other row on a ground one tone darker so the eye tracks across; rows touch. The column that matters is one filled block in the accent or ink colour running the full height of the table behind its cells and rising 24px above the first row, with its text reversed. Column names sit in the top row at 17px bold. The heading, two to four words at 40–48px, hangs top-left above column 1 with 48px beneath.\",\n  \"mobile\": \"The table turns on its side: one block per capability. The name at 20px bold, then three lines beneath, each giving a column name and its answer at 16px; the featured column's line is set on the filled colour at full width. Blocks alternate the two ground tones.\",\n  \"seenIn\": [\n   \"aww-pp-neue-montreal\"\n  ]\n },\n {\n  \"id\": \"features-one-size-name-columns\",\n  \"role\": \"features\",\n  \"name\": \"One-size name columns\",\n  \"shape\": \"index\",\n  \"tags\": [\n   \"quiet\",\n   \"type-led\",\n   \"dense\"\n  ],\n  \"directions\": [\n   \"contact-sheet\",\n   \"quiet-instrument\",\n   \"name-as-monument\",\n   \"dark-room\",\n   \"uneven-photographs\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Pure text at one size. Three columns start on columns 1, 4 and 7 of the 12-column grid, leaving columns 10–12 empty on purpose. Each column opens with a group name in full ink and continues with a tight stack of six to ten capability names in the soft ink, all at 16–17px, regular weight, line-height 1.25, no bullets and no symbols; one blank line separates group name from stack. Hovering a name brings it to full ink and shows a one-line description in a fixed spot: the top of the empty columns 10–12, at the same size. The heading is no larger than 28px; two or three words, alone on column 1, 96px above the columns. Give the section 20vh of empty ground above and below, so the smallness reads as decided. Works on light or deep grounds.\",\n  \"mobile\": \"Columns stack with 40px between groups; text rises to 18px with line-height 1.4 for touch. Group names stay in full ink. Hover descriptions are dropped; each group ends instead with one sentence in the soft ink that sums it up. The heading is 24px, 48px above.\",\n  \"seenIn\": [\n   \"aww-revelatio-studio\",\n   \"aww-pp-neue-montreal\",\n   \"aww-lama-lama-2\"\n  ]\n },\n {\n  \"id\": \"features-specimens-on-colour-tiles\",\n  \"role\": \"features\",\n  \"name\": \"Specimens on colour tiles\",\n  \"shape\": \"grid\",\n  \"tags\": [\n   \"object-led\",\n   \"colour-field\"\n  ],\n  \"directions\": [\n   \"specimen-catalogue\",\n   \"hero-object\",\n   \"one-motif\",\n   \"colour-chapters\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Each capability is represented by one object photographed alone and shown on a flat colour tile. Columns 1–3 hold the heading (two to four words at 40–52px), top-aligned, with a 30ch sentence beneath and nothing else down the rest of that column. Columns 4–12 hold a grid of five or six tiles in two rows with 10px gaps: tiles are 4:5 except one, which is double width at 8:5 and placed second in the first row. Tile colours rotate through three palette fields. Each photograph is centred at about 70% of its tile's height; on light tiles use mix-blend-mode: multiply so a white studio background disappears. Under each tile, outside it and aligned to its left edge: the capability name at 20px medium and one fact at 16px in the soft ink. No text on the tiles and no hover lift.\",\n  \"mobile\": \"The heading and its sentence sit on top at full width. Tiles become a two-column grid with 8px gaps; the double tile spans both columns at 8:5 and comes first. Names shrink to 17px and facts to 15px, still under each tile.\",\n  \"seenIn\": [\n   \"aww-noho\",\n   \"aww-coffeetech-r\",\n   \"opl-when-you-wish-upon-a-starboy\"\n  ]\n },\n {\n  \"id\": \"features-statements-on-colour-fields\",\n  \"role\": \"features\",\n  \"name\": \"Statements on colour fields\",\n  \"shape\": \"statement\",\n  \"tags\": [\n   \"colour-field\",\n   \"poster\",\n   \"type-led\"\n  ],\n  \"directions\": [\n   \"colour-chapters\",\n   \"loud-flat-poster\",\n   \"type-only-statement\",\n   \"sentence-as-layout\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Three or four full-bleed flat colour fields, each 72–80svh tall, butted together with no gap. Each field holds one benefit and is almost empty. The benefit is a phrase of two to four words at clamp(56px, 9vw, 150px), heavy, leading 0.9, on two lines at most, hugging the bottom-left corner with 28px margins. Its explanation is three lines at 17–18px, 30ch wide, placed near the top at column 8, so the eye travels the diagonal from small text to big phrase. On alternate fields the arrangement mirrors: phrase bottom-right and right-aligned, paragraph top-left at column 2. Text on each field is ink or paper, whichever contrasts more. There is no separate section heading: the first field's phrase is the heading. Nothing else appears on the fields: no images, shapes or buttons.\",\n  \"mobile\": \"Fields are 64svh tall. The paragraph sits top-left at 16px across 80% of the width; the phrase sits bottom-left at 13vw on two lines. Mirroring is dropped; alternate fields right-align the paragraph only, keeping the phrase on the left margin.\",\n  \"seenIn\": [\n   \"opl-anidachi\",\n   \"aww-px-push\"\n  ]\n },\n {\n  \"id\": \"features-rows-with-margin-photographs\",\n  \"role\": \"features\",\n  \"name\": \"Rows with margin photographs\",\n  \"shape\": \"list\",\n  \"tags\": [\n   \"type-led\",\n   \"photo-led\"\n  ],\n  \"directions\": [\n   \"editorial-report\",\n   \"uneven-photographs\",\n   \"place-carries-it\",\n   \"sentence-as-layout\",\n   \"colour-chapters\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Everything hangs from one vertical axis at column 5, about 35% of the width. First the heading: a statement of up to five words at clamp(40px, 5vw, 80px) starting on the axis, vertically centred in an otherwise empty 70svh of ground. Then four or five benefit rows, each starting on the same axis: a title at clamp(28px, 3vw, 48px) and under it a paragraph of 34ch at 17px. Columns 1–4 stay empty. At the right margin each row carries one photograph, top-aligned with its title and deliberately unequal: 240px wide at 4:5 in one row, 320px at 3:2 in the next, 180px square after that. Rows are separated by 96–120px of space, not lines. On a saturated field, set all type in one pale ink and leave the photographs ungraded.\",\n  \"mobile\": \"The axis collapses to the left margin. The statement sits at 9vw in 50svh of empty ground. Each row stacks its title at 26px, the paragraph, then its photograph at alternating widths: 100%, 70% flush right, 55% flush left. 64px between rows.\",\n  \"seenIn\": [\n   \"aww-px-push\"\n  ]\n },\n {\n  \"id\": \"features-paragraph-with-picture-words\",\n  \"role\": \"features\",\n  \"name\": \"Paragraph with picture words\",\n  \"shape\": \"statement\",\n  \"tags\": [\n   \"type-led\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"sentence-as-layout\",\n   \"one-motif\",\n   \"product-performs\",\n   \"editorial-report\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One paragraph does the work of a feature grid. Three or four sentences, 35–50 words in total, set at clamp(30px, 3.6vw, 60px), leading 1.18, medium weight, across columns 1–11, left-aligned. Each sentence names one capability, and directly after that capability's key noun sits an inline slot: an inline-block frame 1em tall and 1.9em wide, radius 0.18em, dropped 0.12em below the baseline, holding a tight photograph crop (object-fit: cover) or a real interface control at readable size. Four slots at most, never two on one line. The nouns keep the weight and colour of the rest; the slots are the only emphasis. Mark it up as a paragraph and give the section a visually hidden heading of two or three words; nothing visible sits above. 72px lower, starting at column 7, one supporting sentence at 18px and the action.\",\n  \"mobile\": \"The paragraph drops to 7vw with leading 1.22 and fills the width. Slots stay inline at 1em tall but narrow to 1.5em wide. If a slot lands alone at the start of a line, let it; do not shrink the type. The supporting sentence and the action follow at full width.\",\n  \"seenIn\": [\n   \"aww-monolog\",\n   \"opl-uncle-rudy\",\n   \"aww-cominvi\",\n   \"opl-midnight-2\"\n  ]\n },\n {\n  \"id\": \"features-capabilities-as-a-menu\",\n  \"role\": \"features\",\n  \"name\": \"Capabilities as a menu\",\n  \"shape\": \"table\",\n  \"tags\": [\n   \"object-led\",\n   \"type-led\"\n  ],\n  \"directions\": [\n   \"page-is-the-object\",\n   \"split-stage\",\n   \"borrowed-category\",\n   \"type-only-statement\",\n   \"quiet-instrument\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"The capabilities are set as a printed menu or price list. One paper-coloured sheet, 520–600px wide and taller than it is wide, sits on a contrasting flat ground, centred or starting at column 2; its top and bottom edges are cut into shallow scallops or a zigzag with clip-path, its sides straight. On it, centred at the top, the heading: two or three words at 44–56px, then 40px of space. Below, items in two or three groups; each group opens with its name at 20px bold. Each item is a row: the name at 19px on the left, a short value on the right (a price, a time, a quantity, 'included'), and between them a leader of round 4px dots (border-bottom: 4px dotted, sitting on the baseline). A description at 15px in the soft ink sits under the name, at most 34ch. 18px between items, 44px between groups.\",\n  \"mobile\": \"The sheet fills the width minus 12px margins and keeps its cut top and bottom edges. Names stay left and values right on one line with the dot leader between; descriptions wrap beneath at 15px. Group names drop to 18px. Padding inside the sheet is 20px.\",\n  \"seenIn\": [\n   \"opl-the-content-architecture\",\n   \"aww-pensatori-irrazionali\"\n  ]\n },\n {\n  \"id\": \"features-shape-marked-small-points\",\n  \"role\": \"features\",\n  \"name\": \"Shape-marked small points\",\n  \"shape\": \"split\",\n  \"tags\": [\n   \"object-led\",\n   \"quiet\"\n  ],\n  \"directions\": [\n   \"one-motif\",\n   \"hero-object\",\n   \"product-performs\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"For the many minor points that do not deserve a row each. Columns 1–5: one photograph inside a single large shape taken from the subject's own geometry (a circle, an arch, a chamfered block), made with clip-path or border-radius, about 78svh tall and pushed 12% past the section's left edge so the viewport crops it. Columns 7–12: the heading, two to four words at 40–48px, then 56px lower a grid of eight to twelve points in three columns with 40px column gaps and 44px row gaps, no cells and no fills. Each point is a title at 17px medium preceded by the same shape drawn at cap height (0.7em, flat fill, inline SVG or a styled span), then two lines at 15px in the soft ink. The small shapes take a different palette colour per column, which is the only colour on the right side.\",\n  \"mobile\": \"The shaped photograph comes first, 82vw wide, cropped by the left edge and no taller than 60svh. The heading follows at 30px. Points become one column with 28px between them; the small shape hangs in the margin to the left of each title, so titles and text share one edge.\",\n  \"seenIn\": [\n   \"opl-dabbit\",\n   \"aww-sstr-friction-reduction\"\n  ]\n },\n {\n  \"id\": \"showcase-two-giant-words-compared\",\n  \"role\": \"showcase\",\n  \"name\": \"Two giant words compared\",\n  \"shape\": \"statement\",\n  \"tags\": [\n   \"type-led\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"type-only-statement\",\n   \"editorial-report\",\n   \"loud-flat-poster\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"No photographs: the thing shown is a pair of words, characters or figures that make the point by comparison (before and after, input and output, ours and the usual). At the top of the section, on one row: the heading, two to four words at 28–36px, at the left margin, and a paragraph of up to 60 words at 17px starting at column 7. Then 12vh of space. Below, two specimens side by side, one starting on column 1 and one on column 7, each set at clamp(180px, 34vw, 520px) with leading 0.8, so each fills about half the viewport's width. The section has a fixed height and overflow: hidden, so its bottom edge cuts both specimens at roughly 60% of their height. One short caption at 16px sits above the top-left of each specimen, naming it. Both specimens share one ink; the difference is in the letterforms or values, not in colour.\",\n  \"mobile\": \"Heading first, then the paragraph, at full width. The two specimens stack, each at 62vw type size in its own 38svh box with overflow hidden so the lower part is cut. Captions sit above each box at 15px. The second box takes the inverse colours of the first.\",\n  \"seenIn\": [\n   \"aww-pp-neue-montreal\"\n  ]\n },\n {\n  \"id\": \"showcase-two-objects-two-fields\",\n  \"role\": \"showcase\",\n  \"name\": \"Two objects, two fields\",\n  \"shape\": \"split\",\n  \"tags\": [\n   \"object-led\",\n   \"colour-field\"\n  ],\n  \"directions\": [\n   \"specimen-catalogue\",\n   \"hero-object\",\n   \"colour-chapters\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Two panels side by side, each 50vw wide and 92svh tall, in two different flat tones from the palette, meeting on a clean vertical edge with no gap. Each panel is dominated by one cut-out object photograph scaled to 130–150% of the panel's width and positioned so the panel's top edge crops it: the reader sees the lower two-thirds of the object, very close. On light panels use mix-blend-mode: multiply to lose a white studio background. Along the bottom of each panel, 28px in from the edges, one row: the name at 20px medium and a price or fact at 17px on the left; on the right, two small rectangular actions, one filled with ink and one with paper. Nothing sits in the middle of a panel. The heading, two to four words at 32–40px, is set at the top-left of the first panel only, in the empty corner beside the object.\",\n  \"mobile\": \"Panels stack, each 78svh tall, the object scaled to 150% of the width and cut by the top and right edges. The bottom row becomes two lines: name and fact, then the two actions side by side at full width. The heading sits top-left on the first panel at 26px.\",\n  \"seenIn\": [\n   \"aww-noho\"\n  ]\n },\n {\n  \"id\": \"showcase-object-in-front-of-type\",\n  \"role\": \"showcase\",\n  \"name\": \"Object in front of type\",\n  \"shape\": \"statement\",\n  \"tags\": [\n   \"object-led\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"hero-object\",\n   \"borrowed-category\",\n   \"loud-flat-poster\",\n   \"sentence-as-layout\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Type and object share one space instead of sitting side by side. Three or four lines of display type, one or two words each, are stacked flush left at clamp(72px, 9vw, 150px) with leading 0.88, starting on the left margin and allowed to leave the right edge (white-space: nowrap; overflow: hidden on the section). The lines step through tones of one ink: one at 45%, one at full strength, the rest at 18%. The object photograph, a cut-out or a studio shot blended with multiply, is absolutely positioned over the upper right of the stack at 40–46vw wide, rotated no more than 6 degrees and above the type in the stacking order, so it hides parts of three or four letters. Under the stack, in columns 8–12, a two-paragraph block at 20px gives the facts. The full-strength line is the heading; nothing sits above it.\",\n  \"mobile\": \"Type drops to 15vw and still runs off the right edge. The object sits at 78vw wide, overlapping the last two lines from below instead of from the right, and is cropped by the right edge. The facts block follows at full width and 17px.\",\n  \"seenIn\": [\n   \"aww-the-watch\",\n   \"opl-aevion\",\n   \"aww-coffeetech-r\"\n  ]\n },\n {\n  \"id\": \"showcase-band-of-unequal-panels\",\n  \"role\": \"showcase\",\n  \"name\": \"Band of unequal panels\",\n  \"shape\": \"strip\",\n  \"tags\": [\n   \"photo-led\"\n  ],\n  \"directions\": [\n   \"place-carries-it\",\n   \"uneven-photographs\",\n   \"name-as-monument\",\n   \"editorial-report\",\n   \"dark-room\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A modest heading, then one wide band of pictures. The heading, two to four words at 36–44px, starts at column 3, left of centre, with 64px beneath it. The band spans the full viewport width edge to edge and is 68svh tall: four photographs standing side by side with no gaps and deliberately unequal widths, a flex row with flex-grow values of 5, 2, 3 and 2. Each panel is cropped with object-fit: cover to a tall slice, so the band reads as one folded view. The first panel carries a two-line title at 28px in paper colour at its top-left, 24px in, over a neutral scrim that covers only that corner. Hovering a panel raises its flex-grow to 6 over 500ms while the others give way; without hover the widths simply stay. One caption line at 16px sits under the band at the left margin.\",\n  \"mobile\": \"The heading sits on the margin at 28px. The band becomes a two-by-two block with no gaps, 84svh tall in total: the first row split 64/36 and the second 36/64, so the slices stay unequal. The title stays on the first panel. No hover behaviour.\",\n  \"seenIn\": [\n   \"aww-white-desert\",\n   \"aww-tengile-malamala-collection\"\n  ]\n },\n {\n  \"id\": \"showcase-close-up-with-column-card\",\n  \"role\": \"showcase\",\n  \"name\": \"Close-up with column card\",\n  \"shape\": \"full-bleed\",\n  \"tags\": [\n   \"photo-led\",\n   \"object-led\"\n  ],\n  \"directions\": [\n   \"hero-object\",\n   \"place-carries-it\",\n   \"dark-room\",\n   \"borrowed-category\",\n   \"pinned-poster\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A full-bleed close-up photograph, 100vw by 100svh, with nothing over most of it. A four-column grid lies on top. One solid card in the ink colour, exactly one grid column wide (about 22vw) and 52svh tall, sits in the second column, vertically centred. Inside it, centred: the item's name at 30–36px, a variant line at 17px, the price or key fact at 17px, a small 3:2 photograph of the whole object (the card shows the whole, the background shows the detail), and at the foot a square-cornered action filling the card's width. The card is opaque, radius 0–6px, with no blur. When the section presents two or three items, each gets its own full-bleed frame and its card moves one column to the right each time, so position carries the sequence. The first card's name is the section heading.\",\n  \"mobile\": \"The photograph fills 100svh, cropped to its most detailed area. The card becomes a full-width block docked to the bottom, 46svh tall, left-aligned inside with 20px padding; the small whole-object photograph sits to the right of the name at 96px wide.\",\n  \"seenIn\": [\n   \"aww-longbow\"\n  ]\n },\n {\n  \"id\": \"showcase-live-demo-with-controls\",\n  \"role\": \"showcase\",\n  \"name\": \"Live demo with controls\",\n  \"shape\": \"split\",\n  \"tags\": [\n   \"ui-led\",\n   \"quiet\"\n  ],\n  \"directions\": [\n   \"product-performs\",\n   \"quiet-instrument\",\n   \"dense-tiles\"\n  ],\n  \"needs\": [\n   \"product-ui\"\n  ],\n  \"blueprint\": \"One filled panel, 680–760px wide and about 640px tall, radius 12px, in a tone clearly darker or lighter than the ground, placed on the text column's left edge or centred, with at least 15vh of empty ground above and below. The panel is split 62/38 into two flat areas that differ by one tone. Left area: the product doing its job on real content at true size. Right area: a narrow column of working controls, six to nine stacked rows 44px tall, each with a name at 14px on the left and a slider, toggle or value on the right; changing one changes the demonstration at once. A text link sits in the panel's bottom-left corner. The heading, two to four words at 24–32px, sits above the panel on its left edge with one sentence at 16px; under the panel, one line of start instruction.\",\n  \"mobile\": \"The panel fills the width. The demonstration takes the top at 4:3; the controls follow beneath as full-width rows 52px tall, only the four most telling ones, with a text link that reveals the rest. Heading and sentence sit above at 24px and 16px.\",\n  \"seenIn\": [\n   \"opl-dialkit\",\n   \"opl-textmode-overlay\"\n  ]\n },\n {\n  \"id\": \"showcase-one-frame-three-distances\",\n  \"role\": \"showcase\",\n  \"name\": \"One frame, three distances\",\n  \"shape\": \"pinned\",\n  \"tags\": [\n   \"photo-led\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"pinned-poster\",\n   \"hero-object\",\n   \"dark-room\",\n   \"sentence-as-layout\",\n   \"place-carries-it\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A wrapper 300vh tall holds a sticky stage of 100svh. On the stage one frame is centred: 30vw wide at 4:5, square corners, overflow hidden. Inside it the same photograph is shown at three distances as the reader scrolls: the whole subject, then scaled to 180% toward one detail, then to 320% on a second detail (transform: scale with a transform-origin per stage, 700ms ease, switched by IntersectionObserver on three invisible markers). The sentence is delivered in halves: its first two or three words sit above the frame at clamp(56px, 8vw, 130px), centred; the last words arrive below the frame at the second stage, overlapping the frame's bottom edge by 0.3em. At the third stage one caption of 28ch at 17px appears to the right of the frame, top-aligned. The two halves together are the heading and stay within two lines.\",\n  \"mobile\": \"The frame grows to 70vw at 4:5 and stays sticky at centre. The first half of the sentence sits above it at 13vw, the second half below it at the same size. The third-stage caption appears under the sentence at 16px, centred.\",\n  \"seenIn\": [\n   \"aww-vero-new-york\",\n   \"aww-illoca\",\n   \"opl-screentune\"\n  ]\n },\n {\n  \"id\": \"showcase-one-image-across-tiles\",\n  \"role\": \"showcase\",\n  \"name\": \"One image across tiles\",\n  \"shape\": \"mosaic\",\n  \"tags\": [\n   \"photo-led\",\n   \"dense\"\n  ],\n  \"directions\": [\n   \"dense-tiles\",\n   \"contact-sheet\",\n   \"editorial-report\",\n   \"colour-chapters\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One photograph is cut across a board of tiles. A grid of six columns and four rows with 8px gaps spans the full width between 12px margins; every tile is square (aspect-ratio: 1). Each tile shows its own piece of the same image: set the photograph as every tile's background at background-size: 600% 400% and step background-position by column and row, so the picture reads whole through the gaps. Five of the twenty-four tiles are swapped for flat colour tiles from the palette, never two adjacent: one holds the heading (two to four words at 2.6vw, top-left, 16px padding), three hold one fact each at 18px, one holds the action. On hover a tile's piece scales to 108% inside its own clip. Choose a photograph with one clear subject, so the board is legible at a glance.\",\n  \"mobile\": \"Three columns by six rows with 6px gaps, the photograph re-cut at background-size 300% 600% from a portrait crop. Four colour tiles only; the heading tile spans two columns in the top row with the heading at 6vw. Facts drop to 15px.\",\n  \"seenIn\": [\n   \"aww-produx-design\",\n   \"aww-ai-in-design-report-2026\"\n  ]\n },\n {\n  \"id\": \"showcase-frame-run-one-lifted\",\n  \"role\": \"showcase\",\n  \"name\": \"Frame run, one lifted\",\n  \"shape\": \"strip\",\n  \"tags\": [\n   \"photo-led\",\n   \"quiet\"\n  ],\n  \"directions\": [\n   \"contact-sheet\",\n   \"uneven-photographs\",\n   \"specimen-catalogue\",\n   \"quiet-instrument\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Columns 1–3 are a nearly empty column: the heading (two to four words at 24–28px) at the top, a link under it, and one or two short notes at 15px much further down, each level with the frame it describes. Columns 4–12 hold a run of six to eight frames of the same subject at one fixed height of 30vh, with natural widths and 6px gaps: the whole view, a tight crop of the same thing, a detail, the reverse side. The run is allowed to leave the right edge. One frame is lifted out of the row: shown at 2.2 times the row height with its bottom aligned to the row's bottom (flex row, align-items: end), so it stands above the others. Under each frame, at 15px: a name on the left and a single fact on the right. Square corners, no captions on the images.\",\n  \"mobile\": \"The heading and link sit on top. The lifted frame comes first at full width. The rest of the run scrolls sideways beneath it at a fixed height of 34vw with 4px gaps and scroll-snap, bleeding off the right edge. Notes are listed under the run at 15px.\",\n  \"seenIn\": [\n   \"aww-serotoninn\",\n   \"aww-butter\",\n   \"aww-no-art\"\n  ]\n },\n {\n  \"id\": \"showcase-output-slips-along-the-edge\",\n  \"role\": \"showcase\",\n  \"name\": \"Output slips along the edge\",\n  \"shape\": \"full-bleed\",\n  \"tags\": [\n   \"photo-led\",\n   \"object-led\"\n  ],\n  \"directions\": [\n   \"page-is-the-object\",\n   \"borrowed-category\",\n   \"place-carries-it\",\n   \"loud-flat-poster\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"For subjects whose result is a piece of text or paper: a receipt, a note, a ticket, a written line. A full-bleed photograph, 100vw by 96svh, sets the scene. In the upper centre, left-aligned in a column starting at 18% of the width, two short paragraphs in paper colour at 28–32px, the first opening with the heading's two to four words; a neutral scrim sits behind that column only. Along the bottom, six paper-coloured slips stand side by side across the full width with 12px gaps, each a filled rectangle of a different height (between 26 and 44svh), their lower ends cut off by the section's bottom edge. Two or three of the slips, not all, are tilted by 1–2 degrees. Each slip carries a sample of real output in the text face at 15px: a bold first line, a divider made of typed characters, then four to eight lines.\",\n  \"mobile\": \"The photograph is 100svh. The paragraphs sit in the top third at 22px. Only three slips show, each 30vw wide, standing along the bottom at different heights, and the row scrolls sideways to reveal the rest. Slip text stays at 14px; do not scale it down.\",\n  \"seenIn\": [\n   \"opl-poetry-camera\"\n  ]\n },\n {\n  \"id\": \"showcase-object-on-a-disc\",\n  \"role\": \"showcase\",\n  \"name\": \"Object on a disc\",\n  \"shape\": \"index\",\n  \"tags\": [\n   \"object-led\",\n   \"colour-field\"\n  ],\n  \"directions\": [\n   \"one-motif\",\n   \"specimen-catalogue\",\n   \"hero-object\",\n   \"colour-chapters\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One section about a viewport tall on a plain ground. A flat filled disc 64vh across, in one palette colour, sits with its centre at 58% of the width; swap the disc for the subject's own shape if it has one. A cut-out object photograph stands in front of it, centred on it, about 78% of the disc's height and breaking the disc's outline at the top. Bottom-left, starting on the margin and ending level with the disc's lower edge: a vertical list of four to six item names at clamp(28px, 2.9vw, 44px), leading 1.15. The selected name is in full ink and the rest at 25%; choosing a name swaps the object (300ms crossfade) and the disc's colour. The heading, two to four words at the same size as the names but in the soft ink, is the first line of that list. One fact about the selected item sits at the disc's right edge at 17px.\",\n  \"mobile\": \"The disc comes first, 86vw across and centred, with the object in front. The names follow as a single sideways-scrolling line at 26px with 24px gaps, the selected one in full ink. The fact sits under the names at 16px.\",\n  \"seenIn\": [\n   \"aww-cominvi\",\n   \"opl-tara\"\n  ]\n },\n {\n  \"id\": \"showcase-square-plate-spare-text\",\n  \"role\": \"showcase\",\n  \"name\": \"Square plate, spare text\",\n  \"shape\": \"split\",\n  \"tags\": [\n   \"colour-field\",\n   \"photo-led\"\n  ],\n  \"directions\": [\n   \"split-stage\",\n   \"page-is-the-object\",\n   \"colour-chapters\",\n   \"editorial-report\",\n   \"one-motif\",\n   \"name-as-monument\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One flat field split 50/50, at least 88svh tall. Left half: a single square photograph filling the half's width minus 40px margins, vertically centred, square corners. A large simple shape may be laid over it to turn the photograph into the object it stands for: a ring 86% of its width with a 6px stroke and a small solid dot at the centre makes a record; a notch cut by clip-path makes a ticket stub. Right half, a flex column with space-between: at the top a row of three plain text tabs at 18px (editions, years, variants), the active one in full ink and the others at 40%; in the middle the title, two to four words at 32–40px bold, with a 34ch description 48px below; along the bottom two filled rectangular cells side by side, each half the column wide and 72px tall, acting as the two actions, one in ink and one a tone off the field.\",\n  \"mobile\": \"The square photograph comes first at full width with 16px margins. The tabs sit under it as one row at 17px. Then the title at 28px, the description, and the two action cells stacked, each full width and 60px tall.\",\n  \"seenIn\": [\n   \"aww-paul-kalkbrenner\"\n  ]\n },\n {\n  \"id\": \"how-it-works-lines-that-step-across\",\n  \"role\": \"how-it-works\",\n  \"name\": \"Lines that step across\",\n  \"shape\": \"statement\",\n  \"tags\": [\n   \"type-led\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"type-only-statement\",\n   \"sentence-as-layout\",\n   \"loud-flat-poster\",\n   \"editorial-report\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"The sequence is written, not counted. Four lines of display type, one stage per line, each a complete short clause that begins with its order word: 'First you send it.' 'Then we take it apart.' 'You choose one.' 'It ships on Friday.' Set at clamp(36px, 4.6vw, 76px), leading 1.0, one line each. The first line starts on column 1 and each following line starts two columns further right (grid-column-start 1, 3, 5, 7), so the block descends as a staircase and the eye follows the diagonal. Under each line, on that line's own left edge and 12px below, a sentence of up to 34ch at 17px in the soft ink. 56px between stages. The last line may take the accent colour as the single emphasis. The first line serves as the heading; there is no title above. Leave the columns to the left of the final stage empty.\",\n  \"mobile\": \"Lines drop to 8.4vw and may wrap onto a second line. The staircase becomes a smaller indent of 6vw per stage, so the fourth line starts 18vw in. Each sentence sits under its line at 16px on the same indent. 40px between stages.\",\n  \"seenIn\": [\n   \"opl-rendez-vous-franceclat\"\n  ]\n },\n {\n  \"id\": \"how-it-works-photographs-down-a-diagonal\",\n  \"role\": \"how-it-works\",\n  \"name\": \"Photographs down a diagonal\",\n  \"shape\": \"stack\",\n  \"tags\": [\n   \"photo-led\",\n   \"quiet\"\n  ],\n  \"directions\": [\n   \"uneven-photographs\",\n   \"place-carries-it\",\n   \"dark-room\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Three stages, three photographs of different sizes placed along a falling diagonal on the 12-column grid. Stage one: a 3:4 portrait in columns 1–4. Stage two: a 1:1 square in columns 6–8, its top edge 220px lower than the first photograph's top. Stage three: a 16:10 landscape in columns 8–12, starting 180px below the bottom of the second. Each stage's text sits in the gap the stagger leaves: a paragraph of up to 36ch at 17px, top-aligned with its photograph and placed in the columns to its right (to its left for the third). Each paragraph opens with a bold run-in phrase that carries the order: 'On the first day', 'A week later', 'By the end'. Square corners; no arrows or connecting marks. The heading, two to four words at clamp(36px, 4vw, 64px) in a light weight, sits alone in columns 7–12 at the very top, level with the first photograph's top edge.\",\n  \"mobile\": \"The diagonal becomes alternating widths: the first photograph at 100%, the second at 62% flush right, the third at 78% flush left. Each paragraph follows its photograph on that photograph's left edge at 16px. 56px between stages. The heading sits above at 30px.\",\n  \"seenIn\": [\n   \"opl-fynza\",\n   \"opl-the-queue\"\n  ]\n },\n {\n  \"id\": \"how-it-works-drag-row-of-moments\",\n  \"role\": \"how-it-works\",\n  \"name\": \"Drag row of moments\",\n  \"shape\": \"carousel\",\n  \"tags\": [\n   \"photo-led\"\n  ],\n  \"directions\": [\n   \"contact-sheet\",\n   \"place-carries-it\",\n   \"uneven-photographs\",\n   \"page-is-the-object\",\n   \"dark-room\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A story told left to right. Top row: the heading, two to four words at 28–36px, at the left margin; at the right margin two solid square buttons, 48px each, for back and forward. Directly beneath, a solid bar 6px tall spans the full width in a soft tone, with a full-ink segment showing how far the row has been scrolled. Then the row itself: six to nine columns, each 280px wide with 32px gaps, in a horizontally scrolling flex container with scroll-snap that bleeds off both viewport edges. Every column reads top to bottom: a one-line caption at 18px bold that carries the order in words ('We met', 'Two winters on', 'The move'), three lines at 15px in the soft ink, then 80–140px of empty space that varies per column, then a 4:5 portrait photograph. Because the spaces vary, the photographs' top edges rise and fall along the row.\",\n  \"mobile\": \"Columns are 72vw wide with 16px gaps, so the next one always shows at the right edge. The buttons are dropped; the 6px progress bar stays under the heading. The empty space inside columns shrinks to 32–64px but still varies from column to column.\",\n  \"seenIn\": [\n   \"opl-sarah-matt-wedding\",\n   \"aww-no-art\"\n  ]\n },\n {\n  \"id\": \"how-it-works-pinned-fragment-changing-state\",\n  \"role\": \"how-it-works\",\n  \"name\": \"Pinned fragment, changing state\",\n  \"shape\": \"pinned\",\n  \"tags\": [\n   \"ui-led\",\n   \"quiet\"\n  ],\n  \"directions\": [\n   \"product-performs\",\n   \"quiet-instrument\",\n   \"split-stage\",\n   \"pinned-poster\"\n  ],\n  \"needs\": [\n   \"product-ui\"\n  ],\n  \"blueprint\": \"Two columns. Right, columns 7–12: a stage that is position: sticky; top: 14vh, holding one fragment of the real interface at true size on a single flat stage colour, about 520px square. Left, columns 1–5: three statements, each in its own block 80vh tall, so one is in view at a time. A statement is a two-line sentence at 28–32px that begins with its order word ('Paste a link.', 'Then pick the parts you want.', 'Share it when it looks right.') plus one supporting line at 16px. The statement nearest the viewport's centre is in full ink; the others sit at 30%. As each statement becomes active the fragment changes to the matching state: an empty field, a filled list with two rows selected, a finished result with its confirmation. Build the states in HTML and switch a class; do not swap screenshots. The heading, two to four words at 24–28px, sits above the first statement.\",\n  \"mobile\": \"The stage is sticky at the top, 46svh tall, the fragment fitted by cropping to its active region, not by shrinking its text. Statements scroll beneath it in blocks 60svh tall at 22px. The stage releases after the third statement.\",\n  \"seenIn\": [\n   \"opl-juggle\",\n   \"aww-cerebrium\",\n   \"opl-vessa\"\n  ]\n },\n {\n  \"id\": \"how-it-works-itinerary-on-a-slip\",\n  \"role\": \"how-it-works\",\n  \"name\": \"Itinerary on a slip\",\n  \"shape\": \"table\",\n  \"tags\": [\n   \"object-led\",\n   \"type-led\"\n  ],\n  \"directions\": [\n   \"page-is-the-object\",\n   \"type-only-statement\",\n   \"split-stage\",\n   \"quiet-instrument\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"The process is printed as an itinerary or receipt. One paper-coloured slip 420–480px wide stands on a contrasting flat ground at columns 7–11; its bottom edge is a zigzag cut with clip-path and its top edge is straight. The heading, two to four words at clamp(40px, 4.4vw, 68px), sits in columns 1–5 with a 30ch paragraph, top-aligned with the slip. On the slip, in the text face at 16px with tabular figures: stages grouped under time headings that carry the order ('Monday', 'Midweek', 'Friday'), each heading in bold with 28px above it. Under a heading, two to four rows; each row has what happens on the left, a duration or time on the right, and a leader of round 4px dots between. The final row is inverted, paper-coloured text on a full-width ink bar 44px tall, and states the result: what the reader holds at the end and the total time.\",\n  \"mobile\": \"The heading and paragraph come first. The slip follows at full width minus 16px margins, keeping its zigzag bottom edge. Rows keep left text, dots and right value on one line; long descriptions wrap under the left text. The inverted final row stays full width.\",\n  \"seenIn\": [\n   \"opl-the-content-architecture\",\n   \"opl-lennys-newsletter-product-pass\"\n  ]\n },\n {\n  \"id\": \"how-it-works-accordion-of-tinted-panels\",\n  \"role\": \"how-it-works\",\n  \"name\": \"Accordion of tinted panels\",\n  \"shape\": \"strip\",\n  \"tags\": [\n   \"colour-field\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"colour-chapters\",\n   \"one-motif\",\n   \"loud-flat-poster\",\n   \"dense-tiles\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A two-column introduction, then one horizontal accordion. Introduction: the heading, two to four words at clamp(36px, 4vw, 60px), in columns 1–5; one paragraph at 18px in columns 7–11. 64px below, a flex row across columns 1–12, 520px tall, of four to six panels with no gaps. The open stage is a panel taking about 58% of the width; the rest are vertical slivers sharing what remains. Order is carried by colour: the first stage is the darkest tone of one hue and each later stage is a lighter flat tint of it, so the row reads dark to light from left to right. A sliver shows only its stage name, rotated 90 degrees and reading upward, at 20px bold, anchored to its bottom-left. The open panel shows the name at 40px top-left, a 36ch paragraph at 18px bottom-left and, optionally, one photograph in its right half. Clicking a sliver opens it (flex-basis transition, 450ms).\",\n  \"mobile\": \"The accordion turns vertical: stages stack at full width as bars 64px tall in the same dark-to-light order, names set horizontally at 18px. The open stage expands to its content height with the paragraph at 17px. The first stage is open by default.\",\n  \"seenIn\": [\n   \"aww-white-desert\"\n  ]\n },\n {\n  \"id\": \"how-it-works-tiles-that-grow\",\n  \"role\": \"how-it-\n\n<!-- [TRUNCATED AT 50KB] -->","skills/taste-skill/library/sites.json":"[\n {\n  \"id\": \"aww-pp-neue-montreal\",\n  \"name\": \"PP Neue Montreal\",\n  \"url\": \"https://neuemontreal.com/\",\n  \"source\": \"Awwwards Site of the Day\",\n  \"kind\": \"other\",\n  \"score\": 8.6,\n  \"idea\": \"A typeface specimen dressed as a vintage city travel guide: the font named after Montreal is sold through guidebook titling, postcards and old tourist footage.\",\n  \"mood\": [\n   \"bold\",\n   \"playful\",\n   \"retro-modernist\",\n   \"typographic\",\n   \"confident\"\n  ],\n  \"archetype\": \"giant-wordmark\",\n  \"hero\": \"Grainy coral-red field. Top row: a monogram in a pale pill at left, a pale-grey pill nav with seven links centred, a black pill button at right. Below at the left margin, a two-line white bold title at about 4.5vw; opposite it, a ring of repeated monograms set around a circle like a stamp. Three full-width black hairlines cut the field into bands: a two-line intro sentence at ~1.6vw sits in the second, and the typeface name fills the third in black bold at ~17vw, two lines, tight leading, 60% of the width. A 4:3 clip of 1960s street footage is inset bottom-right, 29% wide, bottom-aligned with the name.\",\n  \"type\": \"PP Neue Montreal only: Bold for display with -0.01em tracking and leading near 0.9, Text Regular 16px for body and lists. Sizes leap from 16px to 144px headings to a ~240px name; one section enlarges a single lowercase letter to viewport height.\",\n  \"colour\": \"#ed4b44 #1a1a1a #f0e7d4 #18bc42 #b5b5b5 #f2c21a — Each chapter takes a flat field (coral red, near-black, cream, green) with black or cream type; one headline colours every word differently. Warm, print-poster feel with visible grain.\",\n  \"imagery\": \"Archive 1960s city footage, saturated vintage postcards, a handwritten postcard back, and rotated specimen posters and stamp sheets scattered around a headline. All square-cornered and inset, never full-bleed.\",\n  \"layout\": \"24px side margins and full-width hairlines marking bands. Content is left-anchored in three or four columns split by vertical hairlines; chapters alternate between tabular lists, a scattered collage, a centred statement and a giant glyph comparison. A pill nav stays pinned.\",\n  \"sections\": [\n   {\n    \"role\": \"intro\",\n    \"description\": \"Near-black screen split by a vertical hairline at about 75% width. Left: a three-line small heading at the top margin, then a five-line bold oblique headline at ~6vw in which each line is indented further right like a staircase and each word takes its own colour (green, cream, grey, yellow, blue, orange). Right narrow column: two stacked postcards, one saturated photo card and one cream handwritten card with a stamp. A tiny section label sits bottom-left.\"\n   },\n   {\n    \"role\": \"other\",\n    \"description\": \"A dark band of pure tabular type. A body paragraph occupies column one; weight names stack as tight single-line lists in two further columns divided by vertical hairlines. Below, a small label over a full-width rule introduces a two-column timeline: years stacked at the left margin, release notes stacked from the centre line behind a short vertical rule. One text size, leading near 1.0, no decoration at all.\"\n   },\n   {\n    \"role\": \"gallery\",\n    \"description\": \"Dark full-viewport stage with a three-line cream headline at ~4vw placed dead centre. Around it eight or nine specimen artefacts (a stamp sheet, a green poster with a blue numeral, a grey flag chart, a rainbow ticket grid, concentric colour squares) are each rotated 10 to 30 degrees and arranged on a loose ring, several cropped by the viewport edge, as if tossed on a table.\"\n   },\n   {\n    \"role\": \"showcase\",\n    \"description\": \"Cream field. A caption row at the top: a two-line label at the left margin and a five-line paragraph starting at about 55% width. Then a full-width rule carrying a tiny label at each end naming the two cuts. Below it, two black lowercase letters, each roughly half the viewport wide and cropped by the bottom edge, one from each cut, so the reader compares shapes at poster scale.\"\n   }\n  ],\n  \"steal\": [\n   \"Give a product page a borrowed genre (here a tourist guidebook) and let that genre dictate titles, imagery and chapter names.\",\n   \"Cut a flat colour hero into bands with full-width hairlines and set the name at ~17vw in the bottom band beside a small inset film clip.\",\n   \"Scatter rotated print artefacts on a loose ring around a centred headline and let several crop off the viewport.\"\n  ],\n  \"media\": \"The hero is a red printed cover with paper grain; the real media is small, a 418x316 looping 1960s street clip at the bottom right (about 10% of the viewport) beside a wordmark filling about 60% of the width. Later: a postcard pair in the right half of a split, rotated ephemera orbiting a centred statement, full-bleed photo panels that slide up over the previous chapter, a spine accordion, and a full-bleed vintage photograph overscanned 72px each side; square corners, one video.\",\n  \"motion\": \"Black, then a turning seal of logo letters, then the cover by 4.5s; four hero groups rise 25px and fade over 400ms cubic-bezier(0.44,0,0.56,1) at 200ms steps, settling at about 5.5s though the page loaded in 2.5s. Lenis drives a chain of sticky full-screen chapters: ephemera fly off as a photo panel slides up, a headline steps through weights of the variable cut on scroll, and a single glyph rotates and zooms for about 5 screens; about 390 appear fades run over 400ms on a spring-shaped linear() curve, with no reduced-motion rule.\"\n },\n {\n  \"id\": \"aww-seasats\",\n  \"name\": \"Seasats\",\n  \"url\": \"https://www.seasats.com/\",\n  \"source\": \"Awwwards Site of the Day\",\n  \"kind\": \"physical-product\",\n  \"score\": 8.4,\n  \"idea\": \"Calm, dusk-lit seascapes sell autonomous boats as serene instruments, and the navigation is a column of stacked colour swatches taken from that sea-and-sand palette.\",\n  \"mood\": [\n   \"serene\",\n   \"cinematic\",\n   \"engineered\",\n   \"assured\"\n  ],\n  \"archetype\": \"fullbleed-media-overlay\",\n  \"hero\": \"A 10px white frame surrounds everything. The left 84% is one rounded media panel: a dusk scene of a low, solar-decked vessel centred on mirror-flat water, with two larger hulls cropped by the panel's left and right edges. The headline is centred in the panel's upper third, two lines of white light-weight flared serif at 124px (8.6vw). A wordmark in custom wide techno lettering sits top-left; a white rounded button with mono caps and a dark-green square arrow sits bottom-centre. The right 14% is the menu: a full-height column of stacked flat colour blocks (blush, sage, then four darkening olives), each holding left-aligned 15px links, sub-items numbered 01 to 04.\",\n  \"type\": \"seasonMix, a low-contrast serif-sans hybrid, light weight, sentence case, near-zero tracking, at 124px for the headline and about 40px for statements; seasonSans 16px for body and menu; supplyMono uppercase at 9 to 12px for buttons, tags and footer data.\",\n  \"colour\": \"#a6b3bc #232323 #b7c8be #d6c4b8 #2c3620 #e2832a — Slate blues and lilac greys from the seascapes dominate; the menu adds blush, sage and olive blocks; the footer flips to a burnt-orange and rust scene. Text stays white.\",\n  \"imagery\": \"Photoreal rendered footage of autonomous boats on glassy water at dusk: symmetrical, low horizon, lots of sky, full-bleed after the hero. Small square-cornered inset stills with mono tag labels float over the scene.\",\n  \"layout\": \"Mostly full-viewport scenes with one centred text block each, at top or bottom, and the wordmark fixed top-left. Only the hero uses the framed panel-plus-menu split. A thin vertical progress line runs down the right edge.\",\n  \"sections\": [\n   {\n    \"role\": \"features\",\n    \"description\": \"A pinned full-bleed scene shot from the boat's deck: the hull forms a dark symmetrical wedge rising from the bottom edge to a mast at centre, horizon at one-third. At top-centre six short statements are stacked, centred, at 16px; one is white and the others half opacity, and the highlight steps down the list on scroll. For each, small photo cards (150 to 220px wide, square corners, mono tag on the top edge) appear left and right of the mast.\"\n   },\n   {\n    \"role\": \"intro\",\n    \"description\": \"A full-bleed aerial view of dark teal water with several small vessels scattered across the lower half and a faint horizon near the top. A single two-line statement in the light serif at about 40px sits centred near the bottom edge. Nothing else is on screen except the wordmark top-left and the thin progress line at right.\"\n   },\n   {\n    \"role\": \"footer\",\n    \"description\": \"Colour inverts to a burnt-orange haze over rust-red terrain, with black silhouettes of hulls and a keel hanging from the top edge as if seen from below the surface. Mid-height: mono readouts at left reporting distance scrolled in metres and scroll speed in knots with a one-line quip; a link list at 16px in the centre; mono contact details at right. The wordmark fills the full width at the bottom, white, about 130px tall.\"\n   }\n  ],\n  \"steal\": [\n   \"Build the menu as a full-height column of stacked flat colour blocks sampled from the imagery, grouping links by block colour instead of by rules or headings.\",\n   \"List every claim at once, centred and dimmed, and move a single full-opacity highlight through the list on scroll while supporting images appear around a fixed subject.\",\n   \"Give the footer its own opposite-temperature scene and a live readout of how far and how fast the visitor scrolled, in the product's own units.\"\n  ],\n  \"media\": \"A dusk render of the vessel on still water, as a still, a 3s muted loop and a canvas layered together, fills an inset card at about 84% of the width beside a colour-band nav panel and goes full bleed once scrolled. Then a scroll-scrubbed frame sequence on a sticky stage with labelled photo cards floating at depth, small video thumbnails that grow into full-bleed chapter loops, a WebGL globe rising as a half-sphere from the bottom edge, and sticky product renders that turn with the scroll; 18 images, 6 videos, 8px corners on the hero frame and cards.\",\n  \"motion\": \"The preloader wordmark's seven letters slide up out of their masks at 50ms steps, the framed hero arrives at 1.2s and the title fades in softly, settling after about 5s, and smooth scroll then runs 34 sticky elements with no pins: the flythrough is a scrubbed image sequence, a fixed background layer changes the ground per chapter, and the nav collapses to a slim right-edge rail. Title characters rise on cubic-bezier(.215,.61,.355,1) (the house ease, 17 uses) with durations that shorten by 12ms per character, so the end of a word catches up with its start.\"\n },\n {\n  \"id\": \"aww-ai-in-design-report-2026\",\n  \"name\": \"Ai in Design Report 2026\",\n  \"url\": \"https://stateofaidesign.com/\",\n  \"source\": \"Awwwards Site of the Day\",\n  \"kind\": \"other\",\n  \"score\": 8.4,\n  \"idea\": \"A research report laid out like a colour-blocked print annual: a thermal-blurred video collage on top, an oversized tight grotesk title, and flat orange, lilac, sage and black blocks carrying stats, quotes and chapters.\",\n  \"mood\": [\n   \"editorial\",\n   \"bold\",\n   \"colour-blocked\",\n   \"assured\",\n   \"contemporary\"\n  ],\n  \"archetype\": \"editorial-masthead\",\n  \"hero\": \"The top 53% is a full-width video band: blurred, heat-map-like abstract footage in orange, lilac and sage, overlaid with four or five hard-edged rectangles of the same footage in grey or green, two tagged with tiny mono labels in white boxes. The header sits flush on top: a black logo block at far left, an orange link tab running to 40% of the width, two plain links at right. Below the band, on white: a two-line deck at about 1.4vw on a 1% left margin, and from 42% across a two-line title at 8.3vw, medium weight, tracking -0.06em. Bottom row: mono credit left, scroll cue and arrow aligned to the title column.\",\n  \"type\": \"Beausite Classic, a grotesk with some stroke contrast, in Medium for titles and Regular for text; sentence case, tracking -0.06em at display size. Geist Mono for small uppercase labels. Steps: 8.3vw title, about 5.5vw numerals, about 3vw statements, 16px body, 10px mono. Footer wordmark near 96vw.\",\n  \"colour\": \"#ffffff #000000 #fe7141 #cdabfe #d1ddd3 #f0ff1c — White base with flat blocks of orange, lilac, sage and black assigned to whole modules (stat tiles, quote panels, chapter bands), all drawn from the hero footage. Text is black, or off-white on black.\",\n  \"imagery\": \"Hero: abstract blurred video with a heat-map grade, cut into overlapping rectangles. Body: warm documentary photos and clips of people at desks in wood-lined rooms, square-cornered, butted directly against flat colour blocks with no gap.\",\n  \"layout\": \"1% margins and a recurring column line at about 42% where most headings and text begin. Open white text passages ruled by hairlines alternate with tight mosaics in which photos and colour blocks share edges. Each chapter opens with a full-width colour band.\",\n  \"sections\": [\n   {\n    \"role\": \"proof\",\n    \"description\": \"A full-width hairline, a tiny mono label at the left, then seven black partner logos evenly spaced across the full width in one row with generous padding above and below, closed by a second hairline. Immediately beneath, another mono label and a three-line statement at about 3vw, flush left and occupying only the left half, followed by a full-width photo strip.\"\n   },\n   {\n    \"role\": \"stats\",\n    \"description\": \"A mosaic with no gutters. A photo of two people at a laptop fills the left two-thirds at roughly 1:1; the right third is split into two stacked flat tiles, lilac above and sage below. Each tile carries a large numeral with a plus sign at about 5.5vw in its top-left corner and a two-line caption directly beneath; the rest of the tile is empty colour.\"\n   },\n   {\n    \"role\": \"testimonial\",\n    \"description\": \"Quote module as two abutting blocks: a black block on the left 40% holding only a small name and a mono role caption, and a sage block on the right 60% with the quotation at about 3vw, top-left aligned with empty sage beneath. Directly below, a full-width orange band opens a chapter: hairline at top, a large two-digit number with the chapter word under it at left, a two-line title and small paragraph starting at the 42% column.\"\n   },\n   {\n    \"role\": \"footer\",\n    \"description\": \"Black footer. A row of three small source counts along the top, separated by vertical hairlines, then the report name in off-white heavy type at nearly full viewport width with a trademark sign at its top-right, then the year at the same size right-aligned on a second line. Two small link columns with mono headings sit lower left beside the year; a hairline and one row of credits and partner logos close it.\"\n   }\n  ],\n  \"steal\": [\n   \"Start most headings and text at a fixed column line about 42% across, leaving the left for small decks, credits and chapter numbers.\",\n   \"Butt flat colour tiles directly against a photograph with no gutter and put one large numeral plus two caption lines in each tile's top-left corner.\",\n   \"Take the page's flat block colours from the hero footage so the abstract video and the layout read as one palette.\"\n  ],\n  \"media\": \"A video collage covers 100% of the screen at load and lifts to the top ~53% to uncover the title on white. Below, a documentary photograph two thirds wide in a sticky frame beside stacked colour stat blocks, a pinned deck of colour cards each with a 10s clip docked bottom-left, and a carousel of equal stills running off the right edge: 12 images and 6 muted videos, all square-cornered.\",\n  \"motion\": \"No preloader, but the collage re-cuts itself for about 4s before the title lands. Framer drives the sticky stacking (a 1350px photo frame and three 900px chapter cards that peel away to uncover the next); there is no split text, links change colour over .2s cubic-bezier(.44,0,.56,1), and one panel slides 610px in over 500ms cubic-bezier(0.44,0,0.37,1).\"\n },\n {\n  \"id\": \"aww-house-of-honey-1\",\n  \"name\": \"House of Honey\",\n  \"url\": \"https://www.houseofhoney.com/\",\n  \"source\": \"Awwwards Site of the Day\",\n  \"kind\": \"studio-portfolio\",\n  \"score\": 8.4,\n  \"idea\": \"A block-heavy wordmark pierced by a hairline script: the bold-against-delicate contrast is repeated at every scale, with giant pink script behind quiet serif statements.\",\n  \"mood\": [\n   \"glamorous\",\n   \"warm\",\n   \"playful\",\n   \"editorial\",\n   \"confident\"\n  ],\n  \"archetype\": \"giant-wordmark\",\n  \"hero\": \"Top 42% is a flat blush-pink band; the bottom 58% is a full-bleed photograph of a bright living room, arched window on the centre axis, butting against the band with no margin. A tiny nav row sits at the very top with 8px side margins: block logo glyph and five links left, contact link with a small square arrow box far right. The wordmark fills the width edge to edge: two words in ultra-black extended caps, about 120px cap height, dark aubergine, with a hairline script 'of' 230px tall between them, overshooting above and below. Directly beneath, two two-line serif uppercase taglines at 31px, one flush left, one flush right.\",\n  \"type\": \"Wordmark in ultra-black extended caps; statements in noeText serif, uppercase, 31–40px, tight tracking; nav and captions in neueHaasGrotesk around 14px; 'canora' hairline script for the connecting word and for cropped background words at 37vw. Three contrasting voices, each with one job.\",\n  \"colour\": \"#edccbe #331917 #0e0e0e #f26fcb #ffffff — Blush pink and dark aubergine-brown alternate as full fields and as each other's text colour. Hot pink appears only in the oversized script and a 2px divider. Photographs bring saturated colour.\",\n  \"imagery\": \"Editorial interior photography, saturated and daylight-lit. Hero is a full-bleed landscape crop; projects are portrait crops about 5:6 in a three-column grid with 4px gutters and square corners.\",\n  \"layout\": \"Edge-to-edge with 8px outer margins. Typographic sections (small centred label, serif statement, cropped giant script) alternate with a three-column image grid. Blush and brown fields swap each section; hairline link rows close blocks. The footer is a full-width logo glyph.\",\n  \"sections\": [\n   {\n    \"role\": \"intro\",\n    \"description\": \"Dark aubergine field under the hero photo, separated by a 2px hot-pink line. A small sans label centred, then a three-line centred serif uppercase statement at about 31px in blush, 45% of the width. Behind it a hot-pink script phrase set near 37vw runs off both sides and is cut by the section's bottom edge, its ascenders rising into the statement. A smaller serif line follows.\"\n   },\n   {\n    \"role\": \"other\",\n    \"description\": \"Title card before the project grid. Blush field, nearly empty screen. A small label and a one-line serif uppercase heading about 40px sit centred at 55% height. The giant pink script returns, cropped by the bottom edge so only its top half shows and running off both sides.\"\n   },\n   {\n    \"role\": \"work\",\n    \"description\": \"Three columns edge to edge with 4px gutters and 8px outer margins. Portrait photos about 500×580px, square corners. Under each: an uppercase sans title at 14px and a grey line of GPS coordinates. Two rows, then a full-width hairline row with a text link left and a small square arrow box at the far right.\"\n   },\n   {\n    \"role\": \"footer\",\n    \"description\": \"Brown field. The logo glyph is enlarged to full width and about a third of the screen: blush rectangles and quarter-circle arcs with 4px gaps, forming an abstract monogram. Below: four columns of small links, a hairline, two addresses in the first two columns, another hairline, then copyright left and a small blush button right.\"\n   }\n  ],\n  \"steal\": [\n   \"Set a wordmark edge to edge in ultra-heavy extended caps and thread a hairline script connecting word through it that overshoots the cap height both ways.\",\n   \"Use an oversized script word in one hot accent colour as a cropped background layer behind small, calm serif statements.\",\n   \"Split a tagline into two halves, flush left and flush right on the same baseline under the wordmark, instead of centring it.\"\n  ],\n  \"media\": \"The lower 58% of the fold is a full-bleed interior photograph that continues for one full viewport as a five-image crossfading slideshow with a pink progress line on its bottom edge. Below: a three-up grid of 4:5 project tiles with 8px gutters sliding over a giant script marquee, a full-bleed tinted feature photograph with its title docked bottom-left, a full-bleed photograph with an inset colour card, and one giant cropped letterform as the footer's picture, the photographs oversized to 110-170% of their frames for drift and no video anywhere.\",\n  \"motion\": \"There is no visible preloader and the page is whole at 400ms; under Lenis, blocks rise 8px and fade in over 800ms ease-out at 0-260ms staggers (39 WAAPI calls), slideshow crossfades take 600ms cubic-bezier(0.7,0,0.25,1), the oversized photographs drift, and script marquees run on CSS time (90-122s per pair). Page changes use a 1s view transition on the same curve; nothing pins, and there is one reduced-motion rule.\"\n },\n {\n  \"id\": \"aww-white-desert\",\n  \"name\": \"White Desert\",\n  \"url\": \"https://white-desert.com/\",\n  \"source\": \"Awwwards Site of the Day\",\n  \"kind\": \"hospitality\",\n  \"score\": 8.4,\n  \"idea\": \"One word, the destination, set a third of the screen tall over footage like a film title card; sheer scale stands in for remoteness.\",\n  \"mood\": [\n   \"cinematic\",\n   \"epic\",\n   \"luxurious\",\n   \"cold\",\n   \"restrained\"\n  ],\n  \"archetype\": \"bottom-anchored-type\",\n  \"hero\": \"Full-bleed video (the view from an aircraft window over an ice shelf, darkly vignetted by the window frame) fills the viewport. Faint vertical hairlines divide it into six columns. Top-left, three outlined rectangular nav buttons about 120 by 40px with 6px gaps; top-right, two more; between them a small white mountain logo over a condensed caps name. One condensed uppercase word spans almost the full width at 17.8vw, white, centred, anchored so its baseline sits about 35px above the bottom edge. At mid-height a two-line italic serif tagline at about 16px hangs on the first column line at left, and a film-play label sits between two hairlines at right.\",\n  \"type\": \"Three voices: Oswald 400 uppercase for the giant word and footer wordmark (up to 22vw); Cardinal Classic Long, a light high-contrast serif, for caps statements near 32px and italic taglines; Inter Tight 14px for nav and body. Body to display is roughly an 18x jump.\",\n  \"colour\": \"#040608 #ffffff #e9e7e1 #1f2b4d #f5821f #95979a — Footage and near-black open the page; content sections flip to pure white with navy serif type and end on a warm grey footer. One small orange tab is the only accent. Cool overall.\",\n  \"imagery\": \"Aerial and wildlife footage and stills of ice, penguins and rust-coloured rock peaks, natural cool grade, always full-bleed with square corners; trips appear as tall vertical image slices set side by side with no gaps.\",\n  \"layout\": \"A six-column grid made visible by faint full-height hairlines runs through every section. Text blocks are small and hung off column lines, often starting at column two or three, with large voids around them. Full-bleed image screens alternate with nearly empty white text screens.\",\n  \"sections\": [\n   {\n    \"role\": \"intro\",\n    \"description\": \"A white screen with the six vertical hairlines still showing. A serif caps paragraph at about 32px, navy, light weight and tight leading, occupies only columns two to four, left-aligned with its first line indented by half the measure. Above its top-left sits a small italic label ringed by a loose hand-drawn pen scribble. An orange vertical tab with rotated text is fixed to the right edge.\"\n   },\n   {\n    \"role\": \"gallery\",\n    \"description\": \"Leaving the hero, the giant word blurs and dissolves into white mist that becomes the next section's background. Later a full-viewport photograph of jagged rock peaks in snow bleeds to all four edges, with a narrow 13px paragraph from the white section above overlapping its top edge at a column line, so text and image interlock rather than stack.\"\n   },\n   {\n    \"role\": \"showcase\",\n    \"description\": \"A serif caps heading at about 40px sits left of centre with a long pencil-like scribble underline that extends well past the words on both sides. Below, a full-width band of four vertical image panels with no gaps and unequal widths, like an accordion; the first panel carries a two-line italic serif title in white at its top-left.\"\n   },\n   {\n    \"role\": \"footer\",\n    \"description\": \"Warm grey field. The top row holds a small logo, three columns of grey link lists with italic serif group headings and, at right, a stack of square-cornered off-white tiles (a video thumbnail, two half-width buttons, one full-width). Beneath, the brand name in navy condensed caps runs edge to edge at about 22vw. A final strip has award badges left, a centred italic quotation and legal links right.\"\n   }\n  ],\n  \"steal\": [\n   \"Set a single place name in condensed caps at about 18vw, centred and anchored to the bottom edge of full-bleed footage, with everything else on screen at 14-16px.\",\n   \"Leave the column grid visible as faint full-height hairlines across video, white and footer sections, and hang small text blocks off those lines.\",\n   \"Ring or underline small serif labels with a loose hand-drawn pen scribble to put one human mark into an otherwise strict layout.\"\n  ],\n  \"media\": \"An 18s muted aerial and ice-cave clip covers the whole first screen under a scrim, with the title docked along the bottom edge. Later pictures dissolve into the white page through fog-like fades, a horizontal accordion opens one trip panel at half width beside blurred slivers, vertical ice strips wipe across the previous photograph, and a long pinned track of inset cards floats on a full-bleed texture ground before a closing photo panel carrying a quotation; 20 images, one video, square corners and a high-key cold grade.\",\n  \"motion\": \"There is no entrance choreography and footage plays from the first frame; under Lenis the hero title blurs and is swallowed by a sticky fog layer growing from 390 to 900px tall, statement lines fill from grey to navy, the camps heading scrubs from 140px down to 60px, and a pinned horizontal track moves the cards at about 0.56px per scrolled pixel over an 8,328px runway. Blocks rise 20rem with opacity over 1.4s cubic-bezier(.16,1,.3,1), and hovers run .3s cubic-bezier(.5,1,.89,1).\"\n },\n {\n  \"id\": \"opl-applied-imagination\",\n  \"name\": \"Applied Imagination\",\n  \"url\": \"https://applied-imagination.gpc.consulting\",\n  \"source\": \"One Page Love\",\n  \"kind\": \"other\",\n  \"score\": 8.3,\n  \"idea\": \"An essay conceived on a flight is read as a descent: an altimeter ticks from 30,000 ft to zero while you scroll down through halftone clouds to mountains at ground level.\",\n  \"mood\": [\n   \"airy\",\n   \"witty\",\n   \"editorial\",\n   \"dreamlike\"\n  ],\n  \"archetype\": \"type-poster\",\n  \"hero\": \"A pale blue sky fading to warm cream fills the viewport, with white clouds shaded in halftone dots. A tiny serif logotype sits top-centre; no nav. The title, two centred lines of black wedge-serif at 8.9vw, occupies the middle half of the screen and about 73% of its width; a cloud layer passes in front of the second line's baseline so the feet of the letters dissolve into dots. A two-line centred deck at 24px sits beneath. A mono byline strip is centred on the bottom edge with a scroll cue bottom-right. On the left edge at mid-height, a short vertical rule carries a two-line mono altitude readout.\",\n  \"type\": \"fsKim, a sturdy wedge-serif display face, regular weight at 128px with -0.01em tracking for the title and pull quotes; gtAmerica at 24px for the deck and about 16px for essay body; gtAmericaMono uppercase around 11px with wide tracking for byline, altitude and tape labels.\",\n  \"colour\": \"#cbe4f2 #f1e3b5 #0a0a0a #ffc013 #8e2f8f #f04e23 — Sky blue melting into sand yellow is the constant ground and text is black. Saturated magenta, orange and yellow arrive only in collage objects, tape labels and the footer contact card.\",\n  \"imagery\": \"Photo-collage cut-outs (parachutes carrying a treasure chest and a burning dumpster, a pair of legs, mountains) given a coarse halftone dot screen, layered in front of and behind the type against painted clouds.\",\n  \"layout\": \"A narrow text column about 38% wide for essay passages, interrupted by full-width display pull quotes and collage objects floating at the edges. One continuous sky instead of sections, with a fixed left-edge altimeter. Nearly 23 screens, ending on a ground-level landscape.\",\n  \"sections\": [\n   {\n    \"role\": \"intro\",\n    \"description\": \"Sky background, no container. A three-line pull quote in black wedge-serif at about 7vw is centred and tightly leaded. Two cut-out parachutes hang over it: a magenta one from the top-left carrying a chest spilling coins, an orange one at lower right carrying a burning dumpster, each overlapping letterforms. Small mono labels on tilted strips of coloured tape are stuck to the objects. Words in the quote turn from grey to black as they are reached.\"\n   },\n   {\n    \"role\": \"other\",\n    \"description\": \"Running essay text in about 16px grotesk, black, in a single column roughly 38% of the viewport wide, positioned left of centre with large sky margins on both sides. Paragraphs are separated by a blank line; serif sub-statements at about 28px introduce passages. The next display quote is seen rising from below, its letters partly hidden behind cloud and blurred.\"\n   },\n   {\n    \"role\": \"contact\",\n    \"description\": \"Ground level: halftone-screened mountains in green and brown rise from both sides, and the title returns at huge scale, cropped by the top edge and tucked behind the peaks. Centred below is a square-cornered two-panel card: a cream left panel with a short form of two fields and a small orange button, and a magenta right panel with a round portrait, name and a yellow subscribe button. Yellow tape-strip credits sit on the bottom edge.\"\n   }\n  ],\n  \"steal\": [\n   \"Tie a persistent numeric readout to scroll position (altitude falling to zero) so the reader's progress becomes part of the story.\",\n   \"Layer an illustration element in front of the bottom of a giant title so the letters sink into the scene instead of sitting on top.\",\n   \"Apply one coarse halftone dot screen to every photo cut-out so collage pieces from different sources read as one illustration set.\"\n  ]\n },\n {\n  \"id\": \"opl-compile\",\n  \"name\": \"Cursor Compile\",\n  \"url\": \"https://cursor.com/compile\",\n  \"source\": \"One Page Love\",\n  \"kind\": \"event\",\n  \"score\": 8.3,\n  \"idea\": \"The event name drawn as seven looping one-line curves in seven colours, more signature than logotype, on an otherwise whisper-quiet off-white page whose images are re-rendered as rows of coloured characters.\",\n  \"mood\": [\n   \"quiet\",\n   \"hand-drawn\",\n   \"warm\",\n   \"technical\",\n   \"restrained\"\n  ],\n  \"archetype\": \"giant-wordmark\",\n  \"hero\": \"Warm off-white field with no header or navigation. Starting about 23% down, a line-drawn wordmark spans from 8% to 92% of the width and about 29% of the height: each letter is a single 2px stroke looping like a Lissajous figure, each in a different colour (orange, green, olive, lilac, black, brown, blue), overlapping its neighbours. Directly beneath, two 14px captions, one flush left in ink and one flush right in grey. After a gap of about 20% of the viewport, three equal columns sit at the bottom, each topped by a hairline: an 18px statement, a grey 14px paragraph, and an email field over a full-width near-black rectangular button.\",\n  \"type\": \"The only large lettering is the drawn wordmark. All real text is CursorGothic regular in two sizes, 18px and 14px (the largest text on the page is 1.8vw), sentence case, with hierarchy made by ink versus mid-grey rather than by size or weight.\",\n  \"colour\": \"#edece8 #26251e #f07a1f #2e9e3a #2f6bf0 #9b8ff0 — Warm paper ground with near-black and grey text. The wordmark's colours return one at a time as the single ink of each character-rendered image (lilac, teal, green, orange). Event photos are dark and warm.\",\n  \"imagery\": \"Two kinds: landmarks and speaker portraits redrawn as rows of tiny characters in one saturated colour on a tint of the same colour; and dark, warm documentary event photos. All are square-cornered rectangles in strict rows.\",\n  \"layout\": \"About 7% side margins on a three-column grid. Each section has a small two-line heading at left (title in ink, subtitle in grey), then a row or carousel of equal tiles with one-line captions beneath. Very large vertical gaps between sections; a denser photo grid near the end.\",\n  \"sections\": [\n   {\n    \"role\": \"list\",\n    \"description\": \"Tour dates as a three-column grid of 3:2 tiles. Each tile is a city landmark rendered entirely in rows of small characters in one colour on a pale tint of that colour: lilac, teal, green, orange. Under each tile, one caption line: city name in ink, date in grey straight after it, and a status word flush right. A fourth tile wraps alone to the left of a second row, leaving two columns empty.\"\n   },\n   {\n    \"role\": \"gallery\",\n    \"description\": \"Session recordings as stacked carousels. A small heading and grey subtitle, then per stage a tiny label at left with two arrow glyphs at far right and a row of 16:9 dark photo tiles, two full tiles visible and a third cropped by the margin. Each tile has a small white event tag in its bottom-left corner. Caption beneath: speaker name in ink followed by the talk title in grey on the same line.\"\n   },\n   {\n    \"role\": \"about\",\n    \"description\": \"Speaker row: one-line heading at left, arrows at right, then four near-square portrait tiles with 8px gaps, each a face drawn in horizontal rows of characters in one colour on its tint (orange, green, lilac, teal). Some tiles show only plain stripes with the face barely emerging, so portraits appear to resolve from lines as they load or on hover.\"\n   },\n   {\n    \"role\": \"cta\",\n    \"description\": \"After a three-column photo grid with mixed landscape and portrait crops and 8px gaps, the page ends on an empty off-white screen holding one centred sentence at 18px and a small dark pill button beneath it. There are no footer columns, links or legal rows.\"\n   }\n  ],\n  \"steal\": [\n   \"Draw the name as one continuous thin looping stroke per letter, each in a different colour, and let it be the only large element on the page.\",\n   \"Keep all text at two small sizes and build hierarchy from ink versus grey on the same line (name in ink, detail in grey right after it).\",\n   \"Re-render photographs as rows of tiny characters in a single saturated colour on a tint of that colour, one colour per tile.\"\n  ]\n },\n {\n  \"id\": \"opl-the-new-industrials\",\n  \"name\": \"The New Industrials\",\n  \"url\": \"https://thenewindustrials.com/\",\n  \"source\": \"One Page Love\",\n  \"kind\": \"other\",\n  \"score\": 8.3,\n  \"idea\": \"A long-read essay laid out inside a visible drafting grid, where colour fields shift as you read and 3D machine parts drift through the margins and finally assemble into the publisher's initials.\",\n  \"mood\": [\n   \"bold\",\n   \"playful\",\n   \"editorial\",\n   \"engineered\",\n   \"saturated\"\n  ],\n  \"archetype\": \"editorial-masthead\",\n  \"hero\": \"A saturated orange page framed by black hairlines 24px from each edge. Top strip: a monogram logo left, a black pill with orange monospaced title centred, a boxed year right. Under it a row of eight empty outlined cells, 62px tall, like a ruler. A cream panel then fills the remaining width and height. Inside, a WebGL scene of pastel low-poly machine parts with visible wireframes sits behind a two-line uppercase title in a tall condensed slab serif, glyphs about 210px high, spanning 83% of the width. Small monospaced uppercase credits flank it at mid-height; reading time is centred below, with two boxed share links on the bottom edge.\",\n  \"type\": \"Title in a tall condensed slab serif at roughly 14vw cap height, black, uppercase. Essay in Albra Book serif: 34px lead paragraph, 18px running text with generous leading. Supply Mono in tiny uppercase for credits and box labels; a narrow typewriter-like face for the pull quote.\",\n  \"colour\": \"#ff8126 #f1ead8 #161615 #4db3ff #c5f53d #ff5fc0 — The page background changes as you read: orange, then a gradient through lilac into sky blue, then acid lime at the end. Type and hairlines stay black; the 3D parts carry rainbow gradients.\",\n  \"imagery\": \"Real-time 3D machine components (cylinders, gears, polyhedra) in matte pastel with coloured wireframe edges and neon gradient caps; they overlap the title, float into text margins and form letters in the footer.\",\n  \"layout\": \"Black hairlines divide the whole page into cells: one wide text cell flanked by narrow empty ones, each chapter tagged with a small numbered box at its corner. The lead paragraph spans the cell, running text is indented into a narrower column, and full-width quote screens interrupt.\",\n  \"sections\": [\n   {\n    \"role\": \"intro\",\n    \"description\": \"On orange, a ruled cell with a small numbered square at its top-right corner. The opening paragraph is set in serif at about 34px, seven lines, filling the cell with 60px padding. A horizontal hairline closes the cell; the next one indents its text by about 180px and drops to 18px, with a vertical rule marking the indent. The side cells stay empty, so the grid reads as margin furniture.\"\n   },\n   {\n    \"role\": \"other\",\n    \"description\": \"Pull quote: a full-viewport interruption where the grid lines stop. The background becomes a vertical gradient from orange through dusty lilac to sky blue. Centred, five lines of a narrow, widely tracked typewriter-style face at about 48px in dark olive-brown, each letter trailing a soft red vertical smear downward like wet ink. The next cell resumes on the blue that the gradient ended on.\"\n   },\n   {\n    \"role\": \"other\",\n    \"description\": \"Body screens: a single serif column about 960px wide between two vertical hairlines, paragraphs separated by a blank line. One 3D object per screen (a grey-green polyhedron with green edges, an orange hexagonal nut) sits half outside the column, crossing the vertical rule and the page edge at a different height each time, so every screen of text has one sculptural interruption.\"\n   },\n   {\n    \"role\": \"footer\",\n    \"description\": \"Acid-lime field. The publisher's three initials are built as a sculpture from the 3D parts seen earlier, about 60% of the viewport tall and spanning nearly the full width, each letter a different assembly of pipes, gears and blocks in clashing gradients. Below, hairlines form two cells holding monospaced uppercase credits at 10px, aligned to the cells' left padding.\"\n   }\n  ],\n  \"steal\": [\n   \"Draw the layout grid as visible black hairlines, including a row of empty cells, and tag each text block with a small numbered box.\",\n   \"Change the page background colour between chapters of a long read so progress is felt as a shift of colour.\",\n   \"Let one family of 3D objects recur at three scales: behind the title, in the margins, and assembled into a monogram at the end.\"\n  ]\n },\n {\n  \"id\": \"opl-wild-as\",\n  \"name\": \"wild\",\n  \"url\": \"https://craft.wild.as\",\n  \"source\": \"One Page Love\",\n  \"kind\": \"agency\",\n  \"score\": 8.3,\n  \"idea\": \"A studio essay on craft versus AI in which everything decorative is drawn on one square-pixel grid: the hero heatmap, the icons, the diagrams, the marquee lettering and the footer equaliser.\",\n  \"mood\": [\n   \"precise\",\n   \"playful\",\n   \"technical\",\n   \"bright\",\n   \"editorial\"\n  ],\n  \"archetype\": \"editorial-masthead\",\n  \"hero\": \"White page with a barely visible graph-paper grid. The top 22% is a masthead band split by a vertical hairline at 60%: at left, a two-line uppercase headline in a light grotesk at 5.2vw, tight leading, starting 9% from the left and nearly touching the top edge; at right, a two-line uppercase tagline with words spread to justify the column, then a pixel logo and a small right-aligned description. Below, a full-bleed canvas about 45% of the viewport tall: thousands of small squares in yellow, red, lime, cobalt and navy form a heatmap that erodes into white along its lower edge. A 3vw intro paragraph begins at the fold.\",\n  \"type\": \"Sneak in one regular-to-light weight does everything: uppercase 75px headline at -0.035em, a 44px sentence-case intro, section headings near 30px, 13px body. Tiny SF Mono uppercase captions with wide tracking sit under headings. A bitmap pixel face appears once, in the closing marquee. No bold anywhere.\",\n  \"colour\": \"#ffffff #0a0a0a #f2b90f #3b55d9 #1e2340 #e8452c — White page, black type, black buttons. Colour lives only inside the pixel graphics, in a fixed set of yellow, cobalt, navy, red and lime, so every illustration looks related. No section changes background.\",\n  \"imagery\": \"Canvas-drawn square-pixel fields: a heatmap band, particle streams that tighten from scattered dots into a dense ribbon, pixel smiley faces, an equaliser strip. Client work appears once, as three plain square-cornered photo cards.\",\n  \"layout\": \"Content runs from 9% to 91% with a constant split: heading in the left third, body in the right two-thirds, a tiny mono caption under the heading. Full-bleed pixel canvases interrupt the text. A small fixed mono link sits top-right; the ending is centred.\",\n  \"sections\": [\n   {\n    \"role\": \"work\",\n    \"description\": \"Three equal cards in one row, each a 6:5 image with square corners (laptop mock-up, product photo, flat illustration) followed by a centred project name at about 20px and a centred two-line description in small text. No borders, shadows or tags; a small round black arrow button overlaps the right edge of the third image to advance the row. Large white space above and below.\"\n   },\n   {\n    \"role\": \"intro\",\n    \"description\": \"Essay rows: a two- or three-line heading at about 2.2vw in the left third with a tiny wide-tracked mono caption below it; in the right two-thirds, two short justified paragraphs at 13px. Under one row, two pixel-art faces built from black squares (a smile and a frown, about 30px) sit side by side, each over a mono label and a three-line centred caption, forming a two-column comparison.\"\n   },\n   {\n    \"role\": \"how-it-works\",\n    \"description\": \"A four-word heading on two lines and a short paragraph at the left, then a wide canvas diagram: scattered pale-blue and navy squares at the left converge into a tight horizontal ribbon in the middle and fan out again in yellow at the right, a pixel funnel. Below it four narrow columns, each with a small round dark marker, a bold one-word label and two lines of small text.\"\n   },\n   {\n    \"role\": \"cta\",\n    \"description\": \"A single line of bitmap lettering scrolls across the full width, each glyph assembled from yellow squares flecked with red, navy and lime. Centred beneath: a black button with stepped pixel corners, two short grey centred paragraphs and an email line. The page ends with a full-width strip of coloured pixel bars like an audio equaliser, a small black play button centred above it.\"\n   }\n  ],\n  \"steal\": [\n   \"Pick one drawing primitive, a square on a fixed grid, and render every non-text element with it (hero art, icons, diagrams, display lettering, footer) in one five-colour set.\",\n   \"Split a masthead band 60/40 with a vertical hairline: oversized light-weight uppercase headline at left, a word-spaced justified tagline and tiny descriptor at right.\",\n   \"Lay out long copy as rows with the heading in the left third and body in the right two-thirds, and put the tiny mono caption under each heading instead of an eyebrow above it.\"\n  ]\n },\n {\n  \"id\": \"aww-hilden-kaira\",\n  \"name\": \"Hildén & Kaira\",\n  \"url\": \"https://www.hildenkaira.fi/\",\n  \"source\": \"Awwwards Site of the Day\",\n  \"kind\": \"agency\",\n  \"score\": 8.3,\n  \"idea\": \"The agency name is cast in liquid chrome across the full width, and the same chrome becomes emoji that float through the page, tying a social-media pitch to one material.\",\n  \"mood\": [\n   \"brash\",\n   \"glossy\",\n   \"editorial\",\n   \"witty\"\n  ],\n  \"archetype\": \"giant-wordmark\",\n  \"hero\": \"Warm light-grey field. The lowercase serif wordmark, rendered as polished chrome 3D letters with a molten ampersand, runs edge to edge across the top quarter (about 220px tall, 16px side margins). A tilted portrait video roughly 180 by 220px covers two of its letters. Directly under the wordmark, four small nav links centred. Then 300px of nothing, with one chrome flame emoji floating at the far left. The headline sits in the bottom third: three centred lines of narrow display serif at 4.4vw, leading so tight that descenders touch ascenders, a two-line 15px sans sub, and two square-cornered buttons, black and pale lime.\",\n  \"type\": \"PP Editorial New 400 for headlines at 63px, -0.02em tracking and leading near 0.9; PP Neue Montreal 13px for nav, body and buttons. The jump is roughly 5:1 with nothing in between. Stat numerals use the sans at about 60px.\",\n  \"colour\": \"#eae9e6 #181818 #ecfdad #b5b5b5 #ffffff #3aa57a — Warm grey and near-black alternate by section. Pale lime is the single accent: secondary buttons, headline text on dark, stat tiles and service cards. Chrome silver recurs as a material.\",\n  \"imagery\": \"Chrome 3D-rendered lettering and emoji objects (flame, heart, dove, microphone, wink) floating free; vertical phone videos of client content shown as fanned, slightly rotated stacks with white borders. Square corners throughout.\",\n  \"layout\": \"Centred statements with large voids, alternating light and dark full-width bands. Content arrives as square-cornered slabs: a white case card on grey, lime service cards stacking over each other on black. Chrome objects break the grid at the edges.\",\n  \"sections\": [\n   {\n    \"role\": \"testimonial\",\n    \"description\": \"Full-viewport near-black band. A two-line centred serif statement in pale lime at about 4vw sits in the upper third with nothing near it. Two small testimonials are pushed to the bottom-left and bottom-right corners: five tiny stars, two lines of 11px sans, name and title, each centred in its own narrow block. The centre bottom is left empty.\"\n   },\n   {\n    \"role\": \"work\",\n    \"description\": \"Horizontal carousel of wide white slabs on the grey ground, the next slide peeking at the right edge. Left half: a two-line serif title top-left, then far below a red-dot label over a thin rule and two flat tiles side by side, a wide lime one and a narrower brushed-chrome one, each with a tiny caption and a 60px sans numeral. Right half: a grey panel with three vertical videos fanned like playing cards.\"\n   },\n   {\n    \"role\": \"features\",\n    \"description\": \"On black, a centred serif section title, then service cards that pin and stack: a lime slab about 55% wide with serif title top-left, grey serif index number top-right, a small paragraph and black button bottom-left and a vertical video inset bottom-right. White and green slabs peek out beneath it, offset downward, and the top card tilts a degree or two as it scrolls.\"\n   },\n   {\n    \"role\": \"footer\",\n    \"description\": \"A full brushed-silver gradient field. The chrome wordmark repeats at full width across the top. Bottom-left, a small serif label over two short link columns; bottom-right, two square translucent tiles each holding a chrome object (microphone, heart) with a serif label above and three tiny square social buttons below. A hairline and a legal row close it.\"\n   }\n  ],\n  \"steal\": [\n   \"Render the wordmark in one physical material and reuse that material for small floating objects, so decoration and logo are the same thing.\",\n   \"Leave a third of the hero empty between a top-edge wordmark and a bottom-third headline; the gap makes both read.\",\n   \"Set a display serif with leading under 1.0 so lines interlock, and pair it with 13px sans for everything else.\"\n  ]\n },\n {\n  \"id\": \"aww-px-push\",\n  \"name\": \"PX PUSH\",\n  \"url\": \"https://pxpush.com/\",\n  \"source\": \"Awwwards Site of the Day\",\n  \"kind\": \"agency\",\n  \"score\": 8.2,\n  \"idea\": \"A design subscription presented as a retro broadcast: the entire site is seen through a CRT screen, with a chrome logo token floating in the sky as its mascot.\",\n  \"mood\": [\n   \"retro-futurist\",\n   \"cool\",\n   \"technical\",\n   \"cinematic\",\n   \"confident\"\n  ],\n  \"archetype\": \"product-object-centre\",\n  \"hero\": \"Full-bleed photograph of deep-blue sky over a cloud bank, the whole viewport under a CRT treatment: horizontal scanlines, slight blur, dark vignette with rounded corners. Top row with 43px margins: thin techno wordmark left; three links and a start link with a green dot right, split by a vertical hairline; full-width hairline beneath. Then one marquee line at 12vw (173px) in off-white grotesk, cropped at both edges, words separated by a solid dot, closed by a second hairline. Dead centre: a chrome 3D ring token about 400px wide. Bottom-left: a 216×144px royal-blue rounded thumbnail with a two-line mono caption. Bottom-right: a four-line mono uppercase paragraph 450px wide.\",\n  \"type\": \"A semi-condensed grotesk (digest name 'SemiSqueezed') at regular weight carries the 173px marquee, 28px paragraphs and 5vw statements; an uppercase monospace at 11–17px handles tags, captions and link rows. Ten-to-one jump between display and labels; no bold anywhere.\",\n  \"colour\": \"#03049c #71737d #1a1a1a #788ca4 #d9dde6 #c8f31d — Each section is a full colour field: sky photo, mid grey, near-black, then saturated royal blue. Text is off-white or pale lavender; acid lime appears only in small thumbnails, green only as a status dot.\",\n  \"imagery\": \"Sky photograph, a chrome 3D logo token, and client work shown as phone UIs on a blue ground and a poster photographed in a street lightbox. Everything sits under the same scanline filter; tiles have small radii.\",\n  \"layout\": \"A narrow left rail (about 17% wide) carries a bullet, a mono section tag and a small pinne\n\n<!-- [TRUNCATED AT 50KB] -->","skills/taste-skill/library/type.json":"[\n {\n  \"id\": \"switzer-semibold\",\n  \"name\": \"Switzer\",\n  \"class\": \"grotesk-tight\",\n  \"display\": {\n   \"family\": \"Switzer\",\n   \"source\": \"fontshare\",\n   \"slug\": \"switzer\",\n   \"weights\": [\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 600 · tracking -0.04em · leading 0.95 · sentence case; charcoal rather than pure black\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=switzer@400,500,600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Switzer\",\n   \"source\": \"fontshare\",\n   \"slug\": \"switzer\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking -0.005em\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=switzer@400,500,600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Suisse Intl\",\n   \"Neue Haas Grotesk\"\n  ],\n  \"note\": \"One neo-grotesk doing everything: semibold headings pulled tight, small regular text, no capitals and no second voice. Suits software, hardware and studio pages that want to look exact and unshowy.\",\n  \"seenIn\": [\n   \"aww-noho\",\n   \"opl-vessa\",\n   \"aww-aspen-search\",\n   \"opl-rows\"\n  ],\n  \"links\": [\n   \"https://api.fontshare.com/v2/css?f[]=switzer@400,500,600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"general-sans-bold\",\n  \"name\": \"General Sans\",\n  \"class\": \"grotesk-tight\",\n  \"display\": {\n   \"family\": \"General Sans\",\n   \"source\": \"fontshare\",\n   \"slug\": \"general-sans\",\n   \"weights\": [\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 700 · tracking -0.02em · leading 0.9 · sentence case; sizes jump straight from 16px text to 10vw and larger\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=general-sans@400,500,700&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"General Sans\",\n   \"source\": \"fontshare\",\n   \"slug\": \"general-sans\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body and lists, 500 for emphasis · leading 1.45 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=general-sans@400,500,700&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"PP Neue Montreal\",\n   \"Aeonik\"\n  ],\n  \"note\": \"A grotesk with slightly geometric bowls, set bold and very large against plain 16px text with nothing in between. Suits studios, type and product launches, and finance or tech brands that lead with the name.\",\n  \"seenIn\": [\n   \"aww-pp-neue-montreal\",\n   \"aww-moto-finance\",\n   \"opl-brikkenco\",\n   \"aww-nothin\"\n  ],\n  \"links\": [\n   \"https://api.fontshare.com/v2/css?f[]=general-sans@400,500,700&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"schibsted-heavy\",\n  \"name\": \"Schibsted Grotesk\",\n  \"class\": \"grotesk-tight\",\n  \"display\": {\n   \"family\": \"Schibsted Grotesk\",\n   \"source\": \"google\",\n   \"weights\": [\n    800\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 800 · tracking -0.05em · leading 0.88 · sentence case or all lowercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Schibsted+Grotesk:wght@400;600;800&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Schibsted Grotesk\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for paragraphs, 600 for navigation and other functional text · leading 1.4 · tracking -0.01em\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Schibsted+Grotesk:wght@400;600;800&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"ABC Diatype\",\n   \"Khteka\"\n  ],\n  \"note\": \"A compact, warm grotesk set heavy with letters almost touching; small text stays in the same family at semibold. Suits music, events and culture pages where the type is the image.\",\n  \"seenIn\": [\n   \"aww-paul-kalkbrenner\",\n   \"opl-rendez-vous-franceclat\",\n   \"aww-monolog\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Schibsted+Grotesk:wght@400;600;800&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"hanken-medium\",\n  \"name\": \"Hanken Grotesk\",\n  \"class\": \"grotesk-tight\",\n  \"display\": {\n   \"family\": \"Hanken Grotesk\",\n   \"source\": \"google\",\n   \"weights\": [\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 500 · tracking -0.05em · leading 0.9 · sentence case; one statement size (about 6vw) used for every heading\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Hanken+Grotesk:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Hanken Grotesk\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.45 · tracking -0.005em\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Hanken+Grotesk:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Akzidenz Grotesk\",\n   \"LayGrotesk\"\n  ],\n  \"note\": \"Medium-weight grotesk statements at one large size against caption-size text: a two-size system with no bold. Suits portfolios, agencies and tools that speak in short declarative lines.\",\n  \"seenIn\": [\n   \"aww-bleibtgleich26\",\n   \"aww-made-with-gsap-1\",\n   \"opl-locker-land\",\n   \"opl-builders-table\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Hanken+Grotesk:wght@400;500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"bricolage-contrast\",\n  \"name\": \"Bricolage Grotesque\",\n  \"class\": \"grotesk-tight\",\n  \"display\": {\n   \"family\": \"Bricolage Grotesque\",\n   \"source\": \"google\",\n   \"weights\": [\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 600 · tracking -0.04em · leading 0.92 · sentence case; leave optical sizing on so large sizes tighten and gain contrast\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:wght@400;500;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Bricolage Grotesque\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:wght@400;500;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Beausite Classic\",\n   \"F37 Analog\"\n  ],\n  \"note\": \"A grotesk with visible stroke contrast and slightly irregular curves, so headings look drawn rather than engineered. Suits reports, consultancies and design-led software that want warmth without a serif.\",\n  \"seenIn\": [\n   \"aww-ai-in-design-report-2026\",\n   \"aww-illoca\",\n   \"opl-ohhmydesign\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:wght@400;500;600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"franklin-source\",\n  \"name\": \"Libre Franklin / Source Serif 4\",\n  \"class\": \"grotesk-tight\",\n  \"display\": {\n   \"family\": \"Libre Franklin\",\n   \"source\": \"google\",\n   \"weights\": [\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 700 · tracking -0.035em · leading 0.92 · uppercase for the title, sentence case for section headings\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Libre+Franklin:wght@700&family=Source+Serif+4:ital,wght@0,400;0,600;1,400;1,600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Source Serif 4\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    600\n   ],\n   \"italic\": true,\n   \"settings\": \"400 for body, 600 for emphasis, italic for quotations · leading 1.55 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Libre+Franklin:wght@700&family=Source+Serif+4:ital,wght@0,400;0,600;1,400;1,600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Founders Grotesk\",\n   \"Die Grotesk\",\n   \"NON Natural Grotesk\"\n  ],\n  \"note\": \"An American gothic for headings over a sober transitional serif for reading, the pairing of a newspaper front page. Suits essays, annual reports, archives and finance pages that have real paragraphs.\",\n  \"seenIn\": [\n   \"aww-dragonfly-redux\",\n   \"aww-trevor-noah\",\n   \"aww-mosbys-files\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Libre+Franklin:wght@700&family=Source+Serif+4:ital,wght@0,400;0,600;1,400;1,600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"switzer-roman\",\n  \"name\": \"Switzer\",\n  \"class\": \"grotesk-light\",\n  \"display\": {\n   \"family\": \"Switzer\",\n   \"source\": \"fontshare\",\n   \"slug\": \"switzer\",\n   \"weights\": [\n    400\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 400 · tracking -0.03em · leading 1.1 · sentence case; headings stay small (28–40px) and at most one line jumps to 5vw\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=switzer@400,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Switzer\",\n   \"source\": \"fontshare\",\n   \"slug\": \"switzer\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for everything, 500 only for names and links · leading 1.45 · tracking -0.01em; hierarchy by ink against mid-grey\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=switzer@400,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Neue Haas Grotesk 55 Roman\",\n   \"Helvetica Now\"\n  ],\n  \"note\": \"A single roman weight of a Swiss neo-grotesk at two or three modest sizes; position and grey value do the work that size and bold usually do. Suits architects, galleries, studios and any quiet page where photographs carry the scale.\",\n  \"seenIn\": [\n   \"aww-revelatio-studio\",\n   \"opl-spatial\",\n   \"aww-pensatori-irrazionali\",\n   \"opl-compile\"\n  ],\n  \"links\": [\n   \"https://api.fontshare.com/v2/css?f[]=switzer@400,500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"archivo-regular\",\n  \"name\": \"Archivo\",\n  \"class\": \"grotesk-light\",\n  \"display\": {\n   \"family\": \"Archivo\",\n   \"source\": \"google\",\n   \"weights\": [\n    400\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 400 · tracking -0.02em · leading 1.0 · sentence case; never bold, inactive items fade to grey\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Archivo:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Archivo\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 600 for buttons and short emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Archivo:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Scto Grotesk A\",\n   \"Cash Sans\"\n  ],\n  \"note\": \"A sturdy grotesque kept at regular weight even at 88px, so the page reads as composed rather than loud. Suits finance, infrastructure and research pages that need to look sober and current.\",\n  \"seenIn\": [\n   \"aww-sharplink\",\n   \"opl-plastic\",\n   \"opl-lovably\",\n   \"opl-berd\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Archivo:wght@400;600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"clash-grotesk-regular\",\n  \"name\": \"Clash Grotesk\",\n  \"class\": \"grotesk-light\",\n  \"display\": {\n   \"family\": \"Clash Grotesk\",\n   \"source\": \"fontshare\",\n   \"slug\": \"clash-grotesk\",\n   \"weights\": [\n    400\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 400 · tracking -0.03em · leading 0.95 · sentence case, or uppercase for one statement\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=clash-grotesk@400,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Clash Grotesk\",\n   \"source\": \"fontshare\",\n   \"slug\": \"clash-grotesk\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.4 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=clash-grotesk@400,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Sneak\",\n   \"ABC Monument Grotesk\"\n  ],\n  \"note\": \"A slightly narrow neo-grotesk with closed apertures, used at regular weight from marquee size down to paragraphs. Suits agencies and digital studios that want large type without heaviness.\",\n  \"seenIn\": [\n   \"aww-px-push\",\n   \"opl-wild-as\",\n   \"aww-sstr-friction-reduction\"\n  ],\n  \"links\": [\n   \"https://api.fontshare.com/v2/css?f[]=clash-grotesk@400,500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"work-sans-light\",\n  \"name\": \"Work Sans\",\n  \"class\": \"grotesk-light\",\n  \"display\": {\n   \"family\": \"Work Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    300\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 300 · tracking -0.035em · leading 1.0 · sentence case\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Work+Sans:wght@300;400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Work Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.55 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Work+Sans:wght@300;400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"ABC Favorit\",\n   \"Clarkson Light\",\n   \"PP Mori\"\n  ],\n  \"note\": \"A light grotesque with open, slightly old-fashioned shapes; large headings look airy and the text weight beneath stays easy to read. Suits AI and research products, fashion houses and calm brand sites.\",\n  \"seenIn\": [\n   \"aww-cerebrium\",\n   \"aww-squarespace-foundations\",\n   \"aww-boc-studio\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Work+Sans:wght@300;400;500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"anton-work\",\n  \"name\": \"Anton / Work Sans\",\n  \"class\": \"condensed-heavy\",\n  \"display\": {\n   \"family\": \"Anton\",\n   \"source\": \"google\",\n   \"weights\": [\n    400\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 400 (single heavy cut) · tracking -0.01em · leading 0.86 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Anton:wght@400&family=Work+Sans:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Work Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 600 for links and short emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Anton:wght@400&family=Work+Sans:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Druk\",\n   \"Thunder\",\n   \"Acme Gothic\"\n  ],\n  \"note\": \"Compressed heavy capitals stacked tight, with a neutral grotesque kept small beneath. Suits fashion drops, sport, nightlife and any page built as a poster.\",\n  \"seenIn\": [\n   \"aww-serotoninn\",\n   \"opl-juggle\",\n   \"opl-lorenzo-bocchi-photography\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Anton:wght@400&family=Work+Sans:wght@400;600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"big-shoulders-public\",\n  \"name\": \"Big Shoulders / Public Sans\",\n  \"class\": \"condensed-heavy\",\n  \"display\": {\n   \"family\": \"Big Shoulders\",\n   \"source\": \"google\",\n   \"weights\": [\n    800\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 800 · tracking -0.005em · leading 0.88 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Big+Shoulders:wght@800&family=Public+Sans:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Public Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 600 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Big+Shoulders:wght@800&family=Public+Sans:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Founders Grotesk Condensed\",\n   \"PP Neue York\",\n   \"Knockout\"\n  ],\n  \"note\": \"A tall American gothic taken from city signage, blunt and civic, over a plain public-service sans. Suits culture indexes, community projects, bars, sport clubs and local campaigns.\",\n  \"seenIn\": [\n   \"aww-mosbys-files\",\n   \"opl-the-sapphic-bar-index\",\n   \"opl-the-deep-end\",\n   \"aww-colonia-zacamil\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Big+Shoulders:wght@800&family=Public+Sans:wght@400;600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"archivo-compressed\",\n  \"name\": \"Archivo\",\n  \"class\": \"condensed-heavy\",\n  \"display\": {\n   \"family\": \"Archivo\",\n   \"source\": \"google\",\n   \"weights\": [\n    800\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 800 at font-stretch 62% (load the wdth axis and use its narrowest setting) · tracking -0.01em · leading 0.86 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Archivo:wdth,wght@62..125,100..900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Archivo\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"normal width · 400 for body, 500 for buttons and emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Archivo:wdth,wght@62..125,100..900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Helvetica Now Display Condensed\"\n  ],\n  \"note\": \"One variable family pushed to its narrowest, heaviest setting for headlines and relaxed to normal width for text, so display and body share a skeleton. Suits sportswear, campaigns and fintech pages that speak in capitals.\",\n  \"seenIn\": [\n   \"aww-decathlon-yestalgia\",\n   \"opl-uglycash\",\n   \"opl-juggle\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Archivo:wdth,wght@62..125,100..900&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"bebas-garamond\",\n  \"name\": \"Bebas Neue / EB Garamond\",\n  \"class\": \"condensed-heavy\",\n  \"display\": {\n   \"family\": \"Bebas Neue\",\n   \"source\": \"google\",\n   \"weights\": [\n    400\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 400 (single cut, capitals only) · tracking -0.02em, tightening to -0.06em above 15vw · leading 0.85 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Bebas+Neue:wght@400&family=EB+Garamond:ital,wght@0,400;0,500;1,400;1,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"EB Garamond\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": true,\n   \"settings\": \"leading 1.45 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Bebas+Neue:wght@400&family=EB+Garamond:ital,wght@0,400;0,500;1,400;1,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Founders Grotesk Condensed\",\n   \"Cardinal Classic Long\",\n   \"Signifier\"\n  ],\n  \"note\": \"Huge condensed capitals against a light old-style serif with italics: an industrial voice and a literary one, with a twenty-fold size gap between them. Suits crafted physical products, spirits, outdoor goods and hospitality.\",\n  \"seenIn\": [\n   \"aww-longbow\",\n   \"aww-white-desert\",\n   \"aww-mosbys-files\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Bebas+Neue:wght@400&family=EB+Garamond:ital,wght@0,400;0,500;1,400;1,500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"barlow-condensed\",\n  \"name\": \"Barlow Condensed / Barlow\",\n  \"class\": \"condensed-heavy\",\n  \"display\": {\n   \"family\": \"Barlow Condensed\",\n   \"source\": \"google\",\n   \"weights\": [\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 700 · tracking -0.02em · leading 0.9 · uppercase for statements, mixed case for item titles\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@700&family=Barlow:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Barlow\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@700&family=Barlow:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"FF DIN Condensed\",\n   \"Helvetica Now Display Condensed\"\n  ],\n  \"note\": \"Road-sign condensed type with squared curves, bold but not compressed into a wall, with its normal-width sibling for text. Suits logistics, motorsport, hardware and directories with many short titles.\",\n  \"seenIn\": [\n   \"aww-julien-calot\",\n   \"opl-medium-rare\",\n   \"opl-uglycash\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@700&family=Barlow:wght@400;500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"panchang-switzer\",\n  \"name\": \"Panchang / Switzer\",\n  \"class\": \"extended-heavy\",\n  \"display\": {\n   \"family\": \"Panchang\",\n   \"source\": \"fontshare\",\n   \"slug\": \"panchang\",\n   \"weights\": [\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 700 · tracking -0.02em · leading 1.0 · uppercase; four words or fewer per line because the face is very wide\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=panchang@700&display=swap\\\" rel=\\\"stylesheet\\\">\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=switzer@400,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Switzer\",\n   \"source\": \"fontshare\",\n   \"slug\": \"switzer\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=panchang@700&display=swap\\\" rel=\\\"stylesheet\\\">\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=switzer@400,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Monument Extended\",\n   \"Owners Wide\",\n   \"Nimbus Sans Extended\"\n  ],\n  \"note\": \"A flat-sided extended grotesk in heavy capitals, wide enough that two words fill the screen, with a neutral sans kept small. Suits portfolios, real estate, travel and brand sites that want a broad, confident wordmark.\",\n  \"seenIn\": [\n   \"opl-belen-jones\",\n   \"aww-lxl-creative\",\n   \"aww-realevate\",\n   \"aww-the-tuscan-journey-begins\"\n  ],\n  \"links\": [\n   \"https://api.fontshare.com/v2/css?f[]=panchang@700&display=swap\",\n   \"https://api.fontshare.com/v2/css?f[]=switzer@400,500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"tiktok-sans-wide\",\n  \"name\": \"TikTok Sans\",\n  \"class\": \"extended-heavy\",\n  \"display\": {\n   \"family\": \"TikTok Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    800\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 800 at font-stretch 150% (load the wdth axis and use its widest setting) · tracking -0.01em · leading 1.0 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=TikTok+Sans:wdth,wght@75..150,300..900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"TikTok Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"normal width · 400 for body, 500 for emphasis · leading 1.45 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=TikTok+Sans:wdth,wght@75..150,300..900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Herokid Wide\",\n   \"At Aero\",\n   \"Wintyr\"\n  ],\n  \"note\": \"One variable grotesk stretched wide and bold for the headline and the closing statement, then returned to normal width for reading. Suits personal portfolios, apps and tech brands that want width without a second family.\",\n  \"seenIn\": [\n   \"aww-haoqi-design\",\n   \"opl-tara\",\n   \"aww-produx-design\",\n   \"opl-proooof\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=TikTok+Sans:wdth,wght@75..150,300..900&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"unbounded-onest\",\n  \"name\": \"Unbounded / Onest\",\n  \"class\": \"extended-heavy\",\n  \"display\": {\n   \"family\": \"Unbounded\",\n   \"source\": \"google\",\n   \"weights\": [\n    800\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 800 · tracking -0.03em · leading 1.0 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Unbounded:wght@800&family=Onest:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Onest\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Unbounded:wght@800&family=Onest:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"IntraNet\",\n   \"Nekst\",\n   \"Owners Wide\"\n  ],\n  \"note\": \"A wide display sans built from rounded squares, heavy and a little architectural, beside a clean text grotesk. Suits architecture indexes, watches, mobility and events that want a title with a constructed feel.\",\n  \"seenIn\": [\n   \"opl-belgrade-architecture\",\n   \"aww-the-watch\",\n   \"aww-risk\",\n   \"aww-house-of-honey-1\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Unbounded:wght@800&family=Onest:wght@400;500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"chivo-black\",\n  \"name\": \"Chivo\",\n  \"class\": \"heavy-black\",\n  \"display\": {\n   \"family\": \"Chivo\",\n   \"source\": \"google\",\n   \"weights\": [\n    900\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 900 · tracking -0.05em · leading 0.88 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Chivo:wght@400;700;900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Chivo\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for paragraphs, 700 for navigation, tags and links · leading 1.35 · tracking -0.01em\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Chivo:wght@400;700;900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Elza\",\n   \"ABC Diatype Heavy\",\n   \"Suisse Intl Black\"\n  ],\n  \"note\": \"A black grotesque in capitals with letters nearly colliding, and only two sizes on the page: enormous and small. Suits agencies, city and culture projects and musicians who want the type to land like a headline.\",\n  \"seenIn\": [\n   \"aww-glitch-grit\",\n   \"opl-city-of-angels\",\n   \"aww-warm-fuzzy\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Chivo:wght@400;700;900&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"cabinet-grotesk-black\",\n  \"name\": \"Cabinet Grotesk\",\n  \"class\": \"heavy-black\",\n  \"display\": {\n   \"family\": \"Cabinet Grotesk\",\n   \"source\": \"fontshare\",\n   \"slug\": \"cabinet-grotesk\",\n   \"weights\": [\n    800\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 800 · tracking -0.035em · leading 0.9 · lowercase or sentence case, one or two words per line\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=cabinet-grotesk@400,500,800&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Cabinet Grotesk\",\n   \"source\": \"fontshare\",\n   \"slug\": \"cabinet-grotesk\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=cabinet-grotesk@400,500,800&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Champ\",\n   \"Uncut Sans\"\n  ],\n  \"note\": \"A heavy sans with tight joins and an eccentric lowercase, friendly but loud. Suits bookshops, food, consumer subscriptions and marketing studios.\",\n  \"seenIn\": [\n   \"aww-aardvark-book-club\",\n   \"opl-protip-marketing\",\n   \"opl-rendez-vous-franceclat\"\n  ],\n  \"links\": [\n   \"https://api.fontshare.com/v2/css?f[]=cabinet-grotesk@400,500,800&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"epilogue-black\",\n  \"name\": \"Epilogue\",\n  \"class\": \"heavy-black\",\n  \"display\": {\n   \"family\": \"Epilogue\",\n   \"source\": \"google\",\n   \"weights\": [\n    900\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 900 · tracking -0.04em · leading 0.9 · sentence case or title case\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Epilogue:wght@400;500;900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Epilogue\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Epilogue:wght@400;500;900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Die Grotesk D\",\n   \"Acme Gothic\",\n   \"FH Oscar\"\n  ],\n  \"note\": \"A broad black grotesque with a slightly uneven rhythm, at its best as a name set very large in mixed case. Suits entertainers, podcasts, consumer apps and blunt SaaS pages; emphasis comes from colour, not from a change of weight.\",\n  \"seenIn\": [\n   \"aww-trevor-noah\",\n   \"opl-juggle\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Epilogue:wght@400;500;900&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"red-hat-black\",\n  \"name\": \"Red Hat Display / Red Hat Text\",\n  \"class\": \"heavy-black\",\n  \"display\": {\n   \"family\": \"Red Hat Display\",\n   \"source\": \"google\",\n   \"weights\": [\n    900\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 900 · tracking -0.03em · leading 0.92 · uppercase; centred three-line stacks work well\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Red+Hat+Display:wght@900&family=Red+Hat+Text:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Red Hat Text\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Red+Hat+Display:wght@900&family=Red+Hat+Text:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"FH Oscar\",\n   \"Futura Bold\"\n  ],\n  \"note\": \"A geometric black with round bowls and flat terminals, cleaner and more even than a grotesque at the same weight. Suits fintech, apps and portfolios that want heavy type with a tidy, technical finish.\",\n  \"seenIn\": [\n   \"aww-risk\",\n   \"aww-leo-parpeix-portfolio-2026\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Red+Hat+Display:wght@900&family=Red+Hat+Text:wght@400;500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"jost-caps\",\n  \"name\": \"Jost\",\n  \"class\": \"geometric\",\n  \"display\": {\n   \"family\": \"Jost\",\n   \"source\": \"google\",\n   \"weights\": [\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 700 · tracking -0.03em · leading 0.9 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Jost:wght@400;500;700&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Jost\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Jost:wght@400;500;700&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Futura Std Bold\",\n   \"Futura PT\"\n  ],\n  \"note\": \"The pointed, circular geometry of the 1920s in bold capitals, with the same family at reading size. Suits space, science, museums, architecture and anything that should feel like a mid-century poster.\",\n  \"seenIn\": [\n   \"aww-21-hrs-on-the-moon\",\n   \"aww-leo-parpeix-portfolio-2026\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Jost:wght@400;500;700&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"stack-sans-light\",\n  \"name\": \"Stack Sans Headline / Stack Sans Text\",\n  \"class\": \"geometric\",\n  \"display\": {\n   \"family\": \"Stack Sans Headline\",\n   \"source\": \"google\",\n   \"weights\": [\n    300\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 300 · tracking -0.022em · leading 1.05 · sentence case; a heading may be two-tone, grey then full ink\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Stack+Sans+Headline:wght@300&family=Stack+Sans+Text:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Stack Sans Text\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Stack+Sans+Headline:wght@300&family=Stack+Sans+Text:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Mluvka\",\n   \"Roobert\"\n  ],\n  \"note\": \"A geometric sans in a light weight at large size, soft and exact at once, with its text cut underneath. Suits consumer apps, utilities and developer tools that want to feel calm and modern.\",\n  \"seenIn\": [\n   \"opl-screentune\",\n   \"opl-dialkit\",\n   \"opl-typewave\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Stack+Sans+Headline:wght@300&family=Stack+Sans+Text:wght@400;500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"albert-sans-semibold\",\n  \"name\": \"Albert Sans\",\n  \"class\": \"geometric\",\n  \"display\": {\n   \"family\": \"Albert Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 600 · tracking -0.035em · leading 1.0 · sentence case\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Albert+Sans:wght@400;500;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Albert Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Albert+Sans:wght@400;500;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"BT Steinhart\",\n   \"TT Norms Pro\",\n   \"Objektiv\"\n  ],\n  \"note\": \"A geometric grotesque with Scandinavian restraint: round letters, even colour, nothing decorative. Suits logistics, health, property and corporate sites that need to look clear and dependable.\",\n  \"seenIn\": [\n   \"aww-united-carriers\",\n   \"aww-likova\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Albert+Sans:wght@400;500;600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"spartan-figtree\",\n  \"name\": \"League Spartan / Figtree\",\n  \"class\": \"geometric\",\n  \"display\": {\n   \"family\": \"League Spartan\",\n   \"source\": \"google\",\n   \"weights\": [\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 700 · tracking -0.04em · leading 0.88 · lowercase or sentence case\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=League+Spartan:wght@700&family=Figtree:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Figtree\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 600 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=League+Spartan:wght@700&family=Figtree:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Degular\",\n   \"Roobert\"\n  ],\n  \"note\": \"A compact bold geometric with a low waist, punchy in short lowercase lines, over a friendly open text sans. Suits newsletters, consumer products, creators and small shops.\",\n  \"seenIn\": [\n   \"opl-lennys-newsletter-product-pass\",\n   \"opl-near\",\n   \"opl-sand-studio\",\n   \"aww-aardvark-book-club\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=League+Spartan:wght@700&family=Figtree:wght@400;600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"pilcrow-rounded\",\n  \"name\": \"Pilcrow Rounded\",\n  \"class\": \"rounded-friendly\",\n  \"display\": {\n   \"family\": \"Pilcrow Rounded\",\n   \"source\": \"fontshare\",\n   \"slug\": \"pilcrow-rounded\",\n   \"weights\": [\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 700 · tracking -0.05em · leading 0.9 · all lowercase, one or two words per line\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=pilcrow-rounded@400,500,700&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Pilcrow Rounded\",\n   \"source\": \"fontshare\",\n   \"slug\": \"pilcrow-rounded\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0; lowercase throughout is fine\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=pilcrow-rounded@400,500,700&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Milling Triplex\",\n   \"Ease\"\n  ],\n  \"note\": \"A sturdy sans with fully rounded stroke ends, set bold and tight in lowercase with one small size for everything else. Suits toys, gadgets, cosmetics and other objects with soft moulded edges.\",\n  \"seenIn\": [\n   \"opl-when-you-wish-upon-a-starboy\",\n   \"opl-anidachi\",\n   \"aww-artem-shcherbakov\"\n  ],\n  \"links\": [\n   \"https://api.fontshare.com/v2/css?f[]=pilcrow-rounded@400,500,700&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw,\n\n<!-- [TRUNCATED AT 50KB] -->","skills/taste-skill/references/app-screens.md":"# App screens\n\nDashboards, admin, analytics, settings, inboxes, wallets and builders: the screens people work in.\nRead this file whole before you start one. The page run in `SKILL.md` does not apply to them.\n\nA generated dashboard is the average of every dashboard template: a dark or tinted sidebar with a\ncoloured pill on the active item, \"Welcome back\" and a waving hand, four KPI cards each with an icon\nin a tinted circle, a green \"+12.5%\" and a sparkline, a gradient area chart, a zebra table under\nuppercase headers. Nothing in it is wrong and none of it was decided.\n\nThis chapter is distilled from a study of 23 real product screens chosen by the owner: 17 products,\n17 light screens and 6 dark, all at desktop width (1440 or 1512px). Each screen was measured from its\npixels and noted for what works and what fails; the numbers below are those measurements and their\nmedians. The products are not named. What separates these screens from the generated kind, in order\nof how much it shows:\n\n1. **Colour goes on data, not chrome.** The median screen has about 3% coloured pixels; 17 of 23 stay\n   at 5% or less. 12 have no filled primary button at all.\n2. **KPIs are type, not tiles.** No screen puts an icon in a coloured circle on a KPI, and none draws a\n   sparkline on one.\n3. **Surfaces are flat.** 17 of 23 give their cards no shadow; separation is a 1px line or one tone\n   step.\n4. **There is no hero header.** 9 screens have no heading over 16px; where there is one, its median is\n   24px.\n5. **Charts carry almost no chrome.** A single series has no legend; gridlines are 3-7 faint lines or\n   none.\n6. **Navigation recedes.** The active item is a neutral grey pill or a change of text colour; a\n   coloured left bar appears once.\n7. **Tables are rules and alignment.** No zebra striping, no header bands, numbers right-aligned.\n8. **Data states are honest.** Zeros print as zeros, missing values as a grey dash, and an empty\n   section keeps its frame.\n\nTaking the template's devices away is half the job, as it is on a page. The other half is substance:\nthe product's real data, a screen that answers its one question first, and a grid whose arithmetic\ncloses.\n\n**A warning learned in testing.** In the first blind round, screens built with this chapter were\nclean, quiet and correct, and they lost to richer screens built without it. The judges' reasons were\nthe same every time, and each is now a rule below:\n\n- **The first screen was thin.** One large chart of a flat line filled it, and half the blocks the\n  brief asked for started below the fold. On a 1440×900 screen, every block the brief names shows its\n  header and its first rows (§2.2).\n- **The product was missing.** No name, no workspace, no mark: the screen could have belonged to\n  anyone. The shell names the product and the scope (§3.2).\n- **Restraint hid meaning.** A latency rise and a request rise were the same grey. Colour on a change\n  says good or bad, not up or down (§5).\n- **There was nothing to do.** No control for the job the screen exists for. The most frequent job is\n  one click from the first screen (§2.2).\n- **Rows ended ragged** and **a style's move was over-applied** (a tray around every card, an icon\n  rail where people needed labels). Keep the move to where it carries meaning.\n\nQuiet is the starting point, not the goal. A screen that a person would trust shows more of the\nproduct than a template does: its people, its objects, its numbers and the one thing to do next.\n\n**Give the product a face.** After four rounds the judges' top complaint was the same on most\nscreens: \"a well-applied kit, not a product with its own identity\" (stock Geist or Inter, a #f8f8f8\nground, white 12px cards, lime on black). The style's tokens make a screen correct; these make it\nthis product's, and choosing them is a step of the run, not a finish (§2.3):\n\n- **One face from the sheet, chosen before you build.** Each style lists two or three ways it takes a\n  face from the brief: a ground tinted from the product's world, a figure face with character, the\n  brand's hue on the main data element. Choose one, write it in your notes next to the screen's\n  question, and check that it shows on the first screenshot.\n- **The dealt typeface, really loaded.** A build that fell back to the default face landed on the\n  default look; the inspector now fails it.\n- **The product's mark and name** at the top of the shell, drawn for this product (a simple\n  monogram or symbol in the accent, from its name or its object), never a black square with a letter.\n- **One element only this product has**, built from its own things: an energy home's power flow, a\n  bakery's sell-out strip, a leave planner's cover against the minimum, the pace groups of a running\n  club as a unit chart, the couple as three lanes, a deploy's commit as the hero of the overview. The\n  sheet lists the library's signature elements whose words appear in the brief; otherwise invent one.\n  Name it in your notes next to the screen's question.\n- **The one chart hue on the main data element**: today's line, the booked bars, the current period,\n  the margin that breaks. A screen whose only hue is a delta reads as a kit, and the inspector warns\n  when a screen with charts carries no hue on its data (`no-data-hue`).\n- **Its people and objects as themselves**: each person gets a stable initial and a pale tint of their\n  own hue, with people listed next to each other at least 60 degrees apart. These tints are identity,\n  not data: they stay pale and out of the chart legends. Products show their thumbnails, cover art\n  shows the cover.\n- **Words of the trade** in labels and empty states (\"Waiting on the customer\", \"Off sick\", \"Due\n  on the 28th\"), never the generic noun of a template (\"Items\", \"Records\", \"Status\").\n\n**Calendars and timelines** (house rule, from testing; the study has none). People down the left on a\nfixed 160-220px column, grouped under a team subheader rather than repeating the team on every row;\ndays across with faint 1px day lines, weekends one tone step darker, and today marked by a 1px line\nin the one data hue with its date in ink. Bars are 20-24px tall at radius 4. One-line names sit on a\n32px pitch; a name with a subline (team, office) needs 40-44px, or the subline touches the next name.\n**Every kind of booking has its own mark**, so sickness reads apart from a holiday at a glance:\nholiday a pale fill, off sick a 1px diagonal hatch, long leave a darker grey step, working away an\noutline, a pending request a dashed outline. A style with a hue budget may add a 3px left edge in the\nhue for the kind the screen is about. Full colour is only for what needs a decision (a request that\nbreaks cover). A label sits inside its bar; a bar too short for it shows the kind's code inside and\nthe full label in its tooltip, or the label after the bar's end, never over the days before it.\nHoliday markers name their office in a multi-office product. Every swatch in the legend is the mark\nitself, scaled down, and lists only kinds on screen: `Charts.timeline(el, rows, kinds)` draws the bars\nand returns that legend from the same kinds map.\n\n## Contents\n\n1. When this applies\n2. The run for an app screen\n3. The shell\n4. The canvas and the page title\n5. KPIs\n6. Charts\n7. Tables and lists\n8. Forms and settings\n9. Type and colour\n10. Density\n11. Empty, zero, loading and error states\n12. The phone\n13. House rules for app screens\n14. Tells of generated dashboards\n\n## 1. When this applies\n\nAn app screen is worked in rather than read. This chapter covers:\n\n- dashboards and overviews: a seller's day, a project's health, a publication's growth;\n- admin and back office: members, orders, events, a catalogue;\n- analytics and reports, including a generated report with no app around it;\n- settings and billing;\n- list screens to work through: inboxes, queues, tables with filters;\n- wallets and finance homes;\n- builders and editors: flow, form and page builders, canvases;\n- the detail page of one object: an event, a deployment, a customer.\n\nA product site that shows its interface is a page; the interface fragments on it follow these rules\nfor their insides (mark each fragment's root with `data-ui`). When a request holds both, build each\nwith its own run and share one palette and one typeface.\n\nThe study is 23 desktop screens. It has no phone screens, no loading or error states, one settings\npage, no inbox and no dense operations table (the densest screen shows about 120 data points). Where a\nrule below goes past the study, it says **house rule**.\n\n## 2. The run for an app screen\n\nDo these in order. The first three steps decide whether the screen is any good.\n\n### 2.1 Inventory the data and the jobs\n\nThe page run inventories the subject's world; an app screen inventories its data. Write in your notes,\nin 8 to 12 lines:\n\n- **the objects** the screen shows (deployments, invoices, members, events, conversations) and their\n  fields, with units;\n- **realistic magnitudes**: how many objects, a typical amount, the range of a rate, how values move\n  over a day, a month, a year, and for a new account how small they really are;\n- **the people**: who opens this screen, how often (a glance once a day, or an eight-hour session),\n  on what device;\n- **the jobs**: what they do next from here (approve, reply, pay, ship, invite), and which job comes\n  up most;\n- **the product's own things**: its name and mark, the workspace or account it is scoped to, the people\n  in it (two partners, a team of six, the club's members), and the objects people recognise by sight\n  (product photographs in a shop, cover art in a media tool, a map of the route). These are what make\n  a screen belong to this product instead of to a template; plan where each one appears.\n\nThen write the data itself: a small dataset in a JSON or JS file that the screen renders from, with\nbelievable names, amounts that add up to their totals, dates in order and a unit on every figure.\nTotals are computed from the rows, never typed in separately. Small numbers stay small: the studied\nscreens show new accounts with 1, 6 or 9 of something, drawn honestly at their real size. Write the\nfigures that must agree as assertions in the data file (`console.assert(sold - cancelled === rsvps)`,\nthe bins sum to the total, the parts to the whole) and read the console: in testing, a ticket table\nthat did not reconcile with its own KPI cost a judge's trust in the whole screen. Checks that need\ncomputed values (allowance after a request, cover per day) go in the script that computes them.\n\n**Data that tells the truth** (house rules, from testing; judges checked every one of these):\n\n- **A fact shown twice is one variable.** A time window, a total or a state that appears in two cards\n  (the battery full 13:30-16:30 in the KPI label, the shaded span and the battery card) is one value in\n  the data file, and the copy and the chart annotation are both built from it. Two cards that\n  disagree by half an hour cost more trust than a missing card.\n- **Totals and deltas come from the parts as shown.** Sum the rounded pennies the screen displays,\n  never round the unrounded total separately: £21.68 + £8.34 − £3.81 is £26.21, and a screen that\n  says £26.22 is caught. A change is the difference of the two values on screen (£5.28 against\n  £5.22 is +£0.06, not +£0.07).\n- **Every relative figure names its baseline** in the same phrase: \"3 h 40 m before close\", \"45 m\n  earlier than last Sunday\", \"+5 on the usual Monday\". \"Early\", \"up\" or a bare \"+5\" next to another\n  time or figure reads as measured against that one.\n- **One name per time.** Shops close at 15:00 and the tills are cashed up at 15:12; the header and\n  the card use the same words for the same moment, and an error state rewrites the status line.\n- **If a caption has to say which bars are which, encode it in the chart instead**: a marked period in\n  a second tone with its own legend entry, a signed axis, a label on the mark.\n\n### 2.2 Name the screen's one question\n\nEvery screen answers one question first: \"Did today's sales come in?\", \"Which deploy broke?\", \"Who is\nwaiting for a reply?\", \"How much of this month's plan is left?\". Write it in one line. It decides\nthree things:\n\n- **what is biggest.** In the study the largest block is always the one that carries the screen's\n  question, whatever form it takes (a chart, a plan, a ring, a list). The same holds for figures:\n  the largest figure on the screen answers the question the title row's sentence answers. In testing,\n  an 88% sun ratio at 32px out-shouted the 24px charging window the title led with;\n- **what comes first** in the reading order;\n- **what is left out.** The studied settings page shows three usage numbers and links to the\n  analytics screen instead of drawing a chart; four screens draw no chart at all because a few\n  numbers say it.\n\nThen name the screen's **one finding**: the fact in today's data that most needs attention (\"9 no-shows\nwhile 8 people waited for a place\", \"the 23:28 deploy doubled the error rate\", \"eating out is £36 over\").\nPut it where it is read first, as the line under the title or the subline of the headline figure,\nnext to the action it drives. In testing, the finding that mattered sat in a 14px caption at the\nbottom of a card and the screen read as flat.\n\n**Do not rebuild a studied screen.** When the product is of the same kind as a screen in the study (a\nfinance home, a deploy overview), its arrangement is the trap: judges recognised the copies at once.\nTake the structure from the product's own things instead: for a couple's budget, Mia, Joint and Tom\nas three columns running through accounts, plan and bills; for a running club, the pace groups.\n\nThen list the screen's blocks as the answers to its next questions, one line each, the way the page\nrun lists claims. A block with no question is deleted. This is how you avoid the stock order of KPI\nrow, big chart, two small charts, table.\n\nThree more lines, each tested:\n\n- **Everything the brief names is on the first screen.** At 1440×900, every block the brief asks for\n  shows its header and its first rows or its figure. Size the headline block to the question (about\n  200-360px tall), cap long lists at 4-6 rows with \"View all\", and put time-sensitive blocks (bills\n  due, SLAs running out, a failed deploy) before long tables. A chart whose line is flat for most of\n  the window does not get the full width: give it two-thirds and put the next answer beside it.\n- **The most frequent job is one click away.** Name it (\"pack the orders due today\", \"reply to the\n  oldest breach\", \"redeploy the failed build\") and put its control where the answer shows: a primary\n  button in the title row, an action on the row that needs it, a \"View logs\" on the failed item. A\n  screen with no control for its main job reads as a report, not as a tool.\n- **Show the evidence beside the answer.** A judge trusts \"Error rate 0.28%\" more with its spike\n  annotated (\"peaked at 3.9% after the 23:28 deploy, reverted\") than with the number alone. One line\n  of explanation on the event that matters is worth more than a second chart.\n\n### 2.3 Choose a style\n\n```bash\nnode <skill>/scripts/draw.mjs --app --kind <kind> --brief \"<one line about the product>\" \\\n  --screens <screens> [--theme light|dark] [--keep palette,type] --options 3\n```\n\nThis deals up to three styles from `library/app.json` (fewer when only two suit the kind and the\ntheme). `draw.mjs --app --list kinds` (or `styles`, `screens` or `signatures`) prints the choices; the\nscreens are `overview`, `analytics`, `list`, `detail`, `settings`, `wallet`,\n`builder`, `inbox`, `home` and `report`. The library holds seven styles, each distilled from the\nstudied screens that share its move:\n\n| Style | Theme | For | The move |\n| --- | --- | --- | --- |\n| `achromatic-ledger` | light | money homes, reports, settings with usage | No colour in the chrome; charts in ink; one small signal where a figure changed |\n| `framed-sheet` | light | B2B analytics, developer platforms, builders | One tinted L-frame; the page on a white sheet inset 8px, no shadow |\n| `accent-ladder` | light | creator and small-business admin with plans | The full hue on small marks only; its pale tints on every area |\n| `editorial-greeting` | light | team and personal homes | The greeting as the h1 in a centred 12-column column; every figure at regular weight |\n| `pastel-consumer` | light | wallets, budgeting | Pale same-hue tiles under one large radius; quiet money polarity |\n| `true-black-flat` | dark | community, events, media | Elevation by lightness alone; colour only on data |\n| `data-terminal` | dark | markets, monitoring | Every selection is the same 1px accent line; signs, not colour, on numbers |\n\nChoose by how the product is used (long sessions or a quick look, money or media, a team or one\nperson, day or night), not by what is most familiar, and write one line on why. Then deal the sheet:\n\n```bash\nnode <skill>/scripts/draw.mjs --app <the same arguments, without --options> --style <id>\n```\n\nThe sheet gives the style's tokens and type, its shell and one pattern for each screen you named.\nKeep the style's one move intact and take every other value from the defaults in this file. Redraw\n(`--redraw style | shell | screen:<name>`) only for a reason you can state: it contradicts the brand,\nor the product is used in a way the style does not suit. With an existing brand, pass\n`--keep palette,type`, map its colours onto the roles in §9 and keep the style's colour budget.\n\n**Then choose its face, before any markup.** The sheet's \"Its face\" list gives two or three ways this\nstyle takes a face from the brief, and \"Signature elements\" lists the library's elements whose words\nappear in the brief (a power flow for an energy home, a sell-out strip for a bakery, a cover matrix\nand a kind-encoded timeline for a leave planner). Write in your notes, next to the screen's question:\nthe face you chose, the signature element (from the sheet, or your own built from the product's\nthings), and where each appears on the first screen. A style dealt to two products must not give them\nthe same face: in four rounds, the screens that skipped this step were scored as the same kit.\n\n### 2.4 Build the shell\n\nBuild the frame first, empty: the sidebar or rail, the top bar if the shell has one, the canvas with\nits gutters, the title row (§3 and §4). `<skill>/assets/app.css` is a neutral start for all of it:\ncopy it into the project and put the sheet's tokens in its `:root`. Look at it at 1440 and at 390 before any data goes in. Do the\ngrid arithmetic now and write it in a comment: the column count, the gutter, and the sum that proves\nthe cards land on the canvas edges.\n\n### 2.5 Put in the data\n\nRender every block from the dataset; draw the charts from it too, with `<skill>/assets/charts.js`\n(`Charts.line`, `Charts.bars`, `Charts.diverging`, `Charts.ring`, `Charts.barList`, `Charts.plan`,\n`Charts.bullet`, `Charts.timeline`, `Charts.matrix`, `Charts.timeStrip`; the file's header lists their\noptions) or your own SVG to the rules of §6, never a chart library's defaults and never a picture of a\nchart. The newer helpers return `{ svg, legend }`: put that legend in the card's header rather than\ndrawing your own, so each swatch is the mark it explains. Format every figure by §7.4: separators, fixed decimals per\nmetric, a sign on every change, units as smaller grey suffixes, tabular figures, right alignment in\ncolumns. Use the product's own words for labels. No placeholder data: the inspector fails lorem ipsum,\nAcme, John Doe and their kind. Proof is not invented here either: no vanity totals, no \"+12%\" on an\naccount that is a week old.\n\n### 2.6 Build the states\n\nFor every block, build its empty, zero, loading and error state (§11); for every row and control, its\nhover, selected, focus and disabled state. Look at each one in the browser. A screen that only works\nwith full data is half built.\n\n### 2.7 The check\n\n```bash\nnode <skill>/scripts/lint.mjs --app <source files or folder>\nnode <skill>/scripts/inspect.mjs --app <url or path/to/index.html>\n```\n\nA sheet dealt with `--app` switches both tools to the app rules by itself. The inspector opens the\nscreen at 1440, 768 and 390 and measures what this chapter asks for: an h1 (and reports it as the\nscreen's hero); a sidebar that folds on the phone; the canvas used to its right edge; panel shadows\nand borders; the number of corner radii; cards in one row that end apart, where a column of cards\nstacked with the gutter counts as one block (`ragged-row`); a blank band inside a card of over 40px,\nor over 64px before a new section's heading (`panel-void`); icons in tinted squares; numeric alignment and tabular figures; chart hues; colour\nshare, and a screen with charts but no hue on its data (`no-data-hue`); placeholder data; text under\n11px; and the page rules that still hold (contrast, gradients, the banned palettes, emoji). Fix every\n`FAIL`. Treat each `WARN` as wrong unless you can defend it to a designer in one sentence.\n\nThen look at the screenshots, every width, and answer these in writing. This is the critique for an\napp screen: the caps in `critique.md` for pictures, motion and the page's live element are page rules\nand do not apply here.\n\n1. Is the screen's question answered by the biggest thing on it, and is that read first? Is the\n   largest figure the one that answers the title row's sentence?\n2. Does every block share the screen's edges? Is there a dead strip on one side, a card stopping\n   short, an orphan cell, a stretched card with a blank band (a legend pinned to its foot, four rows\n   in a card kept at its neighbour's height)?\n3. Is colour only on data, on status and on the one primary action, and does the main data element\n   carry the one hue? Does the face you chose show on the first screen?\n4. Do the numbers add up, and do they line up digit for digit? List every fact that appears twice\n   and check that the copies agree; recompute each total and change from the values as displayed;\n   check that every relative figure names what it is against.\n5. Does every zero look like a zero and every missing value like a dash? Does every count badge sit\n   on a queue that needs action, with its noun clear from the label?\n6. Does every legend swatch match the mark it explains, and does any caption have to say which bars\n   are which (then encode it in the chart)? Does any label collide with a line or another label?\n7. On the phone, is the navigation folded away, and does each block still answer its question?\n\nFix the worst three, inspect again, look again. Three rounds at most. Judge the pictures: if a problem\nshows in a screenshot, it is real, whatever the code says.\n\n### 2.8 Report\n\nTell the user, briefly: the style dealt (name and seed) and any redraws with their reasons; the face\nyou chose and the signature element; each screen's one question; any check you allowed and why (for example `--allow icon-chips` for node-type\ntiles in a builder); and the sample data that must be replaced with real data, listed so it can be\nfound.\n\nApp screens have no motion floor. Motion is feedback: press, hover, focus, a menu or a sheet opening,\na row arriving. Nothing on the screen performs an entrance (house rule).\n\n## 3. The shell\n\n### 3.1 Five archetypes\n\n| Shell | In the study | What it is |\n| --- | --- | --- |\n| **Open plane** | 5 screens | A labelled sidebar on the page ground (or within 1-2% of it), separated by nothing or by one 1px hairline. No top bar: the header and the cards sit on the ground. The canvas is fluid with a 24-64px gutter, or a centred column. |\n| **Tinted frame, white sheet** | 8 screens | Sidebar and top bar share one tinted ground (#f6f6f6-#f9fbfc) with no rule between them; the page sits on a white sheet inset 8px from the window's right and bottom edges, radius 10-16 (median 16), a 1px #eaeaea-#ededed edge and no shadow. Variants: a flush L-frame, the inset sheet, and floating panels inset 8-12px with a 12px gap. |\n| **Ruled T-frame** | 4 screens | A 210-240px sidebar and a 64px top bar on one ground, divided only by 1px rules. The workspace switcher sits at the top bar's right end behind a full-height divider. Three of the four are dark. |\n| **Icon rail** | 3 screens | An unlabelled rail 50-60px wide (median 55); 15-18px icons on a 34-49px pitch; the active item marked by colour or by a 2% tint band; groups split by 20px hairlines. It saves about 180px of width. |\n| **No sidebar** | 3 screens | A 46-48px top bar over a centred 1088-1208px column with 152-212px gutters; the logo sits on the column's left edge. For reports, viewers and products with few destinations. |\n\nAll six dark screens use one ground everywhere, divided by 1px rules of #161616-#232323 or by nothing.\nNo screen in the study puts a dark or saturated sidebar against a light canvas (0 of 17).\n\n### 3.2 Sidebar\n\n- **Width.** Labelled sidebars run 210-292px; the median is 230 and most sit at 224-240. One floating\n  sidebar card appears (280px wide, 40px in from the window edge).\n- **Rows.** A 32px hit area on a 34px pitch is the mode (7 screens); the roomy versions run 40-52px on\n  a 42-60px pitch. Icons are 14-20px, median 16, outline at about 1.5px stroke on 14 of 16 screens.\n  Labels are 14px at 400 on 12 of 16, in ink or in a grey of #4b4d4f-#63666e, about 8-10px after the\n  icon, with the label column at x 36-48.\n- **Active item.** A neutral grey pill with the label unchanged, on 8 screens: radius 4-16 (median 8),\n  inset 8-14px from the sidebar's edges, a fill of about #e9e9e9-#ededed. On dark, brightness alone:\n  the label goes from #bbb to #fff (3 screens). Colour alone on the icon or label (3, all of them\n  rails or a floating card). A tinted accent fill (3). A left accent bar once in 23. The weight\n  changes on 2. Default: the grey pill on light, brightness on dark.\n- **Groups.** Sentence-case grey labels at 12-13px, never uppercase (9 screens), with 22-56px of air\n  above and 13-33px to the first item; or hairlines instead (4). Utilities such as settings and help\n  pushed to the bottom (5).\n- **Top and bottom.** The workspace or account switcher at the top of the sidebar (7 screens), at its\n  bottom (2), or in the top bar. The bottom holds a user row (8) or one upsell (8); one of those\n  upsells is a filled accent button.\n- **The product is named** (house rule, from testing). The product's mark and name sit at the top of\n  the sidebar or rail, and the scope (workspace, team, project, account) is shown as a switcher or a\n  breadcrumb. A screen whose product cannot be named from the screenshot reads as a template.\n- **Counts on nav items** (house rule, from testing). A count appears only on a queue that needs\n  action, and its noun is clear from the label: \"Requests 5\", \"Price changes 3\". A bare \"Range and\n  prices 9\" left the judge asking nine of what.\n- **Labels by default.** A labelled sidebar unless the product has five destinations or fewer and the\n  screen needs the width (a research or monitoring view); an icon rail always carries the product's\n  mark at the top, a tooltip and an accessible name on every icon. Nav items are other screens, never\n  anchors into the current page (a sidebar that scroll-spies one long page was marked down twice).\n\n### 3.3 Top bar\n\n14 of 23 screens have one; the default is none. Heights fall into two groups: 44-51px (median about\n48) on light chrome, and 64px, usually with a 1px rule. A top bar must hold something real: search,\nthe workspace switcher, or the page or object name. Search sits centred on the window at 548x32 with\na shortcut hint (2 screens), or at 457-537x36 in a no-sidebar bar. The right cluster is inset 24-46px\nfrom the edge. Two screens leave about 1070px of their top bar blank; both are flagged for it.\n\n### 3.4 Right rail and pinned columns\n\nOne screen has a right rail: a fixed 384px column in a `1fr 384px` grid with a 24px gap, starting\nlevel with the first card rather than with the title, its section headings outside the cards and 8px\nabove each. Use one only for a stable secondary stream: recent items, the details of the selected\nobject, share links. A pinned left column appears once: a 306px accounts card at the viewport height\nminus 72px, so net worth stays in view while the rest of the screen scrolls.\n\nFive screens float a button (24-56px), and one of those buttons covers the content it sits on and is\nflagged. House rule: no floating button unless it is the screen's one primary action and covers\nnothing at any width.\n\n## 4. The canvas and the page title\n\n### 4.1 Width and gutters\n\n- **Fluid** (14 screens): side padding 17-64px, median 29, with 24 and 36-40 the common values;\n  content 1120-1312px wide, median about 1204.\n- **Centred** (8 screens): 624, 864, 1088, 1100, 1152, about 1190 and 1208px; median about 1126.\n  Data pages land at 1100-1250 either way. Only two personal homes go narrow (624 and 864), and both\n  are flagged for wasting the width.\n- **Top offset**, from the canvas top to the title: 20-88px, median about 36. Tools sit at 20-36;\n  greeting homes at 50-88.\n- **One gutter.** Use one gap value horizontally and vertically. Mixed gutters (12 against 16, 20\n  against 24, 16 against 12) are flagged on 8 screens.\n\n### 4.2 One left edge, one right edge\n\nThe strongest screens run a single left edge from the header to the last row. One indents its page\nheader by the cards' 24px padding, so the title, the card titles, the numbers and the chart all start\non one line. Row rules may bleed 7-8px past the text column while the text stays on it.\n\nThe grid's arithmetic closes: 3 x 372 + 2 x 17 = 2 x 568 + 16 = 1152; 12 x 77 + 11 x 16 = 1100;\n4 x 144 + 3 x 16 = 624; a second-row card exactly as wide as the two cards above it\n(251 + 24 + 515). Write your sum down.\n\nFailures to avoid, all from the study: cards stopping 120px short of the sheet's right edge; a 0px\nright gutter against a 40px left one; a column centred on the window instead of on the area beside\nthe sidebar (204px on its left, 444px on its right); a medallion 108px off the column's axis. The\ninspector warns when the content stops well short of the right edge.\n\n**Dead space from a grid that does not fit the data** is the commonest failure in the study (10\nscreens): four KPI tiles in a three-column grid, orphaning the fourth; one card alone in a\nthree-column row beside 810px of nothing; a card stretched to its neighbour's height with 250px of\nblank under its legend. Choose the column count from the number of items, let a lone card span, and\ndo not stretch a card's frame over empty space.\n\n**Cards that share a row share a bottom edge.** In testing, rows whose cards stopped 26-190px apart\nwere marked down every time, by judges and by the inspector (`ragged-row`). Balance the row by its\ncontent first: move a list's rows so the two columns hold the same number, cap both lists at the same\ncount, or pair blocks of similar height. Two cards stacked in one column beside a tall card count as\none block: they balance when the column ends level. Only when the contents cannot balance, stack the\ntwo blocks, or let the shorter card fill the row height with its content top-aligned and the footer\naction (a \"View all\", a total) pinned to its bottom so the extra height is not a hole.\n\n**A stretched card stretches only when it has content to fill.** Only an action or a total may be\npinned to a stretched card's foot; a legend or a note stays directly under its chart. In testing, a\ncover card stretched to its neighbour with its legend pinned to the bottom left 60px of blank under\nthe last row, and a sell-out card left 45px above its links. When the content is short, let the card\nkeep its own height (`align-items: start` on the row), move its footer link into its header, or give\nthe row a block of similar height. A filtered block shrinks to its rows, or keeps a fixed number of\nrows with one sentence in the empty ones; four rows over 270px of empty card is a hole. The inspector\nwarns on a blank band of over 40px inside a card (`panel-void`).\n\n**Narrow blocks do not span the canvas.** A table of five columns or fewer, or a list of six rows or\nfewer, runs to about 760px at 1440 and pairs with the next block; stretched to 1300px it leaves\n400-600px voids between a name and its first figure.\n\n### 4.3 The title\n\n- **Every screen has one h1**; the inspector fails a screen without one. 14 screens set it in the\n  canvas at 18-48px, median and mode 24, at 600-700 (700 on 8). The rest have nothing over 16px: a\n  breadcrumb or the top bar names the page. Then the breadcrumb's last item is the h1, at 16px, and\n  the screen's name is still the first thing read.\n- **A noun, not a greeting**: \"Analytics\", \"Overview\", the project's or the object's name. 3 of 23\n  greet, and one adds an emoji, which goes. A greeting suits a personal or team home only.\n- **An optional second line**: one 14-16px grey sentence about the data or the object (the finding,\n  the period, the scope), never about the interface (\"the filters narrow every block…\", \"this page\n  shows…\" read as instructions, not a product), or a 12px line\n  naming the data's source.\n- **Right of the title**: actions only when they are real (10 screens); otherwise nothing. A freshness\n  stamp (\"Updated Jul 27, 4:09 PM\", with a refresh button) on 6.\n- **The primary action.** 12 of 23 have no filled primary button; 5 make it near-black (#1d1f20,\n  #1f2937) or inverted white on dark; 4 fill it with the brand hue. One primary per screen.\n\n### 4.4 Tabs, filters and the date range\n\n- **The date range** at page level (7 screens) or on each card (7), never both. A card that states its\n  own period puts it in its header, right-aligned, in grey.\n- **Underline tabs** (8 screens) always sit on a full-width 1px rule; the indicator is 1-4px (median\n  2), as wide as the label or running 8-11px past it.\n- **A segmented track** once: 48px, #f3f4f6, a white 36px active pill, and the date select inside its\n  right end, so tabs and range read as one row. A segmented control is as wide as its options, and full\n  width only below about 480px: three options spread across a 680px tablet card read as a progress bar.\n- **Control height** in title and filter rows: 28-40px, median 34, clustering at 32 and 36.\n- **Order**: scope on the left (the date first, then the filters), utility and refresh on the right.\n- **Compound filters** that read as a sentence (\"Date | Jun 14 - Jul 13 | Daily\"), 28px tall and 8px\n  apart, once.\n- **To the first card**: 13-64px, median 24.\n\n## 5. KPIs\n\n- **No tile of its own.** 11 of the 20 screens with headline numbers give a KPI no tile: bare text on\n  the page or on a card (5), or one container split by 1px hairlines (6). 9 use one card per KPI,\n  61-147px tall (median about 108). The default is one container split by 1px dividers into equal\n  columns. 7 screens have no KPI row at all and put each headline number in the card that explains\n  it, which is often better.\n- **Count.** 1-6 per row, median 3-4. The count matches the grid: four KPIs get four columns.\n- **Size.** Values 16-40px, median 26, mode 24. Values in their own tile run larger (median 30) than\n  in a shared strip (median 24). Nothing at 48px or over. Labels 12-16px, median 14; the value is\n  about 1.7 times the label.\n- **Weight.** An even split: 400 on 8 screens, 600 on 6, 700-800 on 6. A large number at regular\n  weight under a semibold label is the common pattern. Bold for money only.\n- **Order.** Label above the value on 14 screens; labels grey (#6b6b6b-#aaa) on 13; sentence case.\n- **Nothing else.** No icon in a coloured circle (0 of 23), no sparkline (0 of 23), no tinted tile.\n  An info icon beside the label is fine (5 screens). Units are a smaller grey suffix: \"5 mins\" at 24\n  over 14, \"2 m 24 s\", \"5 /10\".\n- **The answer figure leads.** When one figure is the screen's answer (a balance, net worth, the\n  portfolio's value), it is 30-36px and at least 1.3 times its sibling figures (those at 18-24px). In\n  testing, a 24px portfolio value beside two 24px figures left the screen without a lead. No other\n  figure on the screen is larger: the biggest number answers the title row's sentence, so a\n  secondary ratio in another card stays at the siblings' size.\n- **One figure, one place.** A figure shown in the strip is not repeated in a legend beside it, and a\n  KPI strip whose every cell names a panel below (RSVPs, then an RSVPs panel) is dropped: lead each\n  panel with its own number instead.\n- **A second job.** KPIs may be the chart's series tabs or the list's type filter (the selected card\n  takes a 1.5px border). As tabs, the selected one carries a 2px rule or the active fill and an ink\n  label; the others keep a grey label and their value in ink, at 400 against the selected one's 500.\n  A grey value reads as disabled: in testing, three shops' takings set in grey because they were tabs\n  read as secondary, though they were the brief's first ask. When the tabs are the per-entity\n  breakdown the brief asks for, grey nothing and let the rule alone mark the selection. On a phone the\n  tabs become a 2-up grid with the selected cell filled, or a row that scrolls sideways; never an\n  underline floating inside the grid (`app.css` does both).\n\n### Deltas\n\n- Optional: 9 of the 20 KPI screens show one; 11 do not.\n- 10-15px (median 14), never larger than the label. Text or a small glyph on 6 screens; a pale pill\n  on 3.\n- **The window in words**: \"vs prior 30 days\", \"in the last 90 days\", \"from 0 (last 4 weeks)\" (7 of\n  the 9).\n- **Colour only the number**, or set the whole delta in grey.\n- **Colour says good or bad, not up or down** (house rule, from testing). Every metric has a good\n  direction: latency, error rate, cost, churn and time-to-reply are better when they fall. A change\n  in the bad direction puts `--negative` on the number (or a small down-pointing glyph in that\n  colour); a change in the good direction is `--positive` or grey. A judge read a 2.5× rise in errors\n  set in the same grey as a rise in visits as hiding the screen's only bad news.\n- **Zero or undefined change is grey.** The study's commonest KPI failure is a zero or undefined change\n  shown as a signal: three identical green \"up 100%\" pills grown from zero, a \">999%\", a bold red\n  \"0.00%\", a green \"+0\". When the prior period was zero, write \"+4 (new)\"; when there is nothing to\n  compare, a short grey dash where the delta would be.\n\n## 6. Charts\n\n### 6.1 Which chart for which question\n\n| Question | Form | In the study |\n| --- | --- | --- |\n| Is it moving over time? | One line; an area only with a fill of 15% or less | 9 screens |\n| How much per period? | Columns with square corners | 3 |\n| How is it distributed? | A histogram with equal bins | 1 (its unequal bins are flagged) |\n| Who ranks? | A sorted horizontal bar list, or the row's fill as the bar in a one-figure list | 3 |\n| What share? | A thin ring, or a 100% stacked bar with 2px seams; five parts at most | 5 |\n| How far to the target? | A progress bar, both ends labelled, the fill the true ratio | 4 |\n| How much of the plan is used? | A track as long as the plan, the spent part filled, what is already committed as a lighter segment, an overrun past the track's end in the negative colour (`Charts.plan`) | house rule |\n| Has it drifted from its target? | One row per part: the current share as a bar with a 1px tick at the target (`Charts.bullet`); never two stacked bars to compare | house rule |\n| Where? | A map with a list beside it; the list carries the magnitudes | 1 |\n| Per period, and the running total? | The two side by side at equal width, with the same dates | 1 |\n| Which way did it flow, and how much? | Columns above and below one zero line on one scale, the axis signed and captioned on each side (\"Sold\" above, \"Bought\" below), a marked period in a second tone with its own legend entry (`Charts.diverging`) | house rule |\n| Who is away when? | A timeline of people by day, each kind of booking its own mark (`Charts.timeline`) | house rule |\n| Is there enough cover? | A team-by-day matrix of slack against the minimum (+2, +1, 0, −1), one hue ramping toward the negative colour, the headcount on hover (`Charts.matrix`) | house rule |\n| When in the day, against last time? | One row per item on a shared opening-to-closing axis: a 2px grey track, an ink dot for today, a hollow tick for the comparison day (`Charts.timeStrip`) | house rule |\n\nThree more, from testing:\n\n- **The pair of per-period bars and the running total is used once per screen**, and only when the\n  total crosses a line that matters (capacity, a target). Three such pairs in six charts read as one\n  pattern stamped out.\n- **A series that is flat except for one event** gets at most two-thirds of the width and about 140px of\n  height, or a range capped at about twice its reference line with the off-scale peak labelled\n  (`Charts.line({ max })`). A full-width plot that is 85% empty was the biggest block on a first\n  screen and was marked down.\n- **A forecast is not a fact**: after today the line is dashed and the end value is labelled\n  (`Charts.line({ today, endLabel })`), with the gap to the target bracketed when there is one.\n- **What the brief asks to see over time is drawn on the first screen.** KPI cells may switch the chart\n  only between metrics the brief did not name.\n\nWhen there are only a few numbers, draw no chart: four screens skip it, and the settings page links\nto the analytics screen with \"View more\".\n\n### 6.2 One question, one series\n\nOne series per chart is the norm; three is the most any screen draws. To show another metric, switch\nit with a control (a segmented control, a dropdown, the KPIs as tabs) instead of overlaying lines.\nPlots run 112-264px tall (median about 195) and 316-1136px wide (median about 570), an aspect of 1.8\nto 5.2.\n\n### 6.3 Axes and gridlines\n\n- **Gridlines** run horizontally only on 7 of the 12 cartesian charts, both ways on 3, and not at all\n  on 2. Use 3-5 (the study runs 3-7, median 4-5): 1px, solid, about #e5e5e5 on light (range\n  #cfcfd2-#f2f2f2), #2b2b2b on #111. Dashed lines are allowed in chart grids (4 screens: 3/3, 4/4,\n  3/2.5) and nowhere else on the screen.\n- **No y-axis line.** The baseline is the one heavier line (2px on two screens, 1px on one); full axes\n  on one.\n- **Y ticks**: 4-7, median 5, at 11-16px (median 12) in grey (#5f5f5f-#6c6c6c), on the left (8\n  screens) or the right (2). Round, even steps (0/5/10/15%; 0-600 by 150), the top tick above the\n  maximum, integers for counts, and zero as the baseline for bars and counts.\n- **Never without a scale.** Two screens draw no y-scale and show magnitude only on hover; both are\n  flagged. So are uneven ticks (0/3/6/10), a 0.8 tick on a count, a top tick equal to the maximum so\n  the line hits the plot's edge, and a cumulative axis that starts at 1.\n- **Axis text no larger than the data.** 15-16px ticks beside 14px values are flagged as louder than\n  the numbers.\n- **X labels**: 4-8 per chart, flat, never rotated (40 degrees is flagged), the first and last pulled\n  inside the plot, on one step all the way: a forced closing label after 14:00 on a 90-minute step\n  left a short last gap that a judge measured. Choose a step that lands on the end (hourly from 08:00\n  to 15:00) or leave the end unlabelled. Labelling only the two ends hides when things happened. Irregular dates on a\n  categorical axis are flagged: time goes on a time scale.\n\n### 6.4 Marks\n\n- **Lines** 1-3px, median 2, in straight segments. Four screens smooth their lines, and one smoothed\n  curve invents values between daily totals (flagged), so draw straight segments. No point markers,\n  except a hover dot (8px on one screen).\n- **Fill**: none on 7 of 10 time charts. At most a flat tint of about 14%, or a fade from the line to\n  transparent over 150-200px.\n- **Bars** have square corners (4 screens), or at most a 4px top radius with a square bottom on the\n  baseline. Stacked segments are split by a 1-2px seam.\n- **Colour.** One hue per chart. The accent touches only data on 8 screens, and data ink is under 3%\n  of the pixels on most. Neutral series are fine and often better: a near-black line that turns pale\n  grey after the cursor; a white line against a red one; signs instead of colour (\"+$24,000,000\").\n  But the one hue, when the style has one, goes on the screen's main data element (today's series,\n  the booked bars, the current period, the margin that breaks), not on a secondary chart or a delta:\n  in testing, an all-ink screen with no hue on any of its data read as a kit.\n  One subject keeps one hue across the screen: the same subscribers drawn pink in one chart and indigo\n  in the next is flagged. Unrelated hues on one screen (three, five) are flagged every time. Status\n  colours are for status. The inspector warns over four hues and fails over six.\n- **Legends.** None for a single series (9 charts): the title or the dropdown names it. Otherwise five\n  items at most, as a 5-8px dot with a 12-14px grey label in the card's header, or as a small table\n  (dot, name, value, change) that makes the legend carry data. Never list a series that has no data\n  (flagged). Every swatch is the mark it explains, scaled down: the legend dot is the line's colour,\n  a hatched bar's swatch is hatched. A swatch drawn separately from the mark drifted from it in testing\n  (a black outline with a red edge explaining a red outline); the helpers return the legend built from\n  the same style object as the marks.\n- **Rings** only for three to five parts of a whole that are not already listed beside them (a ring\n  redrawing the spent, due and left figures of the tile next to it was marked redundant). Never\n  labelled on the slices; the total sits in the centre or beside the ring. The\n  screens noted for their rings use thin strokes: 3-5px on a 90-154px ring, 8px on 182px. Two others\n  use 28 and 37px.\n- **Progress bars** are 4-24px tall (median 8), fully rounded, with both ends labelled (\"Skilled 200\"\n  and \"Expert 2,000\"); the fill is the true ratio, so 303 on that scale fills 22px of 392. A zero has\n  no stub (a 6px stub at zero is flagged).\n- **Tooltips** are bare text or a plain box without an arrow: label and value on one line.\n- **Annotate the event that matters.** A step or a spike more than about three times the usual change\n  gets a 1px marker and a 12px label naming its cause (\"Deploy a3f09c1\", \"Newsletter featured\");\n  reference lines (a budget, an SLO, a start time) are 1px dashed with their label at the end. In\n  testing, an unexplained jump was the first thing a judge asked about. `Charts.line`,\n  `Charts.bars` and `Charts.diverging` take `annotations` and `reference`.\n- **Labels never collide.** Annotation labels sit in rows above the plot, each beside the top of its\n  own leader line, and no leader line runs through another label; the rows are reserved only when a\n  label exists, so a chart without one has no dead band above it. The \"Now\" label of a forecast goes\n  on whichever side of its line the series does not cross. Lay labels out after the fonts load, or\n  the label set changes between loads (it did in testing). The helpers do all of this; give a label\n  that may not fit a `short` form.\n- **Use the helper, then extend it.** Draw charts with `assets/charts.js` and add what a chart needs to\n  it, rather than writing new axis code: in testing, every chart written from scratch on a phone put\n  its y labels on top of its line.\n- **Short and empty histories are drawn honestly**: a flat zero line with one spike, missing bars for\n  empty periods, no padded y-range, no \"No data\" picture. Do not give one point the screen's largest\n  plot, though: a lone dot in a full-size grid reads as barren (flagged once).\n\n## 7. Tables and lists\n\n### 7.1 Rows\n\n- Single-line data rows: 36-53px, median 45.\n- Two-line rows with media: 56-92px, median 72. The pitch is the media's height plus 24-32px\n  (48 + 24, 48 + 32, 50 + 30).\n- Key-value and legend rows inside cards: 21-32px.\n- In a two-line cell, line 2 sits about 21px below line 1 (19-23), one size smaller (12-14px) and\n  grey. Two-line labels need a 40-44px pitch at least: on a 32px pitch a subline nearly touched the\n  next row's name and the list ran together (house rule, from testing).\n- Overview lists show 2-5 rows.\n\n### 7.2 Header\n\n- 11-14px, median 12, mostly regular weight, grey, sentence case (9 of the 11 headed tables). The one\n  uppercase header in the study is flagged as louder than the data.\n- **No fill band** (0 of 11) and **no rule under it** on 8 of 11. Where there is a rule, it is the\n  strongest line in the table (#e5e7eb over #f3f4f6 row rules).\n- Header row 36-40px.\n- Numeric headers are right-aligned and flush with their values; a header that stops 15px short of\n  its column is flagged. A header over a control aligns with the control it labels (centred over a\n  column of steppers), and a delta beside a stepper gets its own narrow unlabelled column; three\n  alignments in one header row were flagged.\n- A sort glyph on the active column only.\n\n### 7.3 Dividers\n\n- **No zebra striping** (0 of 23).\n- No row dividers on about half the lists; they rely on a 61-92px pitch or on 2-8px gaps between\n  filled rows.\n- When present: 1px, 3-7% darker than the surface (#ededed-#f4f4f4 on white; #161616 on #000,\n  #1b1a1f on #131217).\n- Extent: bleeding 8-9px past the text edge; starting at the text column and skipping the media; or\n  the full inner width. Pick one per screen.\n\n### 7.4 Figures and alignment\n\n- **Numbers right-aligned**, in tabular figures or a monospace. Every left-aligned numeric column and\n  every column of proportional digits in the study is flagged (durations \"00:00:12\" and \"00:00:04\"\n  that jitter, cents that drift).\n- **Fixed decimals per metric**: money 2, percentages 1 or 2, counts none. Thousands separators\n  everywhere (\"$16,531.54\"); abbreviate only in a capacity line (\"12.7k of 20.0k\"). A sign on ever\n\n<!-- [TRUNCATED AT 50KB] -->","skills/taste-skill/references/colour.md":"# Colour\n\nThe direction sheet deals a palette with named roles. This file is how to apply it so the page looks\ndecided rather than tinted.\n\n## Contents\n\n1. What the study measured\n2. The roles\n3. Proportion\n4. Surfaces without lines or shadows\n5. Colour fields\n6. Dark pages\n7. Colour and photographs\n8. Contrast\n9. Banned families, and what \"warm\" means here\n\n## 1. What the study measured\n\n- 41% of the studied pages are dark, 59% light. A quarter sit on pure white; 12% on pure black.\n- Schemes, as the panel classed them: monochrome plus one accent 23%, light neutral 22%, dark neutral\n  14%, several flat colours 13%, strictly two-tone 12%, colour carried by photographs 9%, one saturated\n  field 6%.\n- Buttons are neutral (black, white, grey) on 52% of sites. A coloured button is a choice, not a\n  requirement.\n- Gradient fills appear on 22% of the top-scored sites and 52% of the weak ones; gradient text on 2%\n  against 13%.\n- One site in 246 has a terracotta primary button and none has a violet one. Those are colours of\n  generated pages, not of the gallery. Warm off-white grounds do occur (32 sites), nearly always with\n  a dark or green ink rather than an orange accent.\n- Top-scored sites change the page's field colour between sections more often (a median of two section\n  grounds against one).\n\n## 2. The roles\n\n```css\n:root {\n  --bg: …;          /* the ground: most of the surface */\n  --surface: …;     /* one tone step from the ground: filled panels, form fields, tiles */\n  --ink: …;         /* main text and the strongest marks */\n  --muted: …;       /* secondary text; still passes contrast on --bg */\n  --accent: …;      /* the one accent */\n  --accent-ink: …;  /* text on the accent */\n  /* --field-1 … --field-n and their inks, when the palette has section fields */\n}\n```\n\nUse the tokens for every colour in the build. A raw hex in a component is a second palette starting.\nDo not add greys between the roles: if you need a quieter text, it is `--muted`; if you need a quieter\nsurface, it is `--surface`.\n\n## 3. Proportion\n\nDecide the shares before colouring anything and check them in the screenshot:\n\n- **Ground:** 70–90% of the page.\n- **Ink:** text and perhaps one inverted section (ink as ground, ground as ink).\n- **Accent:** under 5% of any screen. It marks the action and at most one other recurring thing. The\n  moment it appears in five places it stops meaning \"here\".\n\nPalettes with fields (flat-loud, pastel) work differently: each section is one field at full strength\nand the proportion rule applies inside each section (field, its ink, nothing else).\n\nThe accent is not for headings, icons, bullets, borders or underlines unless the direction sheet says\nso. A headline is ink.\n\n## 4. Surfaces without lines or shadows\n\nWith rules and shadows banned, a surface is told apart from the ground by tone alone:\n\n```css\n.panel { background: var(--surface); }          /* 2–6 lightness points from --bg */\n.field { background: var(--surface); border: 0; } /* inputs: filled, with a clear focus state */\n.field:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }\n```\n\n- One step is enough. If a panel does not read, increase padding or separate with space before\n  reaching for a second tone.\n- Do not nest a panel inside a panel.\n- Images do not need a frame. If a light photograph melts into a light ground, change the crop or set\n  it on `--surface`, do not outline it.\n- A thick bar (4px or more) in ink or accent is a graphic element, allowed where the direction uses\n  it. A 1px line is not.\n\n## 5. Colour fields\n\nA section that changes the whole ground colour is the strongest colour move available, and it replaces\ndividers, cards and background decoration at once.\n\n- Fields meet edge to edge with a hard line. Nothing fades.\n- Every field has its own assigned ink from the palette. Never put `--muted` on a coloured field; use\n  the field's ink at full strength, or at 70% opacity for secondary text if it still passes contrast.\n- Neighbouring fields should differ in lightness, not only in hue, or the page vibrates.\n- Order them like chapters: open strong, rest, surprise, close dark or very light.\n- The page's meta theme colour and the navigation follow the first field.\n\n## 6. Dark pages\n\n- Put `color-scheme: dark` on the root so form controls and scrollbars follow.\n- The ground is a deep tone with a slight tint from the palette, and the ink is a soft light, not\n  `#fff` on `#000`, unless the palette deals exactly that for a stark two-tone direction.\n- Secondary text is where dark pages fail: check `--muted` against the ground (4.5:1).\n- Depth on dark comes from a lighter surface step, never from glows or coloured light.\n- Use lighter font weights than you would on a light page.\n\n## 7. Colour and photographs\n\n- When photographs carry the colour, the interface stays neutral and takes its ink from the darkest\n  tone in the imagery.\n- Do not wash a photograph with the brand colour. Either leave it alone, or commit to a real treatment\n  for every image on the page (all greyscale, or all untouched).\n- Text over a photograph needs a calm region. If there is none, move the text off the image. A neutral\n  scrim (black or the ink colour, 30–55% opacity, flat or fading over the text area only) is the one\n  gradient the inspector allows.\n- A flat field sampled from a photograph (its sky, its shadow) makes a section sit with that image.\n\n## 8. Contrast\n\n- Body text 4.5:1 or better; display type and large numerals 3:1 or better; the dealt palettes meet\n  7:1 for ink on ground.\n- `inspect.mjs` computes contrast for text on flat grounds and fails anything under 2.6:1. It cannot\n  see text over photographs: check those in the screenshots yourself.\n- Do not lower opacity on text to make it \"soft\" unless you have checked the resulting ratio.\n- Focus states and hover states increase contrast, never reduce it.\n\n## 9. Banned families, and what \"warm\" means here\n\nThe inspector fails these:\n\n- **Cream with terracotta.** A yellow-cream ground (roughly hue 22–62, light and noticeably\n  saturated) with a rust, clay or burnt-orange accent is the house look of AI assistants and of the\n  pages they generate. Either half alone is suspect; together they are unmistakable.\n- **Violet and indigo.** The first wave of generated pages was purple; it still reads that way.\n\nIf the brief wants warmth, get it from a low-chroma stone, bone or putty ground (saturation under\nabout 15%), from a deep green, brown or oxblood ink, from photographs, or from a full warm field\n(mustard, tomato red, pink) used flat and with conviction. Warmth is not beige.\n\nIf the brand itself owns one of the banned colours, it is the brand's and you keep it: use\n`--keep palette`, pass `--allow palette-purple` (or the relevant rule) to the inspector, and note it in\nthe report.\n","skills/taste-skill/references/copy.md":"# Words\n\nCopy is the first design decision. A headline that needs four lines cannot be rescued by typography,\nand a page of slogans cannot be rescued by layout. Write the page as plain text before any markup.\n\n## Contents\n\n1. Write the argument first\n2. The two-line headline (with the character budget)\n3. Headline shapes that work\n4. Supporting line, body, buttons\n5. Proof without inventing it\n6. Things that read as generated\n7. Micro-typography\n\n## 1. Write the argument first\n\nAnswer in one line each, in a scratch note:\n\n- Who is reading, and what do they already know?\n- What is this, said the way its maker would say it to a friend?\n- What single thing should the reader believe after one screen?\n- What would make them believe it (a picture of the thing, a number, a name, a demonstration)?\n- What do they do next?\n\nThen list the page as claims, one per section, each with its proof:\n\n```\n1. It is a three-legged oak stool, made to order.             → the stool, large\n2. Each seat is cut from one board, so the grain is yours.    → three close-ups\n3. It takes six weeks, and you can follow it.                 → the stages, photographed\n4. It costs 240 and is delivered by the maker.                → price, button\n```\n\nA section with no claim is filler; delete it. This is also how you escape the stock order of\nhero, logos, features, testimonial, pricing, call to action: the order of the argument is the order of\nthe page.\n\n## 2. The two-line headline\n\nA headline is a title. It is held in one glance. On the studied gallery sites the hero headline has a\nmedian of 5 words and 70% sit on one or two lines at desktop width. Every headline on your page, at\nevery viewport, fits in **two lines or fewer**. `inspect.mjs` measures this at 1440, 768 and 390 pixels\nand fails the page otherwise.\n\nThe constraint is arithmetic, so do it before you fall in love with a sentence:\n\n```\ncharacters per line ≈ line width in px ÷ (font size in px × k)\n\nk ≈ 0.40  condensed faces\nk ≈ 0.50  most grotesks and serifs at display size, tight tracking\nk ≈ 0.58  wide / extended faces, all-caps settings\n```\n\n| Where | Line width | Size | Per line | Two-line budget |\n| --- | --- | --- | --- | --- |\n| Phone 390, 20px gutters | 350px | 44px | ~16 | **~32 characters** |\n| Phone 390, 20px gutters | 350px | 34px | ~21 | ~42 characters |\n| Tablet 768 | 690px | 64px | ~22 | ~44 characters |\n| Desktop, 12-col measure | 1100px | 104px | ~21 | ~42 characters |\n| Desktop, half width | 620px | 72px | ~17 | ~34 characters |\n\nSo a hero headline of **about 32 characters or fewer** (four to six words) survives everywhere at a\nconfident size. Up to about 42 works if the phone size comes down to the mid-30s. Past that you are\nwriting a sentence; move the rest into the supporting line.\n\nControlling the break:\n\n- Give the headline a `max-width` in `ch` so it breaks where you intend, and add\n  `text-wrap: balance` so two lines come out even.\n- Where the break matters (it usually does), author it: `Stools for<br> small kitchens`. Check the\n  phone screenshot; if an authored line wraps there, hide the `<br>` under a breakpoint or shorten.\n- Never fix a long headline only by shrinking it. A timid 28px headline of nine words is worse than\n  five words at 64px.\n- Avoid a single orphan word on line two. Rebalance by cutting a word, not by nudging the width.\n\nSection headings follow the same rule and are shorter: two to five words.\n\n**A statement is not a headline.** An intro sentence or a quotation set large (the manifesto line\nafter the hero, a testimonial) is a paragraph: mark it up as `<p>` or `<blockquote>`, keep it to about\n25 words, and set it at statement size, which the inspector takes as 36px or less on desktop, 32px on\na tablet and 24px on a phone. It may then run to about three lines (four on a phone). Set larger than\nthat, or marked up as a heading, or placed as the main line of the first screen, it is a headline and\ngets two lines. In blind judging, a sentence set big over three or more lines was read as a long\nheadline every time, whatever its markup; if the words matter that much, cut them to a two-line\nheadline instead.\n\n## 3. Headline shapes that work\n\nAll seen repeatedly on the gallery sites. Pick the plainest one that is true.\n\n- **The name.** The brand or the person, set very large, with a one-line description elsewhere.\n  Strongest when the name is short and the subject is visual (studios, restaurants, hotels, people).\n- **What it is.** \"A vinyl shelf in your pocket.\" \"Furniture for small rooms.\" Category, stated with\n  one specific word.\n- **The claim.** \"Your bank won't do this.\" One sentence a competitor could not sign.\n- **The instruction.** \"Understand your money.\" Verb first, short.\n- **The place or the moment.** \"Antarctica.\" \"Lisbon, since 1984.\" For hospitality, events, travel.\n\nShapes to avoid, because they are the average of every landing page:\n\n- The mad-lib: \"The AI-powered platform for modern teams\".\n- The tricolon: \"Fast. Simple. Secure.\" or \"Plan. Build. Ship.\"\n- The correction: \"It's not just a tool, it's a workflow\". Also \"More than a …\".\n- \"X, reimagined / redefined / made simple\". \"Welcome to …\". \"Meet …\" for a product nobody has met.\n- A question the reader did not ask.\n- A headline that needs its colon: \"Ledgerly: invoicing for freelancers\". Drop the name, it is in the\n  navigation.\n- One word of the headline styled differently (italic, serif, coloured, underlined, in a pill).\n\nSentence case. No full stop unless the direction's voice uses them everywhere.\n\n## 4. Supporting line, body, buttons\n\n**Supporting line.** One sentence, at most about 22 words, that says concretely what the thing is and\nwho it is for. It is where the detail cut from the headline goes. It never repeats the headline in\nother words.\n\n**Body.** Short paragraphs of plain statements. Prefer the specific noun and the real number: \"ships\nin a week\" over \"fast delivery\"; \"38 seats\" over \"intimate\". Read every sentence and ask whether a\ndifferent company could print it unchanged; if so, sharpen it or cut it.\n\n**Buttons.** Name the action or the thing: \"Book a table\", \"See the plans\", \"Download for Mac\".\nOne to three words. The primary action keeps one name everywhere on the page. One primary button per\nscreen; a second action is a plain text link. No arrow glyph on every link and button; at most one\narrow, on the primary action, if the direction uses arrows at all.\n\n**Navigation.** The wordmark, up to five plain links, one action. Link labels are single nouns.\n\n## 5. Proof without inventing it\n\nNever invent customers, quotes from named people, press logos, user counts, ratings or benchmarks.\nInvented proof is both dishonest and a recognised tell.\n\nWhen the brief supplies no proof, use what is true by construction:\n\n- Show the thing itself, large. A real demonstration outranks any quote.\n- State how it works, specifically.\n- Use facts from the brief (price, place, year, materials, what is included).\n- If a testimonial or logo section is explicitly requested and no real ones exist, build the section\n  with plainly fictional sample content and say so in your final report so it is replaced before\n  launch. Do not put real company names or real people in it.\n\n**Sample details are different from proof, and they are expected.** Where the brief gives the shape of\nthe content but not every detail (six rooms \"from €140\", \"a short menu\", twelve speakers), write the\nfull set of plausible details: each room with a name, a bed, a view and its own rate; each dish with\nits price; each speaker with a talk title. A design can only be judged at its real density, and a page\nthat shows one rate where six rooms exist looks unfinished. List every sample detail in the report so\nthe client confirms or replaces it.\n\n## 6. Things that read as generated\n\n`lint.mjs` flags most of these.\n\n- Verbs and adjectives of the genre: unlock, unleash, supercharge, elevate, empower, streamline,\n  seamless, effortless, robust, cutting-edge, next-generation, world-class, all-in-one, blazing fast.\n- Labels pretending to be editorial: \"Field notes\", \"The details\", \"Our philosophy\", \"Quietly trusted\n  by\". A section heading can simply be \"Pricing\".\n- Furniture text: locale or time strips, \"Est. 2024\", coordinates, version stamps, \"Scroll\", \"(Scroll\n  to explore)\", fake photo credits, status lines such as \"Available for work\" with a dot, strings of\n  words separated by middle dots or slashes.\n- The em dash as a habit. One or two on a page read as writing; ten read as a model. Use a full stop.\n- Explainer captions that narrate the design: \"A clean, minimal layout for…\".\n- Step labels that duplicate numbers: \"Step 1\", \"Phase 02\".\n- Three parallel items everywhere: three features, three stats, three steps. Use the number the\n  content has.\n\n## 7. Micro-typography\n\n- Curly quotes and apostrophes (“ ” ’), a real ellipsis (…), an en dash for ranges (9–5).\n- Non-breaking space between a number and its unit, and before the last short word of a headline\n  when it would otherwise orphan (`&nbsp;`).\n- `font-variant-numeric: tabular-nums` where numbers line up in columns (prices, tables).\n- `text-wrap: balance` on headings, `text-wrap: pretty` on paragraphs.\n- No all-caps for anything longer than three words; if you set caps, add 0.02–0.06em tracking.\n- No text under 13px. No centred paragraphs longer than three lines. No justified text.\n","skills/taste-skill/references/critique.md":"# Critique — judging the render\n\n`inspect.mjs` passing means nothing banned or broken was measured. It says nothing about whether the\npage is good. This file is how you find out. Use it on the screenshots, never on the code: you wrote\nthe code, so you will read your intentions into it. The pictures only show what is there.\n\n## Contents\n\n1. How to look (fourteen passes, a few minutes)\n2. The score\n3. Caps\n4. Writing the critique\n5. What to fix first\n6. When to stop\n\n## 1. How to look\n\nOpen `desktop-fold.jpg`, then the `desktop-page-*.jpg` sheets, then `mobile-fold.jpg` and the mobile\nsheets. Make each pass on its own; do not blend them.\n\n1. **One second, then five.** Glance and look away. What did you see? There should be exactly one\n   answer: a word, an image, an object. If the answer is \"a website\", there is no focal point. Then\n   give the first screen five seconds as a stranger: can you say what this is, who it is for and\n   what to do next? If the title only makes sense after scrolling, it is not a title.\n2. **Squint.** Blur your attention until text becomes grey bars. The page should reduce to two or\n   three large masses with clear size differences. Many small similar masses means everything is\n   medium and nothing leads.\n3. **Cover the logo.** Could this first screen belong to a competitor, or to a different industry?\n   If swapping the name and the noun in the headline would produce an equally valid page, the page has\n   no idea. Go back to the direction sheet; the idea is written there. Then scroll: does the idea reach\n   the pricing, the FAQ and the footer, or does the page turn into stock blocks after the first screen?\n4. **Edges.** Follow the left edge of every text block down the page. Count the distinct x positions.\n   A composed page has two or three, reused on purpose. Six means things were placed one at a time.\n5. **Space and frame.** Are related things close and unrelated things far? Is the gap between sections\n   clearly larger than any gap inside a section? Is any region empty by accident (a hole) rather than\n   by decision (a rest)? A hole usually sits beside a short column or under a removed decoration.\n   Then look at the frame: are the left and right margins of the page the same? Does any section keep\n   its text in one half and leave the other half empty? Is there a stretch of nothing taller than half\n   a screen? Readers name these first (\"it is pushed to the left\", \"random empty space\"), before any\n   detail; in the study of 100 Sites of the Day about 1 section in 100 left half the width empty.\n6. **Type.** Is the jump from body text to headline decisive (three times or more)? Do you see more\n   than five sizes? Any headline with one orphan word on its last line? Any paragraph wider than about\n   75 characters or centred over more than three lines?\n7. **Colour.** Name the proportions: which colour holds most of the surface, which supports, where is\n   the accent? An accent that appears in ten places means nothing. One that appears on the single\n   action and one detail means \"here\".\n8. **Images.** Count the real pictures: are there at least four, and is there a moving one? A page of\n   drawings only, or of type only, looks unfinished next to one with real photographs and footage.\n   Is every image doing a job (showing the thing, setting the place, proving the claim)?\n   Do the crops share ratios? Is anything a grey box, a stretched photo, a fake screen made of bars?\n   Does the photography share one light and one grade, or is it a stock mix?\n9. **Sameness.** Write one word for each section's layout (split, list, full-bleed, grid, statement,\n   index …). The same word twice in a row, or three times on the page, is the template showing.\n10. **Phone.** Is the mobile screen a composition of its own, with its own crop and its own line\n    breaks, or the desktop page squeezed? Is the first screen still one clear thing?\n11. **Fullness.** Go through the desktop sheets screen by screen. Is each screen a composed poster, or\n    is it a narrow column of small text with dead ground either side? Is any statement held on screen\n    for three screens? An austere page is not a restrained one: if the page could be mistaken for an\n    unfinished wireframe (grey shapes, grey text, one small column), it is underbuilt. A single motif or\n    drawing blown up to fill a whole screen with nothing to read is a hole too, however bold it looks.\n12. **Substance.** Does every section the brief asked for deliver its information completely and at a\n    readable size (the full menu, each room, every speaker, the price and what it includes)? Would the\n    visitor leave knowing what they came to find out? Is the primary action a real button on the first\n    screen?\n13. **Collisions.** Is anything lying on top of a headline, a statement or a button at any scroll\n    position? Does any element run off the edge of the phone screen? A row that scrolls sideways on\n    the phone reads as cut off in a screenshot and to most visitors; wrap it unless the cut is\n    plainly deliberate (a partial card showing at the edge).\n14. **The competitor and the live thing.** Put the nearest competitor's name on the page: does the\n    idea still work? Then name the one live thing (what the visitor can do or what differs each visit).\n    If either answer is weak, that is the first problem of the round, ahead of any detail.\n\nA note from testing: in blind comparisons a richer page full of template devices beat a cleaner page\nthat was thin, every time. The house rules remove the devices; passes 11–13 are where you make sure the\npage did not lose its substance with them.\n\n## 2. The score\n\nScore like an Awwwards juror: four criteria, 1–10 each, weighted **design 40%, usability 30%,\ncreativity 20%, content 10%**.\n\n**Design (40%)** — composition, typography, colour, imagery, craft.\n- 9–10: every screen holds as a poster. Nothing could be removed or moved.\n- 8: confident and coherent; one or two soft spots a designer would notice.\n- 7: clean and professional, a clear system, little tension.\n- 6: tidy but anonymous. Reads as a kit.\n- 5 or less: weak hierarchy, accidental spacing, default type, mismatched images.\n\n**Usability (30%)** — orientation in three seconds, readable text, obvious actions, honest mobile.\n- 9–10: you know what it is, who it is for and what to do without scrolling; flawless on a phone.\n- 8: clear and comfortable; minor friction (a long section, a small target).\n- 7: works, with one real problem (weak contrast somewhere, a cramped phone layout).\n- 6 or less: you have to hunt, or something breaks.\n\n**Creativity (20%)** — an idea you can state in a sentence, carried through.\n- 9–10: a concept specific to this subject that you have not seen applied this way.\n- 8: a clear idea with one memorable move.\n- 7: a tasteful execution of a known approach.\n- 6 or less: the category default.\n\n**Content (10%)** — words and pictures that are specific, true-sounding and edited.\n- 9–10: every line could only be about this subject; imagery is the subject.\n- 7–8: clear and concrete, some generic lines.\n- 6 or less: slogans, filler, stock.\n\n`overall = 0.4·design + 0.3·usability + 0.2·creativity + 0.1·content`\n\nFor calibration: real Sites of the Day land around 7.5–8.0 overall from the jury. An honest 8.5 is\nrare. If your first score for your own work is 9, score it again as the juror who did not build it.\n\n## 3. Caps\n\nThese override the arithmetic.\n\n- Any `FAIL` still reported by `inspect.mjs`: overall cannot exceed **6.0**.\n- A headline of three or more lines at any viewport, an eyebrow label, monospace labels, 01/02/03\n  numbering, a decorative gradient, a shadow on a resting element, or a decorative hairline visible in\n  a screenshot: overall cannot exceed **6.5**, whatever else is true.\n- Pass 3 fails (the page could belong to anyone): creativity cannot exceed **6**.\n- The idea passes for the nearest competitor (pass 14): creativity cannot exceed **7**.\n- Fewer than four real pictures (photographs, archival images, footage; drawings do not count):\n  design cannot exceed **6.5**.\n- A page that barely moves (the inspector's `still-page`), or motion that is one identical fade on\n  every block: design cannot exceed **7**.\n- No live thing (pass 14): creativity cannot exceed **7.5**.\n- Any placeholder (grey box, lorem, \"Image here\"): content cannot exceed **5**.\n- Two or more desktop screens that are mostly empty ground, or a page whose running text is small and\n  grey: design cannot exceed **6.5**.\n- A section the brief asked for that is missing or reduced to a few words: content cannot exceed **6**.\n- No real button for the primary action on the first screen: usability cannot exceed **7**.\n- The five-second pass fails (no clear title saying what this is on the first screen): usability\n  cannot exceed **6**.\n- Unequal page margins, a section huddled on one side with the other half empty, or a blank stretch\n  taller than half a screen: design cannot exceed **6.5**.\n- A section of running text with no heading naming it: usability cannot exceed **7**.\n- Anything covering a headline at any scroll position: usability cannot exceed **6**.\n- A blank band where a reveal did not fire, or content clipped off-screen: usability cannot exceed **5**.\n\n## 4. Writing the critique\n\nWrite it down; do not just think it. Use exactly this shape so rounds can be compared:\n\n```\nROUND n\nSeen in one second: …\nIdea (one sentence): …\nLive thing: …\nLayout words by section: hero=… / …=… / …\nScores: design _ · usability _ · creativity _ · content _ → overall _._\nCaps applied: …\nTop three problems (most visible first), each with the screenshot it shows in and the fix:\n1. …\n2. …\n3. …\n```\n\nName problems the way a designer would to a colleague: \"the supporting paragraph starts 40px left of\nthe headline's edge\", \"the testimonial section is the third split layout in a row\", \"the phone hero\ncrops the bottle out of frame\". \"Could be more polished\" is not a finding.\n\n## 5. What to fix first\n\nFix in this order; later items cannot rescue earlier ones.\n\n1. **The idea.** If pass 3 fails, change the hero concept, not the details.\n2. **Hierarchy.** One dominant element per screen. Make the big thing bigger and the small things\n   fewer before touching anything else.\n3. **Composition.** Shared edges, section spacing, variety of layout between sections, holes.\n4. **Typography.** Scale contrast, line breaks, measure, leading.\n5. **Imagery.** Replace weak pictures, unify crops and grade.\n6. **Colour.** Proportion and accent discipline.\n7. **Detail.** States, focus, small alignments, mobile refinements.\n8. **Motion.** Last.\n\nWhen removing something leaves a gap, do not refill it with an ornament. Close the gap, enlarge what\nremains, or let a picture or a colour field take the space.\n\n## 6. When to stop\n\nRun at most three rounds: critique → fix the top three → re-inspect → critique. Stop early when a round\nfinds no problem a stranger would notice. If round three still scores under 7.5, say so plainly in\nyour report, with the remaining problems listed; do not round up.\n","skills/taste-skill/references/imagery.md":"# Imagery\n\nPictures are where generated pages most obviously give up: a grey box, an icon in a square, a fake\ndashboard, an abstract blob. This file is how to decide what the pictures are, where to find real ones,\nhow to crop and place them, and what to do when there are none.\n\n## Contents\n\n1. What the study measured\n2. Decide what imagery exists\n3. Real pictures from the open collections\n4. The dealt photographs\n5. Cropping and placing\n6. Treatment\n7. Showing software\n8. Drawing the subject\n9. Type and colour alone\n10. Markup and credits\n11. Video\n12. Where pictures and footage go\n\n## 1. What the study measured\n\n- On 60% of the studied sites one piece of media covers at least half of the first screen; on half of\n  them it covers nearly all of it. Top-scored sites: 68% and 56%. Weak sites: 48% and 39%.\n- Only 15% of heroes have no media at all, and those are deliberate typographic statements.\n- Media has square corners on 73% of sites. Where corners are rounded the usual radius is about 12px,\n  applied to every image alike.\n- Top-scored pages carry far more imagery (a median of 37 images against 5 on weak pages): the strong\n  sites show, the weak ones tell.\n- What the imagery is, by the panel's classification: a mix of kinds 32%, photography 14%, generative\n  or WebGL scenes 13%, real product interface 12%, 3D renders 11%, illustration 9%, video 6%, type only\n  3%.\n- Among the 54 sites the panel scored under 6.8, legibility (text lost over a busy image, or too\n  little contrast) was named as a weakness in 13.\n- In the October 2026 study of 91 Awwwards Sites of the Day (section 12), the median page carries 7\n  pictures (top sites 8, the lowest 2) and footage appears on 42% of sites (half of the top ones, one\n  of the 16 lowest).\n- Pictures come in whole screens: 42% of scrolled screens hold none and 19% are 90% picture or more.\n- 94% of pictures have square corners, and on a typical site two ratios hold three-quarters of them.\n\n## 2. Decide what imagery exists\n\nIn order of preference:\n\n1. **The project's own images.** Product shots, the place, the people, the work. Even ordinary\n   photographs of the real thing beat beautiful photographs of something else. Ask what exists; look in\n   the repository.\n2. **Images you can generate** with an image tool in this session. Write prompts as a photographer's\n   brief: subject, angle, light, background, crop ratio, and \"no text\". Generate the hero first and\n   make the rest match its light.\n3. **Real pictures of the subject's world from the open collections** (section 3). Archives,\n   museums and photographers have published millions of pictures anyone may use with a credit: the\n   client's city and street in old postcards, maps of its neighbourhood, its materials, its trade in\n   engravings, museum objects of its kind. Whenever an honest one exists, it beats a drawing of the\n   same thing: it is real, it has detail no drawing in a page's budget reaches, and it carries history.\n   Honest means nobody could take it for the client's own product, room, dish, person or team.\n4. **Pictures you draw in code from the subject itself** (section 8), for what no honest picture\n   exists of: the product's own objects as flat shapes, the place's tiles and windows, a map of its\n   streets, the document a tool produces, the interface of a piece of software. In testing, pages that\n   drew their subject with care beat pages that borrowed unrelated photographs every time, and beat\n   pages that showed nothing.\n5. **The photographs dealt on the direction sheet.** Real photographs of places, light, texture and\n   weather. Use them only where an honestly generic picture fits (the open sea for a house on the sea,\n   fog for a quiet retreat). They cannot stand in for a specific product, dish, room, person or\n   screen: a foggy motorway on a restaurant page reads as stock at once, and jurors notice.\n6. **Type and colour alone,** done on purpose (section 9).\n\nTell `draw.mjs` the truth with `--have`. If you have no product photographs and no image tool, do not\npass `product-photo`; the draw will avoid the directions that depend on showing the object. Pictures\nfound in the open collections are not the project's own: do not pass `photography` for them.\n\n## 3. Real pictures from the open collections\n\n`scripts/assets.mjs` searches four open sources without keys and prints, for each find, a direct image\nURL, the page it comes from, its size, its creator, its licence and a credit line:\n\n- **Openverse**: one index over Flickr, Wikimedia Commons, museums and libraries.\n- **Wikimedia Commons**: archival photographs, old maps, scans of prints and books, places as they\n  look now.\n- **The Art Institute of Chicago** and **The Metropolitan Museum of Art**: public-domain paintings,\n  prints, drawings, photographs, textiles and objects, in large scans.\n\n```bash\nnode <skill>/scripts/assets.mjs \"ghent postcard\"\nnode <skill>/scripts/assets.mjs \"fig\" --source museums --orientation portrait\nnode <skill>/scripts/assets.mjs \"basalt texture\" --min-width 2400 --source openverse,commons\nnode <skill>/scripts/assets.mjs --get commons:36649959,met:707892     # download, record the credits\nnode <skill>/scripts/assets.mjs --credits                             # footer line and report list\n```\n\nBy default it keeps only licences that allow commercial use (CC0, public domain, CC BY, CC BY-SA) and\npictures at least 1000 pixels wide, and checks that every image it prints actually loads.\n`--license pd` keeps only pictures that need no credit; `--orientation`, `--min-width` and `--limit`\nnarrow the list; `--source` picks the sources; `--json` gives the raw results. Each result has a ref\n(`commons:36649959`) that `--get` takes.\n\n**What to search for.** The inventory (SKILL.md step 1), not the category: \"bakery\" finds other\npeople's bakeries. The subject's world is specific:\n\n- **Its place:** the city, the street, the harbour, the valley, in old postcards and photographs\n  (\"ghent postcard\", \"rotterdam harbour 1920\") and as it looks today (\"gent korenmarkt\").\n- **Its maps:** the street plan, the chart of its bay, the geology of its valley (\"ghent old map\",\n  \"nautical chart lisbon\").\n- **Its materials,** close enough to read as a surface: the stone of its quay, the grain of its oak,\n  its glaze, its tiles (\"azulejo tiles\", \"basalt cobblestones\", \"oak grain\").\n- **Its trade's history:** the old tools, the craft in engravings and trade catalogues, patent\n  drawings (\"bread oven engraving\", \"potter's wheel\", \"bicycle patent drawing\").\n- **Museum objects of its kind,** with `--source museums`: a coffee set from about 1810 for a studio\n  that makes coffee sets, a woodblock print of a wave for a surf school, a porcelain plate painted\n  with figs for a fig orchard.\n- **Scientific imagery:** botanical and zoological plates (\"botanical engraving fig\"), star charts,\n  microscope photographs, satellite views of its coast, geological sections.\n\nSearch in the place's own words (azulejo, not \"blue tile\"; Korenmarkt, not \"market square\"), add a\nmedium (postcard, engraving, old map, lithograph, aerial photograph) or a decade, and try two or three\nqueries per idea. The museum sources match best on one or two words (\"fig\", \"harbour\", \"teapot\").\n\n**What makes a good find.**\n\n- It belongs to this subject's world and would not fit the nearest competitor's page.\n- It still reads at the crop the slot needs. Look at it before deciding: `--get` downloads it, then\n  open the file. A title is not a picture.\n- It is large enough: twice the width it is shown at for anything full-bleed (the script prints the\n  largest size available). A 1024-pixel Flickr photograph is a half-width picture at most.\n- It belongs to one family with the others on the page: all engravings, or all photographs from one\n  era, or all close surfaces in one light. A 1900 postcard beside a modern stock photograph beside a\n  botanical plate reads as a scrapbook.\n- No watermark, no burned-in text or logo, no frame or scanner edge you cannot crop away, and no\n  recognisable living person who could be taken for the client's staff or customers.\n\n**Use it creatively.** Found pictures are material, not decoration:\n\n- **One archival photograph as the hero,** full-bleed: the street as it was a century ago, behind the\n  name of the business that stands in it today, with the year in the caption.\n- **A museum engraving enlarged until its line becomes texture,** cropped tight and returning at\n  different scales as the page's one motif (the whole fig plate in the hero, a single leaf of it\n  beside the menu).\n- **An engraving or a map on white paper set with `mix-blend-mode: multiply` on the page's colour\n  field,** so the ink sits on the ground (section 6).\n- **The real map of the street as the contact section,** the door marked, the north and the scale\n  taken from the original.\n- **A material close-up as a whole field:** the quay's stone behind the opening hours.\n- **A run of old postcards or plates as the gallery,** one size, one treatment.\n\nTreatments stay within section 6: untouched, greyscale for the whole set, or multiply on a field.\n\n**Stay honest.**\n\n- **A found picture is never the client's own.** It may show the client's city, its materials, its\n  history, the kind of thing it makes; it may never stand in for the client's product, room, dish,\n  person, team or customers. If a visitor could take it for the client's own (a bakery counter, a\n  plate of pasta, a smiling barista, a guest room), do not use it.\n- **Caption from the source** when a caption helps: what it is and when, as the archive describes it\n  (\"Gand, unloading a steamer, 1905\"). Never write a caption that ties it to the client.\n- **Record and credit every picture.** `--get` writes the source, creator, licence and page of each\n  download to `assets/credits.json`. CC BY and CC BY-SA require a credit with the title, the creator,\n  a link to the source and a link to the licence; `--credits` prints them as one line of HTML for\n  the footer (section 10). Public-domain pictures need no credit; give one anyway.\n- **Respect the licence.** CC BY-SA: an altered version (recoloured, combined with other pictures)\n  must be shared under the same licence. Non-commercial (NC) and no-derivatives (ND) licences are out\n  for a client's site, which is why the script leaves them out unless asked. Read the `note` lines:\n  some pictures carry personality rights or a trademark, are public domain only in the United States,\n  or come with an archive's statement instead of a licence.\n- **Download, do not hotlink.** Save what you use into the project: `--get` puts it in `assets/` at\n  1920 pixels wide (pass `--width 1280` for a picture shown at half the screen, `--width 3840` for a\n  very large hero where the source has it). The page then works offline, does not break when an\n  archive moves a file, and does not load from someone else's server. Every licence the script\n  allows by default permits copying.\n- **List them in the report:** file, title, creator, licence, source page, and where the credit sits.\n  `--credits` prints that list too.\n\nIf two or three honest queries per idea find nothing that fits, draw (section 8). A drawing made for\nthe subject is better than a found picture that is merely nearby. If the script cannot reach any\nsource (no network), draw, and say so in the report. For moving pictures, the same script searches\nreal footage with `--video` (section 11).\n\n## 4. The dealt photographs\n\n- The sheet lists eight from one set so they share a subject and a light. Use three to six.\n- Each line says where the calm area is. Put text there or keep text off the image.\n- More from the same or another set: `node scripts/draw.mjs --photos list`, `--photos <set>`, or\n  `--photos \"fog coast\"` to search descriptions.\n- URLs have the form `https://picsum.photos/id/<id>/<width>/<height>`. Request the exact pixel size you\n  render at twice the CSS size for sharpness, capped around 2400 wide. Add `?grayscale` for\n  black-and-white.\n- These are photographs from Unsplash served by Lorem Picsum under the Unsplash licence. List the ids\n  you used in your report; they are meant to be replaced by the project's own pictures.\n\n## 5. Cropping and placing\n\n- **Choose a small set of ratios and stick to them:** for example 4:5 for portraits, 16:10 for\n  landscapes and 1:1 for details. Random ratios look like a stock dump.\n- **Go large.** A photograph at full width, or at half the screen and full height, has presence. Six\n  small ones in a grid have none. If the image is good, give it the room; if it is not, cut it.\n- **Crop with intent.** Use `object-fit: cover` with an `object-position` chosen per image so the\n  subject sits where the composition needs it (off-centre, on a third, against the text side).\n- **Let images touch edges.** Full-bleed, or bleeding off one side, reads as designed. An image\n  floating with equal margins on all sides reads as placed by default.\n- **Overlap sparingly and on purpose:** a headline whose last line runs over the top edge of the\n  picture, a small image overlapping a large one by a fixed 40–80px. One overlap per screen at most.\n- **Square corners** unless the direction or the one-motif shape says otherwise. If rounded, one radius\n  for every image on the page.\n- **No frames:** no borders, no shadows, no device mock-ups, no browser chrome around pictures.\n- **Captions** are one short line in the small size and soft ink under the image, left-aligned to its\n  edge. Most images need none.\n- Where each picture goes on the page, how large, and what the phone does with it: section 12.\n\n## 6. Treatment\n\nOne treatment for the whole page:\n\n- **Untouched.** The default. Pick images whose light already agrees.\n- **Greyscale.** `filter: grayscale(1) contrast(1.05)`, or `?grayscale` on the URL. Unifies a mixed\n  set instantly and suits editorial and typographic directions. Apply to every image or none.\n- **Multiply on a field.** On a light flat ground, `mix-blend-mode: multiply` makes a white studio\n  background vanish so a product sits directly on the colour.\n- **Darkened for a dark page.** `filter: brightness(0.85) contrast(1.05)` so the image edges sink into\n  the ground.\n\nNot treatments: colour washes over photographs, duotone overlays, blur, grain overlays, vignettes,\ntilted \"polaroid\" frames with shadows.\n\nFor text on a photograph, a neutral scrim covering only the text area: a solid block at 40–55% black,\nor a fade from 55% black to transparent over the lower third. Never a coloured overlay.\n\n## 7. Showing software\n\n- Build a real fragment of the interface in HTML at its true size, with believable content, instead of\n  a shrunken screenshot or a decorative mock-up. Crop to the part that makes the point: one control,\n  one row, one panel.\n- Believable means real labels, real numbers that add up, one item hovered or selected, proper\n  alignment. Grey bars standing in for text are worse than no image.\n- Put the fragment directly on the page or on one flat stage colour. No laptop, no phone frame unless\n  the product is a phone app and the frame is a plain rounded rectangle.\n- Inside a fragment the product's own interface conventions apply (its small radii, its 1px control\n  borders, a shadow on its open menu). Put the attribute `data-ui` on the fragment's root element: the\n  inspector and the linter then leave what is inside alone, and hold the page around it to the house\n  rules. `data-ui` is for cropped fragments only; wrapping a heading or a whole section in it fails.\n  Write the fragment's CSS under a `[data-ui]` selector (`[data-ui] .row { … }`) so the linter can\n  tell it apart from page styles.\n- If the user supplies real screenshots, show them large and uncropped at least once.\n\n## 8. Drawing the subject\n\nWhen nothing real can be photographed and the open collections hold no honest picture of it, draw it,\nand draw it well. Inline SVG and CSS are enough. Drawings and found pictures can share a page: the\nfound ones show the world around the client, the drawings show the client's own things.\n\n- **Draw the subject's own things,** not decoration: the stool's three legs and the grain of its seat,\n  the enamel sign over the bakery door, the hut's two windows and its stove pipe, the street plan, the\n  invoice the tool produces, the festival's stage. If you cannot name what a drawing depicts in the subject's world, it is decoration.\n- **One graphic language for the whole page:** flat filled shapes, no outlines or one consistent\n  stroke weight, the same corner and curve vocabulary everywhere, drawn in the palette's real colours\n  (fields and accent at full strength, not greys). A set of drawings that obviously belong together\n  reads as an identity; a mix of styles reads as clip art.\n- **Colour is the material.** A product sold on its finish is drawn in that finish's colours; a sea house in the\n  sea's blues and the sand; never a page of grey placeholders.\n- **Draw with three levels of detail.** Jurors called simple drawings \"basic\" every time. Give each\n  drawing big shapes that read at a glance, middle shapes that describe the thing (the handle, the\n  window frame, the step), and small details that reward a second look (the maker's mark, the house\n  number, the chipped tile, the hinge, a bird on the roof). Make light with flat tone steps (a lit face\n  and a shaded face of each volume), not gradients. A drawing that would pass as a placeholder icon at\n  full size is not finished.\n- **Draw large and let it work:** the drawing is the hero's dominant element, a full-width band, a set\n  of tiles, the footer mark. Small doodles scattered around read as filler.\n- **Let it carry the idea through the page,** the way a motif does: the same drawn object returns at\n  different scales, the tile grid becomes the opening hours, the map becomes the booking section.\n- **Honesty:** say plainly, in small text near the first drawing or in the footer, that the pictures\n  are drawn until photographs exist, if the client might otherwise be taken to be showing real\n  products. In your report, list which drawings are placeholders for photography.\n- **Not this:** gradient-shaded 3D-looking blobs, isometric clip art, generic line illustrations of\n  people at laptops, abstract floating shapes, icons in squares. Those are the generated look.\n\n## 9. Type and colour alone\n\nThis is a legitimate design, not a gap to disguise. Only 7 of the studied sites use no imagery at all,\nand they hold their own: a median panel score of 7.5 against 7.2 for the whole set.\n\n- Make the typography the image: one statement at 10–14vw, a list set at 5vw, numerals at display size.\n- Use colour at scale: a full field, an inverted section, a two-field split.\n- Use the subject's own shape as one flat motif if the direction calls for it (a circle, an arc, a\n  notch), drawn in CSS, cropped by the viewport.\n- Do not add: icons in squares, abstract gradients, dot grids, wave dividers, floating shapes, emoji,\n  generic line illustrations, or an empty box where a picture \"will go\".\n\n## 10. Markup and credits\n\nA found picture, downloaded into the project with `--get`, used as the hero:\n\n```html\n<img src=\"assets/fig-engraving.jpg\" width=\"1920\" height=\"2807\" fetchpriority=\"high\" decoding=\"async\"\n     alt=\"Hand-coloured engraving of a fig cut open, with its flowers and seeds, in black, pink and green\">\n```\n\nA dealt photograph further down the page:\n\n```html\n<img src=\"https://picsum.photos/id/626/2400/1500\" width=\"2400\" height=\"1500\"\n     alt=\"Red and white lighthouse in a turquoise sea below a chalk cliff\" loading=\"lazy\" decoding=\"async\">\n```\n\nThe credits, as `--credits` prints them, in the footer:\n\n```html\n<p class=\"credits\">Pictures: <a href=\"https://commons.wikimedia.org/wiki/File:Fig_(Ficus_carica_L.);_57_segments_of_flowers_and_fruits_at_Wellcome_V0043000.jpg\">“Fig (Ficus carica L.): 57 segments of flowers and fruits”</a>, <a href=\"https://creativecommons.org/publicdomain/mark/1.0/\">public domain</a>, via Wikimedia Commons.</p>\n```\n\n- Always `width` and `height` (or `aspect-ratio` in CSS) so nothing jumps while loading.\n- `loading=\"lazy\"` on everything except the hero image, which gets `fetchpriority=\"high\"`.\n- `alt` describes the picture in plain words. Decorative repeats get `alt=\"\"`. The script's suggested\n  alt is the archive's title; rewrite it to say what the picture shows.\n- A coloured `background-color` on the image container (the ground or surface tone) so the layout is\n  whole before the image arrives.\n- The credit line is part of the footer's design, at full contrast, with its links. Set it at the body\n  size; one step smaller only on a page with plenty of running text, because a long credit line in\n  small type can become the page's most common text size and fail the inspector's body-size check.\n  One line for all pictures; no credit captions laid over the pictures themselves. Credit only the\n  pictures the page still uses.\n- A broken image fails the inspector. Check every picture in the screenshots.\n\n## 11. Video\n\nA moving picture of the subject's world can carry a section the way a photograph does: the river at\nthe end of the street, the roaster's drum turning, a timber frame going up. `assets.mjs --video`\nsearches real footage without keys: Wikimedia Commons (every video there comes with web-sized\ntranscodes; the best source for short clips), the Internet Archive's Prelinger Archives (industrial,\neducational, city and home films from the 1920s to the 1970s, mostly public domain and mostly long)\nand NASA (the Earth from orbit, launches, aircraft, laboratories). The rest of the Internet Archive is\nleft out: anyone can upload there, and the licence claims are unchecked.\n\n```bash\nnode <skill>/scripts/assets.mjs \"coffee roasting\" --video\nnode <skill>/scripts/assets.mjs \"river\" --video --source commons,nasa --orientation landscape\nnode <skill>/scripts/assets.mjs --get commons:49769620        # the clip, a poster frame, the credit\n```\n\nIt takes a rendition of 720p or smaller (`--res` changes that), lists short clips first, prints each\nclip's length and file size, and flags anything over 25 MB or longer than a minute. `--get` refuses a\nclip over 25 MB unless you pass `--max-mb`, and saves the source's still frame beside it as the\nposter (Commons and NASA; the archive's own stills are too small). An archive film of ten minutes is\ntoo heavy as it stands: trim a few seconds from it with ffmpeg if it is installed, or choose a\nshorter clip. Licences, credits and honesty work exactly as for pictures (section 3).\n\n**Choosing a clip.**\n\n- **Short:** 5 to 20 seconds that loop without a visible jump: water, smoke, a turning drum, traffic,\n  leaves, a crowd from far away. Watch it to the end before choosing.\n- **Light:** under about 5 MB for a section and 10 MB for a hero. In the study sources are 1920×1080\n  (the commonest) or 1280×720, median length 10 s; 720p is plenty behind type. For a full-bleed hero,\n  cut a tall 720×1280 version for the phone, or set `object-position` on the subject.\n- **Clean:** no slate, title card, logo, watermark or burned-in caption. NASA and archive films often\n  open with a slate, and the source's poster frame may be that slate. No recognisable person who could\n  be taken for the client's staff or customers.\n- **Never the client's own:** a found clip of a roastery is not this roastery.\n- **Found clips: one per page, two at most.** A found clip shows the world around the client; a\n  third makes a theme of it. The project's own footage can carry more: in the study a site with\n  footage carries a median of three or four clips. Either way, **one moving picture per screen**;\n  two loops running side by side are noise.\n\n**On the page.**\n\n- Muted, looping, inline, with a poster and a fixed size, as `--get` prints it:\n  `<video autoplay muted loop playsinline preload=\"metadata\" poster=\"assets/river-poster.jpg\"\n  width=\"854\" height=\"480\" aria-hidden=\"true\"><source src=\"assets/river.webm\" type=\"video/webm\"></video>`.\n  No sound and no controls on a decorative loop. `aria-hidden` because it is decoration: whatever the\n  clip says that matters belongs in the text beside it.\n- The poster shows before the clip plays, on slow connections and under reduced motion, so it must\n  work as a picture on its own. If the source's still is a slate or a blur, take a frame from the clip\n  yourself or use a found picture.\n- In the study only 31% of clips had a poster, and the panel recorded the blank and grey boxes\n  before they played as faults. Here every clip has one.\n- Play a clip only while it is in view, and none under `prefers-reduced-motion: reduce`, where the\n  poster shows instead:\n\n  ```html\n  <script>\n    const calm = matchMedia('(prefers-reduced-motion: reduce)');\n    const clips = [...document.querySelectorAll('video[autoplay]')];\n    const inView = new Set();\n    const sync = (v) => {\n      if (calm.matches) return;\n      if (inView.has(v)) v.play().catch(() => {}); else v.pause();\n    };\n    const settle = () => {\n      for (const v of clips) {\n        if (calm.matches) { v.removeAttribute('autoplay'); v.pause(); v.load(); }\n        else if (inView.has(v)) v.play().catch(() => {});\n      }\n    };\n    const watch = new IntersectionObserver((entries) => {\n      for (const e of entries) {\n        if (e.isIntersecting) inView.add(e.target); else inView.delete(e.target);\n        sync(e.target);\n      }\n    }, { threshold: 0.2 });\n    clips.forEach((v) => watch.observe(v));\n    settle();\n    calm.addEventListener('change', settle);\n  </script>\n  ```\n\n- Crop and place it like a photograph (sections 5 and 6): `object-fit: cover`, one ratio, square\n  corners, no frame, a ground-coloured `background-color` while it loads.\n- Never under body text. On a clip put a headline, one line and one action at most, and check the\n  contrast where they sit across the whole loop, not only on the poster: footage that is dark at\n  one second can be bright at the next. If any frame drops below 4.5:1 (3:1 for 24px and up), use the\n  scrim in section 6 or move the text off the clip. Nothing lies on top of a headline or a statement.\n- It is motion: let it be the page's one moving thing, or sit in a section where nothing else moves.\n- Credit it with the pictures: `--credits` prints one footer line for both (\"Pictures and footage:\")\n  and the list for the report, with each clip's length.\n- Where footage goes (hero background, inline loop, the frame that grows, a docked card), and what\n  the study measured about it: section 12. Nothing that matters plays on hover only, and a full film\n  with sound sits behind a play button that opens a player with controls.\n\n## 12. Where pictures and footage go\n\nWhat strong pages do with their pictures, measured on the latest 100 Awwwards Sites of the Day\n(10 July to 17 October 2026, captured at 1440×900 and 390×844). 91 were usable. A panel described where\nevery picture sat and scored each site the Awwwards way, and a script measured how much of each screen\nis picture. \"Top\" means a panel score of 7.5 or more (36 sites), \"lowest\" under 7.3 (16 sites). The\nscores sit close together (6.7 to 7.9) and a single score carries about half a point of noise, so read\nthe links between a placement and the score as leanings, not laws.\n\n### How much of each screen is picture\n\n- **All or nothing.** Counting photographs, footage and picture backgrounds (not canvases), the median\n  scrolled screen in the study is 16% picture, but few screens sit near it: 42% hold no picture and\n  19% are 90% picture or more. Only 19% fall between 20% and 60%. A picture either leads its screen or\n  stays out of it.\n- **About a third, with rests.** On the 67 sites that put pictures in the page, the average screen is\n  36% picture (middle half 18–69%). Top sites sit at 30% and leave 28% of their screens with no picture\n  at all: screens of type are the rests between picture screens.\n- **The first screen.** A picture covers at least half of it on 41% of the sites and nearly all of it\n  on 32%. A full-bleed photograph or film is the whole first screen on 29%; footage is the main hero\n  picture on about a quarter.\n- **A scene is not a picture.** 66 of the 91 keep a WebGL canvas over at least 30% of the screen, so\n  counting canvases the median screen is entirely covered. On the lowest-scored sites that canvas is\n  often all there is: the five lowest usable sites (6.7 to 7.0) draw everything in it and put two\n  pictures at most in the page.\n- **Text is small in area.** The median screen is 8% text. Type is set large and sparse around the\n  pictures, not packed beside them.\n- **Off-centre.** Measured per section across the crawled sites, pictures sit to the left or right\n  939 times, centred 273 times, and full-bleed or behind text 269 times.\n- **The phone carries more picture,** not less: 19% of a phone screen at the median, and 27% of the\n  first phone screen against 17% on desktop. Full-bleed pictures re-crop to portrait and fill the\n  screen; splits put the picture first at full width.\n\n### How many\n\n- **Seven pictures per page** at the median (middle half 1–25). Top sites 8 (middle half 4–27), lowest\n  2 (0–4). The floor in SKILL.md step 6, four and usually six to twelve, is the strong half of the\n  study.\n- **Footage on 42% of sites:** on half of the top sites and half of the middle band, and on one of the\n  16 lowest. A site with footage carries a median of three or four clips.\n- **Three to five placements.** Sites that use two or fewer of the placements below average 7.31;\n  sites that use three or more average about 7.5. The median top site uses four, the median lowest\n  site one. Where the pictures go changes from section to section on a designed page.\n\n### The placements, ranked\n\n| Placement | Sites (of 91) | Top (of 36) | Lowest (of 16) | Mean score with / without |\n| --- | --- | --- | --- | --- |\n| Split: picture in a half or two-thirds | 32 | 17 | 2 | 7.50 / 7.38 |\n| Horizontal gallery | 32 | 13 | 4 | 7.44 / 7.41 |\n| Full-bleed band between sections | 31 | 14 | 3 | 7.48 / 7.40 |\n| Full-bleed picture or film as the first screen | 26 | 10 | 3 | 7.45 / 7.41 |\n| Uneven mosaic | 25 | 11 | 1 | 7.49 / 7.40 |\n| Picture held while text scrolls | 23 | 12 | 1 | 7.52 / 7.39 |\n| Footage behind text | 22 | 8 | 2 | 7.46 / 7.41 |\n| Even grid | 20 | 11 | 2 | 7.48 / 7.41 |\n| Scattered collage | 19 | 6 | 3 | 7.47 / 7.41 |\n| Panel sliding over a held picture | 19 | 8 | 2 | 7.48 / 7.41 |\n| Inset frame that grows | 17 | 7 | 1 | 7.52 / 7.40 |\n| One picture centred on a field | 14 | 5 | 3 | 7.38 / 7.43 |\n| Cut-out object on a flat field | 13 | 7 | 1 | 7.57 / 7.40 |\n| Index with hover preview | 12 | 6 | 1 | 7.49 / 7.41 |\n| 3D gallery | 12 | 4 | 4 | 7.30 / 7.44 |\n| Small card docked in a corner | 11 | 5 | 1 | 7.47 / 7.42 |\n| Picture inside or in front of display type | 11 | 7 | 1 | 7.50 / 7.41 |\n| One small picture beside a statement | 8 | 5 | 0 | 7.56 / 7.41 |\n| Small pictures between words | 6 | 4 | 0 | 7.52 / 7.42 |\n\n- Found on top pages more than their share and almost never on the lowest: the split, the picture held\n  while text scrolls, the uneven mosaic, the inset frame that grows, the cut-out on a flat field, and\n  pictures set with the type (the last three rows together: 24 sites, 16 of them top, 1 lowest).\n- The horizontal gallery is common in every band and lifts nothing. Use it where browsing is the point.\n- The 3D gallery is the one placement that goes with lower scores, and with the lowest usability in the\n  table (5.9 against 6.35 for all sites).\n\n### Each placement\n\nEach entry gives when to use it, the geometry at 1440×900, the phone version and how it fails.\n\n**Split: picture in a half or two-thirds**\n\n- *When.* A claim and the picture that proves it. The commonest way strong pages pair words and a\n  picture.\n- *Geometry.* The picture takes 42% of the width at the median (middle half 33–49%), up to two-thirds,\n  at the full height of its section: 680×850 and 720×900 are typical. 38% of these pictures are\n  portrait, mostly 4:5 or 3:4. The text starts on the 50% line (x = 720) or on the line where the\n  picture ends, top-aligned or docked low, not centred in its half. Let the picture touch the viewport\n  on its outer side: only about 30% do in the study, and the ones with margin on every side read as\n  placed by default (section 5). Alternate sides only across three or more rows.\n- *Phone.* Picture first at full width (4:5, or 4:3 for a landscape), text under it.\n- *Fails.* The same split in three sections running; a picture floating in the middle of its half; a\n  text column narrower than about 30 characters.\n\n**Full-bleed band**\n\n- *When.* One picture carries a whole screen between type screens: the place, the work, the object at\n  full size. One every three or four screens at most.\n- *Geometry.* 100% wide and one to one and a half screens tall (median 900px at 1440×900, middle half\n  890–1,170px; ratios 1.4 to 1.9). For a slow parallax the picture is oversized in its frame by 4–10%\n  (32–72px a side in the study) and travels no further than that. Text is a headline and one line, or\n  nothing, docked 32–64px in from a corner over the calm part of the picture.\n- *Phone.* A portrait re-crop that fills the screen, with `object-position` set on the subject; the\n  text moves to the bottom quarter.\n- *Fails.* 11–14px white text over a bright area; three bands with nothing between them; a band that\n  only decorates.\n\n**Picture held while text scrolls**\n\n- *When.* A list, steps or a long paragraph that all belong to one picture. If the picture changes for\n  each item, it is the index with a preview, below.\n- *Geometry.* A 100vh sticky stage inside a section two to six screens long (runways of 1,800–5,400px\n  are typical in the study). The picture holds one half (685×880 is a typical portrait), two-thirds, or\n  the whole screen with the text passing over it on a solid panel. Text rows about 150px apart, so two\n  or three are in view at once.\n- *Phone.* Release the stick: picture first, text under it. If the picture swaps per item, keep it as\n  a band in the top 40% of the screen.\n- *Fails.* Long runways where the text has faded out and the held picture is all that is left (the\n  panel recorded several empty stages on phones); body copy set on the held picture.\n\n**Inset frame that grows**\n\n- *When.* Once per page, for the film or picture the page is about, as the move from type into\n  picture.\n- *Geometry.* The frame starts centred at 35–50% of the width (549×366, 710×480 and 864×540 in the\n  study) or as a 16px inset round a full screen, and grows to the full width and height over\n  720–2,700px of scroll. Any corner radius goes to 0 as it reaches the edges. A headline sits above it\n  before it starts; nothing else on the screen moves while it grows.\n- *Phone.* Start at full width inside the 16px margins and grow to a full-bleed portrait, or skip the\n  growth.\n- *Fails.* The growth is the only thing on screen for three scrolls; a loading spinner or a blank box\n  in the first frame (give it a poster, start loading before it enters); used twice.\n\n**Uneven mosaic**\n\n- *When.* A body of work, or one place seen several ways: five to twelve pictures.\n- *Geometry.* Two columns, or rows of three on a 24-column grid. Two or three picture widths (for\n  example 32%, 48% and 65% of the width, or 5, 7 and 12 columns), neighbours offset vertically by\n  120–190px, 130–450px between rows, one or two ratios, a caption under each.\n- *Phone.* One column alternating full width and about 70% width, or two columns of 120–180px tiles\n  that keep the offsets.\n- *Fails.* Random ratios with random offsets, which read as a stock dump. Captions in 9–12px mono with\n  index numbers, the award-site habit: here the caption is one line in the text face at body size, with\n  no number.\n\n**Horizontal gallery**\n\n- *When.* A set people browse in any order: products, rooms, events, a team.\n- *Geometry.* Cards 25–35% of the width (435×326 with 20px gaps at 1440: three in full and a fourth\n  cut by the edge), or a strip at one fixed height with mixed widths (576px tall in the study), or a\n  slider whose centre slide is about 73% of the width with 170–180px of each neighbour showing. Always\n  cut by the right edge so it reads as more. A marquee of pictures moves slowly: 60–120s per loop.\n- *Phone.* One card at 75–80% of the width (290–300px of 390) with the next one showing; swipe.\n- *Fails.* Arrows and no drag or swipe; a marquee of things people need to read; a carousel holding the\n  page's one important picture.\n\n**Panel sliding over a held picture**\n\n- *When.* A change of chapter: the picture holds, and the next section rises over it.\n- *Geometry.* The picture is sticky at 100vh; the next section's ground slides up over it at full width,\n  its top edge straight or shaped from the subject (the study has the arch of a building's windows).\n  Here it is a solid panel with square corners: no rounded sheet tops, no frosted glass.\n- *Phone.* Unchanged.\n- *Fails.* Decks of five or six cards whose earlier cards linger as slivers; stacking for its own sake.\n\n**Even grid**\n\n- *When.* An archive only (layout.md §5): a shop range, the team, a menu, the full list of work.\n- *Geometry.* Two, three or four across, equal cells, 8–16px gaps, one ratio (4:5 is the commonest),\n  the caption under each picture.\n- *Phone.* Two across for products, one for work and people.\n- *Fails.* Three equal cards as \"features\". Cards with a dark gradient at the foot so the label can sit\n  on the picture, common in the study: here the label goes under the picture.\n\n**Index with hover preview**\n\n- *When.* A list of eight or more projects or clients where the names matter as much as the pictures.\n- *Geometry.* Rows on a 45–80px pitch, names at 30–60px. One picture at a time, about a third of the\n  width at 16:9 or a portrait 300–450px tall, at a fixed place (the right half from the 50% line, or\n  the centre), swapped within 0.3s. A version that needs no mouse: the names scroll across a picture\n  fixed at the centre and the picture shows whichever name is crossing it. In the study the picture\n  sits on top of the names; here nothing lies on top of large type, so the names pass in front of it.\n- *Phone.* No hover. Give each row a thumbnail about 100px wide, or use the scroll version.\n- *Fails.* Pictures that never appear on a touch screen. Rows divided by hairlines, the award-site\n  habit: here rows are separated by space, and the active row by ink or a change of ground.\n\n**One picture on a field, or one small picture beside a statement**\n\n- *When.* A pause in the page: a single portrait or object. Or a small picture that gives a statement\n  a face.\n- *Geometry.* A single centred picture at 3:4 and 75% of the viewport height, on a ground taken from\n  the picture. Or a small picture 7–26% of the width (108–374px) beside, above or between the lines\n  of a 48–136px statement, aligned to one of its lines.\n- *Phone.* The picture above the statement at 60–100% of the width.\n- *Fails.* Used as the default for every picture: a picture with equal margins on all sides reads as\n  placed by default (section 5).\n\n**Small pictures between words**\n\n- *When.* A statement about the things themselves (materials, people, products), on a screen of its\n  own.\n- *Geometry.* Two to four chips in the statement, from the cap height to three-quarters of the type\n  size tall and one to one and a half times as wide (50×46px in a 60px line; 113×75px between the two\n  words of a 150px name), all from one shoot, square corners. Give them a width and height so the lines\n  do not jump while they load.\n- *Phone.* Keep them inline at the height of the text.\n- *Fails.* More than four; chips from different shoots; a chip that carries information the words do\n  not.\n\n**Picture inside or behind display type**\n\n- *When.* The object is the subject: a product, a building, a person.\n- *Geometry.* A small picture window sits inside a block of 150–200px display type and later opens\n  into the next screen; or the object stands behind the type, showing between and around the letters;\n  or it touches the edge of the word without covering a letter. In the study the object more often\n  stands in front and covers one or two letters, or a line of type runs behind a square picture; here\n  nothing lies on top of a headline (the inspector fails large text a fifth or more hidden), so the\n  type stays in front.\n- *Phone.* Keep it, with the type at about 15vw, and check the word still reads.\n- *Fails.* An object over the letters; type displaced or glitched by the picture.\n\n**Cut-out object on a flat field**\n\n- *When.* Products and objects. The highest mean score in the table, on 7 of the 36 top sites.\n- *Geometry.* The object at 35–60% of the width on a flat ground taken from its own colours, standing\n  on the bottom edge or running off one side, with the type behind or beside it.\n- *Phone.* The object at 80–90% of the width under the headline.\n- *Fails.* A render floating in a void with no ground; a drop shadow added to a cut-out (no resting\n  shadows here; keep a contact shadow only if it was photographed).\n\n**Scattered collage**\n\n- *When.* Archives, ephemera, a festival of many small things. Sparingly: it is about as common on the\n  lowest pages as on the top ones.\n- *Geometry.* Six to sixteen pictures of 100–300px at a few sizes around a centred heading, never over\n  it.\n- *Phone.* Re-stack as overlapping pairs in one column.\n- *Fails.* Tilted prints and stickers with offset shadows, common in the study and not a treatment\n  here (section 6); pictures crossing the text.\n\n**Small card docked in a corner**\n\n- *When.* A standing pointer to the reel or to the next thing.\n- *Geometry.* About 216×144 to 240×140, 30–43px from the corner; one per page.\n- *Phone.* Drop it, or move it into the flow.\n- *Fails.* Content scrolling under it; a second one.\n\n**3D gallery**\n\n- *What.* Pictures on a ring, sphere, helix or tunnel in a WebGL scene, turned by the wheel or by\n  dragging.\n- *In the study.* 12 sites, 4 of them among the 16 lowest; mean score 7.30 against 7.44, usability 5.9\n  against 6.35.\n- *Here.* Do not build one. Show the same pictures as an index with previews or a horizontal gallery.\n\n### Footage\n\n**What the study measured.**\n\n- Footage on 38 of 91 sites (42%): 18 of the 36 top sites, 19 of the 39 in the middle, 1 of the 16\n  lowest. A site with footage carries a median of three or four clips (middle half 1–8).\n- Footage covers at least half of the first screen on about a quarter of the sites, and is full-bleed\n  on nearly all of them.\n- Clips are short: median 10s, middle half 5–14s; 61% run 10s or less and 88% 20s or less.\n- Every decorative clip is muted, loops, plays inline and has no controls. The autoplay attribute is on\n  44% of clips; the rest are started by script, mostly as they come into view.\n- Only 31% of clips have a poster (13 of the 38 sites). The rest show a blank or grey box until they\n  play, and the panel recorded those as blank first paints. Here a poster is required (section 11).\n- Sources: 1920×1080 is the commonest, then 1280×720; tall clips at 450×800 or 540×960 for phones and\n  portrait tiles. Median source width 1,080px.\n- On the page: 16:9 41%, square 19%, portrait (4:5 to 9:16) 25%, 4:3 or 3:2 12%. Corners square on 75%\n  (the rest 8px or less, or 20–32px). `object-fit: cover` on 84%, contain on 16% (product strips, letterboxed\n  films).\n\n**Where it goes.**\n\n- **Hero background:** full-bleed, cover, often oversized by 1–25% so a drift or zoom never shows an\n  edge. Either one slow take or a montage cutting every second or two.\n- **Inline, as a picture:** in splits, tiles and cards, at about a third of the width (median 33%,\n  middle half 24–45%); a third of these clips are under a quarter of the width and fewer than one in\n  ten is full width. Slow, near-still subjects (water, skin, light, a turning object) read as living\n  photographs and sit well among stills.\n- **The frame that grows** (above), for a reel.\n- **A docked card** (above): one small clip in a corner.\n- **On hover:** only two or three sites play clips on hover, all of them in an index or list. Nothing\n  that matters should play on hover only; phones have no hover.\n- **Full films:** about ten sites offer a full film behind a play button that opens a player with\n  controls. None autoplays it.\n- **Sound:** six sites offer sound behind a toggle; no clip starts with sound.\n\n**How text sits on it.**\n\n- Of about 30 sites with a full-bleed picture or film behind text on the first screen, about 14 set the\n  type straight on it and rely on the footage being graded dark where the type sits; about 10 dim it\n  (to half brightness, under a 30–40% dark layer, or with a dark fade along the bottom 180–590px);\n  about 6 keep the text off the picture, above it or on a solid card.\n- What goes on footage in the study is the name or a headline at 47–136px and one short line, docked\n  bottom-left or centred. Where body text at 11–14px went on footage or a busy photograph, the panel\n  named it as a fault, on top-scored sites too.\n- Here: one headline, one line and one action on footage at most, and never body text. Check contrast\n  where the type sits across the whole loop, not only on the poster; if any frame drops below 4.5:1\n  (3:1 for type of 24px and up), use the scrim in section 6 or a solid band.\n\n**On the phone.** Footage re-crops to a full-screen portrait (a separate tall source, or\n`object-position` on the subject); inset frames go full-bleed. One site in the study adds a 40% scrim\non the phone only, where the type covers more of the picture.\n\n### Crops and treatment\n\n- **Ratios.** Of 1,356 pictures and clips measured: 4:5 21%, 16:9 19%, 1:1 16%, 16:10 10%, 3:2 7%, 2:3\n  5%, 4:3 5%, 5:4 4%, 3:4 3%, wider than 2:1 6%, 9:16 or taller 3%. Landscape 52%, portrait 33%,\n  square 15%.\n- **Two ratios do most of the work.** On sites with four pictures or more, the two commonest ratios\n  hold 76% of the pictures. The others (five ratios in all at the median) are exceptions with a reason:\n  one tall portrait in a run of landscapes, one wide band.\n- **Square corners** on 94% of pictures; 62 of the 68 sites with pictures in the page keep at least 80%\n  of them square. Where corners are rounded, it is 5px or less on two-thirds of them, or 20–32px on\n  card interfaces, one value per site.\n- **Cover.** `object-fit: cover` on 78%, contain on 10% (a product on a tile, a letterboxed film).\n- **Untouched.** CSS filters touch pictures on only 9 sites, mostly for hover states. A handful use\n  black-and-white photography as a set; two multiply scanned paper onto the ground. Several keep the\n  interface black, white and grey and let the photographs carry all the colour.\n- **Common in the study, not treatments here** (section 6): a fixed grain layer over the whole page\n  (about a third of the sites), duotone or tinted photographs, blurred copies behind a picture as a\n  glow, tilted prints and stickers with offset shadows.\n- **Oversize only by the distance it moves.** 22 sites move pictures with the scroll, oversizing them by\n  1–25%. Oversize by the travel and no more, on one picture per screen.\n- **Resolution.** The study serves pictures at a median 1.9 times their CSS width, but 17% are served\n  smaller than they are shown and full-width pictures at a median of only 1,440px. Here: twice the CSS\n  width, capped at about 2,400px (section 4).\n\n### Text over pictures\n\n- In the study, text sits on pictures often and is checked rarely: about 28 notes record text set\n  straight on a picture with no scrim, and the faults of 16 sites include text lost over pictures: 8–14px\n  labels and body over photographs, and navigation in a difference blend or with no backing passing\n  over them.\n- Where it works, the text is display size and sits over the calm part (sky, a dark wall, the shadow\n  side), docked in a corner or along one edge. Two other forms in the study: a solid card in the\n  ground colour inset over the photograph and carrying the heading, and text on the white of a picture\n  that fades into the page.\n- Here: on a picture put only display text, one short line and one action. Body text, captions and\n  labels go beside or under it. Measure contrast at the text's own position (4.5:1, or 3:1 for 24px and\n  up). If it fails, move the text to a calmer part, put it on a solid card in the ground colour, or use\n  the scrim in section 6. A fixed navigation that passes over pictures gets a solid band, or hides\n  while scrolling down.\n\n### Rules for a generator\n\n1. **About a third of the page is picture.** Across the scrolled screens, pictures fill 30–40% of the\n   area, and at least one screen in four carries no picture (top sites: 30% and 28%).\n2. **A picture leads its screen or stays small.** A leading picture takes at least 60% of its screen;\n   an accent stays under 10% of it. Avoid screen after screen of pictures at 20–40%: in the study 42% of\n   screens are 0% and 19% are 90% or more.\n3. **Three to five placements per page,** and no two neighbouring sections with the same one. Sites\n   with two or fewer average 7.31, sites with three or more about 7.5.\n4. **Six to twelve pictures, never fewer than four.** Study median 7; top sites 4–27; lowest 2.\n5. **Two ratios for at least 75% of the pictures** (76% in the study), a third only for a deliberate\n   exception. Defaults: 4:5 for portraits, 16:9 or 3:2 for landscapes.\n6. **Square corners on every picture** (94% in the study). If the direction rounds them, one radius of\n   4px for every picture and clip.\n7. **Split pictures take 42–50% of the width, or two-thirds,** at the full height of the section and\n   touching the viewport on their outer side; the text starts on the 50% line. On the phone the\n   picture goes first, full width.\n8. **Full-bleed bands are 100% wide and 100–150vh tall,** one every three or four screens, oversized by\n   10% at most for parallax, with text only in one corn\n\n<!-- [TRUNCATED AT 50KB] -->","skills/taste-skill/references/layout.md":"# Layout\n\nHow the page is put together: margins, the grid, where text sits, how sections differ, navigation,\nendings and the phone. The direction sheet gives the specific compositions; this file gives the habits\nbehind them, taken from the panel's notes on the 114 studied sites that scored 7.3 or higher (counts\nbelow are hand tallies from those notes, so read them as \"about\").\n\n## Contents\n\n1. What strong pages do\n2. Margins and the grid\n3. Where text sits\n4. Empty space\n5. The frame: margins, balance and titles\n6. Sections: carry the idea, vary the arrangement\n7. Navigation\n8. Endings\n9. The phone is a second composition\n10. How pages fail\n\n## 1. What strong pages do\n\n- **Tight margins, content to the edges.** About 45 of 114 use outer margins of 32px or less; only\n  about 8 use 80px or more. The centred 1100–1300px container is the minority among strong sites and\n  the usual frame of the ones the panel called stock.\n- **Text hangs from an off-centre line.** About 22 anchor text to one fixed line that is neither the\n  centre nor the margin: a third across, 42%, the midpoint.\n- **Two or three type sizes with nothing between** (about 30): one very large with one small, or\n  everything small with the scale given to the image.\n- **One thing per screen** (about 20): one statement, one object, one project.\n- **Sections told apart by their ground.** About 20 change the whole background colour at each\n  section; about 12 alternate light and dark; about 10 never change and separate by space alone.\n- **Sections recomposed, not repeated.** About 14 rearrange every section; about 12 alternate a\n  full-bleed image screen with a near-empty type screen.\n- **The system broken once, on purpose** (about 14): one centred line on a split page, one paper card\n  on a dark page, colour held back until the last screen.\n- **Often no navigation bar** (about 45), and endings that are a designed scene rather than link\n  columns.\n- **Few words.** Median 575 on the whole study; some of the best carry under 200.\n\n## 2. Margins and the grid\n\n```css\n:root {\n  --margin: clamp(1rem, 2.2vw, 2rem);   /* 16–32px: tight, so content reaches the edges */\n  --gutter: clamp(0.75rem, 1.4vw, 1.5rem);\n}\n.wrap { padding-inline: var(--margin); }\n.grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gutter); }\n```\n\n- One pair of margins and one grid for the whole page. Every left edge is a column line.\n- Do not wrap the page in a `max-width: 1200px; margin: auto` container by reflex. Let large things\n  (type, images, colour fields) run the full width, and constrain only the measure of running text\n  (`max-width` in `ch` on the paragraph, not on the page).\n- On very wide screens cap the layout at about 1760–1920px, or let type sized in `vw` stop growing with\n  a `clamp()`.\n- Directions that call for wide margins (uneven photographs, the quiet instrument) say so on the\n  sheet; follow the sheet.\n- Never draw the grid. Column lines, crosshairs and guides are banned ornaments here even though they\n  are fashionable; the grid is felt through alignment.\n\n## 3. Where text sits\n\n- **Pick the anchor line and reuse it.** If the hero headline starts at column 5, the section\n  headings, the pricing figure and the footer links start there too. Two or three anchor lines on a\n  whole page; six means nothing was decided.\n- **Off-centre beats centred.** A heading in the left third with its paragraph in the far-right\n  column on the same baseline and nothing between; a headline in the bottom third under a deliberate\n  void; text docked in corners with the middle given to the picture.\n- **Opposite ends.** Two short texts at opposite ends of one baseline (name left, one-line description\n  right) is the commonest alternative to the centred stack.\n- **Centred is a decision.** When a strong page centres, it uses one axis with wide empty flanks and a\n  single element per screen, not a centred stack of heading, paragraph and two buttons.\n- **Rows for long copy:** heading in the left third, body in the right two-thirds, the same split for\n  every row on the page.\n- Stagger sparingly: a second line indented by a third so a two-line headline steps across the screen.\n\n## 4. Empty space\n\nEmpty space is placed, not left over. In the study of 97 Sites of the Day captured in October 2026,\nreaders judged every large empty area either a rest, which something closes, or a hole, which nothing\ncloses. Strong sites have plenty of rests. About half of them still leave at least one hole, and the\nholes are what visitors name (\"big random blank spaces\").\n\n**A void is placed when something closes it.** In the readers' notes the closer is, most often:\n\n- the picture itself (sky, ground, the object, the film) with the type docked at its edge;\n- a picture across the void: the photograph at the far side of an empty band, the full-width row\n  rising under a statement, the opposite picture in a stagger;\n- the type: a headline large enough to span the space, or two short texts at the two ends of one\n  baseline;\n- on a one-screen page, the wordmark, the navigation and one fact in the corners, like a mount around\n  a print.\n\nAbout one closer in five in the study is a hairline or grid line. That device is banned here; close the\nvoid with the picture, the type, a step in ground tone or a field of flat colour.\n\n**Where holes come from.** In order of frequency in the study:\n\n1. A gap between sections stretched too far: bands of 250–760px of plain ground.\n2. Text in one half of a section and nothing in the other.\n3. Content that arrives late: a reveal not yet fired, so the visitor scrolls onto bare ground while the\n   words fade in.\n4. A short block stretched to a full screen: a footer padded to the viewport height, a section title\n   alone on a whole screen.\n5. A pinned scene that holds almost nothing for several screens.\n6. Pictures of different heights top-aligned in a row, leaving a hole under the short one.\n\n**Rules**\n\n- Decide where the void is and name what closes it. If nothing does, it is a hole: move the section's\n  picture into it, make the main element bigger, or take the space out.\n- Keep the void clean: no stray caption, no decorative shape, no faint watermark, no grid lines.\n- Sections sit 120–240px apart on desktop, counted from the last line of one to the first line of the\n  next (the median in the study is about 230–250px), and 72–112px on a phone. A change of ground\n  colour lets the gap be a little smaller. More than about 40% of a screen of plain ground between two\n  sections is a hole.\n- The gap between sections is clearly larger than any gap inside one. Related things sit close and\n  unrelated things far; a heading has at least twice as much space above it as below.\n- No stretch of the page taller than about half a screen holds nothing at all. In the study, runs of a\n  screen or more with nothing in the page were almost always scroll distance for a pinned scene; the\n  pinned stage must then hold something at every scroll position.\n- Content is in place on the first paint. An entrance moves what is already there (see `motion.md`);\n  it never leaves a screen of bare ground while the words arrive.\n- Size a section to its content. `min-height: 100vh` belongs to a section that fills the screen, not\n  to a footer or a lone heading.\n- In a row of pictures of different heights, align the bottoms or put something under the short one,\n  or crop the row to one ratio.\n- A rest is one thing on a screen: a single line, one object, one picture or a field of colour. Once\n  per page at most. A screen of nothing is never a rest, and the inspector fails two near-empty screens.\n- When a section looks empty, the answer is almost never \"add something\". Make the main element\n  bigger, or cut the section.\n\n## 5. The frame: margins, balance and titles\n\nThe frame is what readers judge before any detail: \"no good margin\", \"everything is shifted to one\nside\", \"no clear title\", \"random unclear sections\". The inspector measures each of these. The numbers\nare from the study of 97 Sites of the Day (October 2026).\n\n**One pair of equal margins.**\n\n- The left and right margins are the same, at every width. On the studied sites with scrolling\n  sections the two sides match to a few pixels: 16 and 16, 20 and 21, 32 and 32, 140 and 137. No\n  strong page in the study was pushed to one side.\n- The usual margin is tight: median about 28px at 1440, half the sites between about 18 and 45px, a\n  few at 80px or more. Here it is 16–32px (section 2), and never under 16px at any width, on the phone\n  included. About one award site in seven sets text 8–15px from the edge; that studio habit is\n  excluded here.\n- The navigation sits on the same margins as the content. The commonest small fault in the study is a\n  header on one inset and the page on another (40px against 20px, or 34px on the left against 10px on\n  the right).\n- A bleed is deliberate and starts from the margin: a row of pictures that runs off the right edge\n  begins on the left margin; a display line that bleeds starts or ends on one. A bleed never moves the\n  margin.\n- Asymmetry belongs inside the frame: an off-centre anchor line (a third across, 42%, the centre line)\n  on symmetric margins.\n\n**Use the width the page has set up.**\n\n- In the study about one text section in a hundred leaves half the width empty. Text that sits in one\n  half is common, in roughly one site in three, but the other half then holds the section's own\n  picture (most often), a full-bleed picture behind the text, a second column, a list or a figure.\n- When the text takes one side, put the picture, the second column, the list or the large number on\n  the other. Never leave the other half to plain ground.\n- The middle counts too: a card at the left edge and a lone button at the right with the middle third\n  empty is the same hole.\n- The first screen counts too. When the sentence and the button take the left third above a name\n  docked at the foot, the upper right holds something (the picture or film, one fact, the action) or\n  the name grows up to meet them; in testing, 60% of a first screen left as plain ground under the\n  navigation read as a hole, and the inspector now warns when one empty block takes 28% of the first\n  screen or more.\n- A display line fitted to the width is fitted by measurement (a small script that sets its size from\n  the content box, or SVG text with `textLength`), never by a size guessed for one face: a name that\n  starts on the margin and runs a few pixels off the other edge reads as a mistake.\n- A centred composition has one axis, equal flanks and one thing on it, not a stack of heading,\n  paragraph and two buttons.\n\n**A title that says what this is, on the first screen.**\n\n- Asked whether a stranger could say what the page is within five seconds, readers found that 40 of\n  the 97 first screens say it in words, 42 say it only through pictures, small print or a bare name,\n  and 15 do not say it at all. The last group lost usability and content points, not design points.\n- Size alone does not do it: 66 of the 97 first screens carry a display-size line, but 26 of those are\n  a name, a slogan or a place with nothing saying what is offered.\n- The first screen has one `h1`, at display size (32px or more on desktop; on the clear first\n  screens in the study mostly 50–150px), two lines at most, that says what this is: the name with\n  what it does, the product with what it is for, the event with its date and place. If the `h1` is\n  the name, the line under it, at 18px or more, says what the thing is.\n- It is there on the first paint. About a third of the studied pages still showed a loader or nothing readable 4.5\n  seconds.\n\n**A heading on every section.**\n\n- 82% of the text sections on the studied sites open with a heading: median 57px (40–96px for the\n  middle half), about three and a half times the body size, one or two lines.\n- Headings start on the outer margin or on the page's inner anchor line (in the study about a third\n  each) and in the same place for every section. About a quarter of the headings in the study are\n  centred; centre one moment per page here.\n- Where a studied section has no heading, the usual stand-in is a small label: caps, mono or a number\n  in brackets. All three are banned here. Put the label's words in a heading in the heading face at the\n  section size (\"The rooms\", \"How it works\", \"Prices\"), set them on the anchor line, and let the first\n  sentence carry the rest.\n- A statement can open a section as its heading only when it names what the section holds.\n\n## 6. Sections: carry the idea, vary the arrangement\n\nThe most common failure in every score band is a distinctive first screen followed by stock blocks:\nicon cards, a three-up row, an accordion, a link-column footer. About 25 of the studied sites lose\npoints this way, including several above 7.5.\n\n- **The idea survives to the last pixel.** Ask of each section, pricing and FAQ included: what does\n  the page's idea do here? If the page is a menu, the prices are menu lines. If the name is a\n  monument, the footer is the name again. If the object's shape is the motif, the button and the image\n  masks carry it.\n- **No two neighbours share a layout.** Use the shape of each dealt blueprint (list, split, statement,\n  full-bleed, mosaic, table, strip, pinned …). Count them in the screenshot; a shape used three times\n  is the template showing.\n- **Alternate dense and empty, image and type, light and dark** so the scroll has rhythm.\n- **A repeated module is for archives only** (a work index, a menu, a schedule). Anywhere else,\n  repetition reads as a kit.\n- **Break the system once.** After the page has established its rule, one planned exception (a single\n  centred line, one inverted section, one image at a different scale) is what makes the rule visible.\n- **Short pages are fine.** A quarter of the studied sites are one or two screens. Do not add sections\n  to seem complete; each one must carry a claim (see `copy.md` §1).\n\n## 7. Navigation\n\n- The plain form: the wordmark at one end, three to five text links, one action, all at text size on\n  the page ground with no bar, border or background. Median link count in the study is 3.\n- It is also normal to have less: small links in the corners, a single action, or the navigation\n  folded into the content (a list of section titles that is itself the index).\n- If it stays fixed, it must never sit on top of content: check every scroll position in the\n  screenshots, especially on the phone. Floating pill bars are where the panel most often recorded a\n  nav covering text.\n- On a phone: wordmark and one action in view; the links go in a simple full-screen sheet opened by a\n  text button (\"Menu\"), or move to the footer when there are only three.\n- Navigation is small furniture, however it is drawn. On desktop it takes no more than about a tenth\n  of the first screen; on a phone it is one row. A blueprint that builds the navigation as a column of\n  colour blocks or a stack of tabs gets that treatment on desktop only, and collapses to one row on\n  the phone so the headline, the supporting sentence and the action stay in the first screen. In\n  blind tests a nav that ate the hero cost a whole point of usability.\n\n## 8. Endings\n\n- The page should end on a designed scene. In the study: the name at full width (about 18 of 114), the\n  hero repeated in inverted colours (about 12), a closing scene of its own such as the one contact\n  fact set as a headline (about 14), or simply one quiet line (about 22). Link-column footers appear\n  in the panel's notes only as criticism.\n- The full-width name is strong but already a studio habit; use it when the direction is name-led,\n  otherwise prefer the blueprint dealt for the footer.\n- Put the practical facts (address, hours, email, legal line) in the text face at a readable size, on\n  the same anchor lines as the rest of the page.\n\n## 9. The phone is a second composition\n\nDesign the 390px screen as its own page, not the desktop page squeezed. Strong sites that neglect this\nlose usability points; weak ones are often just broken.\n\n- Each blueprint on the sheet has its own phone paragraph. Build it.\n- Keep one dominant thing on the first screen. A wordmark that was 20vw wide on desktop might stack on\n  two lines at 26vw on the phone and be even stronger.\n- Re-author line breaks; re-crop images to portrait (`object-position` per breakpoint, or a different\n  crop size in the image URL); keep unevenness with alternating widths rather than making everything\n  full width.\n- Margins 16–20px. Body text 16–18px. Touch targets at least 44px high.\n- Check 390px in the inspector's screenshots for every round: sideways scroll and three-line headlines\n  usually appear here first.\n\n## 10. How pages fail\n\nFrom the panel's notes on the 54 sites scoring under 6.8 (counts out of 54):\n\n- The whole page is the category's stock template; swap the logo and it could be any competitor\n  (about 20).\n- Centred headline, pill badge, two buttons, screenshot or tile grid below (about 9).\n- A distinctive hero, then stock modules in the usual order (about 8, and about 17 more in the middle\n  band).\n- A default typeface with no character (about 13).\n- Text too small or too low in contrast (about 13); legibility lost over busy photographs (about 9).\n- An undersized headline and no focal point (about 9).\n- The page never says what the thing is, or shows no work (about 12 and 7).\n- Thin content stretched over many screens, or a single gag (about 11).\n- Gates, preloaders and entry pop-ups before any content (about 9).\n- A phone layout that is the desktop shrunk, or broken (about 8).\n- Fixed elements sitting on content; careless details such as colliding lines (about 7 and 5).\n\nAnd the faults of the best sites, which are not to be copied: body text at 9–13px (about 24 of the 90\nsites at 7.5 or more), information hidden behind the concept (about 20), the idea running out\nmid-page (about 15), text over footage with no scrim (about 12), gates and blank first paints (about\n12), floating elements colliding with content (about 11), and a first screen with no statement of what\nthis is and no action (about 9). Say what the thing is, and offer the action, on the first screen.\n","skills/taste-skill/references/motion.md":"# Motion\n\nRead this before adding any animation. The static page must already be finished and passing\n`inspect.mjs`; motion is the last pass, never a way to rescue a weak layout.\n\n## Contents\n\n1. The budget\n2. What strong pages do with motion\n3. Four questions before any animation\n4. Tokens\n5. Scroll behaviours, ranked\n6. Recipes (copy, then adapt)\n7. Signature moves\n8. Reduced motion and performance\n9. What gives generated motion away\n10. Rules for motion\n\n## 1. The budget\n\nA page that does not move reads as a mock-up; the inspector counts what moves while the page loads and\nscrolls, and fails it under eight elements. The motion layer has five parts:\n\n- **Two or three scroll scenes:** the big, scroll-driven moments award sites are remembered for (a\n  camera flying through a field of pictures, a picture that grows from a window to the whole screen,\n  type that crosses a held stage, cards that deal out and stack). The direction sheet deals them from\n  `library/scenes.json` when the library has scenes for the brief; `references/scenes.md` says how to\n  fill and fit them. They are where the page is bold; everything else stays quiet so they land.\n\n- **One signature moment:** the thing a visitor would describe an hour later: the headline that rises\n  out of a mask, the image that opens like a shutter, the wordmark that scales with the scroll. The\n  direction sheet from `draw.mjs` names one. Build that one well; it is the only move allowed to be\n  loud.\n- **Section entrances, choreographed per section:** the parts of each section arrive in reading order\n  (heading, text, picture, details), staggered 60–90ms, rising 16–32px with opacity, once. Vary the\n  manner with the content instead of stamping one preset everywhere: a list arrives row by row, a\n  picture opens from a mask or settles from a slight scale, a figure counts up once, a statement rises\n  line by line.\n- **Feedback under the hand:** buttons that give on press, links that answer the pointer, cards and\n  pictures that respond on hover, a menu that opens from where it was clicked.\n- **One moving picture:** a found clip as a muted loop with a poster frame, a slow drift or scale on\n  a large photograph, or a scroll-linked move on the hero picture.\n\nWhat is still banned: the same fade-and-slide-up with the same timing on every block, which is the most\ncited motion tell of generated pages; motion that hides content until a script runs, with no fallback;\nbounce and elastic easing; anything that animates layout properties. Uniform motion says nobody decided\nanything; choreographed motion with one protected moment says somebody did.\n\n## 2. What strong pages do with motion\n\nMeasured on the latest 99 Awwwards Sites of the Day (July to October 2026), at 1440 and 390, with\nthe transitions, tweens and scroll triggers recorded while each page loaded and was scrolled. Where\nthe gallery does something the house rules ban, the house version follows.\n\n- **The stack.** Two in three use a smooth-scroll library and three in five ship Three.js; GSAP is\n  named on 56. The quiet layer below (reveals, line rises, the ink fill) needs none of it: CSS scroll\n  timelines and view transitions do that work, though only 3 and 6 of the sites use them. The big\n  scroll scenes are built on GSAP ScrollTrigger, as on the award sites, through the shared stage in\n  `assets/scenes/` (`references/scenes.md`).\n- **Curves.** The curves that really ran are strong ease-outs: expo out (`.16,1,.3,1` and\n  `.19,1,.22,1`) ran on 14 sites, cubic out on 13, quint out on 7, and by number of transitions the\n  quint and expo outs lead every chosen curve. In-out curves are kept for wipes and things that\n  travel (cubic and quart in-out, about 15 sites each). Ease-in appears only for exits, short, before\n  a slow arrival. Colour changes use plain `ease` (46 sites). Overshoot sits in 19 stylesheets and\n  ran on 2.\n- **Durations.** Hover colour 200-300 ms; small interface moves 300-450 ms; reveals and line rises\n  600-1,000 ms; picture openings and wipes 1,100-1,600 ms. The median of everything that ran on a\n  site is 420 ms.\n- **Staggers.** 20-40 ms between characters, 75-120 ms between lines, 50-100 ms between list items.\n- **Scroll-linked motion is locked to the scrollbar.** Of the sites that scrub, 14 of 18 lock it with\n  no smoothing; the other four smooth it by 0.1-3 s. Reveals fire when the element's top is 80-95% of the way\n  down the viewport, once.\n- **How much moves.** A median of 130 elements are moved by script on a page, but they come from a\n  few gestures: one split heading is 20-60 elements. The inspector's floor (8, warning under 16) is a\n  floor, not a target.\n- **Waiting is the most common cost.** 60 of 99 open on a loading screen, 26 of them with a counter.\n  Half the usable pages were still unreadable 2.5 s after the browser said the page had loaded, a\n  third at 4.5 s. The preloaders were not covering slow pages (their documents loaded faster than the\n  rest) and the readers' design marks were the same whatever the wait; only usability fell. House\n  version: no preloader, the message readable on the first frame, the load sequence over by 1.2 s.\n- **Pins cost length.** Two in three scrolling pages hold something sticky or pinned. Those pages\n  are twice as long (a median 16.6 screens against 7.5) for fewer words per screen (27 against 46).\n  House version: at most two held stages, about one screen per step, three screens per stage.\n- **Reduced motion is mostly missing.** 35 of 99 have any `prefers-reduced-motion` rule, 16 have\n  three or more; 5 of 26 scroll-scrubbed scenes have one. Every recipe here keeps the finished state\n  as the reduced state.\n\n## 3. Four questions before any animation\n\n1. **How often will someone see it?** Once per visit (hero load, a section reveal): it can take its\n   time. Many times per visit (hover, menu, accordion): fast and small. Hundreds of times (keyboard\n   actions, typing): no animation.\n2. **What is it for?** Valid answers: it shows where something came from, it confirms an action, it\n   keeps a change from being jarring, it explains how the product works, it is the signature moment.\n   \"It looks nice\" is only valid for the signature moment.\n3. **Which easing?** Entering or leaving: ease-out, so movement starts the instant the eye arrives.\n   Moving between two places on screen: ease-in-out. Colour and opacity on hover: `ease`. Constant\n   travel (marquee, progress): `linear`. `ease-in` makes interfaces feel slow because the first frames\n   barely move; do not use it. The CSS keyword curves are weak, so use the tokens below.\n4. **How long?** Press feedback 100–160ms. Hover 150–200ms. Menus and popovers 150–250ms. Dialogs and\n   drawers 250–450ms. Section and hero reveals 500–900ms. Leaving is quicker than arriving (about 70%).\n\n## 4. Tokens\n\n```css\n:root {\n  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);        /* entrances, moving hovers, UI under 600ms */\n  --ease-expo: cubic-bezier(0.16, 1, 0.3, 1);        /* new: reveals of 800ms and longer, line rises, openings */\n  --ease-in-out: cubic-bezier(0.76, 0, 0.24, 1);     /* wipes, panels, things that travel while visible */\n  --ease-soft: cubic-bezier(0.33, 1, 0.68, 1);       /* slow scale and drift on photographs */\n  --ease-exit: cubic-bezier(0.55, 0.055, 0.675, 0.19); /* new: something leaving for good, short */\n  --t-press: 140ms;\n  --t-hover: 180ms;\n  --t-ui: 240ms;\n  --t-reveal: 800ms;\n  --t-open: 1200ms;                                  /* new: picture openings and clip wipes */\n  --stagger-line: 90ms;                              /* new */\n  --stagger-item: 70ms;                              /* new */\n}\n```\n\nHow the study bears on each:\n\n- `--ease-out` (quint out) is in 28 stylesheets with its near twin and is the single most frequent\n  chosen curve among transitions that ran. Keep it.\n- `--ease-expo` is new. Expo out (`.16,1,.3,1` and `.19,1,.22,1`) is in 28 stylesheets and ran on 14\n  sites, more than any other chosen family, and it is the curve the long reveals use: line rises,\n  picture openings, card entrances of 0.9-1.6 s. Use it for anything at `--t-reveal` or longer; it\n  replaces `--ease-out` in the masked headline and the reveal-on-scroll recipes.\n- `--ease-in-out` (quart in-out) matches its family (14 stylesheets, 7 ran). Keep it for wipes,\n  shutters, menus and page transitions.\n- `--ease-soft` (cubic out) matches the cubic-out family (21 stylesheets, 13 ran), but the study uses it\n  for interface moves of 0.3-0.8 s, where `--ease-out` already serves. Narrow it to slow scale and\n  drift on photographs.\n- `--ease-exit` is new. Ease-in is right for exactly one job: something that leaves for good (an\n  outgoing caption, a replaced slide, a closing panel), short, at about 60-70% of the matching\n  entrance. Never for anything the visitor is waiting to see.\n- Not adopted: `.4,0,.2,1` (38 stylesheets) is a framework default, and overshoot curves (19) stay\n  banned on interface elements.\n- `--t-hover` stays at 180ms. The study's colour hovers run 200-300ms; a little quicker reads as\n  more exact. A hover that moves something (a label roll, an arrow) takes `--t-ui` to 400ms.\n\n## 5. Scroll behaviours, ranked\n\n| Behaviour | Pages of 99 | What it serves | House version |\n| --- | --- | --- | --- |\n| Smooth-scroll library | 67 | A feeling of weight; makes scrubbed scenes easier to build | Optional, through `Stage.smooth()`: Lenis at lerp 0.1-0.14, off for touch and reduced motion |\n| Held (sticky or pinned) stage | 44 | One picture or object carries several claims; chapters | Yes: the scroll scenes (`references/scenes.md`), two or three per page, one to four screens each; other sticky stages three screens at most |\n| Split text | 40 | Lines and words arriving as they are read; hover rolls | Lines for headings and statements; words only for the ink fill; characters only for a heading of one to three words |\n| Colour by chapter | 34 | Tells chapters apart without padding bands | Yes, as hard cuts at section edges; the header ink follows in 300ms |\n| Scroll-scrubbed scene (camera, object, image sequence) | 26 | Explains a product by moving it | Yes, from the scene library, built on the shared stage with a finished composition for reduced motion |\n| Parallax depth | 24 | Depth in collages; pictures drifting inside oversized frames | Travel under 8% of the element, pictures held at 106-110% in their frames |\n| Marquee | 21 | Life on a static band | Existing \"Edge-to-edge marquee\": one per page, pausable |\n| Masked line or word rise | 18 | Headings that arrive like set type | Yes: \"Masked line reveal\" on load, \"Lines that rise on scroll\" below the fold |\n| Wheel drives a scene, no page scroll | 16 | Browsing one object | Not used (see 2.6) |\n| Blur-in | 15 | Soft arrival | At most 8px of blur, 600ms, gone once settled; never on body text |\n| Picture from inset frame to full-bleed | 14 | The hand-over from a type screen to the big picture | Yes: \"Opening window\", about one screen of scroll |\n| Grey-to-ink text fill | 14 | Paces one statement | Yes, once per page, starting at 45% ink: \"Ink fill\" |\n| Sheet slides over a held layer | 11 | Page-turn rhythm between chapters | Yes: new move \"Sheet over a held picture\" |\n| Scramble or decode | 11 | A \"code\" voice | Not used (see 2.6) |\n| Header ink by chapter | 10 | The fixed header stays legible | Yes, with colour by chapter |\n| Horizontal track pinned to vertical scroll | 8 | Walking through rooms or a collection | Native drag row first; pinned only when the row is under three screens long, with keyboard support: \"Sideways gallery\" |\n| Curtain footer | 8 | The page ends as a scene | Existing move |\n| Rolling digits | 6 | Figures that arrive | Yes, for pages whose case is a handful of numbers: \"Rolling figures\" |\n| Index with hover preview | 5 | Navigating work by name | Existing move, upgraded recipe |\n\nText, split by unit: characters on about 20 pages, lines on about 14, words on about 11. Character\nsplits serve short headings and button rolls; on long statements they leave fragments mid-scroll.\n\n## 6. Recipes\n\nAll recipes keep the content visible when JavaScript is off, put every hidden state inside\n`prefers-reduced-motion: no-preference`, and use the tokens above. Two notes that apply to several:\n\n- **Scroll timelines need a scroller to watch.** `animation-timeline: view()` takes the nearest scroll\n  container, and `overflow: hidden` makes one. A picture inside an `overflow: hidden` frame therefore\n  never animates. Use `overflow: clip` on frames, or name the timeline on the section\n  (`view-timeline-name: --hero`) and point the children at that name. This also applies to the\n  existing \"Scroll-linked progress\" recipe.\n- **Scroll-linked means linear.** The scroll is the easing. 14 of the 18 scrubbing sites in the study\n  lock motion to the scrollbar, which is what CSS scroll timelines do.\n\nAll recipes keep content visible when JavaScript is off or slow: the hidden state only applies under\n`html.js`, which a one-line inline script sets.\n\n```html\n<script>document.documentElement.classList.add('js')</script>\n```\n\n### Load sequence in 1.2 seconds\n\nEverything is in the HTML and painted on the first frame; the sequence only adds arrival. Nothing\nwaits for the load event, and nothing in the navigation animates.\n\n```html\n<header class=\"hero\">\n  <h1 class=\"display lines\">\n    <span class=\"line\"><span data-line style=\"--i:0\">Stools for</span></span>\n    <span class=\"line\"><span data-line style=\"--i:1\">small kitchens</span></span>\n  </h1>\n  <p class=\"lead\" data-load style=\"--d:420ms\">…</p>\n  <a class=\"button\" data-load style=\"--d:480ms\" href=\"#stools\">See the stools</a>\n  <figure class=\"hero__picture\" data-open><img src=\"stool.jpg\" alt=\"…\" fetchpriority=\"high\"></figure>\n</header>\n```\n\n```css\n.hero__picture { overflow: clip; margin: 0; }\n@media (prefers-reduced-motion: no-preference) {\n  .js .hero [data-line] { transform: translateY(105%); animation: load-line 800ms var(--ease-expo) forwards; animation-delay: calc(100ms + var(--i) * var(--stagger-line)); }\n  .js .hero [data-load] { opacity: 0; transform: translateY(12px); animation: load-rise 500ms var(--ease-out) forwards; animation-delay: var(--d); }\n  .js .hero [data-open] { clip-path: inset(0 0 100% 0); animation: load-open 1000ms var(--ease-in-out) 150ms forwards; }\n  .js .hero [data-open] img { transform: scale(1.08); animation: load-settle 1100ms var(--ease-expo) 100ms forwards; }\n}\n@keyframes load-line { to { transform: none; } }\n@keyframes load-rise { to { opacity: 1; transform: none; } }\n@keyframes load-open { to { clip-path: inset(0); } }\n@keyframes load-settle { to { transform: none; } }\n```\n\nThe timeline: the headline's lines rise from 100 to 990 ms, the picture opens from 150 to 1,150 ms,\nthe sentence and the button arrive from 420 to 980 ms. All settled by 1.2 s, four things at most.\nPreload the display font (`<link rel=\"preload\" as=\"font\" type=\"font/woff2\" crossorigin>`) so the lines\nrise in the real face, and give the picture `fetchpriority=\"high\"` and a ground colour sampled from it,\nso a slow image opens onto its own colour rather than a blank box. Study: 22 of 91 pages were readable\nat the first intro frame and 11 more by 1.2 s; the intros the readers called respectful finished in\nabout 1-1.2 s; a third of the pages were still unreadable at 4.5 s.\n\n### Masked line reveal (the classic gallery headline)\n\nEach line slides up from behind its own baseline. Because headlines are capped at two lines, you set\nthe line breaks yourself and wrap each line.\n\n```html\n<h1 class=\"lines\">\n  <span class=\"line\"><span data-line style=\"--i:0\">Stools for</span></span>\n  <span class=\"line\"><span data-line style=\"--i:1\">small kitchens</span></span>\n</h1>\n```\n\n```css\n.lines .line { display: block; overflow: hidden; padding-bottom: 0.08em; margin-bottom: -0.08em; }\n.lines [data-line] { display: block; }\n@media (prefers-reduced-motion: no-preference) {\n  .js .lines [data-line] {\n    transform: translateY(105%);\n    animation: line-up 900ms var(--ease-out) forwards;\n    animation-delay: calc(var(--i) * 110ms + 150ms);\n  }\n}\n@keyframes line-up { to { transform: none; } }\n```\n\nThe `padding-bottom` / negative margin pair stops descenders (g, y, p) being clipped by the mask.\nOn a narrow phone the two authored lines may each wrap; check the mobile screenshot, and if they do,\nauthor a shorter mobile break with a `<br class=\"only-wide\">` pattern or reduce the size.\n\n### Reveal on scroll (once)\n\nFor the two or three sections that deserve it, not for every block.\n\n```css\n@media (prefers-reduced-motion: no-preference) {\n  .js [data-reveal] { opacity: 0; transform: translateY(24px); transition: opacity 700ms var(--ease-out), transform 900ms var(--ease-out); }\n  .js [data-reveal].is-in { opacity: 1; transform: none; }\n}\n```\n\n```js\nconst io = new IntersectionObserver((entries) => {\n  for (const e of entries) if (e.isIntersecting) { e.target.classList.add('is-in'); io.unobserve(e.target); }\n}, { rootMargin: '0px 0px -12% 0px', threshold: 0.1 });\ndocument.querySelectorAll('[data-reveal]').forEach((el) => io.observe(el));\n```\n\nNever attach reveals with a scroll listener, never replay them when the element re-enters, and never\nleave anything at `opacity: 0` if the observer fails to fire (the `html.js` gate handles no-JS; the\n`unobserve` handles replays).\n\n### Image shutter\n\nAn image opens from one edge while scaling down slightly inside its frame. Gallery staple; use it for\nthe one hero or showcase image.\n\n```css\n.shutter { overflow: hidden; }\n@media (prefers-reduced-motion: no-preference) {\n  .js .shutter { clip-path: inset(0 0 100% 0); transition: clip-path 1100ms var(--ease-in-out); }\n  .js .shutter img { transform: scale(1.12); transition: transform 1500ms var(--ease-soft); }\n  .js .shutter.is-in { clip-path: inset(0); }\n  .js .shutter.is-in img { transform: none; }\n}\n```\n\n### Press and hover\n\n```css\n.button { transition: transform var(--t-press) var(--ease-out), background-color var(--t-hover) ease, color var(--t-hover) ease; }\n.button:active { transform: scale(0.97); }\n.link { text-decoration: underline; text-decoration-color: transparent; text-underline-offset: 0.2em; text-decoration-thickness: 0.07em; transition: text-decoration-color var(--t-hover) ease; }\n@media (hover: hover) and (pointer: fine) {\n  .button:hover { background-color: var(--accent-strong); }\n  .link:hover { text-decoration-color: currentColor; }\n}\n```\n\nHover styles go behind `(hover: hover)` because touch devices fire hover on tap and leave it stuck.\nHover should raise contrast, never lower it. Do not change font weight on hover (the text reflows).\nDo not lift or scale every card on hover; one consistent, small response is enough.\n\n### Scroll-linked progress without JavaScript\n\nFor a wordmark that scales as the hero leaves, an image that drifts a few percent, or a progress bar.\nWrap in `@supports` so browsers without scroll timelines get the static state.\n\n```css\n@supports (animation-timeline: view()) {\n  @media (prefers-reduced-motion: no-preference) {\n    .drift { animation: drift linear both; animation-timeline: view(); animation-range: entry 0% exit 100%; }\n    @keyframes drift { from { transform: translateY(-4%); } to { transform: translateY(4%); } }\n  }\n}\n```\n\nKeep the travel small (under 8% of the element). Large parallax makes text hard to read and looks\ndated.\n\n### Pinned story\n\nA section whose heading stays put while items pass. Use `position: sticky`; do not hijack scrolling.\n\n```css\n.story { display: grid; grid-template-columns: 5fr 7fr; gap: var(--gutter); align-items: start; }\n.story__title { position: sticky; top: 18vh; }\n@media (max-width: 800px) { .story { grid-template-columns: 1fr; } .story__title { position: static; } }\n```\n\n### Index with preview, anchored to the row\n\nRows of names; pointing at a row or tabbing to it opens one frame level with that row. The frame\nfollows the row, never the pointer.\n\n```html\n<section class=\"index\">\n  <ul class=\"index__list\">\n    <li><a class=\"index__row\" href=\"/work/harbour-house\" data-preview=\"/img/harbour-house.jpg\">\n      <span class=\"index__name\">Harbour House</span><span class=\"index__year\">2025</span>\n      <img class=\"index__thumb\" src=\"/img/harbour-house-small.jpg\" alt=\"\" loading=\"lazy\" width=\"640\" height=\"400\">\n    </a></li>\n    <!-- … -->\n  </ul>\n  <div class=\"index__frame\" aria-hidden=\"true\"><img alt=\"\"></div>\n</section>\n```\n\n```css\n.index { position: relative; }\n.index__list { list-style: none; margin: 0; padding: 0; }\n.index__row { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: 0 var(--gutter); padding-block: 0.3em; font-size: var(--step-head); color: inherit; text-decoration: none; transition: opacity var(--t-hover) ease; }\n.index__thumb { order: -1; flex-basis: 100%; width: 100%; height: auto; margin-bottom: 0.4rem; }\n.index__frame { display: none; }\n@media (hover: hover) and (pointer: fine) {\n  .index__list { max-width: 62%; }\n  .index__thumb { display: none; }\n  .index__list:has(.index__row:hover, .index__row:focus-visible) .index__row:not(:hover, :focus-visible) { opacity: 0.4; }\n  .index__frame { display: block; position: absolute; top: 0; right: var(--margin); width: 30%; aspect-ratio: 4 / 3; z-index: 1; pointer-events: none; clip-path: inset(100% 0 0 0); transition: clip-path 320ms var(--ease-out), transform 360ms var(--ease-out); }\n  .index__frame.is-open { clip-path: inset(0); }\n  .index__frame img { width: 100%; height: 100%; object-fit: cover; }\n}\n@media (prefers-reduced-motion: reduce) { .index__frame { transition: none; } }\n```\n\n```js\n(() => {\n  const root = document.querySelector('.index');\n  if (!root) return;\n  const frame = root.querySelector('.index__frame');\n  const picture = frame.querySelector('img');\n  const fine = matchMedia('(hover: hover) and (pointer: fine)');\n  let warmed = false;\n  const show = (row) => {\n    if (!fine.matches) return;\n    if (!warmed) { warmed = true; root.querySelectorAll('[data-preview]').forEach((a) => { new Image().src = a.dataset.preview; }); }\n    picture.src = row.dataset.preview;\n    const y = row.offsetTop + row.offsetHeight / 2 - frame.offsetHeight / 2;\n    const max = root.offsetHeight - frame.offsetHeight;\n    const opening = !frame.classList.contains('is-open');\n    if (opening) frame.style.transitionProperty = 'clip-path';   // open in place, do not slide in from the top\n    frame.style.transform = `translateY(${Math.min(max, Math.max(0, y))}px)`;\n    if (opening) { frame.getBoundingClientRect(); frame.style.transitionProperty = ''; }\n    frame.classList.add('is-open');\n  };\n  const hide = () => frame.classList.remove('is-open');\n  root.querySelectorAll('.index__row').forEach((row) => {\n    row.addEventListener('pointerenter', () => show(row));\n    row.addEventListener('focus', () => show(row));\n  });\n  root.addEventListener('pointerleave', hide);\n  root.addEventListener('focusout', (e) => { if (!root.contains(e.relatedTarget)) hide(); });\n})();\n```\n\nOn touch screens each row shows its own picture above the name. Study: 5 pages navigate work this way;\nframes from about 470x270 to large plates behind the list; the other rows dimmed to about 0.3 (0.4 here, the floor for dimmed text). The\nimage trails and cursor-borne previews seen elsewhere in the study are the gimmick version.\n\n### Lines that rise on scroll\n\nFor a section heading or a statement whose line breaks you do not control. Splits after the fonts\nload, reveals once, then gives the plain text back so it rewraps normally. Plain text only (no links or\nemphasis inside).\n\n```html\n<h2 class=\"head\" data-lines>Turned by hand in one small workshop</h2>\n```\n\n```css\n[data-lines] .line { display: block; overflow: clip; padding-bottom: 0.12em; margin-bottom: -0.12em; }\n[data-lines] .line > span { display: block; }\n@media (prefers-reduced-motion: no-preference) {\n  .is-split .line > span { transform: translateY(110%); }\n  .is-split.is-in .line > span { transform: none; transition: transform 900ms var(--ease-expo) calc(var(--i) * var(--stagger-line)); }\n}\n```\n\n```js\n(() => {\n  const els = [...document.querySelectorAll('[data-lines]')];\n  if (!els.length || !('IntersectionObserver' in window) || matchMedia('(prefers-reduced-motion: reduce)').matches) return;\n  const restore = (el) => { el.textContent = el.dataset.text; el.classList.remove('is-split', 'is-in'); };\n  const split = (el) => {\n    const text = el.textContent.trim().replace(/\\s+/g, ' ');\n    el.dataset.text = text;\n    el.textContent = '';\n    const words = text.split(' ').map((word) => {\n      const s = document.createElement('span');\n      s.style.display = 'inline-block';\n      s.textContent = word;\n      el.append(s, ' ');\n      return s;\n    });\n    const lines = [];                                   // group the words by the line they landed on\n    for (const w of words) {\n      const last = lines.at(-1);\n      if (last && Math.abs(last.top - w.offsetTop) < 4) last.words.push(w.textContent);\n      else lines.push({ top: w.offsetTop, words: [w.textContent] });\n    }\n    el.textContent = '';\n    lines.forEach((line, i) => {\n      const mask = document.createElement('span');\n      const inner = document.createElement('span');\n      mask.className = 'line';\n      inner.style.setProperty('--i', i);\n      inner.textContent = line.words.join(' ');\n      mask.append(inner);\n      el.append(mask, ' ');\n    });\n    el.classList.add('is-split');\n  };\n  const io = new IntersectionObserver((entries) => {\n    for (const e of entries) {\n      if (!e.isIntersecting) continue;\n      io.unobserve(e.target);\n      e.target.classList.add('is-in');\n      e.target.querySelector('.line:last-of-type > span')\n        .addEventListener('transitionend', () => restore(e.target), { once: true });\n    }\n  }, { rootMargin: '0px 0px -12% 0px' });\n  document.fonts.ready.then(() => els.forEach((el) => { split(el); io.observe(el); }));\n  let width = innerWidth;                               // a width change before the reveal: give the text back\n  addEventListener('resize', () => {\n    if (innerWidth === width) return;\n    width = innerWidth;\n    els.filter((el) => el.matches('.is-split:not(.is-in)')).forEach((el) => { io.unobserve(el); restore(el); });\n  });\n})();\n```\n\nStudy: masked rises from 100-120% below the line, 0.6-1.2 s, 75-120 ms between lines, triggered when\nthe block's top is 80-95% down the viewport. Reduced motion: the script does not run; the text is plain.\n\n### Opening window\n\nThe hand-over from a type screen to the one big picture: the picture first shows as a window in the\nmiddle of a held stage and opens to full-bleed over about one screen of scroll.\n\n```html\n<section class=\"opening\">\n  <div class=\"opening__stage\">\n    <img src=\"workshop-wide.jpg\" alt=\"The workshop at first light, benches cleared\" width=\"2400\" height=\"1500\">\n  </div>\n</section>\n```\n\n```css\n.opening__stage { height: 100svh; overflow: clip; }\n.opening__stage img { display: block; width: 100%; height: 100%; object-fit: cover; }\n@supports (animation-timeline: view()) {\n  @media (prefers-reduced-motion: no-preference) {\n    .opening { height: 200svh; view-timeline-name: --opening; --inset-y: 20%; --inset-x: 28%; }\n    .opening__stage { position: sticky; top: 0; animation: opening-window linear both; animation-timeline: --opening; animation-range: contain 0% contain 75%; }\n    .opening__stage img { animation: opening-settle linear both; animation-timeline: --opening; animation-range: contain 0% contain 75%; }\n  }\n}\n@media (max-width: 700px) { .opening { --inset-y: 18%; --inset-x: 8%; } }\n@keyframes opening-window { from { clip-path: inset(var(--inset-y) var(--inset-x)); } to { clip-path: inset(0); } }\n@keyframes opening-settle { from { transform: scale(1.15); } to { transform: none; } }\n```\n\nThe section is two screens tall; the stage is held for one, and the window is fully open after three\nquarters of it, so the full-bleed picture rests for a moment before the page moves on. Study: 14 pages;\nstart windows 38-60% of the width; runways 600-1,800 px, and the readers asked for one to two screens.\nWithout scroll timelines, and under reduced motion, the picture is a full-bleed screen.\n\n### Held picture, passing captions\n\nThe pinned story built for photographs: the picture holds on one side while short captions pass on\nthe other; the caption at the middle of the screen is lit and its picture is shown.\n\n```html\n<section class=\"steps\">\n  <figure class=\"steps__media\">\n    <div class=\"steps__pictures\">\n      <img src=\"seasoning.jpg\" alt=\"Ash boards stacked to season\" class=\"is-on\">\n      <img src=\"turning.jpg\" alt=\"A leg being turned on the lathe\">\n      <img src=\"finish.jpg\" alt=\"Oil rubbed into a finished seat\">\n    </div>\n    <figcaption class=\"steps__count\" aria-hidden=\"true\"></figcaption>\n  </figure>\n  <ol class=\"steps__list\">\n    <li class=\"steps__item\"><h3>Seasoned for a year</h3><p>…</p></li>\n    <li class=\"steps__item\"><h3>Turned by hand</h3><p>…</p></li>\n    <li class=\"steps__item\"><h3>Finished with oil</h3><p>…</p></li>\n  </ol>\n</section>\n```\n\n```css\n.steps { display: grid; grid-template-columns: 7fr 5fr; column-gap: var(--gutter); }\n.steps__media { margin: 0; align-self: start; }           /* a stretched grid item cannot stick */\n.steps__pictures img { display: block; width: 100%; height: auto; }\n.steps__list { list-style: none; margin: 0; padding: 0; }\n.steps__item { min-height: 80svh; display: flex; flex-direction: column; justify-content: center; }\n.js .steps__media { position: sticky; top: 0; height: 100svh; display: flex; flex-direction: column; justify-content: center; gap: 0.75rem; }\n.js .steps__pictures { position: relative; aspect-ratio: 4 / 5; max-height: 80svh; }\n.js .steps__pictures img { position: absolute; inset: 0; height: 100%; object-fit: cover; opacity: 0; transition: opacity 500ms ease; }\n.js .steps__pictures img.is-on { opacity: 1; }\n.js .steps__item { opacity: 0.4; transition: opacity var(--t-ui) ease; }\n.js .steps__item.is-active { opacity: 1; }\n@media (max-width: 800px) {\n  .steps { display: block; }                               /* the section, not a grid area, contains the sticky picture */\n  .js .steps__media { height: auto; z-index: 1; background: var(--bg); padding-block: 0.5rem; }\n  .js .steps__pictures { aspect-ratio: 3 / 2; max-height: 42svh; }\n  .steps__item { min-height: 60svh; }\n}\n@media (prefers-reduced-motion: reduce) { .js .steps__pictures img, .js .steps__item { transition: none; } }\n```\n\n```js\n(() => {\n  const root = document.querySelector('.steps');\n  if (!root || !('IntersectionObserver' in window)) return;\n  const items = [...root.querySelectorAll('.steps__item')];\n  const pictures = [...root.querySelectorAll('.steps__pictures img')];\n  const count = root.querySelector('.steps__count');\n  const show = (i) => {\n    items.forEach((el, k) => el.classList.toggle('is-active', k === i));\n    pictures.forEach((el, k) => el.classList.toggle('is-on', k === i));\n    if (count) count.textContent = `${i + 1} of ${items.length}`;\n  };\n  const io = new IntersectionObserver((entries) => {\n    for (const e of entries) if (e.isIntersecting) show(items.indexOf(e.target));\n  }, { rootMargin: '-45% 0px -45% 0px' });                 // a band across the middle of the screen\n  items.forEach((el) => io.observe(el));\n  show(0);\n})();\n```\n\nWithout JavaScript the pictures and captions are two plain columns. Study: inactive items at 20-40%\n(dims of 10-15% read as missing text, so the floor here is 40%), crossfades of 400-600 ms, about one\nscreen per step; the readers asked for a visible count on any held sequence of more than two steps.\nThe count is a plain sentence in the body face, not a zero-padded numeral.\n\n### Sideways gallery\n\nA row of pictures that the vertical scroll moves sideways while the stage is held, for a short\ncollection (eight items or fewer). The native drag row is the base; the pinned version is added only\non wide screens with motion allowed, and only when the row is under three screens long.\n\n```html\n<section class=\"gallery\">\n  <div class=\"gallery__stage\">\n    <h2 class=\"head\">Eight kitchens, one stool</h2>\n    <ul class=\"gallery__track\">\n      <li class=\"gallery__item\"><a href=\"/kitchens/leith\"><img src=\"leith.jpg\" alt=\"A narrow galley kitchen in Leith\" width=\"1200\" height=\"1500\"><span>Leith</span></a></li>\n      <!-- … -->\n    </ul>\n  </div>\n</section>\n```\n\n```css\n.gallery__track { display: flex; gap: var(--gutter); list-style: none; margin: 0; padding: 0 var(--margin); overflow-x: auto; scroll-snap-type: x mandatory; scroll-padding-inline: var(--margin); }\n.gallery__item { flex: 0 0 min(72vw, 28rem); scroll-snap-align: start; }\n.gallery__item img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover; }\n.gallery.is-pinned .gallery__stage { position: sticky; top: 0; height: 100svh; display: flex; flex-direction: column; justify-content: center; gap: 2rem; overflow: clip; }\n.gallery.is-pinned .gallery__track { overflow: visible; scroll-snap-type: none; }\n.gallery.is-pinned .gallery__item { flex-basis: calc(62svh * 0.8); }\n```\n\n```js\n(() => {\n  const root = document.querySelector('.gallery');\n  if (!root) return;\n  const track = root.querySelector('.gallery__track');\n  const wide = matchMedia('(min-width: 900px) and (prefers-reduced-motion: no-preference)');\n  let dx = 0, queued = false;\n  const place = () => {\n    queued = false;\n    if (!root.classList.contains('is-pinned')) return;\n    const p = Math.min(1, Math.max(0, -root.getBoundingClientRect().top / dx));\n    track.style.transform = `translate3d(${(-p * dx).toFixed(1)}px, 0, 0)`;\n  };\n  const measure = () => {\n    root.classList.add('is-pinned');                     // measure the row as it would be when pinned\n    track.style.transform = '';\n    dx = track.scrollWidth - track.clientWidth;\n    const pin = wide.matches && dx > 0 && dx < innerHeight * 3;\n    root.classList.toggle('is-pinned', pin);\n    root.style.height = pin ? `${innerHeight + dx}px` : ''; // one pixel of scroll moves the row one pixel\n    place();\n  };\n  track.addEventListener('focusin', (e) => {             // keyboard: bring the focused item into view\n    if (!root.classList.contains('is-pinned')) return;\n    const item = e.target.closest('.gallery__item');\n    const x = Math.min(dx, Math.max(0, item.offsetLeft - parseFloat(getComputedStyle(track).paddingLeft)));\n    scrollTo({ top: root.getBoundingClientRect().top + scrollY + x, behavior: 'instant' });\n  });\n  addEventListener('scroll', () => { if (!queued) { queued = true; requestAnimationFrame(place); } }, { passive: true });\n  addEventListener('resize', measure);\n  addEventListener('load', measure);\n  wide.addEventListener('change', measure);\n  measure();\n})();\n```\n\nStudy: 8 pages pinned a horizontal track; their pages ran a median 25 screens, and the readers' worst\ncases spent 9 screens on three cards and 10,000-23,000 px of wheel on one track. Here the speed is 1:1\nand the hold ends when the last picture reaches the margin. Phones, narrow windows, reduced motion and\nlong rows all get the native row with snapping, which also works with touch, trackpads and the\nkeyboard. Never put the only copy of a call to action inside the moving row.\n\n### Receding hero\n\nAs the first screen leaves, its picture sinks a little and darkens while the words lift away a little\nfaster, so the hero recedes instead of simply scrolling off.\n\n```html\n<header class=\"hero\">\n  <img class=\"hero__picture\" src=\"kitchen.jpg\" alt=\"…\" width=\"2400\" height=\"1600\" fetchpriority=\"high\">\n  <div class=\"hero__copy\"><h1 class=\"display\">…</h1><p class=\"lead\">…</p></div>\n</header>\n```\n\n```css\n.hero { position: relative; min-height: 100svh; overflow: clip; display: grid; align-items: end; view-timeline-name: --hero; }\n.hero__picture { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }\n.hero::after { content: ''; position: absolute; inset: 0; background: var(--ink); opacity: 0; pointer-events: none; }\n.hero__copy { position: relative; z-index: 1; padding: var(--margin); }\n@supports (animation-timeline: view()) {\n  @media (prefers-reduced-motion: no-preference) {\n    .hero__picture { animation: hero-sink linear both; animation-timeline: --hero; animation-range: exit 0% exit 100%; }\n    .hero::after { animation: hero-dim linear both; animation-timeline: --hero; animation-range: exit 0% exit 100%; }\n    .hero__copy { animation: hero-lift linear both; animation-timeline: --hero; animation-range: exit 0% exit 70%; }\n  }\n}\n@keyframes hero-sink { to { transform: translateY(8%) scale(1.06); } }\n@keyframes hero-dim { to { opacity: 0.35; } }\n@keyframes hero-lift { to { transform: translateY(-6%); opacity: 0; } }\n```\n\nThe `exit` range runs from the moment the hero's top meets the top of the screen until its bottom\ndoes, which for a first screen is the first screen of scroll. Study: hero pictures that sink and dim as\nthey leave, a heading scrubbed from 140 to 60 px, a title card that scales down on the phone; the\nreaders called it quiet and the page \"one sheet\". Travel stays under 8%; the overlay is a flat ink at\nup to 35%, not a gradient. Static where unsupported or reduced.\n\n\n\n\n\n### Page to page\n\nNavigation between pages of the site with the browser's own view transitions: the old page fades\nquickly, the new one rises in, and the picture the visitor clicked travels into place as the new\npage's hero. No library, no full-screen curtain.\n\n```css\n/* on every page */\n@view-transition { navigation: auto; }\n@media (prefers-reduced-motion: reduce) { @view-transition { navigation: none; } }\n::view-transition-old(root) { animation: vt-leave 200ms var(--ease-exit) both; }\n::view-transition-new(root) { animation: vt-arrive 380ms var(--ease-out) 60ms both; }\n::view-transition-group(*) { animation-duration: 480ms; animation-timing-function: var(--ease-in-out); }\n::view-transition-image-pair(*.picture) { overflow: clip; }\n::view-transition-old(*.picture), ::view-transition-new(*.picture) { height: 100%; object-fit: cover; }\n@keyframes vt-leave { to { opacity: 0; } }\n@keyframes vt-arrive { from { opacity: 0; transform: translateY(16px); } }\n```\n\n```html\n<!-- on the index: the card picture of one project -->\n<img src=\"/img/leith.jpg\" alt=\"…\" style=\"view-transition-name: kitchen-leith; view-transition-class: picture\">\n<!-- on that project's page: its hero picture -->\n<img src=\"/img/leith-wide.jpg\" alt=\"…\" style=\"view-transition-name: kitchen-leith; view-transition-class: picture\">\n```\n\nEach name may appear once per page. Browsers without cross-document view transitions simply navigate.\nStudy: 16 pages load a page-transition library and run full-screen curtains of 0.7-2.4 s; 6 use view\ntransitions. The new page should be readable within half a second.\n\n### Ink fill\n\nOne statement that fills from part-ink to full ink as it rises through the screen, line by line. It is\nreadable before it fills; the fill only sets the pace.\n\n```html\n<p class=\"statement head\" data-fill>Nine people, one workshop, no catalogue: every stool is made for the kitchen it goes to.</p>\n```\n\n```css\n[data-fill] { --fill: var(--ink); color: var(--fill); }\n@supports (animation-timeline: view()) {\n  @media (prefers-reduced-motion: no-preference) {\n    .is-filling > span { display: inline-block; color: color-mix(in oklab, var(--fill) 45%, transparent); animation: ink-fill linear both; animation-timeline: view(); animation-range: cover 20% cover 45%; }\n  }\n}\n@keyframes ink-fill { to { color: var(--fill); } }\n```\n\n```js\n(() => {\n  if (!CSS.supports('animation-timeline: view()') || matchMedia('(prefers-reduced-motion: reduce)').matches) return;\n  document.querySelectorAll('[data-fill]').forEach((el) => {\n    const words = el.textContent.trim().split(/\\s+/);\n    el.textContent = '';\n    words.forEach((word, i) => {\n      const s = document.createElement('span');\n      s.textContent = word;\n      el.append(s, i < words.length - 1 ? ' ' : '');\n    });\n    el.classList.add('is-filling');\n  });\n})();\n```\n\nEach word watches its own position, so the words of a line fill together as the line moves from three\nquarters of the way down the screen to just past half way. Set `--fill` on a dark chapter to its ink.\nStudy: 14 pages scrub a statement from grey to ink; unread words started at about 25-30% and settled\nframes still caught statements half pale, which reads as disabled text. Here: one statement per page,\nthree to five lines, 32px or larger, starting at 45% (about 3:1 against the ground, enough for large\ntext). Full ink without scroll timelines or under reduced motion.\n\n### Rolling figures\n\nFor pages whose case is a handful of numbers: each digit rolls up to its value once, the columns a\nbeat apart. The real number stays in the text for screen readers and search.\n\n```html\n<p class=\"figure\"><span class=\"display\" data-roll>1987</span> the year the first stool was sold</p>\n```\n\n```css\n.roll__digits { display: inline-flex; font-variant-numeric: tabular-nums; line-height: 1; }\n.roll__col { display: inline-block; height: 1em; overflow: clip; }\n.roll__strip { display: flex; flex-direction: column; transform: translateY(calc(var(--d) * -1em)); }\n.roll__strip > span { height: 1em; }\n@media (prefers-reduced-motion: no-preference) {\n  .roll:not(.is-in) .roll__strip { transform: none; }\n  .roll.is-in .roll__strip { transition: transform 1100ms var(--ease-expo) calc(var(--i) * var(--stagger-item)); }\n}\n```\n\n```js\n(() => {\n  const els = [...document.querySelectorAll('[data-roll]')];\n  if (!els.length) return;\n  els.forEach((el) => {\n    const value = el.textContent.trim();\n    const said = Object.assign(document.createElement('span'), { className: 'sr-only', textContent: value });\n    const shown = Object.assign(document.createElement('span'), { className: 'roll__digits' });\n    shown.setAttribute('aria-hidden', 'true');\n    let i = 0;\n    for (const ch of value) {\n      if (!/\\d/.test(ch)) { shown.append(ch); continue; }\n      const col = Object.assign(document.createElement('span'), { className: 'roll__col' });\n      const strip = Object.assign(document.createElement('span'), { className: 'roll__strip' });\n      strip.style.setProperty('--d', ch);\n      strip.style.setProperty('--i', i++);\n      for (let n = 0; n < 10; n++) strip.append(Object.assign(document.createElement('span'), { textContent: n }));\n      col.append(strip);\n      shown.append(col);\n    }\n    el.classList.add('roll');\n    el.replaceChildren(said, shown);\n  });\n  if (!('IntersectionObserver' in window)) { els.forEach((el) => el.classList.add('is-in')); return; }\n  const io = new IntersectionObserver((entries) => {\n    for (const e of entries) if (e.isIntersecting) { e.target.classList.add('is-in'); io.unobserve(e.target); }\n  }, { rootMargin: '0px 0px -15% 0px' });\n  els.forEach((el) => io.observe(el));\n})();\n```\n\nStudy: 6 pages roll digit columns (stats, a year, coordinates), about 0.9-1.1 s per column on an\nexpo-out, staggered by column. Use it for three or four figures at display size, never in running text\nand never for a value that changes after load. Reduced motion: the figure is set at its value.\n\n### Accordion\n\n```css\n.acc__panel { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 320ms var(--ease-out); }\n.acc__panel > div { overflow: hidden; }\n.acc[open] .acc__panel, .acc__item.is-open .acc__panel { grid-template-rows: 1fr; }\n```\n\nAnimating `grid-template-rows` from `0fr` to `1fr` opens to the content's real height without measuring\nit in JavaScript.\n\n### Menu or dialog\n\n```css\n.menu { transform-origin: top right; transition: opacity var(--t-ui) var(--ease-out), transform var(--t-ui) var(--ease-out); }\n.menu[hidden], .menu.is-closed { opacity: 0; transform: scale(0.97) translateY(-6px); pointer-events: none; }\n```\n\nThings open from where they were triggered (`transform-origin` at the trigger). Nothing enters from\n`scale(0)`; start at 0.95–0.98. A centred dialog is the one case that scales from its centre.\n\n## 7. Signature moves\n\nThe direction sheet names one. Each of these was seen repeatedly on the studied gallery sites.\n\n| Move | What happens | Build with |\n| --- | --- | --- |\n| Masked headline | Lines rise from behind their baselines on load | Masked line reveal recipe |\n| Shutter image | Hero or showcase image opens from an edge, settling from 1.12 scale | Image shutter recipe |\n| Scaling wordmark | A giant wordmark shrinks or grows a few percent as the hero scrolls out | Scroll-linked recipe on `scale` |\n| Pinned story | A heading holds while its items scroll past | Sticky recipe |\n| Index with preview | Text rows; the hovered row shows its image | Index with preview, anchored to the row |\n| Curtain footer | The last section is revealed from under the page as you reach the end | `position: sticky; bottom: 0` footer under a main with a background and `z-index` |\n| Slow crossfade | Hero image crossfades through 3–4 photographs, 5–6s each | Stacked images, opacity keyframes, pause when the tab is hidden |\n| Edge-to-edge marquee | One line of very large type travels sideways, slowly | Duplicate the content, `translateX(-50%)` linear loop, pause on hover and under reduced motion |\n| Drag row | A horizontally scrollable row of large images with scroll snapping | `overflow-x: auto; scroll-snap-type: x mandatory`, no library |\n| Colour by chapter | Each chapter is its own full-bleed colour field, so the ground changes at section edges; a fixed header takes the ink of the chapter beneath | Section backgrounds in CSS; `base.js` sets `--header-ink` from `data-ink`. Never recolour the whole page from an observer |\n| Opening window | A type screen hands over to the big picture: a window in the middle of a held stage opens to full-bleed over about one screen | Opening window recipe |\n| Ink-fill statement | One statement fills from 45% to full ink as it rises through the screen | Ink fill recipe |\n| Sheet over a held picture | A full-bleed photograph holds for one screen; the next chapter slides up over it as an opaque sheet | A 100svh `position: sticky; top: 0` figure followed by a section with its own background and a higher `z-index`; no script |\n| Sideways gallery | A short row of pictures moves sideways while the vertical scroll holds the stage | Sideways gallery recipe |\n| Pushed line | One line of very large type is pushed sideways by the scroll, reading whole at the middle of its run | `animation-timeline: view()` on the line, `translateX` from 12% to -12%, linear; static where unsupported |\n| Rolling figures | The few figures that make the case roll up to their values once | Rolling figures recipe |\n| Carried picture | The picture clicked in a list travels into place as the next page's hero | Page to page recipe |\n\nPick by subject. A portfolio wants the index with preview; a restaurant wants the slow crossfade; a\nproduct wants the shutter on its hero object. If the move says nothing about the subject, it is\ndecoration and the page is better without it.\n\nPick by subject, as before: the opening window for a product or a place with one great photograph; the\nsheet for chapters that each own a picture; the sideways gallery for a short set of rooms, kitchens or\npieces; the pushed line for a brand whose claim is a word; rolling figures for a report, a fund or a\npractice that leads with numbers; the carried picture for a portfolio whose index and case pages are\nboth built.\n\n## 8. Reduced motion and performance\n\n- `prefers-reduced-motion: reduce` means fewer and gentler, not none: keep opacity and colour changes,\n  drop travel, scale, parallax and autoplay. All recipes above are written inside\n  `no-preference` blocks so the reduced state is simply the finished state.\n- Animate `transform`, `opacity` and `clip-path`. Animating `width`, `height`, `top`, `left`, `margin`\n  or `padding` forces layout on every frame. `grid-template-rows` for accordions is the accepted\n  exception because it is short and rare.\n- Do not drive many children from one changing CSS variable on a parent; set the transform on the\n  element that moves.\n- `will-change` only on an element that is about to animate, removed afterwards.\n- Pause loops when off screen or when the tab is hidden.\n- No scroll hijacking and no custom cursor. They cost usability, which is 30% of an Awwwards score and\n  the line most winners score lowest on. Smoothing only through `Stage.smooth()`, which stays off for\n  touch and reduced motion.\n\n## 9. What gives generated motion away\n\n- The same fade-up on every block.\n- A dozen staggered entrances in the hero.\n- Hover lift or zoom on every card and image.\n- Bounce or elastic easing on interface elements.\n- Infinite loops that mean nothing: pulsing dots, floating shapes, shimmering text, rotating badges.\n- A reveal that never fires and leaves a blank band in the page. Run `inspect.mjs` after the motion\n  pass and look at every screenshot for missing content.\n\n### Seen in the latest Sites of the Day\n\nSeen in the study, with how often, and what the house does instead.\n\n- **Preloaders and counters (60 of 99; 26 with a counter).** Half the usable pages were unreadable\n  2.5 s after load, a third at 4.5 s; the preloaders sat mostly on pages that had already loaded, and\n  25 of the 29 that loaded in under 3 s still showed nothing readable at 4.5 s. Counters stalled,\n  outlasted the load or were tweens with nothing behind them. House: no preloader. If a scene must\n  load, the HTML first screen (headline, picture, action) is there at once and the scene fades in\n  behind it when ready.\n- **Gates (10 of 99): enter, sound, age or gesture before any content.** House: none. Sound is a\n  control on the page, off by default.\n- **Scroll hijacking (16 wheel-driven scenes, 9 of them endless, plus 14 single screens where the wheel\n  does nothing).** The visitor cannot tell where they are, how much is left or how to get out, and the\n  keyboard and screen readers get nothing. Usability 6.01 against 6.50 for pages that scroll. House:\n  native scroll; any scene is \n\n<!-- [TRUNCATED AT 50KB] -->","skills/taste-skill/references/research.md":"# The study\n\nEverything numeric in this skill comes from here. Cite these figures; do not round them up or invent\nothers.\n\n## Contents\n\n1. Method and its limits\n2. Scores\n3. Where the idea comes from\n4. Headlines\n5. Type\n6. Devices: what separates strong from weak, and what does not\n7. Colour and shape\n8. Imagery and page structure\n9. What the inspector says about the gallery itself\n10. The 25 highest-scored sites and their ideas\n11. How the skill was tested\n12. The October 2026 study: 100 Sites of the Day\n13. The app-screen study\n\n## 1. Method and its limits\n\n- **Sample.** 248 sites collected on 5 October 2026: 156 from One Page Love (the latest gallery pages\n  and the category listings) and 92 Awwwards Sites of the Day (the three most recent listing pages).\n  247 loaded; 246 were re-measured with the final probe.\n- **Capture.** Headless Chrome at 1440×900 and 390×844. For each site: the first viewport, five more\n  frames while scrolling with real wheel input, the mobile first viewport, and a measurement pass in\n  the page (computed styles, text geometry, colours, fonts actually loaded).\n- **Panel.** 21 model reviewers each studied about 12 sites from the screenshots and the measurements,\n  described them (idea, hero, type, colour, imagery, layout, sections) and scored them the Awwwards\n  way: design 40%, usability 30%, creativity 20%, content 10%. These are model judgements from still\n  frames, not human jurors and not the real Awwwards scores. Batches mixed both sources so each\n  reviewer saw a spread.\n- **Usable sets.** 235 sites were usable for the panel (12 showed only a preloader, an entry gate or a\n  bot wall). 202 were measurable for typography (a page with at least 25 words and a detectable\n  headline). \"Top\" below means panel score 7.5 or higher (82 measurable sites); \"weak\" means under 6.5\n  (23 measurable sites).\n- **Limits.** One capture per site on one day. Some heroes were caught mid-animation or behind a cookie\n  notice. WebGL-heavy sites are under-described by text measurements. The eyebrow detector counts any\n  small short label directly above a large heading, so it over-counts against the panel's stricter\n  reading (60% measured against 35% observed). Motion was inferred from frames, not watched. The sample\n  is whatever the two galleries had recently featured; it is fashion as much as quality.\n\n## 2. Scores\n\n| | All 235 | One Page Love (151) | Awwwards (84) |\n| --- | --- | --- | --- |\n| Median overall | 7.2 | 7.1 | 7.5 |\n| Middle half | 6.8–7.6 | | |\n| 8.0 or higher | 25 sites (11%) | | |\n| 7.5 or higher | 90 sites (38%) | | |\n| Under 6.5 | 29 sites | | |\n\nMedian by criterion: design 8, usability 7, creativity 7, content 7. Among the top 25: design 9,\nusability 7, creativity 8, content 8. Usability is the one line that does not rise with the rest: the\nbest sites are no easier to use than the average one. Do not copy their gates, preloaders, tiny text\nor hidden navigation.\n\n## 3. Where the idea comes from\n\nThe clearest pattern in the panel's notes: high scores go with a concept taken from the subject, and\nlow scores go with its absence. The weakest entries' ideas were recorded in words like \"none beyond the\nstandard dark SaaS launch formula\", \"no visual idea beyond clarity\", \"no strong idea\". The strongest\nwere sentences only that subject could own (section 10).\n\nRecurring engines among the 7.3+ sites, each the basis of a direction in the library:\n\n- **The product demonstrates itself.** A colour picker's loupe reads the page's own background; a list\n  tool is sold with tiny working lists; a photo app's page is a wall of its own output.\n- **The page is an artefact from the subject's world.** A wedding site that is the invitation; an\n  archive as tabbed folders; a coupon with a cut line; a portfolio as a contact sheet.\n- **The name is the hero.** Wordmarks as wide as the screen, a photograph set inside the name like a\n  letter, a name split to opposite corners with the page between.\n- **One motif from the subject drives everything.** A tool's octagonal section as button, mask and\n  loader; two circles for two accounts; a café's stripes.\n- **Dressed as another category.** A money app as a streetwear drop; an industrial roaster as a design\n  object; a parcel service as a fairground.\n- **The place carries it.** One full-bleed view and a name along the bottom edge.\n- **A fixed stage.** A title or object stays put while content swaps beneath it.\n- **One section, one colour.** Flat fields as chapters.\n- **Radical understatement.** A 27px headline and tiny live demonstrations, carried through completely.\n\nHero types, by the panel's classification (top sites against weak sites): full-bleed media with type\nover it 16% / 10%; giant wordmark 14% / 0%; typographic poster 13% / 7%; text beside media 10% / 3%;\n**centred statement with media below 7% / 24%**. The centred headline over a screenshot is the weak\nsites' signature layout.\n\n## 4. Headlines\n\n| Hero headline | All | Top | Weak |\n| --- | --- | --- | --- |\n| Words, median | 5 | 5 | 5 |\n| Words, middle half | 3–9 | 2–8 | 3–8 |\n| Characters, median | 32 | | |\n| One line at 1440 | 47% | | |\n| Two lines or fewer at 1440 | 70% | 71% | 83% |\n| Two lines or fewer at 390 | 57% | | |\n| Three lines or fewer at 390 | 82% | | |\n\nAwwwards heroes are shorter (median 4 words, 76% within two lines) than One Page Love's (6 words, 66%).\nSection headings have a median of 3 words. Length does not separate strong from weak; nearly everyone\nin the gallery writes short headlines. The two-line limit in this skill is a house rule that most of\nthe gallery already meets on desktop and that takes care to meet on a phone.\n\n## 5. Type\n\n| | All | Top | Weak |\n| --- | --- | --- | --- |\n| Hero size, median | 72px (5.0vw) | 6.0vw | 4.7vw |\n| Hero size, middle half | 3.0–7.6vw | 2.5–9.7vw | 2.7–6.1vw |\n| Largest text on the page, median | 6.4vw | 8.4vw | 5.0vw |\n| Largest text, upper quarter starts at | 10.4vw | 12.5vw | 6.7vw |\n| Hero on a phone, median | 40px | | |\n| Hero tracking, median (middle half) | -0.01em (-0.03 to 0) | | |\n| Hero leading, median (middle half) | 1.0 (0.95–1.1) | | |\n| Body size, median (middle half) | 16px (14–18) | | |\n| Headline ÷ body, median | 4.3 | 4.7 | 4.0 |\n| Typefaces carrying 3%+ of text | one 31%, two 45%, three 22% | | |\n| Distinct font sizes, median | 8 | | |\n\nHero weight: regular 48%, medium 18%, semibold 6%, bold or heavier 22%, light 6%. Capitals 24%.\nCentred 39% overall, 52% on weak sites. Display classes by the panel: neo-grotesk 48%, transitional\nserif 11%, geometric sans 10%, condensed 6%, extended 6%, old-style serif 4%, custom lettering 4%.\n\nStrong sites push the extremes: their biggest type is bigger and their range is wider. Weak sites\ncluster in the middle.\n\n## 6. Devices: what separates strong from weak, and what does not\n\nMeasured in the page unless marked (panel).\n\n**More common on weak sites (the data supports avoiding them):**\n\n| Device | Top | Weak |\n| --- | --- | --- |\n| Icon-topped feature cards (panel) | 1% | 28% |\n| Rows of identical cards with a small icon (measured) | 7% | 26% |\n| Pill badges (panel) | 14% | 34% |\n| Pill-shaped label above a heading (measured) | 5% | 26% |\n| Tiny uppercase letter-spaced labels, any | 16% | 57% |\n| Tiny uppercase letter-spaced labels, three or more | 6% | 43% |\n| Gradient fills (not counting scrims) | 22% | 52% |\n| Gradient text | 2% | 13% |\n| Shadows on resting elements, any | 24% | 48% |\n| Shadows, five or more | 10% | 30% |\n| Emoji in the page | 10% | 26% |\n| Eyebrow labels (panel) | 32% | 45% |\n\n**No real difference:**\n\n| Device | Top | Weak |\n| --- | --- | --- |\n| Backdrop blur anywhere | 32% | 39% |\n| Italic-serif accent word (panel) | 4% | 7% |\n| Thin rules, any | 61% | 52% |\n\n**More common on strong sites (banned here anyway, as house style):**\n\n| Device | Top | Weak |\n| --- | --- | --- |\n| Monospace labels (panel) | 44% | 24% |\n| Monospace anywhere outside code (measured) | 45% | 26% |\n| Index numbering (panel) | 38% | 21% |\n\nMonospace captions, index numbers and ruled grids are the present fashion of award sites. They are\nexcluded from this skill by the owner's choice, not by the data: they are the devices generators copy\nfirst, and a page that cannot lean on them has to find structure in space, tone and scale.\n\n## 7. Colour and shape\n\n- Dark page ground 41%; pure white 25%; pure black 12%; a warm off-white 13%.\n- Scheme (panel): monochrome plus one accent 23%, light neutral 22%, dark neutral 14%, several flat\n  colours 13%, two-tone 12%, photographic 9%, one colour field 6%.\n- Primary buttons are neutral (black, white, grey) on 52% of sites. One site in 246 has a terracotta\n  button; none has a violet one.\n- Median number of distinct section grounds: 2 on top sites, 1 on weak sites.\n- Button shape: top sites square (0–2px) 52%, fully round 23%, small radius 19%, medium (9–16px) 6%.\n  Weak sites fully round 59%, medium 24%, square 18%.\n- Media corners are square on 73% of sites; where rounded, the median radius is 12px.\n- Buttons in the first viewport: none on 55% of top sites and 39% of weak ones.\n\n## 8. Imagery and page structure\n\n- Hero media covers at least half the first viewport on 60% of sites (top 68%, weak 48%) and nearly\n  all of it on 50% (top 56%, weak 39%). No hero media: 15%.\n- Video is present on 49% of sites and a canvas element on 49% (top 62%, weak 35%).\n- Images per page, median: 24 overall, 37 on top sites, 5 on weak ones.\n- Imagery kind (panel): mixed 32%, photography 14%, generative or WebGL 13%, product interface 12%,\n  3D render 11%, illustration 9%, video 6%, type only 3%. Median panel score is lowest for\n  illustration-led (6.9) and product-interface-led (7.1) pages and highest for video and type-only\n  (7.5).\n- Page length, median: 8.7 screens and 575 words (middle half 1.6–14.4 screens, 250–956 words). A\n  quarter of the sites are a single screen or two.\n- Navigation: a median of 3 links; fixed or sticky on 66%.\n- Density (panel): airy 46%, balanced 45%, dense 9%. Alignment: centred 33%, mixed 31%, left-anchored\n  17%, modular grid 13%, free 6%.\n- Asked to describe each site's most interesting sections, the panel picked a pricing, testimonial or\n  FAQ section only 7, 12 and 9 times across 235 sites. Where strong sites have them at all, they are\n  not where the design effort goes, and they avoid the stock form.\n\n**From the panel's written notes on the 114 sites scoring 7.3 or more** (hand tallies, approximate;\n`layout.md` turns these into practice):\n\n- Outer margins of 32px or less on about 45; 80px or more on about 8. A centred 700–1300px container\n  on about 15, several of them the pages the panel called stock.\n- Text anchored to a fixed off-centre line on about 22. Text docked in corners or at opposite ends of\n  a baseline on about 25 and 15.\n- Two or three type sizes with nothing between on about 30; no note describes a graded five-step\n  scale.\n- One thing per screen on about 20. A full background colour per section on about 20; alternating\n  light and dark on about 12.\n- Every section recomposed on about 14; one planned exception to the page's own system on about 14.\n- No conventional top navigation bar on about 45; small corner links on about 22; a single link or\n  button on about 10.\n- Endings: the name at full width about 18, the hero repeated inverted about 12, a closing scene of\n  its own about 14, no footer or a single line about 22. Link-column footers are mentioned only as\n  criticism.\n- Motion (inferred from frames): autoplaying video about 50; pinned or fixed stages about 40; text\n  reveals about 30 (blur-in 10, masked line rises 8, scroll-tied word colouring 7); horizontal strips\n  about 27; marquees about 26; media swapped behind a fixed element about 15; scroll-linked scaling\n  about 12. Rare: hover effects (4 mentions), parallax (6), accordions (5), bounce or spring motion\n  (none). About 10 strong sites show little or no motion at all.\n- How weak sites fail (54 sites under 6.8): the category's stock template about 20; centred headline,\n  pill badge, two buttons and a screenshot about 9; stock modules after a distinctive hero about 8,\n  plus about 17 in the middle band; a characterless default typeface about 13; text too small or too\n  faint about 13; never saying what the thing is about 12.\n- Faults of the best sites (90 at 7.5 or more), not to be copied: text at 9–13px about 24;\n  information hidden behind the concept about 20; the idea running out mid-page about 15; text over\n  footage with no scrim about 12; gates, preloaders and blank first paints about 12.\n\n## 9. What the inspector says about the gallery itself\n\nRunning this skill's own `inspect.mjs` rules over the 202 measurable gallery sites: the median site\nhas 4 `FAIL`s and only 4% have none. The rules that fire most: headline over two lines somewhere on\nthe page 60%, eyebrow-like label 60%, thin rules 50%, monospace 37%, shadows 32%, gradients 29%, index\nnumbering 29%.\n\nSo the house style is deliberately stricter than the gallery. It is not a description of award sites;\nit is a narrower target inside what they do: their scale, their ideas, their imagery and restraint,\nwithout the ornaments that have since become a uniform.\n\n## 10. The 25 highest-scored sites and their ideas\n\nThe panel's one-sentence reading of each. Notice that every one names something only that subject\ncould own. (Several use devices this skill bans; take the idea, not the ornament.)\n\n| Site | Source | Score | Idea |\n| --- | --- | --- | --- |\n| PP Neue Montreal | Awwwards | 8.6 | A typeface specimen dressed as a vintage city travel guide: the font named after Montreal is sold through guidebook titling, postcards and old tourist footage. |\n| Seasats | Awwwards | 8.4 | Calm, dusk-lit seascapes sell autonomous boats as serene instruments, and the navigation is a column of stacked colour swatches taken from that sea-and-sand palette. |\n| AI in Design Report 2026 | Awwwards | 8.4 | A research report laid out like a colour-blocked print annual: a video collage on top, an oversized tight grotesk title, and flat orange, lilac, sage and black blocks carrying stats, quotes and chapters. |\n| House of Honey | Awwwards | 8.4 | A block-heavy wordmark pierced by a fine script: the bold-against-delicate contrast is repeated at every scale, with giant pink script behind quiet serif statements. |\n| White Desert | Awwwards | 8.4 | One word, the destination, set a third of the screen tall over footage like a film title card; sheer scale stands in for remoteness. |\n| Applied Imagination | One Page Love | 8.3 | An essay conceived on a flight is read as a descent: an altimeter ticks from 30,000 ft to zero while you scroll down through clouds to mountains at ground level. |\n| Cursor Compile | One Page Love | 8.3 | The event name drawn as seven looping one-line curves in seven colours, more signature than logotype, on an otherwise whisper-quiet off-white page. |\n| The New Industrials | One Page Love | 8.3 | A long-read essay laid out inside a drafting grid, where colour fields shift as you read and machine parts drift through the margins and finally assemble into the publisher's initials. |\n| Wild | One Page Love | 8.3 | A studio essay in which everything decorative is drawn on one square-pixel grid: the hero heatmap, the icons, the diagrams, the lettering and the footer. |\n| Hildén & Kaira | Awwwards | 8.3 | The agency name is cast in liquid chrome across the full width, and the same chrome becomes the objects that float through the page, tying the pitch to one material. |\n| PX Push | Awwwards | 8.2 | A design subscription presented as a retro broadcast: the entire site is seen through a CRT screen, with a chrome logo token as its mascot. |\n| Illoca | Awwwards | 8.2 | Software for architects sold as a drafting table: a two-colour illustrated studio on graph paper that the scroll pushes into until the drawing fills the screen. |\n| Aspen Search | Awwwards | 8.2 | The page is a tile system with no margins: the two-word name is split across cells that alternate type, dithered image, black and one mint green. |\n| Dragonfly Redux | Awwwards | 8.2 | A crypto fund presented as a terminal artefact: every picture is rendered in characters, framed by four letters of the name pinned to the viewport corners. |\n| Monolog | Awwwards | 8.2 | A studio pitch run as an asymmetric sheet: a narrow left column carries the sales talk while a wide right column stacks a very heavy headline and the proof. |\n| The Queue | One Page Love | 8.1 | An essay on queueing where the queue is the ornament: a line of drawn figures stands along the bottom of the hero and returns between chapters in changing period dress. |\n| Paul Kalkbrenner | Awwwards | 8.1 | Swiss poster typography for a techno artist: the name as one black line with a photo set inside it like a glyph, then every chapter gets its own flat colour. |\n| Vero New York | Awwwards | 8.1 | A keepsake treated like couture: a slow close-up film opens, then a white sculpture of a dress stays pinned at centre while one sentence passes over it. |\n| Depo Luxe | Awwwards | 8.1 | A film production roster shown as a full-screen reel in which every step is one film with only a title, a director and a client, set like credits at body size. |\n| Longbow | Awwwards | 8.1 | The page is built on a visible four-column construction grid, and cars, cards and a giant condensed marquee are slotted into its cells like objects on an artboard. |\n| Mosby's Files | Awwwards | 8.0 | An archive of architects presented as a physical stack of coloured index-tab file folders that you flip through. |\n| Sarah & Matt Wedding | One Page Love | 8.0 | The site is the invitation: a letterpress-style card opens the page, and its ornaments and small typographic parts become the components for everything after it. |\n| Zara Webb | One Page Love | 8.0 | A one-woman newborn-care practice presented like a hand-made keepsake: a mascot rabbit, scalloped and flower-shaped cut-outs, candid film photographs. |\n| Noho | Awwwards | 8.0 | Furniture sold through people misusing it (wearing, balancing on, hiding behind chairs on flat colour backdrops) while the interface stays quiet. |\n| Juggle | One Page Love | 8.0 | The headline literally drowns: a flat blue field rises to half height and the lines below the waterline change colour. |\n\nFull notes on any studied site: `node scripts/draw.mjs --site <id>` (ids appear on direction sheets).\n\n## 11. How the skill was tested\n\nSix client briefs (an invoicing tool, a restaurant, a designer's portfolio, a ceramic product, a\nguesthouse, a design conference), each with no photographs. For every brief a fresh agent built the\npage three ways: with no skill (baseline), with another published design skill (atelier, three briefs)\nand with this skill. Every build was photographed by `inspect.mjs` in the same way and judged blind\nby a separate agent with the juror brief (Awwwards weights, anonymous A/B/C folders, screenshots\nonly). The skill was revised after each round from the jurors' reasons and the builders' notes.\n\n| Round | Briefs | This skill | Baseline | Atelier | Wins |\n| --- | --- | --- | --- | --- | --- |\n| 1 | 4 | 6.6 | 7.7 | 6.8 | 1 of 4 |\n| 2 | 3 | 7.1 | 8.0 | | 0 of 3 |\n| 3 | 3 | 7.5 | 7.5 | | 1 of 3 |\n| 4 (unseen briefs) | 3 | 6.9 | 7.9 | 7.5 | 0 of 3 |\n| 5 (same three) | 3 | 7.7 | 7.8 | 7.2 | 2 of 3 |\n\nUnder the inspector, the final builds measured 0 FAIL each; the baselines measured 8 to 13 FAIL each\n(eyebrows, monospace labels, 01/02/03 numbering, hairlines, gradients, shadows, three-line headlines,\ntext under 13px).\n\nWhat the jurors rewarded, in the order they named it: an idea that belongs to this client and not to\nthe category (the competitor test); one live thing on the page; full content at a readable size; a\nfirst screen with one dominant element and a real button; drawings of the subject with detail. What\nthey punished: a quiet page that read as empty, a small headline, text sliding over pictures or cut\nat the top, a page recoloured mid-section, rows cut at the right edge, a large sentence over three or\nmore lines (read as a long headline whatever its markup), navigation that took over the first screen.\nEach of these is now a rule in SKILL.md or a check in the inspector.\n\nLimits: one juror per brief per round, so single scores carry about half a point of noise; the round-5\nbriefs had been seen in round 4; jurors are models, not people.\n\n## 12. The October 2026 study: 100 Sites of the Day\n\nA second study, made for v2.1, of the latest 100 Awwwards Sites of the Day (10 July to 17 October\n2026), with a different aim from the first: where the pictures and footage sit, how pages move, and\nthe frame (margins, balance, empty space, titles). About three in four of these sites were also in\nthe first study.\n\n- **Capture.** Headless Chrome at 1440×900 and 390×844 on 18 October 2026: four frames of the first\n  4.5 seconds after load, every screen while scrolling with real wheel input (one frame at rest per\n  step; the mid-step frames were cut from the top of the document instead of the viewport, so they\n  were not used), five phone screens, and a measurement pass in the page: every picture and\n  clip with its box, ratio, fit and corners; every section's content edges and pictures; blank runs;\n  the CSS that loaded (curves, durations, keyframes, breakpoints, feature counts); the animations,\n  transitions and script-driven moves that actually ran; GSAP tweens and scroll triggers where the\n  page exposed them. Nothing a site owns (code, copy, pictures) is reproduced in the skill; only\n  measurements and descriptions in our own words.\n- **Panel.** One model reader per site studied its frames and measurements, described the idea, the\n  first screen, the frame, every section, where each picture sits, the motion and what not to copy,\n  and scored it the Awwwards way. 91 of 99 captures were usable (the rest showed a gate, a bot wall or\n  a firewall page). Scores ran 6.7 to 7.9 (median 7.45); \"top\" means 7.5 or more (36 sites), \"lowest\"\n  under 7.3 (16).\n- **What it changed.** Where pictures and footage go: `imagery.md` §12. What strong pages do with\n  motion, new tokens, recipes and the gimmicks to avoid: `motion.md` §2, §4–6 and §9–10. Empty space\n  and the frame: `layout.md` §4–5. New compositions in `library/heroes.json` and `sections.json` and\n  notes on media and motion in `library/sites.json` (`draw.mjs --site <id>`).\n- **Headline numbers.** Pictures fill a median 16% of a scrolled screen, but in whole screens: 42% of\n  screens hold none and 19% are 90% picture or more. The median page carries 7 pictures (top 8,\n  lowest 2) and 42% carry footage (half of the top sites, one of the 16 lowest). 94% of pictures have\n  square corners. Strong ease-outs are the curves that ran (expo and quint out); the median of all\n  that ran on a site is 420ms. 60 of 99 open on a loading screen, and a third of the usable pages were\n  still unreadable 4.5 seconds after load, with no gain in the design marks. About 1 text section in\n  100 leaves half the width empty; the outer margins of strong pages match to a few pixels; 82% of\n  text sections open with a heading; 15 of 97 first screens never say what the thing is, and those\n  lose usability points.\n- **Limits.** One capture per site on one day; a WebGL scene can render blank in a headless browser;\n  the scroll-linked frames are partly an artefact of smooth-scroll libraries; one reader per site, so\n  single scores carry about half a point of noise.\n\n## 13. The app-screen study\n\nFor dashboards and app screens (v2.1), a separate study of 23 real product screens chosen by the\nowner (17 products, 17 light and 6 dark, at 1440–1512px): each screen measured from its pixels by a\nreader with full-resolution crops, six cross-cutting reports (shell, data and charts, tables and\nforms, visual language, taste, styles), and a synthesis into `references/app-screens.md` and\n`library/app.json` (seven styles, five shells, screen patterns). The screenshots stay private; the\nskill carries only the measurements and the rules. Blind test rounds of app screens built with and\nwithout the skill then shaped the warnings at the top of that file.\n","skills/taste-skill/references/scenes.md":"# Scroll scenes\n\nThe big moments of a page: stretches of scroll where the page stops being a column of sections and\nbecomes a scene. A camera flies through a field of pictures, a picture grows from a window to the whole\nscreen, a word buckles under the scroll, a set of photographs orbits and lands in a grid. These are what\nvisitors remember from award sites, and what a page built from tidy sections alone never has.\n\nThe scene library is taken apart from recent Awwwards Sites of the Day (October 2026: 43 sites recorded\nframe by frame while scrolling, 261 scenes described, 30 types), rebuilt from scratch in our own code,\ntested frame by frame at desktop and phone width and under reduced motion, and reviewed against the\nscenes it came from. Nothing a site owns is in them. Until `library/scenes.json` ships the draw deals\nnone; a page that needs a scene builds one on the stage (section 8), with every rule here.\n\n## Contents\n\n1. What a scene is\n2. Putting a scene on a page\n3. Filling it\n4. Fitting it to the page\n5. The phone, reduced motion, no script\n6. Checking it\n7. Rules for scenes\n8. When no scene in the library fits\n9. The catalogue\n\n## 1. What a scene is\n\nA tall section whose stage holds still while the page scrolls past it. The stage is\n`position: sticky`; the section is (hold + 1) screens tall, so the stage is held for `hold` screens;\na GSAP timeline is scrubbed from 0 to 1 by that scroll. Nothing captures the wheel: the scrollbar always\ntells the truth, the keyboard and the trackpad work as everywhere else, and the scene ends.\n\nWhat a scene is not: a fade-up, a small parallax, a sticky footer, a marquee. Those are the quiet layer\n(`references/motion.md`). A scene changes the whole screen.\n\nThe direction sheet deals two or three (section 9 of the sheet), from different families, each placed\non the section of the argument it can carry. Build them in step 6, with that section: a scene is\ncomposition, not decoration added at the end.\n\n## 2. Putting a scene on a page\n\nCopy the shared stage and the dealt scene's files into the project (`assets/scenes/stage.css`,\n`stage.js`, `<id>.css`, `<id>.js`). Each scene file's header comment lists the markup it expects and\nits options; `assets/scenes/demo/<id>.html` is a complete working page to read beside it.\n\n```html\n<head>\n  <script>document.documentElement.classList.add('js')</script>\n  <link rel=\"stylesheet\" href=\"scenes/stage.css\">\n  <link rel=\"stylesheet\" href=\"scenes/<id>.css\">\n</head>\n<body>\n  …\n  <section class=\"scene\" data-scene=\"<id>\" data-options='{\"hold\": 3}' aria-label=\"…\">\n    <div class=\"scene-stage\">\n      <!-- the markup from the scene file's header, filled with this page's content -->\n    </div>\n  </section>\n  …\n  <script src=\"https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js\"></script>\n  <script src=\"https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/ScrollTrigger.min.js\"></script>\n  <script src=\"https://cdn.jsdelivr.net/npm/lenis@1.3.26/dist/lenis.min.js\"></script>\n  <script src=\"scenes/stage.js\"></script>\n  <script src=\"scenes/<id>.js\"></script>\n  <script>Stage.smooth(); Stage.init();</script>\n</body>\n```\n\n- Load SplitText (`gsap@3.15.0/dist/SplitText.min.js`) only when a scene file says it needs it.\n- `Stage.smooth()` adds weighted wheel scrolling (Lenis at lerp 0.12). It stays off for touch and for\n  reduced motion. Leave it out on a quiet page; the scenes work either way.\n- `Stage.init()` starts every `[data-scene]` on the page. A page with two scenes loads both files.\n- The versions are pinned. Do not change them to `@latest` or an unpinned major.\n\n## 3. Filling it\n\nA scene is only as strong as what goes in it. The scene file's header and the sheet's \"Content\" line\nsay how many pictures and words it takes; these hold for all of them:\n\n- **Pictures of one family.** Same light, same grade, same kind of subject: a field of mismatched stock\n  photographs breaks the illusion of one space faster than any timing error. Real pictures of the\n  subject's world (`assets.mjs`), the project's own, or the dealt photographs, in that order\n  (`references/imagery.md`). Size each to its largest display size, set `width` and `height`.\n- **Words that read in a breath.** A held statement is 4 to 12 words; captions are one to four words in\n  the text face, sentence case. One statement on screen at a time.\n- **The scene says something about the subject.** A fly-through of the studio's work, the route a\n  shipment really takes, the four rooms of the house, the product's change of state. A scene filled\n  with unrelated pictures is a gimmick and reads as one.\n- **Real content only.** If the scene needs eight pictures of the subject and there are three, take the\n  `--redraw scenes`, never pad it with stand-ins.\n\n## 4. Fitting it to the page\n\n- The scene files read the page's tokens: `--ground`, `--ink`, `--muted`, `--accent`,\n  `--font-display`, `--font-text` (with fallbacks). Set them on `:root` from the sheet and the scene\n  takes the page's colour and type. Check the demo against your page, not the other way round.\n- Display type in a scene uses the dealt display face and the two-line headline rule; statements stay\n  at statement size.\n- Leave a quiet section between two scenes (a text section, a list, a plain picture) so each one lands.\n  Two scenes back to back read as one long ride and the second loses.\n- A scene on the first screen must be readable at progress 0: the title, the sentence and the action are\n  there on the first frame (motion rule 1), and the scene starts moving only when the visitor scrolls.\n- Give the section a heading. If the design has no visible heading in the scene, the section still\n  carries one (`aria-label` on the section and a real heading in the finished composition).\n\n## 5. The phone, reduced motion, no script\n\n- **The phone.** Each scene has a phone plan in its file: the same scene with changed numbers, a\n  simpler version, or `phone: 'rest'`, where the phone shows the finished composition. Touch scrolling\n  is never smoothed. Look at the phone sheet as carefully as the desktop one.\n- **Reduced motion and no script.** The section is an ordinary section showing the finished\n  composition: the same content, laid out to read without motion. Nothing is hidden waiting for a\n  script. The inspector's `reduced-hidden` check and the reduced sheet of `scenes.mjs` show it.\n- **A failed CDN** falls back to the finished composition too (the stage adds `.is-rest`). The\n  inspector fails a scene that rests on desktop (`scene-not-live`), so a broken script cannot pass.\n\n## 6. Checking it\n\n```bash\nnode <skill>/scripts/scenes.mjs <page>        # every scene at 0, 10 … 100%, desktop and phone, and reduced motion\nnode <skill>/scripts/inspect.mjs <page>       # the gate; with scenes on the sheet it also films the scroll\n```\n\n`scenes.mjs` writes one contact sheet per scene and width to `.taste-skill/scenes/`. Read every one.\nAt every frame ask: is there one clear thing to look at; can the statement on screen be read; is\nanything popping, blank, cut off or crossing the words; is it as bold as it should be? The inspector's\n`desktop-film-NN.jpg` shows the whole page's scroll a third of a screen at a time: check that the\nscenes and the quiet sections between them make a rhythm, and that nothing between them is empty.\n\n## 7. Rules for scenes\n\n1. **Two or three per page,** from different families, a quiet section between them. The inspector\n   warns over four (`many-scenes`) and when scenes hold more than 60% of the page (`scene-heavy`).\n2. **Each holds one to four screens:** about one screen per beat of the story; a hold with nothing new\n   to show is cut, not padded.\n3. **Native scroll only.** No wheel capture, no locking the page, no scenes that only run on a click.\n   Smoothing only through `Stage.smooth()`.\n4. **Readable at its rest points.** The statement on screen reads whole; nothing passes over text while\n   it is being read; text on a picture has a flat scrim or a calm area under it.\n5. **Inside a scene the scene's numbers apply** (motion rule 7): a picture may grow from a window to the\n   whole screen, type may cross the stage, a camera may fly through pictures. Outside scenes, the quiet\n   limits of `references/motion.md` hold.\n6. **Transform, opacity, clip-path.** Nothing that forces layout on every frame. Pictures decoded before\n   they move.\n7. **The house rules hold inside scenes:** no monospace captions, no 01/07 counters (a plain \"3 of 7\" if\n   a count is needed), no gradients (flat scrims), no shadows or glows, no hairline decoration, no\n   decorative particles, no violet.\n8. **The finished composition is designed,** not an afterthought: it is what reduced motion, a failed\n   script and some phones see.\n\n## 8. When no scene in the library fits\n\nRedraw first (`--redraw scenes`). If the brief really needs a scene the library does not have, build it\non the same stage so it inherits the guards:\n\n```js\nScenes['my-scene'] = (root, opts = {}) => Stage.scene(root, {\n  hold: opts.hold ?? 2,          // screens the stage is held for\n  scrub: opts.scrub ?? true,     // true when Lenis runs; 0.4-0.8 without it reads as weight\n  phone: 'same',                 // or 'rest', or { hold, build } for a phone plan\n  build(tl, { q, phone }) {      // positions are fractions of the scene, 0-1\n    tl.fromTo(q('.picture'), { clipPath: 'inset(30% 30% 30% 30%)' }, { clipPath: 'inset(0% 0% 0% 0%)', duration: 0.6 }, 0)\n      .to(q('.title'), { yPercent: -40, autoAlpha: 0, duration: 0.25 }, 0.7);\n  },\n});\n```\n\nand write its CSS finished composition first, then the live layout under `.scene.is-live`. Check it\nwith `scenes.mjs` like any other.\n\n## 9. The catalogue\n\n(Generated from `library/scenes.json`; the draw deals from it. `node <skill>/scripts/draw.mjs --list\nscenes` prints it.)\n","skills/taste-skill/references/tells.md":"# Tells — the dated registry\n\nA tell is a device that makes a page read as generated. Tells are not bad design in themselves; most\nbegan as good ideas on good sites. They became tells by being produced by default, everywhere, without\na reason. That is why this registry is dated, and why it never names a replacement font, colour or\ncomponent: every published \"use this instead\" list has become the next wave of tells within months.\nReplacements here are procedures (draw from the library, derive from the subject), not products.\n\n`scripts/inspect.mjs` and `scripts/lint.mjs` detect most entries. Status: **banned** means the\ninspector fails the page; **warned** means it flags it and you need a reason.\n\n## Contents\n\n1. First wave (2023–2024)\n2. Second wave (2025)\n3. Third wave (2025–2026): the \"fix\" that became the look\n4. Gallery fashion, banned as house style\n5. Structural tells\n6. Copy tells\n7. Motion tells\n8. Why removal is not enough\n\n## 1. First wave (2023–2024)\n\n| Tell | Status | Do instead |\n| --- | --- | --- |\n| Violet / indigo gradients on hero, buttons and glows | banned | The dealt palette; flat colour |\n| Gradient-filled headline text | banned | Solid ink |\n| Glass panels: backdrop blur, translucent cards | warned (2 or more) | Opaque surfaces one tone step from the ground |\n| Glowing or gradient \"Get started\" button | banned | Flat button named for its action |\n| Soft grey drop shadow under every card | banned | Tone step, or no box |\n| Three identical feature cards, each with an icon in a rounded square | banned | The dealt section blueprint |\n| Emoji as icons or bullets | banned | Words, or a real picture |\n| Centred headline, subtitle, two buttons, screenshot below | no rule; the draw avoids it | The dealt hero |\n| The same typeface on every generated page | warned (lint: default-font) | The dealt type system |\n\n## 2. Second wave (2025)\n\n| Tell | Status | Do instead |\n| --- | --- | --- |\n| Eyebrow / kicker: tiny tracked uppercase label above every heading | banned | Fold it into the heading, or delete |\n| Pill badge above the hero headline (\"New\", \"Beta\", \"Introducing\") | banned | Say it in the supporting sentence |\n| One word of the headline in italic serif, colour or underline | warned | One face, one colour |\n| Bento grid of rounded tiles as the feature section | warned as card rows | A composed section; tiles only in the dense-tiles direction, filled, strict sizes |\n| Near-black ground with one neon accent and a glow | banned via shadow, gradient | A dealt dark palette, no glow |\n| Floating rounded pill navigation with blur | warned | A plain bar |\n| Fake dashboard hero built from grey bars and donut charts | no rule; see imagery.md §7 | A real interface fragment, or no image |\n| Decorative status dot (\"Available for work\", pulsing \"live\") | lint: bounce | Remove |\n| Fade-and-rise on every section | no rule; see motion.md | One signature move |\n\n## 3. Third wave (2025–2026): the \"fix\" that became the look\n\nThe remedy published for the first two waves was \"warm it up and make it editorial\". Models adopted\nthe remedy wholesale and it is now the most recognisable generated look of all.\n\n| Tell | Status | Do instead |\n| --- | --- | --- |\n| Yellow-cream ground + terracotta / rust / clay accent | banned together; terracotta banned alone; cream warned | The dealt palette. Warmth from a low-chroma stone, a deep ink, a photograph, or a full warm field |\n| High-contrast or soft serif display as the shortcut to \"premium\" | no rule | The dealt type system, whatever class it is |\n| Oversized italic serif headline | no rule | As dealt |\n| Broadsheet cosplay: hairline rules everywhere, zero radius, dense columns | banned via hairline | Structure from space and tone |\n| \"Field notes\", \"Quietly trusted by\", \"On our desks\": performative labels | lint: copy | Plain section names |\n\n## 4. Gallery fashion, banned as house style\n\nThese are common on award sites right now. In the study they appear *more* often on the top-scored\nsites than on the weak ones (panel observations: monospace labels 44% against 24%, index numbering 38%\nagainst 21%; measured thin rules 61% against 52%). They are banned here regardless, by the owner's\ndecision: they are the first things a generator copies from the gallery, they carry no information,\nand a page built without them has to find real structure.\n\n| Tell | Status | Do instead |\n| --- | --- | --- |\n| Monospace micro-labels, mono as a \"technical\" voice, mono captions | banned | The text face; tabular figures for data |\n| Index numbering: 01 / 02 / 03, (001), \"Step 02\", numbered section markers | banned | Order by position, scale, or the words; `<ol>` when it is truly a list |\n| Thin rules: hairline dividers, ruled grids, 1px outlined boxes and tiles | banned (boxes: 3 or more) | Space, tone steps, filled shapes, a thick bar if a bar is the idea |\n| Design-tool chrome as ornament: crosshairs, crop marks, selection handles, dashed guides, rulers | banned via hairline, dashed | Remove |\n| Agency micro-meta: local time, coordinates, weather, version stamps, \"©2026 — Scroll\", middle-dot strings | lint: copy; micro-label | Remove |\n| Tiny uppercase letter-spaced captions scattered around the viewport | banned (3 or more) | Sentence case at readable size, placed with the content it describes |\n\nTiny tracked capitals are the one item in this group the data condemns as well: 16% of top sites\nagainst 57% of weak ones.\n\n## 5. Structural tells\n\n| Tell | Status | Do instead |\n| --- | --- | --- |\n| Headline as a full sentence at display size, three or four lines | banned (over two lines) | A title of about five words; the rest goes below |\n| Stock section order: hero, logos, features, testimonial, pricing, CTA | no rule; see copy.md §1 | The order of the argument |\n| Every section the same layout family | critique.md pass 9 | Different composition per section, from the sheet |\n| Everything centred | warned over 72% | Left-anchored, one centred moment |\n| One medium border radius (12–16px) on everything | none | Square or fully round, chosen once |\n| Nine nearly equal font sizes | warned over 9 | Five sizes, far apart |\n| Invented social proof: logos, quotes, star rows, \"10,000+ teams\" | copy.md §5 | Real proof, or none |\n| Text or a CSS box where a picture belongs | critique.md cap | A real picture, or a design that needs none |\n\n## 6. Copy tells\n\nFlagged by `lint.mjs`: the genre's verbs and adjectives (unlock, supercharge, seamless, elevate,\neffortless, cutting-edge, all-in-one …); the correction (\"not just X, it's Y\"); tricolon headlines;\n\"Get started\" and \"Learn more\" as labels; more than a handful of em dashes; lorem ipsum. See\n`copy.md` §6.\n\n## 7. Motion tells\n\nIdentical fade-up on every block; a dozen staggered hero entrances; hover lift on every card; bounce\neasing; infinite loops that mean nothing; reveals that fail and leave a blank band. See `motion.md` §9.\n\n## 8. Why removal is not enough\n\nA page with every tell removed and nothing put in their place is an empty page with good manners, and\nthat is a tell too (the \"avoidance aesthetic\": anyone could guess it from the category plus the list of\nthings to avoid). The tells were filling a gap where an idea should have been. The order of work in\n`SKILL.md` exists to fill that gap first: the idea from the subject, the dealt composition, real\npictures or committed type, and only then the checks.\n","skills/taste-skill/references/type.md":"# Type\n\nTypography is most of what a visitor sees and most of what makes a page look designed or assembled.\nThe direction sheet deals you a type system (faces, weights, settings). This file is how to use it.\n\n## Contents\n\n1. What the study measured\n2. The scale: few sizes, far apart\n3. Setting display type\n4. Setting text\n5. Loading the fonts properly\n6. One family or two\n7. Details that separate set type from typed text\n8. Mistakes the inspector cannot see\n\n## 1. What the study measured\n\nFrom 202 measurable sites out of the 247 studied (Chrome, 1440×900 and 390×844):\n\n| | Median | Middle half | Note |\n| --- | --- | --- | --- |\n| Hero headline size | 72px (5.0vw) | 43–109px | Top-scored sites: 6.0vw median |\n| Largest type on the page | 6.4vw | up to 10.4vw | Top-scored sites 8.4vw, weak sites 5.0vw |\n| Hero headline on a phone | 40px | 32–59px | |\n| Hero tracking | -0.01em | -0.03 to 0 | Tighter as size grows |\n| Hero leading | 1.0 | 0.95–1.1 | |\n| Body size | 16px | 14–18px | |\n| Headline ÷ body size | 4.3 | | Top-scored sites 4.7 |\n| Typefaces in real use | 2 | 31% use one, 45% two, 22% three | |\n| Hero weight | regular 48%, medium 18%, bold or heavier 22% | | Big type does not need to be bold |\n| Hero in capitals | 24% | | |\n| Hero centred | 39% | | 52% on the weak sites |\n\nTwo things to take from it. First, size contrast is the main lever and the best sites pull it harder.\nSecond, weight is not: half of the heroes are set in a regular weight. Scale and spacing make type\nconfident; bold is one option among several.\n\n## 2. The scale: few sizes, far apart\n\nThe panel described about 30 of the 114 strongest sites as using two or three type sizes with nothing\nin between, and none as using a graded five- or six-step scale. So: one display size, one text size\nand a small size carry the page; a lead size and a heading size exist for when they are needed. Five\nis the ceiling. The common failure is nine sizes that are all near each other (16, 18, 20, 24, 28,\n32…), which reads as mush. Choose steps that are clearly different:\n\n```css\n:root {\n  --step-small: clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem);   /* 13–14px  captions, legal */\n  --step-body:  clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem);    /* 17–19px  paragraphs */\n  --step-lead:  clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem);      /* 20–26px  supporting line, large body */\n  --step-head:  clamp(2rem, 1.3rem + 3.2vw, 4rem);             /* 32–64px  section headings */\n  --step-display: clamp(3rem, 1rem + 9vw, 9rem);               /* set by the hero blueprint */\n}\n```\n\n- `--step-display` belongs to the direction. A monument wordmark is 16–24vw; a quiet instrument's\n  headline is 28px. Use the size the hero blueprint gives, as a `clamp()` so it scales with the\n  viewport but is bounded on phones and very wide screens.\n- Keep the gap: the display size should be at least four times the body size on desktop, and nothing\n  should sit between `--step-lead` and `--step-head` unless the design truly needs a sixth size.\n- Resist a \"subheading\" size for every card and label. If two sizes look almost the same, make them\n  the same.\n\n## 3. Setting display type\n\nLarge type exposes spacing that is invisible at text size. Apply all of these to anything over 40px:\n\n```css\n.display {\n  font-size: var(--step-display);\n  line-height: 0.95;              /* 0.85–1.05; tighter for capitals and condensed faces */\n  letter-spacing: -0.035em;       /* -0.02 to -0.05em; use the value on the direction sheet */\n  font-kerning: normal;\n  text-wrap: balance;\n  max-width: 14ch;                /* choose the measure so lines break where you want */\n  margin: 0;\n}\n```\n\n- **Tracking scales with size.** The larger the type, the tighter it needs to be; a value right for\n  120px will choke 32px. Set tracking per step, not once for all headings.\n- **Leading below 1.0 needs checking.** Look for collisions between descenders and the ascenders or\n  accents of the next line. Two-line headlines make this easy to verify by eye.\n- **All capitals** want slightly open tracking (0 to +0.03em) even at display size, and leading around\n  0.9.\n- **Optical alignment.** Big letters with round or diagonal left edges (O, C, A, T, W) look indented.\n  Pull the headline left by about 0.04–0.06em (`margin-left: -0.05em`) so it aligns optically with the\n  text beneath it.\n- **Viewport-wide type.** For a line that must span the screen, size it in `vw` and verify at 390 and\n  1440; set `white-space: nowrap` and let the container clip rather than wrap. Calculate the size from\n  the character count: `font-size ≈ container width ÷ (characters × k)` with k from `copy.md` §2.\n- Never add a text shadow, an outline stroke, or a gradient fill to display type.\n\n## 4. Setting text\n\n```css\nbody { font-size: var(--step-body); line-height: 1.5; font-kerning: normal; text-rendering: optimizeLegibility; }\np { max-width: 62ch; text-wrap: pretty; margin: 0; }\np + p { margin-top: 0.9em; }\n.lead { font-size: var(--step-lead); line-height: 1.35; max-width: 40ch; }\nsmall, .caption { font-size: var(--step-small); line-height: 1.45; }\n```\n\n- Measure: 45–75 characters. Wider than that and the eye loses the next line; the inspector warns\n  past about 88.\n- Leading: 1.45–1.6 for body, tighter (1.3–1.4) for the larger lead size, looser for long reading.\n- Secondary text is the same face in a softer ink (`--muted`), not a lighter weight and not smaller\n  than 13px.\n- Do not centre paragraphs longer than three lines. Do not justify.\n- Light text on a dark ground looks heavier: drop one weight step or add 0.01em tracking, and raise\n  leading slightly.\n\n## 5. Loading the fonts properly\n\nThe sheet gives a `<link>` tag. Use it exactly; do not swap in a face you prefer.\n\n```html\n<link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\n<link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin>\n<link href=\"…from the direction sheet…\" rel=\"stylesheet\">\n```\n\n```css\n:root {\n  --font-display: \"Family From Sheet\", \"Helvetica Neue\", Arial, sans-serif;\n  --font-text: \"Family From Sheet\", Georgia, serif;\n}\n```\n\n- Request only the weights you use (usually two or three in total).\n- Always give a fallback stack of the same broad kind (sans for sans, serif for serif).\n- In a framework, use its font loader with the same family and weights (`next/font/google`, or a\n  self-hosted `@font-face` with `font-display: swap`). Fontshare faces load from the\n  `api.fontshare.com` stylesheet on the sheet.\n- After building, `inspect.mjs` reports the families that actually rendered. If it warns that a face\n  did not load, the screenshots show a fallback and nothing you judge from them is real. Fix the link\n  first.\n\n## 6. One family or two\n\nA third of the studied sites use a single family for everything, and it is the safest way to look\ncoherent. When the dealt system has two faces:\n\n- Give each a job and never swap them: one sets headlines, the other sets everything else.\n- Do not introduce a third face for labels, numbers or quotes.\n- Do not mix two faces inside one headline.\n- Italic is for titles of works and real emphasis inside paragraphs, never as decoration.\n\n## 7. Details that separate set type from typed text\n\n- Curly quotes and apostrophes, real dashes, a real ellipsis (see `copy.md` §7).\n- `font-variant-numeric: tabular-nums` for prices, tables, dates in columns; `oldstyle-nums` suits\n  serif body text.\n- `text-underline-offset: 0.18em; text-decoration-thickness: 0.07em` on links, so underlines clear the\n  descenders.\n- `hyphens: none` on headings. `overflow-wrap: anywhere` only on long URLs or emails.\n- A heading belongs to the text after it: space above a heading is at least twice the space below.\n- `::selection { background: var(--accent); color: var(--accent-ink); }` and a visible\n  `:focus-visible` outline in the accent, so even the browser's own states belong to the design.\n- Do not change weight on hover; the line reflows.\n\n## 8. Mistakes the inspector cannot see\n\n- A headline that passes the two-line rule but breaks badly: one orphan word on line two, or a break\n  that splits a phrase (\"Stools for small / kitchens\"). Author the break.\n- Display type so tight that letters touch, or so loose it falls apart.\n- A confident hero followed by section headings almost as large. Keep one size dominant per screen.\n- Body text set in the display face when that face was drawn for large sizes only.\n- Everything bold. If every line is emphasised, none is.\n"},"files":{".agents/plugins/marketplace.json":"{\n  \"name\": \"taste-skill\",\n  \"interface\": {\n    \"displayName\": \"Taste Skill\"\n  },\n  \"plugins\": [\n    {\n      \"name\": \"taste-skill\",\n      \"source\": {\n        \"source\": \"url\",\n        \"url\": \"https://github.com/Leonxlnx/taste-skill.git\",\n        \"ref\": \"main\"\n      },\n      \"policy\": {\n        \"installation\": \"AVAILABLE\",\n        \"authentication\": \"ON_INSTALL\"\n      },\n      \"category\": \"Design\"\n    }\n  ]\n}\n",".claude-plugin/marketplace.json":"{\n  \"name\": \"taste-skill\",\n  \"description\": \"tasteskill: art direction for coding agents, for websites, product pages, dashboards and app screens, checked in a real browser.\",\n  \"owner\": {\n    \"name\": \"leonxlnx\",\n    \"email\": \"hello@tasteskill.dev\"\n  },\n  \"plugins\": [\n    {\n      \"name\": \"taste-skill\",\n      \"description\": \"tasteskill v2: art direction for websites, product pages, dashboards and app screens, with a library of researched directions, real pictures from open collections and a real-browser inspector.\",\n      \"version\": \"2.1.4\",\n      \"source\": \"./\",\n      \"skills\": [\"./skills/taste-skill\"],\n      \"author\": {\n        \"name\": \"leonxlnx\",\n        \"email\": \"hello@tasteskill.dev\"\n      },\n      \"homepage\": \"https://github.com/Leonxlnx/taste-skill\",\n      \"repository\": \"https://github.com/Leonxlnx/taste-skill\",\n      \"license\": \"MIT\",\n      \"keywords\": [\"skills\", \"frontend\", \"design\", \"taste\", \"ui\", \"dashboard\"]\n    }\n  ]\n}\n",".codex-plugin/plugin.json":"{\n  \"name\": \"taste-skill\",\n  \"version\": \"2.1.4\",\n  \"description\": \"tasteskill v2: art direction for websites, product pages, dashboards and app screens, checked in a real browser.\",\n  \"author\": {\n    \"name\": \"leonxlnx\",\n    \"url\": \"https://github.com/Leonxlnx\"\n  },\n  \"homepage\": \"https://github.com/Leonxlnx/taste-skill\",\n  \"repository\": \"https://github.com/Leonxlnx/taste-skill\",\n  \"license\": \"MIT\",\n  \"keywords\": [\n    \"skills\",\n    \"frontend\",\n    \"design\",\n    \"taste\",\n    \"ui\"\n  ],\n  \"skills\": \"./skills/\",\n  \"interface\": {\n    \"displayName\": \"Taste Skill\",\n    \"shortDescription\": \"Art direction for websites, dashboards and app screens.\",\n    \"longDescription\": \"tasteskill v2 from Leonxlnx/taste-skill: researched directions, real pictures and a real-browser inspector for websites, product pages, dashboards and app screens.\",\n    \"developerName\": \"leonxlnx\",\n    \"category\": \"Design\",\n    \"capabilities\": [],\n    \"websiteURL\": \"https://github.com/Leonxlnx/taste-skill\",\n    \"defaultPrompt\": [\n      \"Design a distinctive frontend without generic AI patterns.\",\n      \"Redesign this interface while preserving its brand.\",\n      \"Build the dashboard for this product with real data and charts.\"\n    ]\n  }\n}\n","skills/taste-skill/README.md":"# tasteskill v2 (`design-taste-frontend`)\n\nA design skill for coding agents, built from a study of 247 curated sites (One Page Love and Awwwards\nSites of the Day, October 2026). It gives an agent an art direction instead of letting it fall back on\nthe average landing page, holds it to a strict no-ornament house style, and makes it look at its own\nrender before calling the work done.\n\n## How it works\n\n1. **Inventory.** The agent lists what only this client has: the name and what it means, the street,\n   the numbers, the one constraint, the materials, the hours.\n2. **Draw.** `scripts/draw.mjs` deals three of 20 directions (each an idea engine seen on the\n   strongest studied sites); the agent picks the one that can carry something from the inventory, and\n   the script deals the rest: a hero composition, section compositions, a type system of real free\n   fonts, a palette, photographs, a motion, studied references, and under every blueprint a list of\n   where it disagrees with the house rules. Recent draws are remembered so projects do not repeat.\n3. **Idea and live thing.** One sentence tying the client's own material to the direction's device,\n   checked against the nearest competitor, and one thing the visitor can do on the page.\n4. **Build** from the sheet, words first, full content. When the project has no photographs of its\n   own, `scripts/assets.mjs` finds real pictures of the subject's world in open collections (its\n   street in old postcards, old maps, its materials, engravings of its trade, museum objects of its\n   kind), downloads them into the project and records their credits; the subject is drawn in code\n   only where no honest picture exists.\n5. **Gate.** `scripts/lint.mjs` (source) and `scripts/inspect.mjs` (real browser, 1440 / 768 / 390)\n   measure the house rules: headlines of two lines or fewer, no eyebrow labels, no monospace, no\n   01/02/03, no thin rules, no gradients, no resting shadows, no cream-and-terracotta, no violet, and\n   the faults blind jurors punished: no focal point, empty screens, text covered or cut, long pins,\n   sideways rows, faded text.\n6. **Look.** The inspector saves screenshots; the agent critiques them with an Awwwards-weighted\n   rubric, fixes the top three problems and repeats, at most three rounds.\n\nFive rounds of blind tests against a no-skill baseline and another design skill are recorded in\n`references/research.md` §11.\n\n## Contents\n\n```\nSKILL.md                 the run, the house rules, the laws\nreferences/              copy, type, colour, layout, imagery, motion, critique, tells, research\nscripts/draw.mjs         deal options / a direction / reprint / redraw; --alternatives, --photos, --site\nscripts/assets.mjs       search open image collections (Openverse, Wikimedia Commons, Art Institute of\n                         Chicago, the Met) and, with --video, real footage (Wikimedia Commons, Internet\n                         Archive, NASA); --get downloads with the credit, --credits prints them\nscripts/lint.mjs         static scan for banned patterns and stock phrases\nscripts/inspect.mjs      render, measure, photograph\nscripts/lib/             zero-dependency Chrome DevTools client, the in-page probe, the rules\nlibrary/                 directions (20), heroes, sections, type systems, palettes, photographs,\n                         studied sites, motions\nassets/base.css, base.js an optional neutral foundation\nevals/evals.json         six briefs for testing the skill against a no-skill baseline\n```\n\n## Requirements\n\nNode 22 or newer and an installed Chrome, Edge or Chromium for `inspect.mjs` (it drives the browser\nover the DevTools protocol with Node's built-in WebSocket; nothing is installed). `draw.mjs`,\n`lint.mjs` and `assets.mjs` run on Node 18+; `assets.mjs` needs network access and no API keys. Set\n`CHROME_PATH` if the browser is somewhere unusual.\n\n## Install\n\nCopy this folder to your skills directory, for example `~/.claude/skills/design-taste-frontend/`, or keep it in\na repository under `.claude/skills/`.\n\n## Notes\n\n- Photographs in the library are served by Lorem Picsum from Unsplash, under the Unsplash licence.\n  They are placeholders for atmosphere; replace them with the project's own pictures.\n- Pictures found with `assets.mjs` keep their own licences. By default it offers only CC0, public\n  domain, CC BY and CC BY-SA, and `--get` records the title, creator, licence and source of every\n  download in `assets/credits.json`. The page must carry the credits (`--credits` prints them).\n- `assets.mjs --video` finds short clips of the subject's world, takes a 720p-or-smaller rendition,\n  refuses files over 25 MB unless `--max-mb` is passed, and saves a poster frame with each clip; how\n  to use one on a page (muted loop, poster, stopped under reduced motion) is in\n  `references/imagery.md` §11.\n- Fonts are loaded from Google Fonts and Fontshare. Check each face's licence for your use.\n- The scores in `references/research.md` are model judgements from screenshots, not Awwwards scores.\n- The draw history lives in `~/.taste-skill/history.json` (set `TASTE_SKILL_HISTORY` to move it).\n  Delete it to reset.\n- A build takes an agent roughly 30–45 minutes and a few hundred thousand tokens with the full\n  look-and-fix loop; most of that is finding or drawing pictures when a project has no photographs.\n","skills/taste-skill/SKILL.md":"---\nname: design-taste-frontend\ndescription: >-\n  tasteskill v2, the anti-slop frontend skill. Art direction for websites, distilled from a study of\n  247 curated gallery sites (One Page Love, Awwwards Sites of the Day). Deals researched directions\n  (idea, composition, type, palette, photographs, section blueprints) from a library, enforces a strict\n  no-slop house style with a real-browser inspector, and runs a look-and-fix loop on screenshots. Use\n  this whenever you build, design, redesign, restyle, polish or review a landing page, marketing site,\n  portfolio, product page, one-pager, hero or any public-facing web page, in any stack (HTML/CSS, React,\n  Next.js, Vue, Svelte, Astro, Tailwind) — also when the user says a page looks generic, templated,\n  \"AI-made\", sloppy, or asks to make it look designed, premium, award-level or less like every other\n  site. Also for app screens: dashboards, admin and analytics views, settings, inboxes and other screens\n  people work in, with their own run and rules.\n---\n\n# tasteskill v2\n\nA page built by a model usually looks like the average of every page the model has seen: a centred\nheadline over three lines, a little label above it, a row of icon cards, a soft gradient, a few thin\nrules and a monospace caption. Nothing in it is wrong and nothing in it was decided.\n\nThis skill replaces those defaults with decisions, in four ways:\n\n1. **A script deals the directions, you choose among them.** Asked to invent a look, a model picks\n   the category default every time. `scripts/draw.mjs` deals three of twenty researched directions;\n   you choose the one that carries the subject's idea, and the script then deals its type system,\n   palette, hero and section compositions from a library distilled from 247 real sites.\n2. **The idea comes from the subject.** In the study, what separated the best sites from the forgettable\n   ones was a concept taken from the thing itself, not the styling.\n3. **A house style with no ornaments,** measured in a real browser by `scripts/inspect.mjs`, so the\n   rules are checked rather than hoped for.\n4. **You look at what you made.** Screenshots at three widths, a juror's rubric, fix, look again.\n\nOne warning learned in testing. Taking the ornaments away is only half the job; a page that has lost its\nlabels, rules and cards and gained nothing in their place reads as thin, and blind jurors rightly prefer\na richer page with tells over an empty page without them. The other half is substance: type set\nlarger, whole fields of colour, real pictures of this subject's world (found or drawn), and every\nsection carrying its full content. The skill is built to give you that; do not trade it for restraint.\n\nIn the commands below `<skill>` is this skill's folder. Run them from the project's root, so the\nworking files land in `.taste-skill/` there. The scripts need Node 22+ and an installed Chrome, Edge\nor Chromium, and install nothing. `assets.mjs` also needs network access; it uses no API keys.\n\n## Page or app screen\n\nDecide first which of two kinds of work this is.\n\n- **A page** is read and scrolled: a landing page, a marketing or product site, a portfolio, an\n  event, a restaurant, a one-pager. It follows **the run** below.\n- **An app screen** is worked in: a dashboard, an admin or analytics view, settings, billing, an inbox\n  or queue to work through, a wallet, a list with filters, an editor or builder. It follows\n  **`references/app-screens.md`**: its own run, its own draw (`draw.mjs --app`), its own house rules\n  (quiet borders, small labels and repeated panels are normal there; gradients, glows, icons in tinted\n  squares, rainbow charts and invented vanity numbers are not) and `inspect.mjs --app`. Read that file\n  whole before you start; the page run below does not apply.\n\nA product site that shows its app is a page; the interface fragments on it follow the app-screen\nrules for their insides. Deal the product's app style once, in its own folder, with the page's colours\nand type kept:\n\n```bash\nnode <skill>/scripts/draw.mjs --app --kind <kind> --brief \"<the product>\" --keep palette,type --out .taste-skill/app\n```\n\nand build every fragment the page shows (the hero's live screen, a feature's crop, a chart) as a real\npiece of that app: `assets/app.css` for its panels, tables and controls, `assets/charts.js` for its\ncharts, real data that adds up, one finding stated, cropped and scaled the way the page's blueprint\ntreats a picture. A fragment that looks like a working product is the strongest picture a software page\nhas; grey bars and lorem numbers are the weakest. When a request mixes both (a landing page and the\ndashboard behind it), build each with its own run and one shared palette and typeface.\n\n## The run\n\nDo these in order. Steps 1–5 take a few minutes and decide whether the page is any good.\n\n### 1. Read the brief and the project\n\nFind out what is real: the subject, the audience, the one thing the page must get someone to do, the\nstack, any existing brand (colours, fonts, logo), and above all **what imagery truly exists**: the\nproject's own photographs or product shots, a real interface that can be shown, an image generation\ntool you can call, or nothing. Do not plan around pictures you do not have. Nothing of its own is\nrarely nothing at all: the subject's city, street, materials and history are in open archives and\nmuseums, free to use with a credit (step 6, `scripts/assets.mjs`).\n\nIf the request is vague, decide and state your reading in one line instead of asking. Ask only when a\nmissing fact blocks the work (for example, no product name).\n\nThen **inventory the subject** in your notes: eight to twelve things that belong to this client and to\nno competitor. Look for its name and what the name means; its address, door number, street and\nneighbourhood, and what that place looks like (its tiles, signs, paint colours, typefaces on its shop\nfronts, its light, its weather); the numbers in the brief (seats, rooms, minutes to the sea, the\nprice, the year); the constraint it lives with (only one batch a month, closed in winter, by\nappointment); its materials and colours; its rituals and hours (the oven lit at five, the ferry at\nseven); the printed things of its world (a timetable, a label, a ticket, a sign). This list is where\nthe idea comes from in step 4. In blind tests, the page that won each brief was built from an item on\nsuch a list (the client's name and what it means, the street it stands in, the one constraint that\nmakes it what it is), and the pages that lost had a good composition with a category idea. The list\nis also your picture search: each place, material and printed thing on it is a query for step 6.\n\n### 2. Write the argument\n\nBefore any design, list the page as claims with their proof, one line per section, the way\n`references/copy.md` §1 shows. The claims decide which sections exist and in what order. Delete any\nsection that has no claim. This is how you avoid the stock sequence of hero, logos, three features,\ntestimonial, pricing, call to action.\n\n### 3. Draw the direction\n\n```bash\nnode <skill>/scripts/draw.mjs --sector <sector> --brief \"<one line about the subject>\" \\\n  --sections <roles in the order of your argument> [--tone <tone>] [--have <assets>] [--keep palette,type] \\\n  --options 3\n```\n\nThis deals three directions and prints a short summary of each. Hold each one against your inventory:\nwhich way of composing can carry something only this client has? Choose that one, not the most\nfamiliar, and write one line in your notes on why. In testing, a single random direction that did not\nsuit the subject was the commonest cause of a weak page. Then deal the full sheet:\n\n```bash\nnode <skill>/scripts/draw.mjs <the same arguments, without --options> --direction <chosen id>\n```\n\n- `--sector`: `node <skill>/scripts/draw.mjs --list sectors`. Pick the closest.\n- `--sections`: roles from `--list roles` (features, showcase, how-it-works, testimonial, proof, stats,\n  pricing, faq, cta, footer, intro, about, work, gallery, list, contact). The hero is implied.\n- `--tone` (optional): quiet, bold, warm, technical, playful, luxury, editorial. Only pass it when the\n  brief clearly asks for one.\n- `--have`: assets that really exist, comma-separated: `photography` (the project's own photographs of\n  the place, people or work), `product-photo` (photographs of the specific product, or an image tool\n  that can make them), `product-ui` (real screenshots), `illustration`, `video`. Leave it out if you\n  have none: the draw then avoids compositions that depend on them and the sheet says how to fill\n  picture slots honestly (software shows its own interface built in HTML; a product with no photographs\n  is drawn and set among real pictures of its world, never a fake product shot). Pictures you will\n  find in the open collections are not the project's own; leave them out of `--have`.\n- `--keep palette,type`: when the brand already fixes colours or typefaces. The draw then deals only\n  the composition, and you map the brand's values onto the roles.\n\nThe command prints a **direction sheet**. It is the art direction for this build:\n\n- **Adopt it.** Do not blend it with the layout you would have made anyway. If it feels unfamiliar,\n  good: the familiar layout is the one this skill exists to prevent.\n- Redraw one slot (`--redraw hero | type | palette | photos | scenes | section:<role> | direction`) only for a\n  reason you can state: it contradicts a stated brand constraint, or needs an asset that does not\n  exist. Never redraw to get something more comfortable. Record every redraw in your report.\n- When a dealt section cannot hold the real content (it compares three plans and there is one price;\n  it wants five quotations and there are none), do not bend the content to fit. List the others with\n  `--alternatives <role>`, pick the one whose assumptions match the content, and take it with\n  `--redraw section:<role>=<id>`.\n- **Check the palette against the subject.** A dealt palette is a set of proportions (one ground, one\n  ink, one accent, fields) as much as a set of colours. If its colours fight the subject's own material\n  (candy pastels for a peat whisky, neon for a mountain hut), redraw the palette once; if the subject\n  has unmistakable colours of its own (its material, the paint of its street, the landscape outside\n  its windows), keep the dealt proportions and take the colours from the subject instead, and say so\n  in the report.\n- Reprint it any time with `node <skill>/scripts/draw.mjs --show`. In a long session, re-read it before each\n  section you build.\n\n### 4. Find the idea\n\nThe direction is a way of composing. The idea is what makes the page belong to this subject and no\nother. Write this sentence in your notes and do not start building until both blanks are filled from\nthe subject itself:\n\n> On this page, **[something that belongs to the subject]** becomes **[the device the direction calls for]**.\n\nPlaces to look for the first blank:\n\n- **Its output.** What does the thing produce? Put the real output on the page as material. (A camera\n  that prints poems delivered its copy as paper slips.)\n- **Its object or shape.** What does it physically look like, in cross-section, in silhouette?\n  Enlarge it, crop it, make it the frame or the one motif.\n- **Its name.** Can the letters hold a photograph, stack into a wall, split to two corners?\n- **Its place.** Is there one view that makes someone want to be there?\n- **Its ritual.** Is there a sequence the page can perform as it scrolls?\n- **Its artefact.** What printed thing already exists in its world: ticket, menu, label, receipt,\n  invitation, folder, manual?\n- **Its opposite.** Which other category owns the feeling this one lacks?\n\nFill the first blank from your inventory (step 1), not from the category. **The competitor test:** put\nthe nearest real competitor in the sentence (the bakery two streets away, another oak furniture maker,\nanother hut on the same mountain). If the sentence still works, the idea belongs to the category: a\nloaf of bread is every bakery; the seven doors of the street this one is named after are only this one.\n\"Clean and modern\" is not an idea. The sites the study's panel scored lowest were the ones whose idea\nwas recorded as \"none beyond the standard formula\".\n\n**One live thing.** Give the page one thing the visitor can do, or that is different for each visit,\nmade from the idea: pick a wood and see the chair in it; type your name and see it cut in the\nfoundry's letters; set the loan and read the real monthly figure; see whether the hut's stove is lit\nright now and how long until the last ferry; choose a size and see it against the room. In blind tests every winning page had one and the jurors named it first. Rules: it uses the subject's real content, it works on a phone with a thumb, it has a plain\nfallback without script, it never blocks reading, and it is one thing, not a playground. It is\nbuilt in step 6 as part of the page, not added as motion in step 9.\n\n**The scenes carry the idea too.** The scroll scenes on the sheet are devices waiting for a subject.\nDecide what each one shows from your inventory before building: the fly-through passes through this\nstudio's own title cards, the route is the road this shipment really takes, the picture that opens to\nthe whole screen is the room the guest will wake up in. A scene filled with pictures that could belong\nto anyone is a screensaver.\n\n### 5. Write the words\n\nWrite the whole page as a copy deck (plain text) before markup, following `references/copy.md`:\n\n- **Every headline fits in two lines or fewer at every width.** Do the arithmetic in copy.md §2 before\n  committing to a sentence: about 32 characters is safe everywhere at a confident size. The studied\n  gallery heroes have a median of 5 words and 32 characters.\n- One supporting sentence, directly under the headline (32–48px below it) and shown with it, never\n  docked at the foot of the first screen or held back by an animation. When the headline is a name or\n  a figure of speech, this sentence says plainly what the thing is. One primary action, named for what\n  it does, as a real button on the first screen.\n- **The first screen answers the visitor's first question in large type.** For an event: what it is,\n  when and where (the dates belong in the headline or at the second size, never only in small text).\n  For a product: what it is and what it costs or does. For a person: who and what they do. Every\n  section the visitor came for (the line-up, the menu, the rooms, the price) has its own heading and\n  its own place in the navigation.\n- **Write the full content.** Every section the brief asks for delivers its information completely:\n  the whole menu with prices, each room with its own details, every speaker and talk, the price with\n  what it includes, an answer for each real question. Thin sections are the commonest reason a clean\n  page loses to a busier one.\n- Sample details are expected where the brief leaves gaps (dish names, room names and rates, project\n  titles) so the design is seen at full density; list them in the report for the client to confirm.\n  Proof is never invented: no customers, quotes, reviews, press, logos or business statistics.\n\n### 6. Build it, still\n\nBuild the page with motion switched off in your head; a page that needs animation to look finished is\nnot finished. Order of work:\n\n1. **Tokens.** Colour and type roles from the sheet as CSS custom properties. Everything downstream\n   references tokens only. `<skill>/assets/base.css` is a neutral foundation you may start from (reset, token\n   names, fluid type steps, grid, focus and selection styles, the motion helpers); it has no look of\n   its own.\n2. **The hero, exactly as the blueprint describes it,** at desktop and at phone width. Get the big\n   thing big and the small things small before anything else exists.\n3. **Each section from its blueprint,** with this project's content. Keep the geometry, change the\n   subject. Neighbouring sections must not share a layout. **Carry the idea into every section,**\n   pricing, FAQ and footer included: the commonest failure in the study, even among good sites, is a\n   distinctive first screen followed by stock blocks.\n4. **Imagery,** in this order of preference:\n   1. the project's own;\n   2. generated, if you have an image tool;\n   3. **real pictures of the subject's world from the open collections,** whenever an honest one\n      exists. Search them with `node <skill>/scripts/assets.mjs \"<query>\"` (Openverse, Wikimedia\n      Commons, the Art Institute of Chicago and the Met; only licences that allow commercial use, by\n      default). Search the inventory, not the category: its street in old postcards, an old map of the\n      neighbourhood, its material up close, its trade in engravings, a museum object of its kind, a\n      botanical plate, a star chart. Use them large and with intent: one archival photograph as the\n      hero, an engraving enlarged into the page's motif, the real map of the street as the contact\n      section. Look at each before choosing; `--get <ref>` downloads it into `assets/` and records\n      its source and licence, and `--credits` prints the credit line for the footer. A found picture\n      shows the world around the client and is never presented as the client's own product, room,\n      dish, person or team;\n   4. **drawn in code from the subject itself,** for what no honest picture exists of (its objects,\n      its tiles, its windows, its product's interface, made as one consistent flat graphic language in\n      the palette's real colours);\n   5. the photographs dealt on the sheet, only where an honestly generic picture fits (the sea for a\n      sea house), never as a stand-in for the subject;\n   6. type and colour alone.\n\n   When the project has footage or a real picture of its own process or product, the first screen\n   shows it, large (about 40% of the screen or more). Never write a sentence on the page about where\n   the pictures come from or what they are not (\"none of these shows our bar\"): a caption says what\n   the picture is, and the credit line sits small in the footer. A portfolio whose work is invented\n   for the brief draws each piece as a finished still of that work (its title card with its own type,\n   an end frame, a poster), with real detail, never as a pictogram of the client's product.\n\n   **The floor, which the inspector checks:** at least four real pictures on the page, usually six to\n   twelve (photographs, archival images, maps, engravings, footage, raster artwork; for software, its\n   cropped interface fragments count too). SVG drawings do not count toward the floor: draw what no\n   picture exists of, and still carry real pictures. Add one moving picture wherever an honest clip\n   exists: search it with `assets.mjs --video \"<query>\"` and use it as a muted loop with a poster\n   frame. Models skip pictures and footage because finding them is work; the page fails without them.\n\n   `references/imagery.md` covers searching, licences and credits, video, drawing, crops and treatments.\n5. **The live thing** from step 4, built into the section where it proves the claim (often the hero\n   or the booking), with real content, a thumb-sized phone version and a plain fallback.\n6. **The scroll scenes,** when the sheet deals them (section 9), each with the section it carries: the page's big\n   moments, the camera that flies through the work, the picture that opens to the whole screen, the\n   word that buckles under the scroll. Copy the shared stage and the scene's files from\n   `<skill>/assets/scenes/`, fill the scene with this project's own pictures and words, and set the\n   page's tokens so it takes the page's look. A scene is composition: it decides how long the page is\n   and what each screen shows, so it is built now and seen in every look round, not added at the end.\n   `references/scenes.md` says how to put one on a page, fill it, fit it and check it;\n   `assets/scenes/demo/<id>.html` is a working example of each.\n7. **Fullness.** Look at each desktop screen as a poster: one dominant thing and the content it\n   carries. A screen that is mostly empty ground is an underbuilt section, not a rest; one deliberate\n   rest per page is the limit, and the inspector fails a page with two or more near-empty screens.\n   Running text is in the full ink at 16px or more; grey is for secondary notes.\n8. **The frame.** The page has one pair of equal outer margins at every width, and every section uses\n   the width the page has set up: when its text sits in the left half, the right half holds its\n   picture, its second column, its list or its figure, never nothing. Asymmetry lives inside the grid,\n   never in the frame: a void is placed only when something closes it on the far side. No stretch of\n   the page taller than about half a screen holds nothing at all; sections are 120–240px apart on\n   desktop. Every section the visitor came for opens with a heading that names it, and the first\n   screen carries the page's title in an `h1`. These are what readers name first when a page looks\n   wrong (\"no clear title\", \"random empty space\", \"everything is pushed to one side\"), and the\n   inspector measures each of them.\n9. **States and semantics.** Real links and buttons, visible focus, alt text, a phone layout that is\n   its own composition.\n\nRead `references/type.md`, `references/colour.md` and `references/layout.md` when you need the detail\nbehind a decision; the laws below are the short form.\n\n### 7. Gate\n\n```bash\nnode <skill>/scripts/lint.mjs <source files or folder>\nnode <skill>/scripts/inspect.mjs <url or path/to/index.html>\nnode <skill>/scripts/scenes.mjs <url or path/to/index.html>     # when the page has scroll scenes\n```\n\n`scenes.mjs` photographs every scroll scene at 0, 10 … 100% of its hold, on desktop and on a phone,\nand the reduced-motion page; with scenes on the sheet, `inspect.mjs` also films the whole scroll\n(`desktop-film-NN.jpg`). A scene that never started or rests on desktop is a `FAIL`.\n\n`lint.mjs` scans source for banned patterns and stock phrases. `inspect.mjs` opens the page in a real\nbrowser at 1440, 768 and 390 pixels, measures it (headline line counts, type sizes, fonts actually\nloaded, colours, rules, shadows, gradients, contrast, overflow, and the frame: equal margins, sections\nhuddled on one side, blank stretches, the title, untitled sections, text against the screen edge) and\nsaves screenshots to `.taste-skill/inspect/`. Fix every `FAIL`. Treat each `WARN` as wrong unless you can defend it to a\ndesigner in one sentence. Re-run until there are no `FAIL`s. Do not argue with the meter and do not\nhide things from it. The inspector serves local files over a throwaway local server; if the page must\nalso open straight from the file system, open `index.html` that way once before you finish.\n\n### 8. Look\n\nPassing the gate means nothing banned was measured. It does not mean the page is good. Open the\nscreenshots the inspector lists (every viewport, with your image viewer or Read tool) and critique them\nwith `references/critique.md`: the fourteen passes, the Awwwards-weighted score, the caps. Write the critique\ndown in its format, fix the top three problems, run the inspector again, look again. Three rounds at\nmost.\n\nJudge only the pictures. If a problem is visible in a screenshot, it is real, whatever the code says.\n\n### 9. Move\n\nNow build the motion layer. It is required, and it is more than one fade: the inspector counts the\nelements that really move while the page loads and is scrolled, and fails a page under eight (it warns\nunder sixteen). Any scroll scenes are already built (step 6); around them the layer has four parts:\n\n1. **The signature move** named on the sheet: one, done well (a dealt scene can be it).\n2. **An entrance for the parts of every section:** the heading, then the text, then the picture,\n   staggered by 60–90ms, rising 16–32px with opacity, triggered once as the section enters. Not one\n   fade for the whole block, and never content that stays hidden if the script fails.\n3. **Feedback on every control:** press, hover and focus on buttons, links, cards and the live thing.\n4. **One moving picture:** a found clip as a muted loop, a slow scale or drift on a photograph, or a\n   scroll-linked move on the hero picture.\n\nTransform and opacity only; every move has a `prefers-reduced-motion` fallback that keeps the content\nand drops the travel. A move that changes the colour or the layout of whole screens (colour by\nchapter, a pinned story) is part of the composition, so build it in step 6 and let every look round see\nit. `references/motion.md` has the tokens and tested recipes. Then run the inspector once more and check\nevery screenshot for content that failed to appear.\n\n### 10. Report\n\nDo not report until all of these are true; each one was skipped in a test run that came out badly:\n\n- `inspect.mjs` shows **0 FAIL** at 1440, 768 and 390, on the final version of the page.\n- You opened every screenshot it listed after the last change, not only the first screen.\n- With scroll scenes: `scenes.mjs` ran on the final page with no problems, and you read every sheet\n  (desktop, phone, reduced motion).\n- A stranger reading the first screen for five seconds can say what this is and what to do.\n- Every section has a heading; the margins match on both sides; no stretch of the page is empty.\n- The critique of your last round is written down in the shape of `references/critique.md` §4.\n\nTell the user, briefly: the direction dealt (name and seed) and any redraws with reasons; the idea\nsentence and the live thing; the final scores from your last critique round and what still falls short;\nevery found picture and clip with its title, creator, licence and source page (`assets.mjs --credits` prints\nthe list) and where its credit sits on the page; which bundled photographs and which drawings stand in\nfor photography (so they can be replaced); and any sample content that must be swapped before launch.\nDo not claim a check you did not run.\n\n## House rules\n\nThese hold on every build, whatever the direction. `inspect.mjs` measures them.\n\n| Rule | Instead |\n| --- | --- |\n| **Headlines: two lines or fewer, at every width.** Every `h1`–`h6`, and the main line of the first screen whatever its tag. | Cut words. Then widen the measure. Size last. |\n| **A clear title on the first screen**, in the page's one `h1`, and a heading on every section. | Say what this is: the name with what it does, the product with what it is for, the event with its date and place. |\n| **Equal outer margins; no section huddled on one side** with the other half of the screen empty. | Close every void with something on its far side: the section's picture, a second column, a list, a figure. |\n| **No blank stretches** taller than about half a screen. | The normal section gap. A deliberate rest is a placed picture or a field of colour, once per page. |\n| **Statements are paragraphs.** An intro sentence or a quotation set large is marked up as `<p>` or `<blockquote>`, stays at statement size (36px or less on desktop, 24px on a phone) and runs to about 25 words, three lines. | Larger than that it is a headline and the two-line rule applies. In blind tests jurors read a 42px sentence over four lines as a four-line headline. |\n| **No eyebrows.** No small label above a heading, no pill badge above the headline, no \"New ·\" chip. | Put the information in the heading or the first sentence, or drop it. |\n| **No monospace** outside real code blocks. | The text face. Tabular figures where numbers align. |\n| **No index numbering.** No 01 / 02 / 03, no (001), no \"Step 2\". | Order shown by position, size, or the words. A real `<ol>` if order matters. |\n| **No thin rules.** No hairline dividers, no 1px outlined boxes, no grid lines, crosshairs or crop marks. | Space. A step in background tone. A change of scale. A filled shape. |\n| **No gradients.** Not as backgrounds, not on buttons, not in text. | Flat colour, or a real photograph. A neutral scrim under text on a photo is the one exception. |\n| **No shadows on things at rest.** No glows. | A tone step between surfaces. Shadows only on what truly floats: a menu, a dialog. |\n| **No assistant palette.** No yellow-cream ground with terracotta or rust; no violet or indigo. | The dealt palette. |\n| **No tiny uppercase letter-spaced labels.** | Sentence case at a readable size. |\n| **No icon-topped feature cards, no rows of identical cards.** | The dealt section blueprint. |\n| **No glass.** No backdrop blur panels, no floating pill navigation. | A plain bar: wordmark, a few links, one action. |\n| **No emoji, no gradient blobs, no decorative shapes, no fake dashboards of grey bars.** | A real picture, a real interface fragment, or nothing. |\n| **No styled accent word** in a headline (italic, serif, coloured, underlined). | One face, one colour. The words carry the emphasis. |\n| **Two typefaces at most,** usually one. | The dealt type system. |\n\nThree places keep their own conventions and are left alone by the inspector: real code in\n`<pre>`/`<code>` (monospace is correct there), real tables and form fields (they may have lines), and\na real interface fragment whose root carries the attribute `data-ui` (the product's own borders and\nmenus; see `references/imagery.md` §7).\n\nWhy these, honestly. Some are what the study measured: among the 247 sites, those the panel scored\n7.5 or higher used icon feature cards 1% of the time against 28% for sites under 6.5, pill badges 14%\nagainst 34%, gradients 22% against 52%, shadows 24% against 48%, tiny tracked caps 16% against 57%.\nOthers are the owner's taste and go against current gallery fashion: monospace labels, index numbers\nand hairline grids are actually *more* common on award sites than on weak ones, which is exactly why\ngenerators imitate them and why they now read as costume. They are banned here without exception.\n`references/tells.md` keeps the dated registry.\n\nRemoving ornament leaves space. Never fill it with another ornament. Fill it with scale (make the main\nthing larger), with the full content, with a picture made for this subject, or with a field of flat\ncolour. Leave it empty on purpose once per page at most.\n\n## Laws of the craft\n\nShort form. Numbers are from the study unless marked as house style.\n\n**Type**\n- Two or three sizes do the visible work: one very large, one small, nothing in between. Median\n  headline-to-body ratio on the studied sites is 4.3; the best go far beyond (largest type: median\n  8.4vw on the top sites against 5.0vw on the weak ones).\n- Display type: tracking -0.02 to -0.05em, leading 0.85–1.05. Text: 16–20px, leading 1.45–1.6,\n  45–75 characters per line.\n- Five sizes on a page is the ceiling. One family is normal (a third of the studied sites); two is the\n  limit.\n- Left-aligned by default. Centre at most one moment.\n\n**Space**\n- One grid, one pair of tight margins (16–32px), used everywhere; large things run to the edges. Text\n  blocks share two or three left edges on the whole page.\n- Asymmetry inside the grid, never in the frame: the two outer margins are equal, and an off-centre\n  heading is answered by something at the far side of the grid.\n- The gap between sections is clearly larger than any gap inside one: 120–240px on desktop (the study's median is about 240).\n- Each section has a different composition from its neighbours; none is a card grid.\n\n**Colour**\n- One ground, one ink, one accent. The accent appears on the action and perhaps one other thing.\n- Running text in the full ink. A page set in soft grey reads unfinished.\n- Surfaces are separated by a small step in tone, never by a line or a shadow.\n- A section may change the whole field colour. Nothing fades into anything.\n\n**Imagery**\n- One dominant image beats six small ones. On the top-scored sites the hero media covers at least half\n  the first screen 68% of the time.\n- Same crop ratios, same treatment, square corners unless the direction says otherwise (73% of the\n  studied sites leave media square).\n- No image is better than a placeholder, an icon, or an abstract shape. A picture drawn for this\n  subject, in its colours and with care, is better than either. A real picture of its world, found\n  and credited, is better still.\n- Every found picture is downloaded into the project, credited on the page and listed in the report.\n  None is presented as the client's own.\n- Nothing ever lies on top of a headline or a statement (the inspector fails it).\n\n**Components**\n- Buttons: flat, one fill colour, either square-cornered or fully round, decided once (top sites: 52%\n  square, 23% pill; the 9–16px \"soft\" radius is the weak-site default). Most strong heroes have no\n  button at all, or one.\n- Navigation: wordmark, three to five plain links, one action. No bar chrome.\n- The footer is a designed close, not a sitemap: on most strong sites the name returns at full width.\n\n## Special cases\n\n**An existing brand or design system.** Pass `--keep palette,type`, map the brand's colours and faces\nonto the roles, and take only composition from the draw. The house rules still apply; if the brand\nitself requires a banned device (its logo sits in a gradient, its accent is violet), keep the brand\nasset, say so in the report, and pass `--allow <rule>` to the inspector for that rule only.\n\n**Redesign, restyle or review of an existing page or app screen.**\n\n1. **Record the before.** Run the project as it is and inspect it into its own folder\n   (`inspect.mjs <url> --out .taste-skill/before`, with `--app` for an app screen) and lint its\n   source. Read the code: the framework, the styling method (Tailwind v3 or v4, CSS modules,\n   styled-components, plain CSS), the components, and what must survive: routes, forms, data,\n   behaviour, the brand's own assets.\n2. **A review stops here.** Critique the before screenshots with `references/critique.md`, list the\n   findings with the inspector's measurements, and name the three changes that would move the page\n   most.\n3. **Keep the stack, the content and what works.** No framework or styling-library migration; check the\n   dependency file before adding anything. A restyle keeps the layout and takes type, colour and\n   components from a dealt direction (`--keep` whatever the brand fixes); a redesign deals a full\n   direction and rebuilds the sections from its blueprints inside the existing components. Either way\n   proceed from step 2 of the run with the page's real content.\n4. **Order of work, biggest effect for least risk:** type (faces and scale), colour (one ground, one\n   ink, one accent), the frame (margins, section rhythm, a title on the first screen and a heading on\n   every section), states (hover, focus, loading, empty, error), then the stock components (icon\n   cards, pill badges, gradient blobs, card grids) replaced by the dealt blueprints.\n5. **Prove it.** Inspect again into `.taste-skill/after`, compare before and after at every width,\n   click through every link, form and menu that worked before, and report the before and after\n   measurements side by side.\n\n**A component or a single section, not a page.** Skip the draw unless there is no direction to follow.\nMatch the surrounding design, apply the house rules and the laws, and still inspect the result.\n\n**No checkout, no form backend.** The primary button goes to the real destination when the brief names\none. Otherwise it opens an email with a written subject and body (`mailto:` with the visitor's choices\nfilled in), or, for a shop, it points at `#checkout` and the report says it must be wired before\nlaunch. Never fake a payment form.\n\n**No Chrome or Node 22.** Run `lint.mjs` (Node 18+), take screenshots with whatever browser tool you\nhave, and critique those. Say in the report that the inspector could not run.\n\n**No network.** If `assets.mjs` reaches no source, draw the pictures and say in the report that the\nopen collections could not be searched.\n\n## Files\n\n| File | Read it when |\n| --- | --- |\n| `references/app-screens.md` | Any dashboard, admin, settings or other app screen: its own run, rules, tokens and checks. |\n| `references/copy.md` | Writing the argument and the copy deck (steps 2 and 5). The two-line arithmetic. |\n| `references/type.md` | Setting type: scales, tracking, measure, loading fonts, pairing. |\n| `references/colour.md` | Applying the palette: roles, proportions, tone steps, dark pages, contrast. |\n| `references/layout.md` | Grid, margins, rhythm, section variety, navigation, footer, the phone composition. |\n| `references/imagery.md` | Choosing, finding, crediting, cropping and treating pictures; what to do with none. |\n| `references/motion.md` | Step 9. Budget, tokens, recipes, reduced motion. |\n| `references/scenes.md` | Step 6, when the sheet deals scroll scenes: putting one on a page, filling, fitting, the phone, checking, the catalogue. |\n| `references/critique.md` | Step 8. How to look, how to score, what to fix first. |\n| `references/tells.md` | The dated registry of generated-page tells and what each is replaced by. |\n| `references/research.md` | The study: method, numbers, what the best and worst sites do. Cite it, do not guess. |\n| `scripts/draw.mjs` | Deals and reprints the direction; `--photos`, `--site <id>` for more references; `--app` deals an app style instead. |\n| `scripts/assets.mjs` | Step 6: searches open collections for real pictures of the subject's world; `--get` downloads with the credit, `--credits` prints them. |\n| `scripts/lint.mjs` · `scripts/inspect.mjs` | The gate. |\n| `scripts/scenes.mjs` | The gate for scroll scenes: each scene at 0-100% of its hold, desktop, phone, reduced motion. |\n| `assets/base.css` · `assets/base.js` | An optional neutral foundation to build on. |\n| `assets/scenes/` | The scroll scenes: the shared stage (`stage.js`, `stage.css`) and, for each scene in the library, its `.js`, `.css` and a working demo page in `demo/`. |\n| `assets/app.css` · `assets/charts.js` | For app screens: a neutral shell, panels, tables and controls, and small SVG charts drawn to the app rules. |\n| `library/` | The data the draw reads: directions, heroes, sections, type systems, palettes, photographs, studied sites, motions, scroll scenes (`scenes.json`), and the app styles, shells and screen patterns (`app.json`). Do not read it whole; use the script. |\n","skills/taste-skill/evals/evals.json":"{\n  \"skill_name\": \"design-taste-frontend\",\n  \"how_to_run\": \"For each eval, give the prompt to a fresh agent that has this skill, and to a second fresh agent without it (the baseline). Render both with scripts/inspect.mjs and have a judge who does not know which is which score the screenshots with references/critique.md. Record inspector FAIL counts for both. Evals 7 to 10 are app screens: inspect them with --app (a sheet dealt by draw.mjs --app switches it on by itself) and judge them with the app-screen passes in references/critique.md.\",\n  \"evals\": [\n    {\n      \"id\": 1,\n      \"name\": \"saas-invoicing\",\n      \"prompt\": \"Build a landing page for Ledgerly, an invoicing tool for freelance designers. What it does: you write an invoice in under a minute, the client pays by card or bank transfer, and it sends polite reminders by itself when an invoice is overdue. It costs 9 euros a month flat, with a 14-day free trial and no card needed. Include pricing and a short FAQ. There is no existing brand and no screenshots; the product name is all we have. Plain static HTML, CSS and JS in one folder.\",\n      \"expected_output\": \"A static landing page with a clear idea drawn from invoicing itself, headlines of two lines or fewer at 1440/768/390, no eyebrow labels, no monospace, no index numbering, no thin rules, no gradients or shadows, a non-default palette and type system, a pricing section that is not three cards, and no invented customers or statistics.\",\n      \"files\": []\n    },\n    {\n      \"id\": 2,\n      \"name\": \"restaurant-osteria\",\n      \"prompt\": \"Make a one-page website for Osteria Nove, a 38-seat Italian restaurant in Alfama, Lisbon. Handmade pasta, a short natural wine list, dinner only, Tuesday to Saturday from 19:00. Address: Rua dos Remédios 9. Reservations by phone (+351 21 000 0009) or email (mesa@osterianove.pt). The page needs the menu (invent a believable short one: antipasti, pasta, dolci, with prices in euros), hours, address and how to book. We have no photographs yet. Static HTML/CSS/JS.\",\n      \"expected_output\": \"A one-page restaurant site with a specific idea (for example the page as the menu itself), the menu set typographically without divider lines, practical information easy to find, bundled photographs used only as atmosphere and listed for replacement, and all house rules met.\",\n      \"files\": []\n    },\n    {\n      \"id\": 3,\n      \"name\": \"portfolio-designer\",\n      \"prompt\": \"I'm Mara Lindqvist, a product designer in Stockholm with eight years in fintech and health apps. I need a portfolio homepage: six selected projects (make up plausible names, clients, years and one-line descriptions), a short about paragraph, and a way to contact me (mara@lindqvist.studio). I don't have project images ready, so design it so it still looks finished without them, or use placeholders that I can swap. Static HTML/CSS/JS.\",\n      \"expected_output\": \"A portfolio page that looks finished without project imagery (a typographic index, a name-led hero, or atmosphere photographs clearly marked for replacement), with a designed footer, a phone layout that is its own composition, and all house rules met.\",\n      \"files\": []\n    },\n    {\n      \"id\": 4,\n      \"name\": \"product-ceramics\",\n      \"prompt\": \"Launch page for Kiln, a ceramic pour-over coffee set (dripper, carafe and two cups) that is hand-glazed in small batches in Porto. It costs 84 euros and ships across the EU within a week. The glaze is mixed by hand so no two sets are identical. We have not shot product photos yet, so there are no images of the set. One page, with a way to buy (a button is enough). Static HTML/CSS/JS.\",\n      \"expected_output\": \"A product page that does not fake product photography: it either commits to type and colour, uses one shape from the object as a motif, or uses atmosphere photographs honestly, with the price and purchase action clear, and all house rules met.\",\n      \"files\": []\n    },\n    {\n      \"id\": 5,\n      \"name\": \"guesthouse-ericeira\",\n      \"prompt\": \"Website for Casa Mirante, a six-room guesthouse on the cliffs above Ericeira, Portugal. Rooms from 140 euros a night with breakfast included; ten minutes' walk to the surf at Ribeira d'Ilhas; open March to November. One page: what it is, the rooms, what's nearby, and how to book (email reservas@casamirante.pt). We have no photographs yet. Static HTML/CSS/JS.\",\n      \"expected_output\": \"A calm, photograph-led or type-led one-pager whose hero is one clear thing, with rooms and booking information easy to find, bundled coast photographs used as atmosphere and listed for replacement, and all house rules met.\",\n      \"files\": []\n    },\n    {\n      \"id\": 6,\n      \"name\": \"conference-format\",\n      \"prompt\": \"Landing page for Format, a two-day design conference in Rotterdam on 14 and 15 May 2027. Twelve speakers (invent plausible names and talk titles), 400 seats, tickets at 390 euros, venue: Maassilo. Sections: what it is, the line-up, the schedule in brief, tickets, and a short FAQ. No brand exists yet beyond the name. Static HTML/CSS/JS.\",\n      \"expected_output\": \"An event page with a strong typographic or colour idea, the line-up and schedule set as structured text without divider lines or index numbers, a ticket section that is not three cards, and all house rules met.\",\n      \"files\": []\n    },\n    {\n      \"id\": 7,\n      \"name\": \"app-budget-overview\",\n      \"prompt\": \"Build the main screen of Ledgerly, a budgeting app for couples who share money: the October overview with their accounts and balances, the spending plan (planned against spent by category), bills due in the next 14 days and recent transactions. Two people use it, Mia and Tom. Desktop first, and it must work on a phone. Static HTML/CSS/JS.\",\n      \"expected_output\": \"An app screen, not a landing page: a quiet shell (sidebar or rail), a clear screen title, numbers that add up and are right-aligned with tabular figures, one chart per question, colour spent on data and status only, no icons in tinted squares, no gradients or glows, no placeholder names, and a phone layout where the navigation folds away. inspect.mjs --app passes.\",\n      \"files\": []\n    },\n    {\n      \"id\": 8,\n      \"name\": \"app-deploy-dashboard\",\n      \"prompt\": \"Dashboard for Relay, an edge deployment platform for web teams: one project's overview with recent deployments (status, branch, commit message, author, duration, region), requests and p95 latency over the last 24 hours, the error rate, and usage against the plan's limits. Dark theme. Static HTML/CSS/JS.\",\n      \"expected_output\": \"A dense, readable dark screen on a neutral (not navy) ground: one surface step or one hairline between regions, a deployments table with honest statuses and aligned numbers, charts with few gridlines and one series each, IDs in monospace at most, no rainbow series, no glow, and app inspector checks passing.\",\n      \"files\": []\n    },\n    {\n      \"id\": 9,\n      \"name\": \"app-settings-billing\",\n      \"prompt\": \"Workspace settings for Proofline, a design-review tool: general settings, members and roles (a members table with an invite form), billing (current plan, seats, invoices) and notifications. Static HTML/CSS/JS, desktop and phone.\",\n      \"expected_output\": \"A settings screen with a label column beside its fields (or stacked fields on a phone), labels above inputs, one control height, quiet borders, honest disabled states, a members table with right-aligned figures and one status pill per row, and no decorative icons or gradients.\",\n      \"files\": []\n    },\n    {\n      \"id\": 10,\n      \"name\": \"app-support-queue\",\n      \"prompt\": \"The queue screen of Hearth, a support inbox for a six-person SaaS team: the list of conversations with assignee, priority, channel and time to the SLA, the open conversation with the customer's details beside it, plus filters and saved views. Static HTML/CSS/JS.\",\n      \"expected_output\": \"A three-region work screen (navigation, list, conversation) that stays readable at 1440 and folds to one region at a time on a phone, with status shown once per row, times in words, no tinted icon squares or emoji, and app inspector checks passing.\",\n      \"files\": []\n    }\n  ]\n}\n","skills/taste-skill/library/app.json":"{\n  \"version\": 1,\n  \"about\": \"App-screen library for tasteskill: styles (directions), shells and screen patterns, distilled from the study of 23 desktop product screens (17 light, 6 dark, 17 products) chosen by the owner. Every number is a measurement from the study or a median over it, except where a note says a value was moved for contrast or for the house palette bans. Reference products are not named; the screenshots stay private.\",\n  \"styles\": [\n    {\n      \"id\": \"achromatic-ledger\",\n      \"name\": \"Achromatic ledger\",\n      \"theme\": \"light\",\n      \"basis\": \"4 screens: a seller home, a per-agent insights page, a generated report, a settings page with usage numbers\",\n      \"suits\": [\n        \"finance\",\n        \"commerce\",\n        \"devtools\",\n        \"support\",\n        \"report\",\n        \"workspace\",\n        \"builder\"\n      ],\n      \"idea\": \"The chrome holds no colour at all; money and counts are set in ink, the one chart hue marks the screen's main data element, and the only other hue is a small signal where a figure changed.\",\n      \"colourBudget\": \"under 1% coloured pixels; the chrome is ink, the one chart hue goes on the main data element, and the only other hue is a small change signal\",\n      \"tokens\": {\n        \"ground\": \"#f8f8f8\",\n        \"surface\": \"#ffffff\",\n        \"raised\": \"#eeeeee\",\n        \"border\": \"#e6e6e6\",\n        \"rule\": \"#f0f0f0\",\n        \"control\": \"#d4d4d4\",\n        \"text\": \"#0a0a0a\",\n        \"muted\": \"#6b6b6b\",\n        \"accent\": \"#141414\",\n        \"positive\": \"#2e7d32\",\n        \"negative\": \"#c4242a\",\n        \"warning\": \"#92400e\",\n        \"chart\": [\n          \"#141414\",\n          \"#8a8a8a\",\n          \"#1d5fbf\"\n        ],\n        \"pills\": {\n          \"positive\": [\n            \"#dcfae5\",\n            \"#04250e\"\n          ],\n          \"negative\": [\n            \"#ffedea\",\n            \"#831c1e\"\n          ],\n          \"warning\": [\n            \"#fffbeb\",\n            \"#92400e\"\n          ],\n          \"neutral\": [\n            \"#eeeeee\",\n            \"#3d3d3d\"\n          ]\n        },\n        \"radius\": {\n          \"card\": 8,\n          \"control\": 6\n        },\n        \"font\": {\n          \"family\": \"Geist\",\n          \"second\": \"Geist Mono, for IDs and keys only\",\n          \"fallback\": \"Inter, system-ui, sans-serif\",\n          \"sizes\": {\n            \"title\": 24,\n            \"section\": 16,\n            \"kpi\": 30,\n            \"body\": 14,\n            \"small\": 12\n          },\n          \"weights\": [\n            400,\n            500,\n            700\n          ],\n          \"note\": \"700 is for money figures only; every other number is 400-500.\"\n        },\n        \"density\": \"sparse\",\n        \"rowHeight\": 44,\n        \"sidebarWidth\": 256,\n        \"gap\": 12,\n        \"pad\": 24,\n        \"controlHeight\": 36\n      },\n      \"shell\": \"open-plane\",\n      \"shellAlternatives\": [\n        \"icon-rail\",\n        \"no-sidebar\"\n      ],\n      \"signature\": \"No brand colour anywhere in the chrome: the one primary action is near-black (a grey pill, #e5e5e5, is the secondary), the main data element (today's series, the booked bars, the current period) takes the one chart hue, #1d5fbf, and everything else is drawn in ink with the comparison or the part after the cursor in grey, zero balances are set in grey, and the only hue on the screen is a small triangle or a short coloured number where a figure changed.\",\n      \"identity\": [\n        \"A ground from the product's world in place of #f8f8f8, one level off white and low in chroma: a stone (#f4f3f1) for a bakery or a shop, a sage (#f2f5f2) for a garden or a greenhouse, a blue-grey (#f2f4f7) for a ledger or a meter. Cards stay white; a warm tint stays under the cream check (saturation under about 15%).\",\n        \"The one chart hue (#1d5fbf, or the brand's own hue at 3:1 or more on white) on the screen's main data element: today's line, the booked bars, the current period's column, the margin that breaks. The chrome stays ink and the hue stays under 1% of the screen.\",\n        \"Every figure in Geist Mono, as the style's decision, so money and counts read as a ledger's columns while the text stays Geist. Lint and the inspector flag mono; give the reason in the report.\"\n      ],\n      \"avoid\": [\n        \"a brand-coloured primary button\",\n        \"tinted cards or tinted KPI tiles\",\n        \"a coloured chart where one series in ink says it\",\n        \"bold on anything but money\",\n        \"a chart with no y-scale (the study's one example of this look hid magnitude behind hover and was flagged)\",\n        \"a grey pill as the only button for the screen's main job: in testing an Approve repeated in grey on every row left the screen without a primary\"\n      ],\n      \"notes\": \"The studied screens of this kind used 11-12px card radii, which §9.4 counts among the rare middle values; the library sets the tight pair (8 and 6) so the style lands on the bimodal rule. After testing, the chart hue moved from an unused third series colour onto the main data element: a screen whose only hue was a delta read as a kit.\"\n    },\n    {\n      \"id\": \"framed-sheet\",\n      \"name\": \"Framed sheet\",\n      \"theme\": \"light\",\n      \"basis\": \"6 screens: a developer platform overview, an analytics overview, an events analytics tab, a list detail, a reports dashboard, a flow builder\",\n      \"suits\": [\n        \"analytics\",\n        \"devtools\",\n        \"builder\",\n        \"smb-admin\",\n        \"support\",\n        \"commerce\",\n        \"report\"\n      ],\n      \"idea\": \"The app chrome is one tinted L-shaped frame; the work sits on a white sheet with a hairline edge and soft corners, so depth comes from a single tone step and no shadow.\",\n      \"colourBudget\": \"under 3%; the brand shrinks to the logo and a 2px tab underline, the data carries the chroma\",\n      \"tokens\": {\n        \"ground\": \"#f9fbfc\",\n        \"surface\": \"#ffffff\",\n        \"raised\": \"#f4f6f8\",\n        \"active\": \"#ebedee\",\n        \"border\": \"#e8eaec\",\n        \"rule\": \"#f0f1f2\",\n        \"control\": \"#cdced1\",\n        \"text\": \"#131416\",\n        \"muted\": \"#5d5f60\",\n        \"accent\": \"#1b6c80\",\n        \"positive\": \"#1e7b4f\",\n        \"negative\": \"#c4242a\",\n        \"warning\": \"#92400e\",\n        \"chart\": [\n          \"#1b6c80\",\n          \"#2f70bb\",\n          \"#a86f0c\"\n        ],\n        \"pills\": {\n          \"positive\": [\n            \"#dcfae5\",\n            \"#04250e\"\n          ],\n          \"negative\": [\n            \"#ffedea\",\n            \"#831c1e\"\n          ],\n          \"warning\": [\n            \"#fffbeb\",\n            \"#92400e\"\n          ],\n          \"neutral\": [\n            \"#ebedee\",\n            \"#353736\"\n          ]\n        },\n        \"radius\": {\n          \"card\": 8,\n          \"control\": 6,\n          \"sheet\": 16\n        },\n        \"sheetInset\": 8,\n        \"font\": {\n          \"family\": \"IBM Plex Sans\",\n          \"second\": \"IBM Plex Mono, for IDs and keys only\",\n          \"fallback\": \"Inter, system-ui, sans-serif\",\n          \"sizes\": {\n            \"title\": 22,\n            \"section\": 16,\n            \"kpi\": 28,\n            \"body\": 14,\n            \"small\": 12\n          },\n          \"weights\": [\n            400,\n            500,\n            600\n          ],\n          \"note\": \"KPI values at 400; the semibold goes on the label and the active tab.\"\n        },\n        \"density\": \"medium\",\n        \"rowHeight\": 48,\n        \"sidebarWidth\": 228,\n        \"gap\": 24,\n        \"pad\": 24,\n        \"controlHeight\": 32\n      },\n      \"shell\": \"framed-sheet\",\n      \"shellAlternatives\": [],\n      \"signature\": \"One tinted frame holds the sidebar and the 48px top bar with no rule between them; the page is a white sheet inset 8px from the window's right and bottom edges, with a 1px edge, 16px corners and no shadow. The active tab is a 2px underline in ink or the accent; everything else in the chrome is grey.\",\n      \"identity\": [\n        \"The frame tinted from the product's colour in place of #f9fbfc: one low-chroma step of its hue (a green-grey for a climate or farm tool, a blue-grey for an observability tool, a stone for a print shop). The sheet stays white.\",\n        \"The brand's own hue from the brief as --chart-1 in place of the dealt teal, on the main series and the one selected state, at 3:1 or more on white, never violet or indigo.\",\n        \"IBM Plex Mono for IDs, keys and the figures in tables (one job): its figures have their own drawing, and a developer reads them as the product's.\"\n      ],\n      \"avoid\": [\n        \"a border between the sidebar and the top bar\",\n        \"a shadow under the sheet\",\n        \"cards whose border is heavier than the sheet's (#cdcfcf on cards read as heavy in the study)\",\n        \"a fourth nesting level: frame, sheet and card are enough\",\n        \"different gutters for the KPI row and the chart row (20 against 24 was flagged)\"\n      ],\n      \"notes\": \"The study's second data hue in this style was an orange (#e88e46) that falls inside the house terracotta range; the third chart colour here is an amber moved out of that range and darkened to 3:1 on white.\"\n    },\n    {\n      \"id\": \"accent-ladder\",\n      \"name\": \"Accent ladder\",\n      \"theme\": \"light\",\n      \"basis\": \"3 screens: a newsletter home, a network analytics overview, a cap-table company home\",\n      \"suits\": [\n        \"creator\",\n        \"smb-admin\",\n        \"community\",\n        \"analytics\"\n      ],\n      \"idea\": \"One brand hue at full strength only on small marks, and its pale tints doing all the area work: the active nav row, a plan card, badges and progress tracks.\",\n      \"colourBudget\": \"3-10%, nearly all of it as pale tints of the one hue\",\n      \"tokens\": {\n        \"ground\": \"#f9fafb\",\n        \"surface\": \"#ffffff\",\n        \"raised\": \"#f3f4f6\",\n        \"border\": \"#e5e7eb\",\n        \"rule\": \"#f2f2f2\",\n        \"control\": \"#d1d5db\",\n        \"text\": \"#111827\",\n        \"muted\": \"#5f6672\",\n        \"accent\": \"#b8336a\",\n        \"accentSoft\": \"#fdf2f7\",\n        \"accentTrack\": \"#f8dbe8\",\n        \"accentInk\": \"#6b1d3e\",\n        \"positive\": \"#247b50\",\n        \"negative\": \"#c4242a\",\n        \"warning\": \"#92400e\",\n        \"chart\": [\n          \"#b8336a\",\n          \"#6b7280\",\n          \"#d4618f\"\n        ],\n        \"pills\": {\n          \"positive\": [\n            \"#dcfce7\",\n            \"#14532d\"\n          ],\n          \"negative\": [\n            \"#ffedea\",\n            \"#831c1e\"\n          ],\n          \"warning\": [\n            \"#fffbeb\",\n            \"#92400e\"\n          ],\n          \"neutral\": [\n            \"#f3f4f6\",\n            \"#374151\"\n          ],\n          \"accent\": [\n            \"#fdf2f7\",\n            \"#6b1d3e\"\n          ]\n        },\n        \"radius\": {\n          \"card\": 8,\n          \"control\": 6\n        },\n        \"font\": {\n          \"family\": \"DM Sans\",\n          \"second\": null,\n          \"fallback\": \"Inter, system-ui, sans-serif\",\n          \"sizes\": {\n            \"title\": 32,\n            \"section\": 18,\n            \"kpi\": 24,\n            \"body\": 14,\n            \"small\": 12\n          },\n          \"weights\": [\n            400,\n            500,\n            600,\n            700\n          ],\n          \"note\": \"700 for the page title only.\"\n        },\n        \"density\": \"sparse\",\n        \"rowHeight\": 45,\n        \"sidebarWidth\": 230,\n        \"gap\": 24,\n        \"pad\": 24,\n        \"controlHeight\": 32\n      },\n      \"shell\": \"open-plane\",\n      \"shellAlternatives\": [\n        \"ruled-t-frame\"\n      ],\n      \"signature\": \"The full hue goes only on small marks: the one filled-button style, the data series and the active nav icon. Its 50-200 tints carry every area: the active nav row (tint fill with the dark ink of the hue), the plan or trial card, badges and progress tracks. The primary action may instead be near-black, as on the study's newsletter home.\",\n      \"identity\": [\n        \"The ladder built from the brand's own hue (its logo, the brief's object) in place of the dealt raspberry: the full hue on small marks, its pale tints on areas, never violet or indigo.\",\n        \"The product's objects in the lead block: the newsletter's latest issue as its cover, the shop's products as 40px thumbnails, the course's lessons with their own art.\",\n        \"A ground one level toward the hue's palest tint (#fbf7f8 for the raspberry) in place of #f9fafb, so the page and the tints read as one family.\"\n      ],\n      \"avoid\": [\n        \"the full hue on large areas\",\n        \"a second accent family (four families on one screen was flagged in the study)\",\n        \"a gradient on the trial chip or upgrade button\",\n        \"a left accent bar on the active nav row on top of the tint (seen once in 23 screens)\",\n        \"violet or indigo\"\n      ],\n      \"notes\": \"All three studied screens of this kind used violet, purple or pink as the one hue. The move does not depend on the hue, so the house's violet and indigo ban holds and the library deals a raspberry instead.\"\n    },\n    {\n      \"id\": \"editorial-greeting\",\n      \"name\": \"Editorial greeting\",\n      \"theme\": \"light\",\n      \"basis\": \"2 screens: a team workspace home and a personal insights home\",\n      \"suits\": [\n        \"workspace\",\n        \"creator\"\n      ],\n      \"idea\": \"A personal or team home that opens with a typeset greeting in a centred column; every number below it is set at regular weight on tonal panels.\",\n      \"colourBudget\": \"under 2% for the accent; tonal panels carry the structure\",\n      \"tokens\": {\n        \"ground\": \"#ffffff\",\n        \"surface\": \"#f9f9f9\",\n        \"raised\": \"#ffffff\",\n        \"border\": \"#eaeaea\",\n        \"rule\": \"#f3f3f3\",\n        \"control\": \"#d9d9d6\",\n        \"text\": \"#1f201d\",\n        \"muted\": \"#636361\",\n        \"accent\": \"#1b6e66\",\n        \"positive\": \"#2e7d32\",\n        \"negative\": \"#b42318\",\n        \"warning\": \"#92400e\",\n        \"chart\": [\n          \"#1f201d\",\n          \"#1b6e66\",\n          \"#8c8c88\"\n        ],\n        \"pills\": {\n          \"positive\": [\n            \"#dcfae5\",\n            \"#04250e\"\n          ],\n          \"negative\": [\n            \"#fdecea\",\n            \"#7a1d14\"\n          ],\n          \"warning\": [\n            \"#fffbeb\",\n            \"#92400e\"\n          ],\n          \"neutral\": [\n            \"#f3f3f3\",\n            \"#3d3d3a\"\n          ]\n        },\n        \"radius\": {\n          \"card\": 22,\n          \"control\": 999\n        },\n        \"font\": {\n          \"family\": \"Instrument Sans\",\n          \"second\": \"Instrument Serif, for the greeting only\",\n          \"fallback\": \"Inter, system-ui, sans-serif\",\n          \"sizes\": {\n            \"title\": 48,\n            \"section\": 14,\n            \"kpi\": 32,\n            \"body\": 14,\n            \"small\": 12\n          },\n          \"weights\": [\n            400,\n            500,\n            600\n          ],\n          \"note\": \"The 48px title is the serif greeting; set in the sans it is 24/400. Every figure is 400.\"\n        },\n        \"density\": \"sparse\",\n        \"rowHeight\": 63,\n        \"sidebarWidth\": 224,\n        \"gap\": 16,\n        \"pad\": 20,\n        \"controlHeight\": 38\n      },\n      \"shell\": \"open-plane\",\n      \"shellAlternatives\": [\n        \"framed-sheet\"\n      ],\n      \"signature\": \"The greeting is the h1, in a centred 1100px column on a real 12-column grid (77px columns, 16px gutters), with spans that change by row but share column lines (3/3/3/3, then 9/3, then 6/6, so every internal edge meets one above it). Every figure below is set at regular weight on tonal panels, one layer each: a panel one step off white holds its title and its content directly; a white inner card is used once, for the main chart.\",\n      \"identity\": [\n        \"The greeting names this team or household and today's one fact, set from the data (\\\"Morning, Okoro house. The car is ready by 06:10.\\\"), never \\\"Welcome back\\\".\",\n        \"Each person's stable hue as a pale tint on their avatar and their own lane or column (a couple and their joint account as three lanes): identity, not data, so it stays out of the chart legends.\",\n        \"A surface from the product's world in place of #f9f9f9, one level toward its material (a sage for a garden, a stone for a kitchen, a blue-grey for a studio), with the page white kept.\"\n      ],\n      \"avoid\": [\n        \"an emoji in the greeting\",\n        \"a tracked uppercase date above the greeting (put the date after it or in the grey line below)\",\n        \"a 624-864px column on a desktop screen (both were flagged as wasted width)\",\n        \"a tray around every card (a grey panel with a white card 6px inside it, on every block, read as a bento template in testing)\",\n        \"red as the accent: in testing red marked a record week of upgrades and read as an alarm; red is for the failing fact only\"\n      ],\n      \"notes\": \"One studied screen set its greeting in a serif at 48/700 and its counts in a mono; the other set the greeting at 24/400 in the sans. The red is the second screen's chart red moved two degrees of hue out of the house terracotta range. After testing, the studied red accent was replaced by a deep teal: red on good news read as an alarm.\"\n    },\n    {\n      \"id\": \"pastel-consumer\",\n      \"name\": \"Pastel consumer\",\n      \"theme\": \"light\",\n      \"basis\": \"2 screens: a wallet home and a personal finance home\",\n      \"suits\": [\n        \"wallet\",\n        \"finance\"\n      ],\n      \"idea\": \"Categories are coded by pale tints whose ink is the dark of the same hue, all under one large radius, and each headline sum sits inside the card that explains it.\",\n      \"colourBudget\": \"5-8%, as pale tiles and data marks\",\n      \"tokens\": {\n        \"ground\": \"#f3f5f7\",\n        \"surface\": \"#ffffff\",\n        \"raised\": \"#f2f8fd\",\n        \"border\": \"#e6e6e6\",\n        \"rule\": \"#f4f4f4\",\n        \"control\": \"#d6d9dd\",\n        \"text\": \"#1b1d1f\",\n        \"muted\": \"#5c6064\",\n        \"accent\": \"#1d5fd6\",\n        \"accentSoft\": \"#dcf1ff\",\n        \"accentInk\": \"#0a3a80\",\n        \"positive\": \"#2f7a45\",\n        \"negative\": \"#c41c29\",\n        \"warning\": \"#92400e\",\n        \"chart\": [\n          \"#1d5fd6\",\n          \"#b45309\",\n          \"#2a8798\"\n        ],\n        \"pills\": {\n          \"positive\": [\n            \"#dcfae5\",\n            \"#04250e\"\n          ],\n          \"negative\": [\n            \"#ffedea\",\n            \"#831c1e\"\n          ],\n          \"warning\": [\n            \"#fffbeb\",\n            \"#92400e\"\n          ],\n          \"neutral\": [\n            \"#eef1f4\",\n            \"#3a3d40\"\n          ],\n          \"accent\": [\n            \"#dcf1ff\",\n            \"#0a3a80\"\n          ]\n        },\n        \"radius\": {\n          \"card\": 20,\n          \"control\": 10\n        },\n        \"font\": {\n          \"family\": \"Manrope\",\n          \"second\": null,\n          \"fallback\": \"Inter, system-ui, sans-serif\",\n          \"sizes\": {\n            \"title\": 28,\n            \"section\": 20,\n            \"kpi\": 32,\n            \"body\": 16,\n            \"small\": 14\n          },\n          \"weights\": [\n            400,\n            500,\n            600\n          ],\n          \"note\": \"Money at 24-32px; card titles regular; semibold for net worth, bill amounts and actions.\"\n        },\n        \"density\": \"medium\",\n        \"rowHeight\": 72,\n        \"sidebarWidth\": 240,\n        \"gap\": 24,\n        \"pad\": 24,\n        \"controlHeight\": 40\n      },\n      \"shell\": \"open-plane\",\n      \"shellAlternatives\": [\n        \"icon-rail\"\n      ],\n      \"signature\": \"Pale category tiles with the dark of their own hue as ink (#dcf1ff with #0a3a80), one large radius (20px on cards, stepping down to 10, 8 and 5 inside), and quiet money polarity: income green with a plus sign, spending in ink, no red on ordinary outgoings. Tints go on small tiles, avatars and chips; a panel that holds a list stays white. When the product has people (two partners, a family), each gets one hue, at least 60 degrees from the next.\",\n      \"identity\": [\n        \"The tile hues from the account's own colours (the card's colour, each pot's colour in the app) in place of the dealt cobalt, each tile pale with the dark of its own hue as ink.\",\n        \"The money's own objects: the card art at its real ratio, merchant marks at 24px in the rows, the goal's picture on its pot.\",\n        \"Manrope's figures carry the balance: 30-36px at 600 with tabular figures and the pence in a smaller grey, so the number itself is the face.\"\n      ],\n      \"avoid\": [\n        \"a gradient balance card\",\n        \"two data palettes on one page (flagged in the study)\",\n        \"red on every outgoing amount\",\n        \"a 624px phone-width column on a desktop screen (flagged as a stretched phone screen)\",\n        \"a KPI strip on top: the sums belong in their cards\",\n        \"whole panels tinted per person or category beside white cards (two surface languages on one screen)\"\n      ],\n      \"notes\": \"The two studied screens used a pure #0000ff and an indigo #4723f5 as their brand colour, and pastels such as #7cbecf that fall under 3:1 on white. The library uses a cobalt that reads as blue rather than indigo, and data colours darkened to at least 3:1 on the card.\"\n    },\n    {\n      \"id\": \"true-black-flat\",\n      \"name\": \"True-black flat\",\n      \"theme\": \"dark\",\n      \"basis\": \"5 screens: an events back office, an event analytics tab, a community overview, an artist studio home, an artist insights page\",\n      \"suits\": [\n        \"community\",\n        \"creator\",\n        \"markets\"\n      ],\n      \"idea\": \"Night mode on true black: sidebar, top bar and page share one ground, elevation is a lightness step alone, and colour is confined to data marks.\",\n      \"colourBudget\": \"at or under 3%; the accent never touches buttons, tabs or nav\",\n      \"tokens\": {\n        \"ground\": \"#000000\",\n        \"surface\": \"#111111\",\n        \"raised\": \"#2a2a2a\",\n        \"border\": \"#1a1a1a\",\n        \"rule\": \"#161616\",\n        \"control\": \"#444444\",\n        \"text\": \"#ffffff\",\n        \"muted\": \"#b4b4b4\",\n        \"faint\": \"#949494\",\n        \"accent\": \"#c6f24e\",\n        \"positive\": \"#c6f24e\",\n        \"negative\": \"#e5484d\",\n        \"warning\": \"#e5a93b\",\n        \"chart\": [\n          \"#c6f24e\",\n          \"#e6e6e6\",\n          \"#6b6b6b\"\n        ],\n        \"pills\": {\n          \"positive\": [\n            \"#222a10\",\n            \"#c6f24e\"\n          ],\n          \"negative\": [\n            \"#2c1a20\",\n            \"#e5566f\"\n          ],\n          \"warning\": [\n            \"#2b2414\",\n            \"#e5a93b\"\n          ],\n          \"neutral\": [\n            \"#222222\",\n            \"#ffffff\"\n          ]\n        },\n        \"radius\": {\n          \"card\": 20,\n          \"control\": 999\n        },\n        \"font\": {\n          \"family\": \"Inter\",\n          \"second\": null,\n          \"fallback\": \"system-ui, sans-serif\",\n          \"sizes\": {\n            \"title\": 20,\n            \"section\": 16,\n            \"kpi\": 24,\n            \"body\": 14,\n            \"small\": 12\n          },\n          \"weights\": [\n            400,\n            500,\n            600\n          ],\n          \"note\": \"Nothing above 600; inactive nav labels #bbb, active #fff.\"\n        },\n        \"density\": \"medium\",\n        \"rowHeight\": 80,\n        \"sidebarWidth\": 210,\n        \"gap\": 14,\n        \"pad\": 22,\n        \"controlHeight\": 36\n      },\n      \"shell\": \"ruled-t-frame\",\n      \"shellAlternatives\": [\n        \"no-sidebar\"\n      ],\n      \"signature\": \"Elevation by lightness alone (#000 ground, #111 card, #2a2a2a nested panel) with no borders or shadows on cards; the active nav item is marked only by its label going from #bbb to #fff; the primary control is made primary by inversion, a white 36px pill with black text.\",\n      \"identity\": [\n        \"The one data hue from the product's world in place of the dealt lime: a solar amber (#f2b33d) for an energy home, a sky blue (#4cb3f0) for water or weather, a lime only for sport. It is still the only hue on data and never touches buttons, tabs or nav. A green or yellow-green hue is also --positive; an amber that sits beside --warning leaves the warning to its pill pair.\",\n        \"A ground with the product's temperature: the studied #000 for media and events, a warm near-black (#0e0d0c) for a home, a cool one (#0c0d0f) for a monitor, with cards one lightness step above it (#181716, #15171a). Never navy or slate.\",\n        \"A signature element from the product's world as the lead: the energy home's power flow (sun, house, battery and grid with their live kW), an event's doors against capacity, an artist's release with its cover.\"\n      ],\n      \"avoid\": [\n        \"a navy or slate dark theme\",\n        \"glow, neon borders or shadows\",\n        \"a hue per chart (five hues across four charts was flagged)\",\n        \"the accent on buttons, tabs or nav\",\n        \"a 64px top bar left empty across most of its width (flagged twice)\"\n      ],\n      \"notes\": \"The studied screens of this kind used a violet-magenta (#dd6cff) and an orange (#ff5500) as their one data hue. The library deals a lime, which keeps the move and stays clear of the violet ban; because the lime is a yellow-green, it is also the positive colour (a second, mint green beside it read as two greens). The greys are #b4b4b4 for secondary text and #949494 for meta, 32 levels apart rather than the 20 of the measured #aaa and #969696, which read as one grey; #949494 still holds 4.5:1 on the #2a2a2a nested panel.\"\n    },\n    {\n      \"id\": \"data-terminal\",\n      \"name\": \"Data terminal\",\n      \"theme\": \"dark\",\n      \"basis\": \"1 screen: a stock research view. Keep it narrow.\",\n      \"suits\": [\n        \"markets\",\n        \"devtools\"\n      ],\n      \"idea\": \"A research or monitoring screen read in long sessions: cards darker than the ground, tabular digits that stack, signs instead of colour, and every selection marked by the same 1px accent line.\",\n      \"colourBudget\": \"under 3%; the accent is never more than a 1px line\",\n      \"tokens\": {\n        \"ground\": \"#171719\",\n        \"surface\": \"#131217\",\n        \"raised\": \"#212023\",\n        \"border\": \"#222224\",\n        \"rule\": \"#1b1a1f\",\n        \"control\": \"#3a3a3e\",\n        \"text\": \"#ffffff\",\n        \"muted\": \"#8a8c92\",\n        \"accent\": \"#4a8ad6\",\n        \"positive\": \"#44a282\",\n        \"negative\": \"#e5566f\",\n        \"warning\": \"#d9a441\",\n        \"chart\": [\n          \"#f2f2f3\",\n          \"#e5566f\",\n          \"#4a8ad6\"\n        ],\n        \"pills\": {\n          \"positive\": [\n            \"#1b2828\",\n            \"#5fc39c\"\n          ],\n          \"negative\": [\n            \"#2c1a20\",\n            \"#e5566f\"\n          ],\n          \"warning\": [\n            \"#2a2416\",\n            \"#d9a441\"\n          ],\n          \"neutral\": [\n            \"#212023\",\n            \"#bdbdc0\"\n          ]\n        },\n        \"shadow\": \"0 12px 28px rgba(0,0,0,.2)\",\n        \"radius\": {\n          \"card\": 6,\n          \"control\": 999\n        },\n        \"font\": {\n          \"family\": \"Public Sans\",\n          \"second\": null,\n          \"fallback\": \"Inter, system-ui, sans-serif\",\n          \"sizes\": {\n            \"title\": 26,\n            \"section\": 20,\n            \"kpi\": 20,\n            \"body\": 13,\n            \"small\": 12\n          },\n          \"weights\": [\n            400,\n            500,\n            600,\n            700\n          ],\n          \"note\": \"Section titles 20/400 in the muted grey; card titles 16/600; tabular figures everywhere.\"\n        },\n        \"density\": \"dense\",\n        \"rowHeight\": 42,\n        \"sidebarWidth\": 50,\n        \"gap\": 24,\n        \"pad\": 32,\n        \"controlHeight\": 34\n      },\n      \"shell\": \"icon-rail\",\n      \"shellAlternatives\": [],\n      \"signature\": \"Every selection (tab, toggle, range, nav item) is a 1px accent line exactly as wide as its label, placed on the nearest existing edge; numbers stay white or grey and carry their sign in the text ('+$24,000,000').\",\n      \"identity\": [\n        \"Every figure in a monospace as the style's decision (IBM Plex Mono or JetBrains Mono for each price, count and time, digits that stack), with the text in Public Sans. Lint and the inspector flag mono; give the reason in the report.\",\n        \"The one accent line from the product's world in place of the dealt blue (the exchange's or the team's hue): still the only selection mark, never violet or indigo.\",\n        \"A signature of the market or the system as the lead: an order book's depth as two mirrored bar lists, an incident as a minute-by-minute strip, a region map with the list beside it.\"\n      ],\n      \"avoid\": [\n        \"filled pill tabs or a coloured segmented control\",\n        \"a chart with no scale and no dates (the studied screen had none and was flagged)\",\n        \"tertiary text under 4.5:1 (#4c4c4f read at about 2:1 in the study)\",\n        \"lighter cards with borders and a glow\",\n        \"green and red on every number; the one column whose job is \\\"what moved today\\\" and a negative headline figure may carry the polarity colours\"\n      ],\n      \"notes\": \"The studied screen's muted grey #82848a and red #d4405d were lifted to #8a8c92 and #e5566f so text passes 4.5:1 on the card. Its card list rows sit on a 28px pitch and its table rows on 42px.\"\n    }\n  ],\n  \"shells\": [\n    {\n      \"id\": \"open-plane\",\n      \"name\": \"Open plane\",\n      \"basis\": \"5 of 23 screens\",\n      \"suits\": [\n        \"finance\",\n        \"wallet\",\n        \"workspace\",\n        \"creator\",\n        \"analytics\"\n      ],\n      \"numbers\": {\n        \"sidebarWidth\": \"230-256 (230, 240, 256 in the study; 280 and 292 with a built-in icon rail)\",\n        \"separation\": \"none, or one 1px hairline; the sidebar sits on the page ground or within 1-2% of it\",\n        \"navPitch\": 34,\n        \"navRowHeight\": 32,\n        \"navIcon\": \"16px outline, about 1.5px stroke\",\n        \"navLabel\": \"14px, 400, grey or ink\",\n        \"activeItem\": \"neutral grey pill, radius 6-12, inset 8-12px from the sidebar edges (#e9e9e9-#ededed)\",\n        \"topBar\": \"none\",\n        \"canvas\": \"fluid with a 24-64px gutter, or a centred 1100px column\"\n      },\n      \"blueprint\": \"The labelled sidebar sits on the page ground with nothing or one hairline between it and the canvas; there is no top bar, and the page header and cards sit straight on the ground about 32-36px from the top. Workspace or account switcher at the top of the sidebar, primary nav on a 34px pitch, groups under 12-13px sentence-case grey labels with 22-56px of air above, utilities and the user row pushed to the bottom. Cards are white on the off-white ground (or the sidebar is white with a 1px border on a #f9fafb canvas). The canvas is fluid with one gutter value, or a centred column for personal homes.\",\n      \"phone\": \"The sidebar folds into a 48px top bar holding the screen's name, a menu button that opens a full-screen sheet with the nav and the switcher, and at most one action. Content takes the full width with 16px margins.\"\n    },\n    {\n      \"id\": \"framed-sheet\",\n      \"name\": \"Tinted frame, white sheet\",\n      \"basis\": \"8 of 23 screens, in three variants\",\n      \"suits\": [\n        \"analytics\",\n        \"devtools\",\n        \"builder\",\n        \"smb-admin\",\n        \"support\"\n      ],\n      \"numbers\": {\n        \"chrome\": \"#f6f6f6-#f9fbfc (a warm #f7f6f2 once)\",\n        \"sheetInset\": \"8px from the window's right and bottom edges (12 and 16 once each)\",\n        \"sheetRadius\": \"10-16, median 16\",\n        \"sheetEdge\": \"1px #eaeaea-#ededed, no shadow\",\n        \"sidebarWidth\": \"220-263 (228 on two screens)\",\n        \"topBar\": \"48px on the chrome ground with no rule; search 548x32 centred on the window with a shortcut hint\",\n        \"contentPadding\": 24,\n        \"floatingVariant\": \"both panels inset 12px with a 12px gutter, radius 10\"\n      },\n      \"blueprint\": \"Sidebar and top bar share one tinted ground with no rule between them, forming an L; the page lives on a white sheet. Variant one: the sheet butts against the sidebar and the top bar and is inset 8px from the right and bottom edges, 16px radius, 1px edge. Variant two: a flush L-frame with no inset, the frame marked by one rule. Variant three: sidebar and content are two floating panels inset 12px from every edge with a 12px gutter. The top bar, when present, is 48px and holds a centred search, the account button and a help or AI icon. Inside the sheet the content has 24px padding and starts with the breadcrumb or title row.\",\n      \"phone\": \"The frame disappears: the sheet becomes the screen, with a 48px top bar (menu button, title, one action) on the chrome tint. The search moves into the menu sheet or behind an icon.\"\n    },\n    {\n      \"id\": \"ruled-t-frame\",\n      \"name\": \"Ruled T-frame\",\n      \"basis\": \"4 of 23 screens (3 dark, 1 light)\",\n      \"suits\": [\n        \"community\",\n        \"creator\",\n        \"smb-admin\"\n      ],\n      \"numbers\": {\n        \"sidebarWidth\": \"210-240\",\n        \"topBar\": \"64px with a 1px bottom rule\",\n        \"rules\": \"1px; #1a1a1a on #000, #f2f2f2 on white\",\n        \"navPitch\": \"34 (dark) or 40 (light)\",\n        \"switcher\": \"at the top bar's right end, behind a full-height 1px divider\",\n        \"contentGutter\": \"29px from the sidebar rule and the window edge\"\n      },\n      \"blueprint\": \"A 210-240px sidebar and a 64px top bar share one ground, divided only by 1px rules. The workspace or community switcher sits at the right end of the top bar behind a full-height divider; the sidebar holds the wordmark and the nav on a 34px pitch with sentence-case group labels. On dark, the active item is its label going from #bbb to #fff. The top bar must carry something real (search, the back link and object name, the switcher): two studied screens left about 1070px of it blank and were flagged.\",\n      \"phone\": \"The top bar stays at 48-56px with the switcher reduced to its mark; the sidebar becomes a full-screen menu sheet or a bottom bar of four or five destinations.\"\n    },\n    {\n      \"id\": \"icon-rail\",\n      \"name\": \"Icon rail\",\n      \"basis\": \"3 of 23 screens\",\n      \"suits\": [\n        \"markets\",\n        \"devtools\",\n        \"finance\",\n        \"wallet\"\n      ],\n      \"numbers\": {\n        \"railWidth\": \"50-60, median 55\",\n        \"icon\": \"15-18px outline\",\n        \"pitch\": \"34-49\",\n        \"active\": \"icon colour alone, or a full-bleed 50px band at a 2% tint, or a 1px accent bar on the rail's border\",\n        \"groups\": \"short 20px hairlines, no labels\",\n        \"utilities\": \"pushed to the bottom after a gap of about 200px\"\n      },\n      \"blueprint\": \"An unlabelled rail of 50-60px carries the brand mark at the top and 15-18px outline icons on a 34-49px pitch; groups are split by 20px hairlines, utilities sit at the bottom. The rail sits on the page ground with a 1px edge, or is white with a faint 4px shadow on a grey ground. It saves about 180px of width against a labelled sidebar, so it suits products with few destinations and screens that need the width. Icons need tooltips and an accessible name.\",\n      \"phone\": \"The rail becomes a bottom bar with the same four or five icons, each with a short label under it.\"\n    },\n    {\n      \"id\": \"no-sidebar\",\n      \"name\": \"No sidebar\",\n      \"basis\": \"3 of 23 screens\",\n      \"suits\": [\n        \"report\",\n        \"creator\",\n        \"community\"\n      ],\n      \"numbers\": {\n        \"topBar\": \"46-48px on the page ground, no border\",\n        \"column\": \"centred, 1088-1208px\",\n        \"gutters\": \"152-212px at a 1512px window\",\n        \"logo\": \"on the column's left edge\",\n        \"links\": \"14-15px semibold grey\"\n      },\n      \"blueprint\": \"A 46-48px top bar on the page ground over a centred 1088-1208px column; the logo sits exactly on the column's left edge and the bar's right cluster ends near its right edge, so header and content share one column. Three to five text links, a 36px search, the account. Use it for generated reports, viewers and products with few destinations; with a sticky bar on the same ground, give it a 1px rule when content scrolls under it (the studied bar without one sliced content off).\",\n      \"phone\": \"The bar keeps the logo, a search icon and a menu button; the links move into the menu sheet. The column becomes the full width with 16px margins.\"\n    }\n  ],\n  \"patterns\": [\n    {\n      \"id\": \"kpi-strip-chart-rail\",\n      \"name\": \"KPI strip, main chart and a side rail\",\n      \"screen\": \"overview\",\n      \"kinds\": [\n        \"creator\",\n        \"smb-admin\",\n        \"community\",\n        \"analytics\"\n      ],\n      \"basis\": \"a newsletter home; a community overview\",\n      \"blueprint\": \"Title row: a 24px noun or the product's name at 600-700, an optional 14-16px grey line under it, and the one primary action on the right, bottom-aligned with that line. 16-24px below, the scope row: section tabs and the date range in one row of 32-36px controls, or a 48px segmented track with the range select inside its right end. Then a grid of 1fr and a fixed 384px rail with a 24px gap. Main column: one KPI container split by 1px dividers into 3-5 equal cells (14px grey label, 24px value at 400-600, a 12px caption naming the baseline and window), then the main chart card, which is the largest thing on the screen, then the next card, all 16px apart. Rail: 16px headings outside their cards, 8px above each and 16px after the previous card; a recent-items list of 3-5 rows on a 45px pitch with 1px rules, closed by a 30px outlined 'View all' button instead of pagination. The rail starts level with the first card, not with the title.\",\n      \"phone\": \"The rail moves below the main column; the KPI container becomes a 2-column grid; tabs scroll inside their own row.\"\n    },\n    {\n      \"id\": \"kpi-tabs-chart\",\n      \"name\": \"KPIs as the chart's tabs\",\n      \"screen\": \"overview\",\n      \"kinds\": [\n        \"finance\",\n        \"commerce\"\n      ],\n      \"basis\": \"a seller home\",\n      \"blueprint\": \"One card per subject, 8-16px apart: the main chart card runs full width, and any card holding a table of five columns or fewer, or a short list, pairs with its neighbour in two columns, the page header indented by the card padding so the title, the card titles, the numbers and the plot share one left edge. Balances that do not change during the day go first, in one container split by 1px dividers into equal columns; a zero balance is grey and its caption becomes the next step. In the main card, 2-4 KPIs sit in a row and act as the chart's series tabs: the selected one carries a 2px rule and an ink label, the others keep a grey label and their value in ink at a lighter weight (a grey value reads as disabled); when the tabs are the per-entity breakdown the brief asks for (takings by shop), nothing is greyed and the rule alone marks the selection. Choosing one swaps the series. Under them, one line chart as wide as the card's content (about 1136x220 in the study): 3-4 solid 1px gridlines, 4-6 round y ticks at 12px, a 2-3px line in ink with straight segments and no fill, an 8px hover dot with a 1px dashed guide and the line after the cursor in pale grey. Close with a 2-3 row comparison table on a 36px pitch, value and change columns right-aligned under a 14px grey header such as 'vs prior Monday'.\",\n      \"phone\": \"KPI tabs become a 2-up grid above the chart, with the selected cell marked by a fill (never an underline floating inside the grid) or a row of tabs that scrolls sideways; the chart is full width, 160-200px tall, with 4 x labels; the comparison table keeps its two right-aligned columns.\"\n    },\n    {\n      \"id\": \"chart-pairs\",\n      \"name\": \"Per-period and running-total pairs\",\n      \"screen\": \"analytics\",\n      \"kinds\": [\n        \"community\",\n        \"smb-admin\",\n        \"analytics\"\n      ],\n      \"basis\": \"a network analytics overview\",\n      \"blueprint\": \"Title at 24-32px with one sentence under it saying what the filters do, then one filter row of 36-38px controls (one filled or near-black, the rest borderless or text, a reset link last) and 16-24px to the KPIs. KPI row: 3 equal cards in the content column (3 x 372 + 2 x 17 = 1152 in the study) or one divided container; a 16px label over the value with the change written as a phrase on the value's baseline ('+8 in the last 90 days'), grey when it is zero. Then one row per metric: the per-period column chart on the left and its cumulative line on the right, at equal width (2 x 568 + 16 = 1152) and with the same x ticks; square bars, a 2px straight line, integer ticks from zero, no legend because each chart has one series. One gap value horizontally and vertically.\",\n      \"phone\": \"Pairs stack, the cumulative chart directly under its per-period chart; KPI cards become a single column of label-value rows.\"\n    },\n    {\n      \"id\": \"insights-share-tables\",\n      \"name\": \"Insights with share tables\",\n      \"screen\": \"analytics\",\n      \"kinds\": [\n        \"analytics\",\n        \"devtools\",\n        \"builder\"\n      ],\n      \"basis\": \"a per-agent insights page\",\n      \"blueprint\": \"No cards: sections are carried by whitespace and a 16/500 heading with one 14px grey sentence under it saying what the section shows. A row of up to 6 KPIs on a fixed pitch (12px grey label over a 30px tabular value, no boxes, no dividers), then one full-width time chart (about 218px plot, 5 hairline gridlines, 11-12px grey ticks, a dot legend under the title, a 'Compare to previous period' text button on the right). Then a 2 x 2 grid of small tables with a 24px gutter whose rows align across the two columns. Each table: a header of 12px grey labels with no fill and no rule, 44px rows with 2px gaps whose rounded fill (#f5f7f9, radius 8) is the data bar, its width the row's share divided by the largest share; Share in 12px grey and Count in 14px ink, both right-aligned. An empty table keeps its header and shows one dashed 1px box about 38px tall with one sentence ('No Slack channel usage in this range.').\",\n      \"phone\": \"KPIs become a 2 x 3 grid; the chart is full width; the share tables stack in one column and keep their row bars.\"\n    },\n    {\n      \"id\": \"table-filter-bar\",\n      \"name\": \"Table with tabs and a filter bar\",\n      \"screen\": \"list\",\n      \"kinds\": [\n        \"community\",\n        \"devtools\",\n        \"commerce\",\n        \"support\",\n        \"smb-admin\"\n      ],\n      \"basis\": \"an events back office, a tracks studio, a sessions overview\",\n      \"blueprint\": \"Title row: an 18-24px title on the left, at most an outlined secondary and the one primary (36px) on the right. Underline tabs for the list's states on a full-width 1px rule with a 2px indicator as wide as the label; 22-32px below, the toolbar: a search of about 252-316 x 32-36 on the left, the count ('7 events') and the sort on the right. The table sits on the panel or page ground with no card around it: a header of 12-13px grey sentence-case labels with no fill and no rule, rows on a 48-56px pitch for one line or 72-92px with a thumbnail (media height plus 24-32px), 1px rules 3-7% darker than the ground or no rules at all, the identity column given the most width, numbers right-aligned in tabular figures with the unit muted ('5 /10'), one status mark per row and one kebab at the far right. Drop a column that is empty in every row (a blank co-host column left a 300px dead band). On an overview, cap the rows and link to the full list; on the full list, state the total and load more at the end.\",\n      \"phone\": \"Rows become two-line items: identity and the key number on line 1, the secondary fields in 13px grey on line 2, the kebab at the right. Tabs scroll in their own row; the search becomes a full-width field.\"\n    },\n    {\n      \"id\": \"count-cards-filter\",\n      \"name\": \"Count cards that filter\",\n      \"screen\": \"list\",\n      \"kinds\": [\n        \"community\",\n        \"commerce\",\n        \"support\"\n      ],\n      \"basis\": \"an events back office\",\n      \"blueprint\": \"Above a list, 3-5 equal count cards (61px tall, 12px padding, a 13px grey label over a 16/600 value, 8px gap) are the type filter: the selected card gets a 1.5px accent border and a pale accent fill, and the list below shows that type only. Zero counts print as '0' in the same style; no deltas, no icons. This is one place where a row of identical small cards is right: the cards are peers and each one does work.\",\n      \"phone\": \"The count cards become a horizontally scrolling row of chips with the count inside each, or a select above the list.\"\n    },\n    {\n      \"id\": \"settings-two-column\",\n      \"name\": \"Settings in two columns\",\n      \"screen\": \"settings\",\n      \"kinds\": [\n        \"devtools\",\n        \"smb-admin\",\n        \"support\",\n        \"workspace\",\n        \"commerce\",\n        \"analytics\",\n        \"finance\",\n        \"wallet\",\n        \"creator\",\n        \"community\",\n        \"builder\",\n        \"markets\",\n        \"report\"\n      ],\n      \"basis\": \"one settings page; stacking from a narrow rail card. The basis is thin.\",\n      \"blueprint\": \"A centred column of about 1152px. Each section is one row: a label column of about 450px (16/500 title, 14px grey description; the title's cap top 6-8px below the panel top, level with the panel's first line) beside a panel of about 700px with a #fafafa fill, 16px radius, 16px padding, no border and no shadow. Sections are split by a full-width 1px rule with 32px above and below. Inside a panel: field labels 14/500 above 40px white inputs (1px #e8e8e8, radius 10), 8px from label to field, 16px between fields, 24px from the description to the first label, 16px to the Save button; switch rows with a 14/500 title, a 20px status badge 8px after it, a 14px grey description and a 28x16 toggle 16px from the right edge, centred on the title line. A plan-gated feature shows a 48px tinted strip with a 32px button directly above its panel, and the panel stays readable. When a panel runs much taller than its label, put the section's help or a summary of the current values in the label column rather than 250px of nothing.\",\n      \"phone\": \"Each section stacks: title and description, then the panel at full width. Inside, label, 8-10px, field, 16-26px to the next pair; toggles stay on the right of their title.\"\n    },\n    {\n      \"id\": \"settings-with-usage\",\n      \"name\": \"Settings with usage on top\",\n      \"screen\": \"settings\",\n      \"kinds\": [\n        \"devtools\",\n        \"smb-admin\",\n        \"support\"\n      ],\n      \"basis\": \"one settings page\",\n      \"blueprint\": \"Use this only when usage is the question of the view (a plan, billing or quota view), and show only numbers no section below repeats, at a size below the h1. When a settings screen also reports usage, put 3-4 usage numbers in one row on top (a 14px grey label, a 30px regular value, a 12px change pinned to the card bottom with its window in words, a grey dash where there is no comparison) and link out to the analytics screen ('View more') instead of drawing a chart. Below, the two-column settings rows. One dark primary per screen. Keep upsell to one surface: the studied settings page carried three nags (a top banner, a setup button and a gated strip) and was flagged for it.\",\n      \"phone\": \"The usage row becomes a 2-column grid of label-value pairs; settings rows stack.\"\n    },\n    {\n      \"id\": \"wallet-balance-actions-assets\",\n      \"name\": \"Balance, actions and assets\",\n      \"screen\": \"wallet\",\n      \"kinds\": [\n        \"wallet\",\n        \"finance\"\n      ],\n      \"basis\": \"a wallet home\",\n      \"blueprint\": \"One column whose every element snaps to its two edges. A balance card (1px border, 16px radius, about 134px tall) holding one 32px figure and one line under it in which only the change is coloured ('-$0.09 in the last 30 days'); the title says what the figure is, so it needs no label. 32px below, 4 equal action tiles in a pale tint with dark same-hue icon and 12-14px label (4 x 144 + 3 x 16 = 624 in the study; scale the column and keep the arithmetic). 32-40px below, text tabs for the asset kinds on a 1px rule with a 2px ink indicator as wide as the word, a network or account select on the right of the same row. Then the asset table: 72px rows (48px round icon plus 24px), no dividers, two-line cells pairing a 16px value with a 14px grey unit amount, numeric columns right-aligned to shared edges, change as a small solid triangle and a coloured percentage, zero change grey, a missing share a grey em dash. On a desktop do not leave the column at phone width: the study's 624px column was flagged as a stretched phone screen; widen it to 864-1100 or give it a second column.\",\n      \"phone\": \"This pattern is phone-first: the same column at full width with 16px margins, the 4 tiles in one row, the table as two-line rows with the value right-aligned.\"\n    },\n    {\n      \"id\": \"finance-home-pinned-rail\",\n      \"name\": \"Finance home with a pinned accounts column\",\n      \"screen\": \"overview\",\n      \"kinds\": [\n        \"finance\",\n        \"wallet\"\n      ],\n      \"basis\": \"a personal finance home\",\n      \"blueprint\": \"No page header and no KPI strip: cards start 36px from the top and each headline sum sits in the card that explains it. On the left, a 306px accounts card pinned at the viewport height minus the 36px margins opens with net worth (16/600 label left, value right) and holds the account tree with no dividers: groups 16px ink, categories 14px ink, leaves 14px grey indented 8px, values right-aligned, a 30px pitch and about 45px between groups; an empty group is a bordered box with an '+ Add account' link instead of $0.00. On the right, a 2-column grid with 24px gaps of cards that answer this month's questions, each with its own period caption: the plan (spanning both columns; a ring with an empty hole, a dot legend, the available figure beside it with a per-day line), recent spending as 61px two-line rows (payee over category, amount over date, right-aligned) and upcoming bills. Income is green with a plus sign; spending stays in ink.\",\n      \"phone\": \"Net worth becomes the first card; the account tree collapses to its groups with totals; the month cards stack.\"\n    },\n    {\n      \"id\": \"builder-canvas\",\n      \"name\": \"Builder canvas\",\n      \"screen\": \"builder\",\n      \"kinds\": [\n        \"builder\"\n      ],\n      \"basis\": \"a flow builder in analytics mode\",\n      \"blueprint\": \"No global navigation: a 44px top bar on the window ground with no rule (an exit arrow, the object's name at 16/600 with a status pill, and on the right 16px icon buttons on a 40px pitch, a secondary and a near-black primary, split by 1px dividers). Below, two panels on the ground with 8px outer margins and a 12px gap, both wi\n\n<!-- [TRUNCATED AT 50KB] -->","skills/taste-skill/library/directions.json":"[\n {\n  \"id\": \"name-as-monument\",\n  \"name\": \"The name as a monument\",\n  \"sectors\": [\n   \"agency\",\n   \"studio-portfolio\",\n   \"personal-portfolio\",\n   \"hospitality\",\n   \"restaurant\",\n   \"music\",\n   \"culture\",\n   \"fashion\",\n   \"event\",\n   \"architecture\",\n   \"real-estate\",\n   \"physical-product\",\n   \"consumer-app\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"bold\",\n   \"editorial\",\n   \"luxury\"\n  ],\n  \"needs\": [],\n  \"idea\": \"The name is the headline. Set it so large that it becomes architecture: as wide as the viewport, cropped by an edge, or stacked to fill the screen. Nothing else on the first screen competes; the description of what this is drops to a single small sentence. The idea comes from treating the name's letters as material. Ask what the subject can do to its own name: a photograph of the work sits inside a counter or replaces a letter, the name repeats down the page like a reel, the letters are split to opposite corners and the page happens between them. In the study this was the single most common device among sites scoring 7.5 or more.\",\n  \"composition\": \"First screen: the wordmark spans 88–100% of the viewport width (font-size 16–24vw, set with a clamp so it never wraps), anchored either to the bottom edge with its descenders nearly touching it, or dead centre with everything else pushed to the corners. One line of supporting text at 16–20px sits in a corner on a shared margin; navigation is three or four words in the opposite corner. After the hero the page is deliberately small and calm: a narrow text column or a simple two-column grid, so the contrast with the monument holds. The name returns once more at full width as the footer, in the inverse colours. Margins are tight (20–32px) so the type reaches the edges. Two type sizes do nearly all the work: the monument and a small text size, with one mid size for section headings.\",\n  \"typography\": \"One family. The display cut must survive enormous sizes: tight tracking (-0.04 to -0.07em), leading 0.8–0.9, optical kerning on. Section headings are modest (28–40px) on purpose.\",\n  \"typeClasses\": [\n   \"grotesk-tight\",\n   \"condensed-heavy\",\n   \"extended-heavy\",\n   \"heavy-black\",\n   \"serif-display\"\n  ],\n  \"colour\": \"Two values carry the page (ground and ink). The accent, if used at all, appears on one thing only: the single action or the inset image frame. The footer inverts ground and ink.\",\n  \"paletteTags\": [\n   \"light-neutral\",\n   \"dark-neutral\",\n   \"two-tone\",\n   \"mono-accent\"\n  ],\n  \"imagery\": \"Few images, used as inserts in the typography rather than as illustrations beside it: one photograph inside or behind the name (a 4:5 or 1:1 frame replacing a letter, or tucked between two words), then a short run of large full-width or half-width photographs further down. Square corners. No collage of small thumbnails.\",\n  \"sectionTags\": [\n   \"type-led\",\n   \"quiet\",\n   \"poster\"\n  ],\n  \"motion\": \"scaling-wordmark\",\n  \"richness\": \"Scale. The size of the name against the smallness of everything else is the entire visual event, so protect both ends: do not shrink the name to make room, and do not let body text creep above 20px.\",\n  \"pitfalls\": \"A long name set small is just a logo. If the name has more than about 12 characters, stack it on two lines or crop it with the viewport edge; never drop below 12vw. Do not add a second big headline under the name. Do not decorate the letters.\",\n  \"seenIn\": [\n   \"aww-nothin\",\n   \"opl-kereliott\",\n   \"aww-paul-kalkbrenner\",\n   \"opl-nia-creative\",\n   \"aww-house-of-honey-1\",\n   \"aww-produx-design\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"sentence-as-layout\",\n  \"name\": \"The sentence is the layout\",\n  \"sectors\": [\n   \"agency\",\n   \"saas\",\n   \"ai-product\",\n   \"dev-tool\",\n   \"nonprofit\",\n   \"culture\",\n   \"education\",\n   \"physical-product\",\n   \"consumer-app\",\n   \"finance\",\n   \"health\",\n   \"event\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"bold\",\n   \"editorial\"\n  ],\n  \"needs\": [],\n  \"idea\": \"One short sentence, set at poster scale, is the composition. The trick that makes it an idea rather than a big headline: something from the subject sits inside the sentence where a word would be. A strip of photograph fills the gap between two words; a small live fragment of the product replaces the noun; the object the sentence names is pictured at the size of a letter. Write the sentence first, find the word that can be shown instead of said, and put the showing in its place. The reader completes the sentence with their eyes.\",\n  \"composition\": \"The sentence is four to seven words and runs as one or two full-width lines at 9–13vw. Inline with the type, on the baseline, sits one media slot: a rounded-rectangle or square frame exactly one line-height tall and two to three ems wide, holding a photograph or a looping crop. Above and below the sentence the screen is empty except for a small navigation line and one supporting sentence set small, both on the same left margin. Later sections repeat the grammar at smaller scale: each is a short statement on the left six columns with its proof (image, figure, list) on the right, so the page reads as a series of sentences with evidence. Generous vertical space (160px or more) between sections.\",\n  \"typography\": \"Display weight with real presence (medium to bold), tracking -0.03 to -0.05em, leading 0.95–1.0 so two lines sit close. The inline frame aligns to cap height and baseline exactly; set it with em units so it scales with the type.\",\n  \"typeClasses\": [\n   \"grotesk-tight\",\n   \"serif-display\",\n   \"condensed-heavy\",\n   \"serif-light-large\"\n  ],\n  \"colour\": \"A calm ground with ink at full contrast. The only colour comes from the photograph inside the sentence; if the palette has an accent, use it once, on the action.\",\n  \"paletteTags\": [\n   \"two-tone\",\n   \"light-neutral\",\n   \"single-field\",\n   \"mono-accent\"\n  ],\n  \"imagery\": \"One strong, simple photograph that reads at small size (a face, an object, a texture, a horizon), cropped to a wide strip inside the sentence. The same image may open to full width in the next section, so the small slot feels like a window onto something larger.\",\n  \"sectionTags\": [\n   \"type-led\",\n   \"poster\",\n   \"quiet\"\n  ],\n  \"motion\": \"masked-headline\",\n  \"richness\": \"The collision of big type and one live image inside it. Because there is only one image on the first screen, choose it with care and give it perfect alignment to the letters.\",\n  \"pitfalls\": \"The sentence must be short enough for two lines on a phone, where the inline frame drops to its own line between the two halves. Do not style one word differently to fake the device. Do not use more than one slot per sentence.\",\n  \"seenIn\": [\n   \"aww-colonia-zacamil\",\n   \"aww-bleibtgleich26\",\n   \"opl-spatial\",\n   \"aww-coffeetech-r\",\n   \"opl-midnight-2\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"pinned-poster\",\n  \"name\": \"The pinned poster\",\n  \"sectors\": [\n   \"culture\",\n   \"music\",\n   \"event\",\n   \"fashion\",\n   \"personal-portfolio\",\n   \"studio-portfolio\",\n   \"physical-product\",\n   \"ecommerce\",\n   \"hospitality\",\n   \"consumer-app\"\n  ],\n  \"tones\": [\n   \"bold\",\n   \"editorial\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Something stays put while everything else changes. A title holds its place across the viewport and the images beneath it swap; the name is split to two opposite corners and the page passes between the halves; a single frame stays centred while its contents change. Every scroll step is a new cover of the same magazine. The idea suits subjects that are a series (a book of portraits, a line-up, a collection, a set of projects): the fixed element says what the series is, the changing element shows its members.\",\n  \"composition\": \"A sticky layer holds the fixed element for the height of two to three viewports: usually the title at 10–14vw across the middle or top of the screen, or two words pinned to the top-left and bottom-right corners. Under it, a stack of full-height panels scrolls by, each a single large photograph (portrait 4:5, centred, 40–50% of the viewport wide) with one line of caption at the same small size everywhere. The title sits above the images in the stacking order and uses `mix-blend-mode: difference` or a solid colour that reads on every panel. When the pinned run ends, the page releases into ordinary flowing sections with a narrow measure. Build with `position: sticky`; never hijack the scroll.\",\n  \"typography\": \"The pinned title is the only large type on the page. Captions and body share one small size (15–17px). Tight tracking and solid weight so the title reads over photographs.\",\n  \"typeClasses\": [\n   \"grotesk-tight\",\n   \"condensed-heavy\",\n   \"heavy-black\",\n   \"extended-heavy\"\n  ],\n  \"colour\": \"One strong title colour against a pale or dark ground. Each panel may take its own flat ground colour sampled from its photograph.\",\n  \"paletteTags\": [\n   \"two-tone\",\n   \"photographic-neutral\",\n   \"single-field\"\n  ],\n  \"imagery\": \"A series of photographs with the same crop ratio and the same framing (all portraits, all objects, all rooms), so that swapping them reads as one image changing. Five to eight in the pinned run.\",\n  \"sectionTags\": [\n   \"photo-led\",\n   \"poster\",\n   \"type-led\"\n  ],\n  \"motion\": \"pinned-story\",\n  \"richness\": \"Repetition with change. The fixed title makes each new photograph feel like an event, so the photographs must be good and consistent.\",\n  \"pitfalls\": \"If the title is not legible over every panel, the idea fails: test each one. Keep the pinned run under six viewports or it feels like a trap. On a phone the title shrinks to 16–18vw and stays pinned at the top; panels become full-width. A pin longer than three screens, or one where the screens under it are nearly empty, read in blind tests as a stuck page. Every screen under the pin needs its own content, and nothing may pass over the pinned words.\",\n  \"seenIn\": [\n   \"opl-city-of-angels\",\n   \"aww-normal-is-boring\",\n   \"aww-glitch-grit\",\n   \"aww-revelatio-studio\"\n  ],\n  \"allow\": [],\n  \"needsPictures\": true\n },\n {\n  \"id\": \"colour-chapters\",\n  \"name\": \"Colour chapters\",\n  \"sectors\": [\n   \"agency\",\n   \"music\",\n   \"event\",\n   \"education\",\n   \"nonprofit\",\n   \"saas\",\n   \"consumer-app\",\n   \"culture\",\n   \"physical-product\",\n   \"health\",\n   \"finance\",\n   \"ai-product\"\n  ],\n  \"tones\": [\n   \"bold\",\n   \"playful\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Every section is a chapter with its own flat colour, floor to ceiling. The page reads like a set of posters hung in a row, held together by one typeface and one grid. The colours are not decoration: they come from the subject (the brand's packaging, the artist's record sleeves, the product's own colour ways, the categories of the content) and each chapter's colour means that chapter. Decide the sequence like a designer orders a book: a strong opener, a quiet second, a surprise in the middle, a dark or very light closer.\",\n  \"composition\": \"Sections are full-bleed fields, each at least 90svh tall, butted directly against each other with no gap and no divider. Inside every field the same 12-column grid and the same margins apply, and each field holds one thing: a huge heading (8–12vw) with a small paragraph, or one photograph with a caption, or one list. Text colour is chosen per field for strong contrast (ink or paper, never grey). Headings start on the same left edge in every chapter, so the eye feels the system as colours change. The navigation and the footer take the colours of the first and last chapter.\",\n  \"typography\": \"One typeface in two weights. Headings very large and tight; body 18–20px. Because colour is loud, the type stays plain: no italics, no second face.\",\n  \"typeClasses\": [\n   \"grotesk-tight\",\n   \"heavy-black\",\n   \"geometric\",\n   \"rounded-friendly\"\n  ],\n  \"colour\": \"Four to six flat fields used at full strength, one per section, each with its assigned text colour. No tints, no gradients between them: the hard edge where two fields meet is the look.\",\n  \"paletteTags\": [\n   \"flat-loud\",\n   \"pastel-fields\"\n  ],\n  \"imagery\": \"Sparing. One photograph or object per chapter at most, either cut out and sitting directly on the colour, or a plain rectangle with generous colour around it. Photographs should be simple enough not to fight the field.\",\n  \"sectionTags\": [\n   \"colour-field\",\n   \"type-led\",\n   \"poster\"\n  ],\n  \"motion\": \"colour-on-scroll\",\n  \"richness\": \"Colour at scale. A whole screen of one saturated colour is rich on its own, so a chapter needs few elements; it still needs its content at full size, because a coloured screen with one small line on it reads as empty.\",\n  \"pitfalls\": \"Check contrast on every field with the palette's assigned ink. Do not put cards on the fields. Do not use more than six colours. Two neighbouring fields should differ clearly in lightness as well as hue.\",\n  \"seenIn\": [\n   \"aww-warm-fuzzy\",\n   \"aww-paul-kalkbrenner\",\n   \"opl-anidachi\",\n   \"aww-aardvark-book-club\",\n   \"aww-ai-in-design-report-2026\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"place-carries-it\",\n  \"name\": \"The place carries it\",\n  \"sectors\": [\n   \"hospitality\",\n   \"restaurant\",\n   \"real-estate\",\n   \"architecture\",\n   \"event\",\n   \"health\",\n   \"culture\",\n   \"nonprofit\"\n  ],\n  \"tones\": [\n   \"quiet\",\n   \"luxury\",\n   \"warm\"\n  ],\n  \"needs\": [],\n  \"idea\": \"For a place, the photograph is the argument. One full-bleed image of where you would be standing fills the first screen, and the design steps back: the name sits along the bottom edge like a film title, or small in a corner, and nothing else interrupts the view. The page that follows keeps that restraint: few words, large pictures, long pauses. The designer's work here is editing: choosing the one frame that makes someone want to be there, and then not covering it.\",\n  \"composition\": \"First screen: a single photograph at 100vw by 100svh, focal point kept clear of text. The name is set either very large (14–20vw) hugging the bottom edge with 16–24px of margin, or small (20–28px) top-left with a one-line description bottom-left. Navigation is two to four words in the top corners in the same small size. If text sits on the image, a soft neutral scrim under the text area only. Below, sections alternate between a short centred or left-set paragraph in a narrow column (max 52ch) with wide empty margins, and photographs shown large: one full-bleed, then a pair at different sizes, then one portrait offset to the right. Practical information (hours, address, rates, booking) is gathered once near the end in a plain two-column block.\",\n  \"typography\": \"A face with some grace for the name; small, calm, well-spaced text everywhere else. Sentence case. Body 17–19px with leading around 1.55.\",\n  \"typeClasses\": [\n   \"serif-display\",\n   \"serif-light-large\",\n   \"condensed-heavy\",\n   \"grotesk-light\"\n  ],\n  \"colour\": \"Neutral paper or deep neutral ground chosen to flatter the photographs; text ink drawn from the darkest tone in the imagery. Colour lives in the pictures.\",\n  \"paletteTags\": [\n   \"photographic-neutral\",\n   \"dark-neutral\",\n   \"earth\"\n  ],\n  \"imagery\": \"The dealt set is the palette. Choose four to six photographs with the same light. The hero image must have a calm area for the name. Full-bleed or large with square corners; never thumbnails, never a carousel of ten.\",\n  \"photoTreatment\": \"Leave photographs ungraded. If text overlays one, darken only the area behind the text with a neutral scrim.\",\n  \"sectionTags\": [\n   \"photo-led\",\n   \"quiet\"\n  ],\n  \"motion\": \"slow-crossfade\",\n  \"richness\": \"The photographs, at full size, uninterrupted. Empty paper around short text makes the next image land harder.\",\n  \"pitfalls\": \"A weak hero photograph cannot be fixed by typography; pick again. Do not stack a headline, a paragraph and two buttons on the image. Do not use a booking bar that covers the bottom of the view; one small action is enough.\",\n  \"seenIn\": [\n   \"aww-white-desert\",\n   \"opl-eagles-nest\",\n   \"aww-tengile-malamala-collection\",\n   \"aww-izanami\",\n   \"aww-seasats\"\n  ],\n  \"allow\": [],\n  \"needsPictures\": true\n },\n {\n  \"id\": \"page-is-the-object\",\n  \"name\": \"The page is the object\",\n  \"sectors\": [\n   \"restaurant\",\n   \"event\",\n   \"hospitality\",\n   \"culture\",\n   \"music\",\n   \"physical-product\",\n   \"ecommerce\",\n   \"nonprofit\",\n   \"education\",\n   \"personal-portfolio\",\n   \"consumer-app\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"warm\",\n   \"playful\",\n   \"editorial\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Find the printed or physical artefact that already exists in the subject's world and build the page as that thing. A wedding site is the invitation card. A restaurant is its menu. A conference is the ticket; a record is its sleeve; a shop is the receipt or the swing tag; an archive is a stack of tabbed folders; a course is the syllabus sheet. The artefact supplies everything a template would otherwise invent: its proportions, its typographic manners, its way of grouping information. Visitors recognise the object instantly, which is why these pages feel specific.\",\n  \"composition\": \"The first screen shows the artefact as a single filled panel (paper colour on a contrasting ground) centred or offset, with believable proportions: a card at 5:7, a ticket at about 2.2:1 with a notch cut by `clip-path`, a menu as a tall sheet. All primary content lives on it, set the way that object is set: centred and symmetrical for an invitation, in tidy aligned columns for a menu or ticket. The ground behind is a flat colour or one full-bleed photograph. As the page continues, each section is another piece of the same stationery: a second card, a tear-off stub, a folded panel, always filled shapes with real edges (straight, notched, scalloped, perforated by a dotted `border` of round dots at 4px or more), never outlined boxes. The footer is the back of the object.\",\n  \"typography\": \"Take the manners of the artefact: a bookish serif with small caps avoided, or a blunt condensed face for tickets and posters. Sizes stay within what print would use relative to the panel; the name is large on the panel, details are small and exact.\",\n  \"typeClasses\": [\n   \"serif-text\",\n   \"serif-display\",\n   \"slab\",\n   \"condensed-heavy\",\n   \"grotesk-tight\"\n  ],\n  \"colour\": \"Paper and ink plus the ground the paper sits on. Two or three flat colours in total, like a two-colour print job.\",\n  \"paletteTags\": [\n   \"two-tone\",\n   \"earth\",\n   \"light-neutral\"\n  ],\n  \"imagery\": \"Optional. One photograph behind the object, or small photographs placed on it like tipped-in plates. The object itself is the image.\",\n  \"sectionTags\": [\n   \"object-led\",\n   \"type-led\",\n   \"colour-field\"\n  ],\n  \"motion\": \"curtain-footer\",\n  \"richness\": \"Recognition. The shaped edges, the print-like alignment and the limited inks make a familiar object out of plain HTML.\",\n  \"pitfalls\": \"Choose an artefact that truly belongs to the subject, or it becomes costume. Shape the edges with fills and `clip-path`; an outlined rectangle with a thin border is not an object. Keep text sizes readable on a phone, where the object becomes full width with its shaped edge kept at top and bottom.\",\n  \"seenIn\": [\n   \"opl-sarah-matt-wedding\",\n   \"aww-mosbys-files\",\n   \"opl-the-deep-end\",\n   \"opl-weeksync\",\n   \"opl-le-petit-bleu\",\n   \"opl-archiv\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"one-motif\",\n  \"name\": \"One motif\",\n  \"sectors\": [\n   \"saas\",\n   \"finance\",\n   \"consumer-app\",\n   \"ai-product\",\n   \"dev-tool\",\n   \"health\",\n   \"physical-product\",\n   \"restaurant\",\n   \"education\",\n   \"nonprofit\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"playful\",\n   \"technical\",\n   \"warm\",\n   \"bold\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Take one shape from the subject and let it run the whole system. A drilling tool's octagonal cross-section becomes the buttons, the image masks and the loader. A two-account money app becomes two circles that recur as icon, inline dot and section colour. A café's striped awning becomes every band on the page. Look at the product, the logo, the object or the word in the headline and find the simplest geometry in it (a circle, an arc, a chamfer, a stripe, a notch, a ring). Then use only that shape, at three or four very different scales, everywhere a designer would normally reach for a generic rounded rectangle.\",\n  \"composition\": \"Hero: the motif appears once at enormous scale as a flat filled shape, cropped by the viewport (a circle 120vh across entering from the right, a chamfered block filling the lower half), with a short headline at 6–8vw and one supporting sentence set on the remaining ground, left-aligned on a shared margin. Through the page the motif returns as: the mask for every photograph (via `clip-path` or `border-radius` made from the same geometry), the shape of the primary button, the bullet beside list items at text size, and one full-width band that separates the two halves of the page. Sections use simple two-column or single-column layouts so the shape is the only thing with character.\",\n  \"typography\": \"A clean geometric or grotesk face that echoes the shape (round bowls for circles, squared terminals for chamfers). Medium weight; headings 6–8vw in the hero and 3–4vw after.\",\n  \"typeClasses\": [\n   \"geometric\",\n   \"grotesk-tight\",\n   \"rounded-friendly\"\n  ],\n  \"colour\": \"The motif carries the accent colour at large scale, flat. Everything else is ground and ink. A second motif colour is allowed only if the subject has a real pair (two accounts, two modes).\",\n  \"paletteTags\": [\n   \"mono-accent\",\n   \"two-tone\",\n   \"pastel-fields\"\n  ],\n  \"imagery\": \"Photographs appear inside the motif's shape. If there is product interface to show, it sits on a flat colour stage shaped by the motif. Draw the shape with CSS or a simple inline SVG path; do not draw illustrations.\",\n  \"sectionTags\": [\n   \"colour-field\",\n   \"object-led\",\n   \"type-led\"\n  ],\n  \"motion\": \"shutter-image\",\n  \"richness\": \"One shape at many sizes. The giant cropped shape gives the hero mass and colour without a single image.\",\n  \"pitfalls\": \"One motif means one. A circle here, a hexagon there and a blob behind is the generated look this replaces. The motif must come from the subject and you must be able to say from where in one clause.\",\n  \"seenIn\": [\n   \"aww-sstr-friction-reduction\",\n   \"opl-tara\",\n   \"opl-boaxt\",\n   \"opl-midnight-2\",\n   \"opl-superlocal-2026\",\n   \"opl-billow\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"product-performs\",\n  \"name\": \"The product performs\",\n  \"sectors\": [\n   \"saas\",\n   \"dev-tool\",\n   \"ai-product\",\n   \"consumer-app\",\n   \"finance\"\n  ],\n  \"tones\": [\n   \"technical\",\n   \"quiet\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Software is most convincing when it is doing its job in front of you. Instead of describing features, put small, true, working fragments of the product on the page: the actual control, with real content, responding to the pointer. A colour picker's loupe reads the page's own background and prints its value. A list tool lets you tick an item right there. A type-scale plugin sets the page's own headings. Find the one interaction that is the product and make the hero that interaction; then show each further capability as another fragment at real size. No dashboard collage, no browser frame, no screenshots shrunk until unreadable.\",\n  \"composition\": \"Hero: a short plain headline (4–6vw, left-aligned, upper-left third) and one sentence; the rest of the first screen is the main fragment at actual interface size, sitting directly on the page or on one flat stage colour, large enough to read every label. The fragment is built in HTML and works. Below, capabilities are a single-column sequence, each a row of two parts on a 5/7 split: a two-line statement on one side and the relevant fragment on the other, with the fragments varying in size and shape so the column never becomes a zigzag of equal blocks. Fragments are cropped pieces of interface (a menu, a row, a control, a panel edge), not whole windows. One section pins a fragment while three short statements change it.\",\n  \"typography\": \"The marketing type matches the product's interface type so the fragments and the page feel like one thing. Headline modest; interface text at its true size (13–15px) inside fragments.\",\n  \"typeClasses\": [\n   \"grotesk-tight\",\n   \"grotesk-light\",\n   \"geometric\"\n  ],\n  \"colour\": \"Neutral ground. The product's own interface colours provide the colour. At most one flat stage colour behind fragments.\",\n  \"paletteTags\": [\n   \"light-neutral\",\n   \"dark-neutral\",\n   \"mono-accent\"\n  ],\n  \"imagery\": \"The interface fragments are the main imagery: build them carefully with real labels, real numbers and sensible states (one hovered, one selected). Around them, two or three real pictures of the customer's world (found with scripts/assets.mjs), never stock of people at laptops.\",\n  \"sectionTags\": [\n   \"ui-led\",\n   \"quiet\"\n  ],\n  \"motion\": \"pinned-story\",\n  \"richness\": \"Fidelity. A fragment with believable content and a real hover state is more interesting than any illustration. Spend the effort there.\",\n  \"pitfalls\": \"A fake interface made of grey bars and circles is the worst outcome; if you cannot build a believable fragment, change direction. Mark each fragment's root element with the attribute data-ui: inside it the product's own conventions apply (1px control borders, small radii, a shadow on its open menu) and the inspector leaves them alone; outside it the house rules hold as usual. data-ui is for cropped fragments only, never for a page wrapper. Do not put the fragment in a browser or laptop frame.\",\n  \"seenIn\": [\n   \"opl-dabbit\",\n   \"opl-rows\",\n   \"opl-typewave\",\n   \"opl-shelf\",\n   \"opl-uni\",\n   \"opl-kontu\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"quiet-instrument\",\n  \"name\": \"The quiet instrument\",\n  \"sectors\": [\n   \"saas\",\n   \"dev-tool\",\n   \"ai-product\",\n   \"personal-portfolio\",\n   \"consumer-app\",\n   \"finance\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"quiet\",\n   \"technical\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Radical understatement. Where every competitor shouts, this page almost whispers: a headline barely larger than body text, a narrow column, small exact demonstrations, and a great deal of untouched space. The restraint is the claim. It says the thing is simple, finished and sure of itself. This only works when it is carried through completely; one loud element breaks it. In the study, a tool for simple lists sold itself with a 27px headline and 12–14px copy and was one of the most confident pages in the set.\",\n  \"composition\": \"A single column 440–560px wide, placed left of centre (starting at about 22% of the viewport width) or dead centre, running the whole page. The headline is the one large thing on the first screen: two lines at display size (5–7vw), medium weight, starting on the column's left edge and allowed to run wider than the column. The supporting paragraph follows at body size (17–19px) in the full ink. One small primary button and one text link. Below, each point is a short paragraph followed by a compact demonstration or image no wider than the column. Sections are separated only by space (96–140px). Nothing spans the full width until the footer, which is a single quiet line. The first screen is mostly empty and that emptiness is composed: the column's top edge sits at about 30% of the viewport height.\",\n  \"typography\": \"One family, two weights. A display size for the headline (5–7vw), one heading size for section titles (about 32–40px), body at 17–19px, a small size for captions (14–15px). Leading 1.5 for text. Letter-spacing near zero. The typeface must be handsome at small sizes.\",\n  \"typeClasses\": [\n   \"grotesk-light\",\n   \"serif-text\",\n   \"geometric\"\n  ],\n  \"colour\": \"Paper and two inks (full and soft). One accent used on exactly one element per screen.\",\n  \"paletteTags\": [\n   \"light-neutral\",\n   \"mono-accent\"\n  ],\n  \"imagery\": \"Precise rather than loud: cropped interface details at true size, and real photographs of the customer's world held to the column width, each doing one job. One short looping clip can sit at column width too. Never a large stock hero image.\",\n  \"sectionTags\": [\n   \"quiet\",\n   \"ui-led\",\n   \"type-led\"\n  ],\n  \"motion\": \"stillness\",\n  \"richness\": \"Precision. With so little on the page, alignment, spacing and the exact size relationships are the design. Every element shares the column's left edge.\",\n  \"pitfalls\": \"This is the one direction where a small headline is right; the inspector will not object, but do not mix it with a large display line. Emptiness must look decided: keep the column edges exact and the vertical rhythm even. Not suitable when the subject needs emotion or photography to sell. Quiet is not thin: the column must still deliver every piece of content the brief asks for, in full, at 16px or more in the full ink. In blind tests the quiet version lost every time it was quiet everywhere: a small headline beside an empty panel read as unfinished. Quiet means few things, not small things: the headline and the demonstration are large, and every screen holds content.\",\n  \"seenIn\": [\n   \"opl-rows\",\n   \"opl-compile\",\n   \"opl-plastic\",\n   \"opl-bueno-fyi\",\n   \"aww-gil-huybrecht\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"hero-object\",\n  \"name\": \"The object, large\",\n  \"sectors\": [\n   \"physical-product\",\n   \"ecommerce\",\n   \"consumer-app\",\n   \"fashion\",\n   \"finance\",\n   \"health\",\n   \"restaurant\",\n   \"music\"\n  ],\n  \"tones\": [\n   \"bold\",\n   \"luxury\",\n   \"quiet\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"idea\": \"Show the thing, bigger than seems reasonable. One photographed object fills the first screen, scaled until the viewport crops it, with the text small and tucked beside or behind it. The crop is the idea: a record whose edge leaves the top-right corner, a bottle whose shoulder runs off the bottom, a chair seen so close you read its grain. Being that close reads as confidence in the object. Everything else on the page serves it: details as tight close-ups, facts as short lines, one way to buy.\",\n  \"composition\": \"First screen: the object occupies 55–75% of the viewport and breaks at least one edge. It sits on a flat field (ground colour or one bold colour), never in a box. The headline is short and either very large and partly hidden behind the object (10–13vw, the object overlapping two or three letters) or small (28–36px) in the opposite corner with a one-line description. No navigation bar beyond a wordmark and one action. Following sections: a row of three or four close-up details at different crop ratios (not equal tiles), a single wide photograph of the object in use, a plain list of facts set large (materials, size, price) aligned to one edge, then the purchase action. The object returns once at the end from a different angle.\",\n  \"typography\": \"Either very large and structural or very small and precise; pick one for the headline and hold it. Facts are set in the text face at 22–28px, not in a table.\",\n  \"typeClasses\": [\n   \"grotesk-light\",\n   \"grotesk-tight\",\n   \"extended-heavy\",\n   \"serif-light-large\"\n  ],\n  \"colour\": \"A flat field chosen to make the object's own colour sing (its complement, or a tone darker than its shadow side). One field for the whole page, or a second for the facts section.\",\n  \"paletteTags\": [\n   \"single-field\",\n   \"light-neutral\",\n   \"pastel-fields\",\n   \"dark-neutral\"\n  ],\n  \"imagery\": \"Use the product's own photographs if they exist. Otherwise use a still-life from the dealt set as a stand-in and say so. Prefer images with a plain background; use `mix-blend-mode: multiply` on light fields so a white studio background disappears into the page colour.\",\n  \"photoTreatment\": \"Scale the main image well past its container (`width: 120–160%`) and let `overflow: hidden` on the section do the cropping.\",\n  \"sectionTags\": [\n   \"object-led\",\n   \"photo-led\",\n   \"colour-field\"\n  ],\n  \"motion\": \"shutter-image\",\n  \"richness\": \"The object's surface at close range, and the tension of the crop.\",\n  \"pitfalls\": \"A small centred product shot with space all round is a catalogue thumbnail, not this direction. If the image has a busy background it cannot sit on a field; crop tighter or change image. Keep text off the object's focal area.\",\n  \"seenIn\": [\n   \"opl-when-you-wish-upon-a-starboy\",\n   \"opl-plastic\",\n   \"opl-archiv\",\n   \"aww-moto-finance\",\n   \"aww-the-watch\",\n   \"opl-aevion\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"specimen-catalogue\",\n  \"name\": \"The specimen catalogue\",\n  \"sectors\": [\n   \"ecommerce\",\n   \"physical-product\",\n   \"restaurant\",\n   \"fashion\",\n   \"culture\",\n   \"education\",\n   \"health\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"playful\",\n   \"warm\",\n   \"editorial\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"idea\": \"Present what is on offer the way a field guide presents birds: each item alone on a flat colour, same scale, same angle, named plainly. A bakery's pastries become specimens and the specimens become the menu. A furniture maker's chairs each get their own colour tile. The format flatters ordinary objects because it treats each as worth looking at, and it replaces both the feature grid and the product-card grid with something that has a point of view.\",\n  \"composition\": \"Hero: a left-aligned statement of what this is (5–7vw, upper-left) beside or above a tight cluster of four to seven specimen tiles of different sizes arranged as a loose mosaic that runs off the right edge. Each tile is a flat colour square or 4:5 rectangle with one photograph centred on it, no border, 8–12px gaps. The main section is the catalogue itself: a grid of tiles in which each item has its name and one fact set beneath the tile in the text face, aligned left to the tile edge. Tile colours rotate through three or four fields from the palette. One tile in every six or seven is double size. Supporting sections (about, how to order) are plain text on the ground colour, kept short.\",\n  \"typography\": \"Friendly and plain. Item names at 18–22px in medium weight, facts beneath in the soft ink. One big statement in the hero; no other display type.\",\n  \"typeClasses\": [\n   \"grotesk-tight\",\n   \"serif-text\",\n   \"slab\",\n   \"rounded-friendly\"\n  ],\n  \"colour\": \"The tiles are the colour: three or four flat fields from the palette, repeated in a steady rotation. Ground stays neutral.\",\n  \"paletteTags\": [\n   \"pastel-fields\",\n   \"flat-loud\",\n   \"light-neutral\"\n  ],\n  \"imagery\": \"Photographs of single items on plain backgrounds, all cropped to sit at the same apparent size within their tile. On light tiles, `mix-blend-mode: multiply` removes white studio backgrounds. If the subject's own item photographs are missing, use the dealt set and say so.\",\n  \"sectionTags\": [\n   \"object-led\",\n   \"colour-field\",\n   \"photo-led\"\n  ],\n  \"motion\": \"drag-row\",\n  \"richness\": \"Rhythm of colour tiles and the pleasure of comparing like with like.\",\n  \"pitfalls\": \"It needs at least six items that can be shown as objects; with three it is a feature row. Keep labels outside the tiles. No shadows under the objects, no hover lift.\",\n  \"seenIn\": [\n   \"aww-noho\",\n   \"opl-madie\",\n   \"opl-humanoid-index\",\n   \"opl-smallbits\",\n   \"aww-butter\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"borrowed-category\",\n  \"name\": \"Dressed as something else\",\n  \"sectors\": [\n   \"finance\",\n   \"saas\",\n   \"consumer-app\",\n   \"physical-product\",\n   \"health\",\n   \"dev-tool\",\n   \"ai-product\",\n   \"education\",\n   \"nonprofit\",\n   \"real-estate\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"bold\",\n   \"playful\",\n   \"luxury\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Art-direct the subject as if it belonged to a different, more vivid category. A money app is sold like a streetwear drop. An industrial roaster is presented like a design object. Drilling hardware gets the calm of a watch brand. A parcel-locker service becomes a fairground of stickers. Choose the borrowed category by asking what feeling the audience is missing from this kind of product (swagger, calm, glamour, play) and which category owns that feeling. Then take its manners completely: its type, its pacing, its way of photographing things. The contrast between dull subject and vivid dress is what people remember.\",\n  \"composition\": \"Depends on the borrowed category, so decide it explicitly and write it in your notes. Fashion drop: one shouted condensed headline across the full width, a single cropped image under it, then product facts as a blunt list. Watch or perfume: a centred object on a dark field, a small serif name, very few words, long vertical pauses. Poster or zine: flat colour blocks, heavy type, tilted cut-out images. Museum: one item per screen on a plinth-like band of colour with a short label beside it. Whichever you choose, the page structure stays simple (four to six sections) and every section uses the borrowed manners, including pricing and the footer.\",\n  \"typography\": \"The borrowed category's type, fully committed: condensed and loud, or refined and small. No halfway.\",\n  \"typeClasses\": [\n   \"condensed-heavy\",\n   \"serif-display\",\n   \"extended-heavy\",\n   \"heavy-black\"\n  ],\n  \"colour\": \"The borrowed category's palette, which will be unlike the subject's sector norm. That mismatch is intended.\",\n  \"paletteTags\": [\n   \"flat-loud\",\n   \"two-tone\",\n   \"dark-neutral\",\n   \"single-field\"\n  ],\n  \"imagery\": \"Photograph the subject the way the borrowed category would be photographed. With the dealt set, choose images for attitude, not literal relevance, and crop them hard.\",\n  \"sectionTags\": [\n   \"poster\",\n   \"type-led\",\n   \"photo-led\",\n   \"colour-field\"\n  ],\n  \"motion\": \"edge-marquee\",\n  \"richness\": \"Attitude. The page has a recognisable voice from another world, applied to a subject nobody expected it for.\",\n  \"pitfalls\": \"Name the borrowed category in one word before you start, or the result is merely loud. The content must still be clear: what it is, what it costs, how to get it. Avoid borrowing from 'tech startup', which is the default you are escaping.\",\n  \"seenIn\": [\n   \"opl-uglycash\",\n   \"aww-coffeetech-r\",\n   \"aww-sstr-friction-reduction\",\n   \"opl-locker-land\",\n   \"aww-moto-finance\",\n   \"aww-vero-new-york\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"contact-sheet\",\n  \"name\": \"The contact sheet\",\n  \"sectors\": [\n   \"personal-portfolio\",\n   \"studio-portfolio\",\n   \"agency\",\n   \"fashion\",\n   \"culture\",\n   \"architecture\",\n   \"music\",\n   \"ecommerce\"\n  ],\n  \"tones\": [\n   \"quiet\",\n   \"technical\",\n   \"editorial\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Show everything at once, small, in order. The work is laid out like a photographer's contact sheet or an archive drawer: dozens of small frames in strict rows, with all text set at one small size. Nothing is featured, which is the point: the volume and consistency of the body of work is the statement, and the visitor does the choosing. It suits people and studios whose strength is range and output.\",\n  \"composition\": \"The name, or one sentence about the work, sits at display size (6–9vw) across the top of the first screen, and the sheet begins directly under it, still inside the first screen. The first screen opens with three or four short blocks of small text across the top on a 12-column grid (who, what, where to reach them), all at 14–16px, and immediately below, the sheet begins: rows of thumbnails at a fixed height (90–140px) with their natural widths, 6–10px gaps, each project forming a run of four to eight frames preceded by its title in the same small text. The sheet fills the whole page width edge to edge with 16–20px margins. Hovering a run dims the others and shows that project's one-line description in a fixed position. A single enlarged frame may interrupt the sheet once per screen at four times the size.\",\n  \"typography\": \"One face. The name at display size on the first screen; everything else at one text size and one small size; hierarchy below the name comes from position and from a single brighter ink for titles.\",\n  \"typeClasses\": [\n   \"grotesk-light\",\n   \"grotesk-tight\"\n  ],\n  \"colour\": \"Black or white ground, so the thumbnails are the only colour.\",\n  \"paletteTags\": [\n   \"dark-neutral\",\n   \"light-neutral\"\n  ],\n  \"imagery\": \"Many images: at least 24 frames to make a sheet. They can be project photographs from the dealt set cropped to mixed ratios, or page captures of the work. Square corners, no captions on the frames.\",\n  \"sectionTags\": [\n   \"dense\",\n   \"photo-led\",\n   \"quiet\"\n  ],\n  \"motion\": \"index-preview\",\n  \"richness\": \"Density and order. The mass of small images forms a texture; the strict rows keep it calm.\",\n  \"pitfalls\": \"With fewer than about 20 images it looks unfinished; choose another direction. Do not add a big headline above the sheet. On a phone the frames become two per row at a fixed height and each run scrolls sideways. Rows that run past the right edge read as clipped in screenshots and to most visitors: wrap the frames onto the next line, or end each row inside the grid.\",\n  \"seenIn\": [\n   \"aww-gil-huybrecht\",\n   \"opl-smallbits\",\n   \"opl-gunes-atakan-peksen\",\n   \"opl-proooof\",\n   \"aww-oimachi\"\n  ],\n  \"allow\": [],\n  \"needsPictures\": true\n },\n {\n  \"id\": \"editorial-report\",\n  \"name\": \"The printed annual\",\n  \"sectors\": [\n   \"culture\",\n   \"nonprofit\",\n   \"education\",\n   \"finance\",\n   \"saas\",\n   \"ai-product\",\n   \"health\",\n   \"agency\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"editorial\",\n   \"bold\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Lay the page out like a well-designed printed report or magazine feature: a masthead image, a tight oversized title, text held to a strict column line, and colour used in solid blocks the way a two-colour print job would. It gives weight and authority to subjects that are really about content: findings, a manifesto, a programme, a serious product. The reader should feel that someone edited this.\",\n  \"composition\": \"A fixed vertical axis at about 42% of the viewport width organises everything: headings begin on it, body columns hang from it, and the 0–42% zone holds small side notes, figures or stays empty. Masthead: a wide image band (photographic mosaic or a single crop) across the top 45% of the first screen; below it the title at 7–9vw starting on the axis, with a two-sentence standfirst at 20–24px. Sections alternate between text pages (title on the axis, body in one or two columns of 34–40ch to its right) and full-bleed colour pages carrying one large figure, quotation or image mosaic. Mosaics are gutterless: photographs and flat colour tiles butted together in a 4- or 6-cell grid. Page numbers, running heads and other print furniture are left out.\",\n  \"typography\": \"A tight heavy grotesk or a sharp serif for titles; an excellent text face for reading at 18–20px with leading near 1.5. Headings in sentence case, tracked tight.\",\n  \"typeClasses\": [\n   \"grotesk-tight\",\n   \"serif-display\",\n   \"serif-text\"\n  ],\n  \"colour\": \"Paper, ink and two or three solid block colours. A colour page is a whole section in one flat colour.\",\n  \"paletteTags\": [\n   \"flat-loud\",\n   \"two-tone\",\n   \"mono-accent\"\n  ],\n  \"imagery\": \"Photographs used as blocks in mosaics alongside flat colour tiles; mixed subjects are fine if cropped tight and converted to one treatment.\",\n  \"photoTreatment\": \"Give all photographs in a mosaic one treatment: greyscale via `filter: grayscale(1) contrast(1.05)`, or all full colour. Do not mix.\",\n  \"sectionTags\": [\n   \"type-led\",\n   \"colour-field\",\n   \"dense\",\n   \"poster\"\n  ],\n  \"motion\": \"masked-headline\",\n  \"richness\": \"The column line, the mosaics and whole pages of colour give structure and variety without ornaments.\",\n  \"pitfalls\": \"The axis must be exact and reused everywhere or it reads as random indentation. Keep paragraphs to a real reading measure. On a phone the axis collapses to the left margin and side notes move inline above their paragraph.\",\n  \"seenIn\": [\n   \"aww-ai-in-design-report-2026\",\n   \"opl-applied-imagination\",\n   \"opl-the-queue\",\n   \"opl-artem-taradash\",\n   \"opl-belgrade-architecture\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"loud-flat-poster\",\n  \"name\": \"Loud and flat\",\n  \"sectors\": [\n   \"agency\",\n   \"consumer-app\",\n   \"music\",\n   \"event\",\n   \"education\",\n   \"nonprofit\",\n   \"physical-product\",\n   \"saas\",\n   \"culture\"\n  ],\n  \"tones\": [\n   \"bold\",\n   \"playful\"\n  ],\n  \"needs\": [],\n  \"idea\": \"A page with the directness of a street poster: flat saturated colour, the heaviest type you can find, short blunt statements, and photographs cut out and stuck on. It is for subjects with a voice. Write the page as things a person would actually say out loud, and let the design say them at full volume. The craft is in the control beneath the noise: a strict grid, two or three colours, and exact alignment keep it from becoming a mess.\",\n  \"composition\": \"Hero: a statement of three to six words in ultra-heavy type at 11–15vw, filling the width, lines stacked tight (leading 0.85), flush left with 20–28px margins, on a flat saturated ground. One cut-out or hard-cropped photograph overlaps the type from the right or bottom, tilted 3–6 degrees. A single chunky button in the contrasting flat colour. Sections are solid panels in alternating palette colours: one is a row of short statements each on its own panel of unequal width; one is a single photograph bleeding off two edges with a caption block set over a solid colour bar; one is a large plain list. Panels meet edge to edge. Corners are square or use one large radius (28–40px) consistently.\",\n  \"typography\": \"The heaviest weight available, set tight, mostly lowercase or mostly uppercase (choose one). Body text is a plain grotesk at 18–20px.\",\n  \"typeClasses\": [\n   \"heavy-black\",\n   \"condensed-heavy\",\n   \"extended-heavy\",\n   \"rounded-friendly\"\n  ],\n  \"colour\": \"Three or four flat colours at full strength including black or white. Each panel is one colour; text on it is one other.\",\n  \"paletteTags\": [\n   \"flat-loud\"\n  ],\n  \"imagery\": \"Photographs with attitude, cropped hard or cut to a simple shape with `clip-path` (circle, arch, blunt polygon), slightly rotated, overlapping the type. Two or three on the page.\",\n  \"sectionTags\": [\n   \"poster\",\n   \"colour-field\",\n   \"type-led\"\n  ],\n  \"motion\": \"edge-marquee\",\n  \"richness\": \"Colour mass, type mass, and overlap.\",\n  \"pitfalls\": \"Headlines still obey the two-line rule: at 13vw that means very few words, which is correct for this voice. No outlines, no offset shadows, no sticker confetti. Rotation is for two or three images only, never for text blocks.\",\n  \"seenIn\": [\n   \"aww-warm-fuzzy\",\n   \"aww-aardvark-book-club\",\n   \"opl-uglycash\",\n   \"opl-depo-budget-app\",\n   \"aww-trevor-noah\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"split-stage\",\n  \"name\": \"The split stage\",\n  \"sectors\": [\n   \"restaurant\",\n   \"hospitality\",\n   \"personal-portfolio\",\n   \"physical-product\",\n   \"fashion\",\n   \"real-estate\",\n   \"health\",\n   \"culture\",\n   \"ecommerce\",\n   \"saas\",\n   \"consumer-app\"\n  ],\n  \"tones\": [\n   \"warm\",\n   \"quiet\",\n   \"editorial\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Half the screen never moves. One side is a fixed photograph (or object, or product view) that stays in place for the whole visit; the other side is a calm scrolling column with everything you need to read. The fixed half keeps the feeling present while the reader gets on with the facts, like sitting in the room while reading the menu. As sections pass, the fixed image may quietly change to the one that matches.\",\n  \"composition\": \"Desktop: a two-column page, 50/50 or 45/55. One column is `position: sticky; top: 0; height: 100svh` and holds a single photograph filling it edge to edge, or the object centred on a flat field. The other column scrolls and holds all content in a single narrow measure (max 46ch) with comfortable padding (48–72px): name and one-line description first, then sections separated by generous space, then contact and footer. Headings in the scrolling column are modest (32–44px). The column grounds differ: photograph on one side, flat paper colour on the other, meeting at a clean vertical edge. On a phone the fixed half becomes a 60svh image at the top that stays sticky behind the first section, then releases.\",\n  \"typography\": \"A text-first setting: a readable serif or a calm sans at 17–19px, with one display size for the name. Left-aligned throughout.\",\n  \"typeClasses\": [\n   \"serif-text\",\n   \"serif-display\",\n   \"grotesk-light\",\n   \"slab\"\n  ],\n  \"colour\": \"The paper colour of the reading column is chosen against the photograph: a tone taken from its shadows or its lightest area. One ink, optionally one accent ink for links and the action.\",\n  \"paletteTags\": [\n   \"two-tone\",\n   \"earth\",\n   \"light-neutral\",\n   \"photographic-neutral\"\n  ],\n  \"imagery\": \"One excellent portrait-orientation photograph for the fixed half, plus three or four more that crossfade in as their sections arrive. Small inline photographs in the reading column are optional and should be few.\",\n  \"sectionTags\": [\n   \"quiet\",\n   \"photo-led\",\n   \"type-led\"\n  ],\n  \"motion\": \"slow-crossfade\",\n  \"richness\": \"A full-height photograph always in view, against a quiet, well-set column of text.\",\n  \"pitfalls\": \"The reading column must be genuinely well typeset, since it is half the page. Do not put cards or grids in it. Check that the fixed image crops well at short viewport heights. In blind tests the commonest complaint was monotony: several screens of the same split with only the text changing. Change what the reading half holds from section to section (a list, a large figure, a table, a full-colour panel, a drawing) and let at least one section break the split and run full width.\",\n  \"seenIn\": [\n   \"opl-le-petit-bleu\",\n   \"opl-rafael-derolez-2026\",\n   \"opl-flowjam-2\",\n   \"opl-devonshire\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"dense-tiles\",\n  \"name\": \"The well-kept board\",\n  \"sectors\": [\n   \"agency\",\n   \"studio-portfolio\",\n   \"saas\",\n   \"dev-tool\",\n   \"ai-product\",\n   \"culture\",\n   \"music\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"technical\",\n   \"bold\"\n  ],\n  \"needs\": [],\n  \"idea\": \"The whole page is a board of tiles fitted edge to edge with narrow gaps, like a tidy desk seen from above. Each tile is one thing: the name, a statement, a photograph, a number, a link, a short list. There is no hero and no sequence of bands; the page is one continuous composition that the eye roams. It suits subjects with many small true things to show (a studio with work, writing, clients and news; a product with several distinct capabilities) and it replaces the gen\n\n<!-- [TRUNCATED AT 50KB] -->","skills/taste-skill/library/heroes.json":"[\n {\n  \"id\": \"name-under-photograph\",\n  \"name\": \"Name under a photograph\",\n  \"archetype\": \"giant-wordmark\",\n  \"directions\": [\n   \"name-as-monument\",\n   \"place-carries-it\",\n   \"dark-room\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A full-bleed photograph fills the top 58% of the 1440×900 viewport, touching the top, left and right edges, `object-fit: cover`, with its focal point in the upper two-thirds. The lower 42% is a flat ground colour that butts against the photograph with no gap. The name runs across this band on one line, spanning all 12 columns between 24px margins, at clamp(120px, 19vw, 300px), tracking -0.05em, line-height 0.85, its baseline 28px above the bottom edge so descenders nearly touch it. Fit the size to the length of the name so it never wraps. In the strip of ground between photograph and name, 24px under the photograph's edge, sits one row at 17px: the supporting sentence on columns 1–5 at the left margin, and the single action as a small solid rectangular button flush to the right margin. Navigation is four text links at 15px laid over the photograph's top-right corner, 24px in, with a neutral scrim behind that row only if the image is light there. No logo is repeated: the name is the logo. Nothing else is on the screen.\",\n  \"mobile\": \"The photograph takes the top 50svh at full width, re-cropped around its focal point. The name sits under it at 23vw on one line; a name longer than seven characters breaks onto two lines at 21vw, line-height 0.85, and fills the band down to a 16px bottom margin. The supporting sentence at 16px and the action button stack above the name on the left margin. The links collapse to one 'Menu' word over the photograph, top-right.\",\n  \"headline\": \"The name itself on one line, up to about 12 characters at 19vw (drop towards 13vw for longer names), and at most two lines on a phone.\",\n  \"motion\": \"scaling-wordmark\",\n  \"seenIn\": [\n   \"aww-house-of-honey-1\",\n   \"opl-kereliott\",\n   \"aww-lxl-creative\"\n  ]\n },\n {\n  \"id\": \"stacked-name-two-inks\",\n  \"name\": \"Stacked name, two inks\",\n  \"archetype\": \"type-poster\",\n  \"directions\": [\n   \"name-as-monument\",\n   \"colour-chapters\",\n   \"type-only-statement\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One saturated flat field covers the whole 1440×900 viewport and there is no image. The name is broken into two lines and set flush left from a 40px margin at clamp(110px, 15vw, 230px), heavy weight, tracking -0.04em, line-height 0.82 so the lines almost touch. The block starts 14% down and fills the top 58% of the screen; the longer line reaches at least column 11. Line one is set in the light ink and line two in the dark ink, so the break reads as a change of voice: split a two-word name between the lines, or break one long name with a hyphen at a syllable. The top edge carries only small text at 15px, 24px in: a monogram top-left, and two or three text links plus the single action as an underlined link top-right. The supporting sentence, 18px in the light ink and max 30ch, is right-aligned in the bottom-right corner on columns 9–12, its last line 40px above the bottom edge. The bottom-left corner stays empty. The next section begins as a different flat field exactly at the fold.\",\n  \"mobile\": \"The field fills 100svh. The name keeps its two lines and two inks at 21vw, flush left at a 16px margin, starting 18% down; a long name hyphenates rather than dropping below 18vw. The supporting sentence moves to the bottom-left at 16px across the full width, with the action as an underlined link beneath it, 24px above the bottom edge. The top-right links reduce to one word.\",\n  \"headline\": \"The name on exactly two lines, one per ink, each line up to about 8 characters at 15vw on desktop and 21vw on a phone.\",\n  \"motion\": \"masked-headline\",\n  \"seenIn\": [\n   \"opl-marina-rachello\",\n   \"opl-anidachi\"\n  ]\n },\n {\n  \"id\": \"photograph-for-a-letter\",\n  \"name\": \"Photograph for a letter\",\n  \"archetype\": \"giant-wordmark\",\n  \"directions\": [\n   \"name-as-monument\",\n   \"sentence-as-layout\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A flat white or pale ground, about 85% empty. The name sits on one line at the exact vertical centre, bold, at clamp(96px, 10.5vw, 168px), tracking -0.04em, spanning 78–88% of the width with equal side margins. One photograph is set into the line as if it were a glyph. Either it fills the word space between first and last name (a landscape frame one x-height tall and about 1.6em wide, resting on the baseline), or it replaces one round letter of a short name (a square frame exactly one cap-height tall). Build the line as an inline-flex row with `align-items: baseline` and size the frame in em so it scales with the type; square corners, `object-fit: cover`. Navigation is small and pushed to the edges: a 15px wordmark or monogram top-left at a 24px margin and up to five text links at 14px spread evenly across the right half of the top edge. Along the bottom edge, on the same margin: one supporting sentence at 16px starting at column 6, and the single action as an underlined text link flush right.\",\n  \"mobile\": \"The name stacks on two centred lines at 19vw with line-height 0.9. The photograph leaves the line and becomes a 3:2 frame at full width minus 16px margins between the two lines, so the screen reads word, picture, word. A single short name keeps the square frame inline at cap height instead. The supporting sentence and action sit under the block at 16px; the links collapse to one word top-right.\",\n  \"headline\": \"The name on one line with a photograph in its word space or in place of one letter, up to about 16 characters at 10.5vw, splitting into two lines on a phone.\",\n  \"motion\": \"shutter-image\",\n  \"seenIn\": [\n   \"aww-paul-kalkbrenner\",\n   \"opl-nia-creative\"\n  ]\n },\n {\n  \"id\": \"name-split-to-corners\",\n  \"name\": \"Name split to corners\",\n  \"archetype\": \"pinned-stage\",\n  \"directions\": [\n   \"pinned-poster\",\n   \"name-as-monument\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"The name is cut into two halves that stay pinned to opposite corners while the page passes between them. A layer with `position: sticky; top: 0; height: 100svh` and `pointer-events: none` holds both: the first word top-left, 28px from the top and left edges; the second word bottom-right, 28px from the bottom and right edges. Both are set at clamp(72px, 9vw, 140px), line-height 0.85, in white with `mix-blend-mode: difference` so they read on every panel beneath. On the first screen the stage between them is a paper-white panel on columns 1–9 and one full-height photograph on columns 10–12 touching the top, right and bottom edges. The supporting sentence, 20px and max 34ch, starts at column 3 at 44% of the height; the single action is a text link with an arrow directly under it. Three text links are stacked at 15px along the right edge of the white panel at mid-height. The rest of the panel is empty. Later panels, full-height photographs and text panels of different widths, scroll under the pinned halves for three to five viewports; then the layer releases into ordinary sections.\",\n  \"mobile\": \"Both halves stay pinned: the first word top-left and the second bottom-right, each at 15vw with 16px margins. Between them every panel is a full-width photograph 56svh tall followed by its sentence at 17px. On the first screen the photograph crosses the middle band with the supporting sentence and the action link beneath it. The stacked links collapse to one word at the top-right corner.\",\n  \"headline\": \"The name in two halves (two words, or one word cut at a syllable), each up to about 9 characters at 9vw, one per corner, with no other headline.\",\n  \"motion\": \"pinned-story\",\n  \"seenIn\": [\n   \"aww-normal-is-boring\",\n   \"aww-the-state-of-the-gallery\",\n   \"aww-milledollars\"\n  ]\n },\n {\n  \"id\": \"pinned-title-over-portraits\",\n  \"name\": \"Pinned title over portraits\",\n  \"archetype\": \"pinned-stage\",\n  \"directions\": [\n   \"pinned-poster\",\n   \"name-as-monument\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A pale flat ground. The title runs on one line of extra-bold uppercase at clamp(90px, 10vw, 160px), centred, spanning about 82% of the width, its cap line 120px from the top. It lives in a sticky layer (`position: sticky; top: 0; height: 100svh`) stacked above the images and set in one saturated ink that reads on both ground and photograph. Beneath it a single portrait photograph, 2:3, sits centred on columns 5–8 (about 37% of the width) and runs from 90px below the top edge down to the bottom edge, so the title crosses its upper quarter and the middle letters sit on the image. The wordmark sits top-left at 24px in 15px bold; one 'Menu' word sits top-right. Bottom-left on columns 1–3: the supporting sentence as a narrow column at 16px bold, max 26ch, its last line 32px above the bottom edge. Bottom-right: the single action as a solid rectangular button. As the page scrolls, further portraits of identical ratio and position replace the first, five to eight in all, each bringing its own flat ground colour sampled from the photograph, before the layer releases.\",\n  \"mobile\": \"The title stays pinned at the top at 17vw on one line, or two lines at 15vw if longer than ten characters. Each portrait becomes full width minus 16px margins at 2:3 and starts behind the lower half of the title. The supporting sentence follows the first portrait at 16px. The action button is fixed to the bottom-right corner, 16px in. The wordmark shrinks to a monogram top-left.\",\n  \"headline\": \"The title of the series, or the name: one uppercase line of up to about 14 characters at 10vw, two short lines on a phone.\",\n  \"motion\": \"pinned-story\",\n  \"seenIn\": [\n   \"opl-city-of-angels\",\n   \"aww-glitch-grit\"\n  ]\n },\n {\n  \"id\": \"sentence-with-photo-strip\",\n  \"name\": \"Sentence with a photo strip\",\n  \"archetype\": \"inline-media-sentence\",\n  \"directions\": [\n   \"sentence-as-layout\",\n   \"place-carries-it\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A warm flat ground with no navigation bar. One sentence of four or five words runs as a single line of condensed capitals at clamp(120px, 13vw, 200px), sitting on the vertical centre and reaching edge to edge inside 28px margins. Where one word of the sentence would be, a strip of photograph takes its place: a frame exactly one cap-height tall (set in em) and 45–50% of the viewport wide, ratio near 5:1, corners radiused 14px, `object-fit: cover`. Build the line as a flex row with `align-items: baseline` and give the strip `flex: 1` so words and picture always fill the width. The photograph shows the thing the sentence names: a wide view of the place, taken from above or along a horizon, so it survives the letterbox crop. The top third of the screen is empty apart from a 15px wordmark top-left and two text links top-right. About 150px under the sentence the single action sits centred as a small solid button. One supporting sentence at 22px, max 44ch, is centred 48px above the bottom edge.\",\n  \"mobile\": \"The sentence breaks into two lines at 21vw with the strip between them: the first words, then the photograph as a 2:1 frame at full width minus 16px margins with the same 14px corners, then the remaining words. The block is centred vertically. The action button sits 32px under the last line and the supporting sentence under that at 16px. The top links collapse to one word.\",\n  \"headline\": \"A sentence of four or five short words, about 14 characters of type in total, whose missing word is the photograph.\",\n  \"motion\": \"shutter-image\",\n  \"seenIn\": [\n   \"aww-colonia-zacamil\"\n  ]\n },\n {\n  \"id\": \"sentence-split-by-frame\",\n  \"name\": \"Sentence split by a frame\",\n  \"archetype\": \"inline-media-sentence\",\n  \"directions\": [\n   \"sentence-as-layout\",\n   \"pinned-poster\",\n   \"product-performs\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A white or pale ground. One short sentence is broken in two and pushed to the edges: the first half flush to the 32px left margin, the second half flush to the right margin, both on the vertical centre line at clamp(40px, 3.6vw, 60px), medium weight. Between them, dead centre on columns 5–8, sits one media frame: 35% of the viewport wide, 16:9, corners 4px, holding a photograph or a working fragment of the product. The frame belongs to a vertical reel: the bottom 60px of the previous frame shows at the top edge of the viewport and the top 60px of the next at the bottom edge, same width, 24px gaps, so the centre column reads as a strip passing through the sentence. The stage is sticky; the reel advances three or four steps while the two halves of the sentence hold their place. Wordmark top-left; three text links and the single action as a small solid button top-right, all at 15px. Bottom-left on columns 1–4: one supporting sentence at 18px, its last line 32px above the bottom edge. The other corners stay empty.\",\n  \"mobile\": \"The halves stack: the first half of the sentence at 9vw flush left under the wordmark, then the frame at full width minus 16px margins and 4:3, then the second half flush right at 9vw. The neighbouring frames show as 28px slivers above and below. The supporting sentence and the action button follow at 16px. The links collapse to one word.\",\n  \"headline\": \"One sentence of four to six words split into two halves of up to about 14 characters each; the frame between them shows what it is about.\",\n  \"motion\": \"pinned-story\",\n  \"seenIn\": [\n   \"aww-made-with-gsap-1\",\n   \"aww-artem-shcherbakov\"\n  ]\n },\n {\n  \"id\": \"headline-across-two-fields\",\n  \"name\": \"Headline across two fields\",\n  \"archetype\": \"colour-field\",\n  \"directions\": [\n   \"colour-chapters\",\n   \"sentence-as-layout\",\n   \"type-only-statement\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"The viewport is two flat fields meeting at exactly half height: paper above, one saturated colour below, with a hard edge and nothing drawn on it. A two-line headline in black-weight capitals at clamp(96px, 9.5vw, 150px), line-height 0.86, is centred across the seam and spans about 70% of the width, so line one stands on the upper field and line two is cut through its upper third by the seam. The type changes ink where it crosses: above the seam it takes the accent ink, below it a deep ink two steps darker than the lower field, as if submerged. Build it as two stacked copies of the same headline, one per ink, the first clipped with `clip-path: inset(0 0 50% 0)` and the second with `inset(50% 0 0 0)`. Wordmark top-left at 28px; up to four text links and the single action, a solid rectangular button, top-right. One supporting sentence at 20px in the paper colour is centred on the lower field, 56px above the bottom edge. The lower field continues for 30svh past the fold before the next colour begins.\",\n  \"mobile\": \"The same two fields with the seam at 46svh. The headline stays on two lines at 15vw, centred, still cut by the seam and still changing ink. Wordmark top-left and the action button top-right; the links drop into one menu word beside it. The supporting sentence sits on the lower field at 16px, centred, max 28ch, with 40px beneath it.\",\n  \"headline\": \"A statement of two to four words on two lines, up to about 10 characters per line, whose meaning the rising field acts out.\",\n  \"motion\": \"colour-on-scroll\",\n  \"seenIn\": [\n   \"opl-juggle\"\n  ]\n },\n {\n  \"id\": \"swatch-column-beside-view\",\n  \"name\": \"Swatch column beside the view\",\n  \"archetype\": \"split\",\n  \"directions\": [\n   \"colour-chapters\",\n   \"place-carries-it\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A 10px frame of paper colour surrounds the screen. Columns 1–10 are one photograph panel, full height inside the frame, corners radiused 12px, `object-fit: cover`: a wide, calm view with a low horizon and a great deal of sky. The headline is centred in the panel's upper third on two lines of light-weight serif at clamp(72px, 8.6vw, 132px), white, with a neutral scrim behind that band only if the sky is pale. The wordmark sits top-left inside the panel, 28px in. The single action, a white rectangular button, sits bottom-centre, 36px above the panel's lower edge; one supporting sentence at 18px sits bottom-left on columns 1–4, level with it. Columns 11–12 are both the navigation and a preview of the page: a full-height stack of five flat colour blocks of equal height, butted together with no gaps, each holding one text link at 16px in its top-left corner with 20px padding. The five colours are sampled from the photograph, ordered light to dark, and each is the ground colour of the section its link scrolls to. There is no other navigation.\",\n  \"mobile\": \"The photograph panel takes the top 64svh inside an 8px frame, with the headline at 12vw on two lines in its upper third and the action button at its bottom-centre. The swatch column becomes five full-width bars, each 52px tall with its link at 15px, stacked directly under the panel; the first three show above the fold. The supporting sentence moves into the first section.\",\n  \"headline\": \"A two-line statement of three to five words, up to about 14 characters per line at 8.6vw, set over the sky.\",\n  \"motion\": \"colour-on-scroll\",\n  \"seenIn\": [\n   \"aww-seasats\"\n  ]\n },\n {\n  \"id\": \"film-title-on-bottom-edge\",\n  \"name\": \"Film title, bottom edge\",\n  \"archetype\": \"bottom-anchored-type\",\n  \"directions\": [\n   \"place-carries-it\",\n   \"name-as-monument\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One photograph fills the viewport at 100vw by 100svh, `object-fit: cover`, with its subject in the upper two-thirds and a calmer, darker zone along the bottom. The name is one condensed uppercase word, or a short name in a high-contrast serif, set at clamp(150px, 17.5vw, 290px) and sized to span the full width between 32px margins. It is centred and anchored so its baseline sits 34px above the bottom edge, covering roughly the lowest quarter of the frame. A soft neutral dark scrim lies under that bottom band only, about 40% of the height; the rest of the image is untouched. Directly above the name's left end, on the same margin, sits the supporting sentence at 16px on two short lines. Directly above its right end, right-aligned, sits the single action as a small paper-coloured rectangular button. The top edge carries a small emblem or wordmark at the left margin and up to five text links at 15px grouped at the right, all in white. The central half of the screen belongs to the view.\",\n  \"mobile\": \"The photograph is re-cropped to portrait with `object-position` on its subject and fills 100svh. The name stays on the bottom edge at 22vw on one line, or two lines at 20vw beyond eight characters, 20px above the edge. The supporting sentence sits above the name's left end at 15px. The action button moves to the top-right corner and the links collapse to a menu word beside the emblem.\",\n  \"headline\": \"The name of the place: one word of up to about 12 characters at 17.5vw, or two words stacked on a phone.\",\n  \"motion\": \"slow-crossfade\",\n  \"seenIn\": [\n   \"aww-white-desert\",\n   \"opl-eagles-nest\"\n  ]\n },\n {\n  \"id\": \"small-name-open-sky\",\n  \"name\": \"Small name, open sky\",\n  \"archetype\": \"fullbleed-media\",\n  \"directions\": [\n   \"place-carries-it\",\n   \"uneven-photographs\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A single photograph fills the viewport edge to edge with no frame: choose one whose upper 45% is sky, wall or water with nothing in it and whose subject sits low and off-centre. All type is white and stays out of that empty zone. Top-left at a 24px margin, the name is stacked on two or three lines at 14px, like a letterhead. Top-right, three or four text links run in one line at 14px separated by commas, the current one marked by a 2px underline. Bottom-left, 32px from the left and bottom edges, the name repeats as the only larger type: two tight lines at clamp(44px, 4.2vw, 64px), line-height 1.0, regular weight, on columns 1–5. On the same baseline at the bottom-right margin sits the single action as an underlined text link with an arrow, and above it one supporting sentence at 15px, right-aligned, max 32ch. If a lower corner is too bright for white type, darken that corner alone with a neutral scrim. The page below opens on plain paper with one narrow paragraph and wide empty margins.\",\n  \"mobile\": \"The photograph is cropped to portrait around its subject and fills 100svh, its upper half still empty. The small stacked name stays top-left at 13px and the links collapse to one word top-right. The larger name sits bottom-left at 9.5vw on two lines, 20px in. The supporting sentence and the underlined action stack beneath it at 15px, left-aligned, 24px above the bottom edge.\",\n  \"headline\": \"The name set small on two lines of up to about 16 characters each at 4.2vw; the photograph does the work of a headline.\",\n  \"motion\": \"slow-crossfade\",\n  \"seenIn\": [\n   \"aww-kononenko-architectural-bureau\",\n   \"aww-julien-calot\",\n   \"aww-depo-luxe\"\n  ]\n },\n {\n  \"id\": \"invitation-card-cropped\",\n  \"name\": \"Invitation card, cropped\",\n  \"archetype\": \"artefact\",\n  \"directions\": [\n   \"page-is-the-object\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A flat field of one soft colour fills the viewport. Centred on it is a single portrait card in paper colour, 5:7, on columns 4–9, its top edge 190px down and its lower third cut off by the bottom of the viewport, so the page visibly continues as the rest of the card. The card is a filled shape with scalloped inner corners, made with `clip-path` or with four corner circles in the field colour, and no outline. Inside, with 56px padding, everything is centred and symmetrical like letterpress stationery. The two names, or the title, are set in a large italic serif at clamp(56px, 5.6vw, 88px) on two lines, staggered so line one sits left of centre and line two right. Between and beneath them, date, time and place appear as short lines at 15px in sentence case, separated by space and by one solid 10px diamond. The top row sits on the field above the card at 28px margins: a small monogram top-left, three text links centred, and the single action, a solid rectangular button in the ink colour, top-right.\",\n  \"mobile\": \"The card becomes full width minus 12px margins, starts 96px down and is still cropped by the bottom edge, with its scalloped top corners kept. The names stay on two lines at 12vw, centred without the stagger, and the details follow at 15px. The monogram sits top-left and the action button top-right on the field; the three links move onto the card's lower part, below the fold.\",\n  \"headline\": \"The two names or the title on two lines, up to about 12 characters per line, set as they would be printed on the card.\",\n  \"motion\": \"curtain-footer\",\n  \"seenIn\": [\n   \"opl-sarah-matt-wedding\"\n  ]\n },\n {\n  \"id\": \"card-over-dim-room\",\n  \"name\": \"Card over a dim room\",\n  \"archetype\": \"artefact\",\n  \"directions\": [\n   \"page-is-the-object\",\n   \"pinned-poster\",\n   \"dark-room\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A full-bleed, low-key photograph of the room fills the viewport, darkened with `filter: brightness(0.7)` so it reads as atmosphere. Centred over it is one square-cornered panel in a flat warm tone taken from the photograph: columns 4–10, about 55% of the width and 62% of the height, a filled programme card with 32px padding. Along its top edge the three words of the title are spread to the left, centre and right in bold condensed capitals at clamp(28px, 2.5vw, 38px); that line is the headline. Under it sit two left-aligned blocks in the same face and size, line-height 1.0: the facts (date, time, place) as three short lines, then one supporting sentence held to 30ch. Along the card's bottom edge: a credit at left in 14px, the single action as a solid rectangular button in the centre, one text link at right. There is no navigation outside the card. The card is `position: sticky`: as the page scrolls it shrinks with `transform: scale` toward the bottom-left corner and stays there as a ticket-sized stub while photographs of differing sizes pass on a flat ground.\",\n  \"mobile\": \"The photograph fills 100svh and the card sits centred at full width minus 16px margins, 70svh tall. The title words stack as a two-line heading at 9vw at the card's top-left. The facts and the supporting sentence follow at 5.2vw in the condensed face. The action button spans the card's bottom edge. On scroll the card shrinks to a 120px stub pinned bottom-left.\",\n  \"headline\": \"The event or venue name, three words at most and up to about 8 characters each, spread across the card's top edge; two lines on a phone.\",\n  \"motion\": \"pinned-story\",\n  \"seenIn\": [\n   \"opl-the-deep-end\"\n  ]\n },\n {\n  \"id\": \"tabbed-folder-stack\",\n  \"name\": \"Tabbed folder stack\",\n  \"archetype\": \"artefact\",\n  \"directions\": [\n   \"page-is-the-object\",\n   \"one-motif\",\n   \"colour-chapters\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A dark flat ground. A slim top row at 24px holds the wordmark dead centre and one text link far right at 15px. The headline is one centred line of heavy condensed capitals at clamp(96px, 10vw, 160px), spanning about 70% of the width, its cap line 110px from the top. Under it one supporting sentence in a serif at 20px, centred, max 46ch. From 51% of the height down the screen is a stack of five file folders: flat colour bands 86% of the viewport wide, centred, each offset 64px below the one behind so only a strip of the back four shows. Every folder has one trapezoid tab rising 40px from its top edge, cut with `clip-path: polygon()`, at its own horizontal position and in its own colour, holding one section name at 18px. The front folder is open and runs off the bottom edge; it carries the single action as a solid button at its top-left with 32px padding. Each folder links to its section and lends that section its ground colour. The tab shape returns as the button's top corners.\",\n  \"mobile\": \"The headline sits 96px down at 17vw on one line, or two at 15vw, centred, with the supporting sentence at 16px beneath. The folder stack starts at 48svh at full width: bands offset 52px, tabs 32px tall with names at 15px, staggered left, centre and right. The front folder runs off the bottom with the action button at full width inside it.\",\n  \"headline\": \"The name or a two-word statement on one line of up to about 12 characters at 10vw; two lines allowed on a phone.\",\n  \"motion\": \"index-preview\",\n  \"seenIn\": [\n   \"aww-mosbys-files\",\n   \"opl-medium-rare\"\n  ]\n },\n {\n  \"id\": \"striped-card-beside-room\",\n  \"name\": \"Striped card beside the room\",\n  \"archetype\": \"split\",\n  \"directions\": [\n   \"one-motif\",\n   \"page-is-the-object\",\n   \"split-stage\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"The viewport is split 50/50 with a 12px gap and 12px outer margins. The right half is one full-height photograph of the room, corners radiused 16px, `position: sticky` so it stays in view while the left half scrolls. The left half is a printed card: a flat paper-colour panel with the same 16px radius, and the subject's stripe (from its awning, label or ribbon) as the only ornament. Across the card's top runs a band 56px tall made of alternating bars of the single ink colour and paper, each bar 28px wide, built as a flex row of filled blocks. The same stripe returns as an 8px band above the footer and inside the button on hover. Under the band, centred: the wordmark about 300px wide, then a two-line headline in a light serif at clamp(40px, 3.6vw, 56px) in the ink colour, one supporting sentence at 17px held to 36ch, and the single action as a solid rectangular button. Three text links sit in one centred row at 15px, 28px above the card's bottom edge. One ink on paper; the photograph supplies every other colour.\",\n  \"mobile\": \"The photograph comes first at full width inside 12px margins, 48svh tall, with the 16px radius. The card follows and overlaps the photograph's bottom edge by 24px using a negative margin. Its striped band is 40px tall; below it the wordmark at 56% width, the headline at 8vw on two lines, the sentence and the button, all centred. The links wrap into the card's foot.\",\n  \"headline\": \"A warm two-line welcome of three to six words, up to about 18 characters per line at 3.6vw.\",\n  \"motion\": \"slow-crossfade\",\n  \"seenIn\": [\n   \"opl-le-petit-bleu\",\n   \"opl-zara-webb\"\n  ]\n },\n {\n  \"id\": \"giant-cropped-shape\",\n  \"name\": \"Giant cropped shape\",\n  \"archetype\": \"colour-field\",\n  \"directions\": [\n   \"one-motif\",\n   \"colour-chapters\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A plain ground with one flat shape at enormous scale. The shape is the simplest geometry found in the subject (a circle, a ring segment, a chamfered block, an arch), drawn in CSS or as a single inline SVG path and filled with the accent colour. It is about 120vh across and enters from the right, centred near 78% of the width and 55% of the height, so the top, right and bottom edges of the viewport crop it and its left boundary reaches column 7. If the subject has a true pair (two accounts, two modes), a second shape in a second flat colour overlaps the first by a quarter with `mix-blend-mode: multiply`. The headline sits on the bare ground on columns 1–6, vertically centred, flush left at 8% from the left edge: two lines at clamp(64px, 6.4vw, 100px), heavy weight, tracking -0.03em. Beneath it comes one supporting sentence at 19px, then the single action as a solid button cut to the same shape. A bold wordmark sits top-left at 32px; up to three text links sit top-right in the ground colour.\",\n  \"mobile\": \"The shape moves to the bottom: 130vw across, centred horizontally, its top at 56svh, cropped by the left, right and bottom edges. The headline sits above it at 11.5vw on two lines at a 16px margin, starting 15% down, with the sentence at 16px and the motif-shaped button beneath. Wordmark top-left; the links collapse to one word top-right.\",\n  \"headline\": \"Two lines of two or three words each, up to about 12 characters per line at 6.4vw.\",\n  \"motion\": \"shutter-image\",\n  \"seenIn\": [\n   \"opl-tara\",\n   \"opl-superlocal-2026\",\n   \"aww-sstr-friction-reduction\"\n  ]\n },\n {\n  \"id\": \"fragment-on-shaped-stage\",\n  \"name\": \"Fragment on a shaped stage\",\n  \"archetype\": \"split\",\n  \"directions\": [\n   \"product-performs\",\n   \"one-motif\",\n   \"colour-chapters\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A neutral ground. The headline occupies the upper-left third: two lines at clamp(52px, 5.2vw, 80px), medium weight, flush left on columns 1–6 at a 40px margin, starting 150px down. One supporting sentence at 18px, max 40ch, follows, then the single action as a small rectangular button. The rest of the screen belongs to one flat stage in a saturated colour: it spans columns 5–12, begins 42% down, and bleeds off the right and bottom edges. Its top-left corner is cut with the product's own shape using `clip-path` (a notch, a chamfer or a tab two columns wide), the only decoration on the page. On the stage, 56px in from its left and top edges, sits the main fragment of the interface at true size with labels at 13–15px, built in HTML and working: one panel or control about 620px wide, cropped by the bottom edge, never a whole window and never inside a browser or laptop frame. Mark its root with data-ui. Navigation is a plain row at 28px from the top: wordmark left and four text links right at 15px. Nothing overlaps the headline.\",\n  \"mobile\": \"The headline sits under the wordmark at 10vw on two lines, followed by the sentence at 16px and the button. The stage comes next at full width, bleeding off both sides and the bottom, its corner cut kept at 72px wide. The fragment sits 16px inside it at true size; if it is wider than the screen the right edge crops it rather than scaling it down.\",\n  \"headline\": \"A plain statement of what the product does in three to six words, two lines of up to about 16 characters each at 5.2vw.\",\n  \"motion\": \"shutter-image\",\n  \"seenIn\": [\n   \"opl-typewave\",\n   \"opl-vessa\",\n   \"opl-uni\"\n  ]\n },\n {\n  \"id\": \"control-reads-the-page\",\n  \"name\": \"Control that reads the page\",\n  \"archetype\": \"split\",\n  \"directions\": [\n   \"product-performs\",\n   \"quiet-instrument\",\n   \"dark-room\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A near-black or deep neutral ground split into two halves by tone alone: the right half is one step lighter than the left, and they meet at a clean vertical edge at 50%. Left half: a small logo mark top-left at a 40px margin, then two-thirds of empty ground, then everything else anchored bottom-left, 40px from the edges: a one-line headline at clamp(26px, 2.1vw, 32px) in medium weight, one supporting sentence at 17px in the softer ink held to 44ch, and the single action as a light rectangular button. Right half: one fragment of the product, centred, about 450px square, built in HTML and working. It is the product's defining control (a loupe, a picker, a dial, a field) and it acts on the page itself: it reads the real background colour, the real headline size or the pointer position and prints that value in its own readout at 13px. Mark its root with data-ui so the product's own radii and borders apply inside it. There is no navigation bar; one text link sits top-right at 15px.\",\n  \"mobile\": \"The halves stack as two tones. The fragment comes first: 78vw square, centred in the lighter block, which is 58svh tall, still live and reading the page under the visitor's finger. The darker block below holds the headline at 6.4vw on up to two lines, the sentence at 16px and the button, left-aligned at 20px. The logo mark sits top-left over the first block.\",\n  \"headline\": \"One plain line at 26–32px naming what the tool is, up to about 32 characters, wrapping to two lines on a phone.\",\n  \"motion\": \"masked-headline\",\n  \"seenIn\": [\n   \"opl-dabbit\"\n  ]\n },\n {\n  \"id\": \"controls-on-the-sentence\",\n  \"name\": \"Controls on the sentence\",\n  \"archetype\": \"type-poster\",\n  \"directions\": [\n   \"product-performs\",\n   \"sentence-as-layout\",\n   \"type-only-statement\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A dark flat ground with no logo bar: a 14px wordmark top-left and the single action as an underlined text link top-right, both 28px in. The headline is a two-line sentence, centred, at clamp(96px, 9vw, 150px), line-height 1.0, occupying the middle 64% of the width and sitting slightly above the midline. It is set in a variable font and it is the demonstration. Three small control chips from the product sit on top of the sentence, each about 300 by 80px with the product's true radius, a text label and a numeric readout: one above the first line near its left end, one overlapping the start of the second line, and a two-state switch at the lower right. They are tilted 2 to 4 degrees and filled solid, one step lighter than the ground. Each one works: dragging the first changes the headline's weight through `font-variation-settings`, the second changes its letter-spacing, the third toggles uppercase. Mark each chip's root with data-ui. One supporting sentence at 17px, max 40ch, is centred 72px under the headline. The bottom third of the screen stays empty.\",\n  \"mobile\": \"The sentence stays on two lines at 13.5vw, centred at 38% of the height. The three chips shrink to 200 by 60px and move off the letters: one above the sentence and two side by side beneath it, untilted and still live. The supporting sentence follows at 16px. The wordmark stays top-left and the action link top-right.\",\n  \"headline\": \"A two-line sentence of three to five words, up to about 11 characters per line at 9vw, that still reads when its weight and spacing change.\",\n  \"motion\": \"masked-headline\",\n  \"seenIn\": [\n   \"opl-dialkit\"\n  ]\n },\n {\n  \"id\": \"column-on-one-line\",\n  \"name\": \"Column on one line\",\n  \"archetype\": \"quiet-column\",\n  \"directions\": [\n   \"quiet-instrument\",\n   \"product-performs\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A warm off-white page that is more than 80% empty. Everything hangs on one vertical alignment 27% in from the left edge, the start of column 4; nothing is centred and nothing sits to its left. A small logo mark sits on that alignment 56px from the top. About 220px lower the column begins, only 380px wide: a two-line headline at 27px in medium weight, line-height 1.25; one supporting sentence at 15px in the softer ink, line-height 1.5; then, 28px below, the single action as a near-black rectangular button with 4px corners and one text link with an arrow beside it. A sign-in text link sits alone in the top-right corner at 14px; there is no navigation bar. At the bottom edge the first demonstration peeks in on the same alignment: a flat panel one step darker than the page, 368px wide, its top 90px visible, holding two real rows of the product's interface at true size with a visible pointer. Mark the panel's root with data-ui. The right half of the screen is blank on purpose, and nothing spans the full width until the footer.\",\n  \"mobile\": \"The alignment becomes the 24px left margin. The logo mark sits 32px from the top and the column starts at 30% of the height: headline at 24px on two lines, the sentence at 15px, then button and text link side by side. The demonstration panel spans the width between the margins and shows its top 120px above the fold. The sign-in link stays top-right.\",\n  \"headline\": \"A dry two-line statement at 27px, up to about 30 characters per line; it never grows larger at any width.\",\n  \"motion\": \"slow-crossfade\",\n  \"seenIn\": [\n   \"opl-rows\",\n   \"opl-lovably\"\n  ]\n },\n {\n  \"id\": \"single-object-on-plinth\",\n  \"name\": \"Single object on a plinth\",\n  \"archetype\": \"object-centre\",\n  \"directions\": [\n   \"quiet-instrument\",\n   \"hero-object\",\n   \"specimen-catalogue\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"blueprint\": \"An off-white screen that is about 80% empty and does not need to scroll. One photographed object stands dead centre: a studio shot on a plain background, shown 440px tall (about half the viewport height) whatever its width, with `mix-blend-mode: multiply` so its backdrop disappears into the page. It rests on a plinth, a rounded square 520px across filled one step lighter than the page and centred behind it, with no border. The wordmark sits top-left at a 56px margin in a heavy serif or grotesk, about 400px wide (28% of the viewport) and 80px tall; it is the only large type. Opposite it, top-right on the same margin and aligned to the wordmark's top, sits the one supporting sentence at 15px, right-aligned, max 36ch. Centred 40px under the plinth is the single action: a compact email field or button 240px wide with 8px corners. Further objects replace the first in the same position by crossfade, each scaled to the same visual mass. There is no navigation. Nothing else touches the edges, and the object never grows beyond half the viewport height.\",\n  \"mobile\": \"The wordmark sits top-left at 44vw wide with 20px margins and the supporting sentence drops beneath it at 14px. The plinth is 78vw square, centred at 54% of the height, with the object 44svh tall on it. The action sits 32px under the plinth, 40px in from each side. The screen stays mostly empty and the objects swap in place.\",\n  \"headline\": \"None beyond the name: the wordmark top-left, up to about 10 characters, is the only large type and the object is the statement.\",\n  \"motion\": \"slow-crossfade\",\n  \"seenIn\": [\n   \"opl-archiv\",\n   \"opl-humanoid-index\"\n  ]\n },\n {\n  \"id\": \"object-crops-three-edges\",\n  \"name\": \"Object cropped by three edges\",\n  \"archetype\": \"object-centre\",\n  \"directions\": [\n   \"hero-object\",\n   \"loud-flat-poster\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"blueprint\": \"A flat off-white or single bold colour field with no navigation bar: only a small wordmark top-right at 24px and the single action fixed bottom-right as a solid rectangular button. The left 60% of the screen is one object photographed on a plain background and scaled far past its container. Set the image to about 150% of the hero's height, rotate it 10 to 20 degrees and position it so the top, left and bottom edges of the viewport all crop it and only its right-hand third is fully inside; use `overflow: hidden` on the section and `mix-blend-mode: multiply` if the field is light. The headline fills the right half: two stacked lines of very bold lowercase at clamp(120px, 13vw, 210px), right-aligned 16px from the right edge, tracking -0.05em, line-height 0.86, vertically centred. It sits behind the object in the stacking order, so the object's right-hand contour tucks over the first one or two letters of each line. One supporting sentence at 18px, max 28ch, is right-aligned under the headline on columns 9–12. Nothing else is on the screen: no second image, no list.\",\n  \"mobile\": \"The object moves to the top: the image is 150vw wide, rotated, cropped by the top, left and right edges, and occupies the upper 52svh. The headline sits below it at 19vw on two lines, right-aligned at a 12px margin, its first line overlapped by the object's lower contour. The supporting sentence follows at 16px, right-aligned. The action button stays fixed bottom-right.\",\n  \"headline\": \"Two lines of one or two short words each, up to about 8 characters per line at 13vw, partly tucked behind the object.\",\n  \"motion\": \"shutter-image\",\n  \"seenIn\": [\n   \"opl-when-you-wish-upon-a-starboy\"\n  ]\n },\n {\n  \"id\": \"object-splits-the-headline\",\n  \"name\": \"Object splits the headline\",\n  \"archetype\": \"object-centre\",\n  \"directions\": [\n   \"hero-object\",\n   \"sentence-as-layout\",\n   \"dark-room\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"blueprint\": \"One deep, flat ground colour. The object, a low-key studio photograph whose background matches the ground, stands at dead centre, scaled to 66% of the viewport height and tilted about 8 degrees, with its base cropped by the bottom edge. The headline is split around it: line one is centred across the object's upper fifth and line two across its lower fifth, both at clamp(64px, 5.8vw, 92px), regular weight, spanning columns 2–11, so the object fills the gap where a paragraph would normally sit. The type lies above the object in the stacking order in the light ink, so every letter stays readable where it crosses. At the object's mid-height two small text blocks at 14px face each other: the supporting sentence far left on columns 1–2, and two short facts (size, price) far right on columns 11–12, right-aligned, each 32px from its edge. Wordmark top-left; three text links top-centre; the single action top-right as a small light rectangular tab, the only light solid on the screen. The lower corners stay dark and empty.\",\n  \"mobile\": \"The object is 54svh tall, centred, its base cropped by the bottom edge. Line one of the headline crosses its top at 11vw and line two its lower third at 11vw, both centred inside 16px margins. The side text blocks merge into one 15px sentence under the navigation. Wordmark top-left and the action tab top-right; the links collapse to one word.\",\n  \"headline\": \"A two-line statement of four to six words, up to about 16 characters per line at 5.8vw, with the object standing between the lines.\",\n  \"motion\": \"slow-crossfade\",\n  \"seenIn\": [\n   \"aww-zeroz-brand-site\",\n   \"aww-moto-finance\"\n  ]\n },\n {\n  \"id\": \"object-on-the-seam\",\n  \"name\": \"Object on the seam\",\n  \"archetype\": \"object-centre\",\n  \"directions\": [\n   \"hero-object\",\n   \"quiet-instrument\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"blueprint\": \"A white or very pale page organised by one change of tone. A square-cornered panel one step darker than the page (a flat pale blue-grey or warm grey) fills the top 44% of the viewport inside 12px margins; the page colour runs below it. The object, photographed on a plain background and blended with `mix-blend-mode: multiply`, straddles the seam between the two tones: it is about 62% of the viewport wide, starts at column 6 and runs off the right edge, with its upper half over the panel and its lower half over the page. Type is small and exact. The headline is two lines at 24px in medium weight, far left on columns 1–3 at a 32px margin, its first baseline resting exactly on the seam; the second line is set in the softer ink. One supporting sentence at 15px, max 34ch, sits 120px lower on the same margin with the single action as a small rectangular button under it. A plain top row inside the panel at 14px: wordmark left, three text links centred, one text link right.\",\n  \"mobile\": \"The tonal panel takes the top 46svh. The object is 120vw wide, centred on the seam and cropped by the right edge. The headline sits just under the seam at 22px on two lines at a 20px margin, with the sentence at 15px beneath and then the button. The wordmark sits top-left inside the panel; the links collapse to one word top-right.\",\n  \"headline\": \"Two short sentences at 24px, one per line and up to about 28 characters each, the second in the softer ink.\",\n  \"motion\": \"shutter-image\",\n  \"seenIn\": [\n   \"opl-aevion\"\n  ]\n },\n {\n  \"id\": \"statement-beside-specimen-mosaic\",\n  \"name\": \"Statement beside specimen mosaic\",\n  \"archetype\": \"mosaic\",\n  \"directions\": [\n   \"specimen-catalogue\",\n   \"split-stage\",\n   \"uneven-photographs\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"blueprint\": \"The viewport is split 50/50 by tone alone: the left half is the page ground, the right half a field one step darker, meeting at a clean vertical edge with no line. Left half: the wordmark at 22px sits top-left on a 32px margin; under it the statement at clamp(44px, 4.4vw, 68px), bold, tracking -0.04em, leading 1.0, top-left aligned and filling the upper 40% of the half. The lower part of this side stays empty except for one supporting sentence at 18px pinned bottom-left and the single action as a solid rectangle beside it. Right half: a loose mosaic of seven specimen tiles on a 4-column, 3-row grid with 14px gaps. Each tile is a flat palette colour at 3:4 holding one cut-out item, centred, object-fit: contain, mix-blend-mode: multiply. Five cells are left empty so the tiles stagger; one tile spans two columns and two rows; the rightmost column is cropped by the viewport edge. Two text links sit top-right over the darker field. The right half may be position: sticky while the left scrolls.\",\n  \"mobile\": \"The split becomes a stack. The statement comes first at 10.5vw on two lines inside 20px margins, the supporting sentence under it at 16px, then the action. Below, the darker field runs full width and the mosaic becomes two columns of tiles, the right column started 48px lower than the left; five tiles show and the last row is cropped by the bottom of the screen. Navigation is the wordmark and one link.\",\n  \"headline\": \"A 3-5 word statement of what is on offer, at most 28 characters so it holds two lines at 10.5vw on a phone.\",\n  \"motion\": \"shutter-image\",\n  \"seenIn\": [\n   \"aww-noho\"\n  ]\n },\n {\n  \"id\": \"specimen-wall-docked-panel\",\n  \"name\": \"Specimen wall, docked panel\",\n  \"archetype\": \"tiles\",\n  \"directions\": [\n   \"specimen-catalogue\",\n   \"dense-tiles\",\n   \"contact-sheet\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"blueprint\": \"There is no header and no display headline: the whole viewport is a wall of specimens. Square tiles of about 112px (7.8vw) with 8px gaps fill the screen edge to edge in eight rows; alternate rows shift half a tile sideways so the wall reads as brickwork, and tiles at every edge are cropped by the viewport (overflow: hidden on the section). Each tile is a flat fill, rotating through three palette colours, holding one cut-out item at 60% of the tile, centred, with mix-blend-mode: multiply on light fills. A solid panel in the ink colour, 800px wide (columns 4-9) and about 170px tall with square corners, is docked at the bottom centre, 24px above the bottom edge, covering the tiles behind it. Inside, on 28px padding: the sentence that says what this is at 24px semibold on the left across two lines, the single action as a filled rectangle in the paper colour on the right, and beneath them a row holding the wordmark and four text links at 15px. Nothing else overlays the wall.\",\n  \"mobile\": \"Tiles become 22vw squares with 6px gaps, four and a half per row, still offset as brickwork and cropped at both sides. The panel turns into a full-width block fixed to the bottom of the first screen, about a third of its height: the sentence at 6vw on two lines, the action full width beneath it, the wordmark and links in one wrapped row at 14px. The wall fills everything above.\",\n  \"headline\": \"No display line: one plain sentence of up to 56 characters inside the panel names what the items are.\",\n  \"motion\": \"index-preview\",\n  \"seenIn\": [\n   \"opl-smallbits\",\n   \"opl-beige-force\"\n  ]\n },\n {\n  \"id\": \"single-specimen-name-list\",\n  \"name\": \"Single specimen with name list\",\n  \"archetype\": \"object-centre\",\n  \"directions\": [\n   \"specimen-catalogue\",\n   \"borrowed-category\",\n   \"hero-object\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"blueprint\": \"Borrowed from a museum plinth. A calm light ground with roughly 70% left empty. The wordmark is set large for a logo, about 28% of the viewport wide (clamp(64px, 6vw, 92px), heavy serif or grotesk), top-left on a 56px margin; one sentence of description at 15px sits top-right on the same margin, its first line aligned to the top of the wordmark. Dead centre stands one specimen: a flat tile in a palette colour, 400px wide and 460px tall (columns 5-8) with a 16px radius, holding a single cut-out item at about 80% of the tile height, object-fit: contain. Left of the tile, in columns 2-4, a vertical list of item names is right-aligned towards it: the selected name in full ink at 20px, the names above and below stepping down in size and opacity (18, 16, 14px; 60, 35, 15%). Choosing a name swaps the item and the tile colour. Below the tile, centred: the item's one-line fact at 14px, then the single action, a filled rectangle 240px wide. Three text links sit bottom-left at 14px.\",\n  \"mobile\": \"The wordmark sits top-left at 11vw with the description sentence beneath it at 15px. The tile takes the full width inside 20px margins at 4:5, starting at 30% of the height. The name list becomes one horizontal row under the tile that scrolls sideways with scroll-snap, the selected name centred in full ink at 18px. The action sits full width at the bottom of the screen; the links move to the footer.\",\n  \"headline\": \"The name itself as an oversized wordma\n\n<!-- [TRUNCATED AT 50KB] -->","skills/taste-skill/library/motions.json":"[\n {\n  \"id\": \"masked-headline\",\n  \"name\": \"Masked headline\",\n  \"description\": \"On load, each line of the headline rises from behind its own baseline, about 900ms with a strong ease-out, the second line 110ms after the first; the supporting sentence and the action then fade up together. Nothing else on the page performs. Because headlines are two lines at most, you author the line breaks and wrap each line yourself. Recipe: 'Masked line reveal' in references/motion.md.\"\n },\n {\n  \"id\": \"shutter-image\",\n  \"name\": \"Shutter image\",\n  \"description\": \"The one hero or showcase image opens from an edge with a clip-path over about 1.1 seconds while the picture inside settles from 1.12 scale to rest. Use it once, on the image that matters most; later images simply are there. Recipe: 'Image shutter' in references/motion.md.\"\n },\n {\n  \"id\": \"scaling-wordmark\",\n  \"name\": \"Scaling wordmark\",\n  \"description\": \"The giant name responds to the scroll: as the first screen leaves, the wordmark scales down a few percent (or grows from 0.94 to 1 as the footer arrives) on a scroll-linked timeline, so the monument feels heavy. Travel stays under 8%. Static fallback where scroll timelines are unsupported. Recipe: 'Scroll-linked progress' in references/motion.md, animating `scale`.\"\n },\n {\n  \"id\": \"pinned-story\",\n  \"name\": \"Pinned story\",\n  \"description\": \"One element holds its place with `position: sticky` (a title, a frame, a product fragment) while the items that belong to it scroll past or swap inside it. The page's ordinary scrolling does the work; nothing is hijacked. Hold it for about one screen per step and three screens at most, two held stages per page at most, with a line of text on every held screen. Recipe: 'Pinned story' in references/motion.md.\"\n },\n {\n  \"id\": \"index-preview\",\n  \"name\": \"Index with preview\",\n  \"description\": \"Rows of text are the navigation through the work; pointing at a row brings up its image in one fixed frame and dims the other rows. On touch screens each row shows its image inline instead. Fast and exact (about 240ms crossfade), no lag behind the pointer. Recipe: 'Index with preview, anchored to the row' in references/motion.md.\"\n },\n {\n  \"id\": \"curtain-footer\",\n  \"name\": \"Curtain footer\",\n  \"description\": \"The page content slides up like a sheet to uncover the footer waiting beneath it, so the last screen is revealed rather than scrolled to. Build with a sticky footer at the bottom and a main element with its own background and a higher stacking order. No JavaScript.\"\n },\n {\n  \"id\": \"slow-crossfade\",\n  \"name\": \"Slow crossfade\",\n  \"description\": \"The principal photograph quietly changes: three or four images of the same framing crossfade over about 1.6 seconds, holding five to six seconds each, or the fixed image changes when its matching section arrives. It should feel like light shifting in a room. Pause when the tab is hidden; under reduced motion show only the first image.\"\n },\n {\n  \"id\": \"edge-marquee\",\n  \"name\": \"Edge-to-edge marquee\",\n  \"description\": \"One line of very large type travels sideways across the full width at a slow constant speed, as a band between two sections or as the closing statement. Linear timing, duplicated content for a seamless loop, paused on hover and under reduced motion. One marquee per page, carrying real words (the name, the claim), never a list of buzzwords.\"\n },\n {\n  \"id\": \"drag-row\",\n  \"name\": \"Drag row\",\n  \"description\": \"A row of large items wider than the screen that the visitor pulls sideways: native horizontal scrolling with scroll snapping, the first item aligned to the page margin and the last allowed to run off the edge so the row visibly continues. No carousel library, no arrows, no dots.\"\n },\n {\n  \"id\": \"colour-on-scroll\",\n  \"name\": \"Colour by chapter\",\n  \"description\": \"Each chapter is its own full-bleed field of one palette colour, so the ground changes exactly at section edges as you scroll, never as a global recolouring of the screen. The only movement: the fixed header (or the one pinned element) takes the ink of the chapter beneath it, switching with a 300ms colour transition as each edge passes under it. Do not drive the page background from an observer: in blind tests a page recoloured mid-section, with a paragraph sitting on two colours, read as broken twice.\"\n },\n {\n  \"id\": \"stillness\",\n  \"name\": \"Stillness\",\n  \"description\": \"No showpiece. The page is simply there, instantly, and the discipline is the statement. Motion is limited to exact feedback: a 140ms press on the button, a 180ms colour change on links, focus rings that appear without delay. Do not add a load animation or scroll reveals to this direction.\"\n },\n {\n  \"id\": \"opening-window\",\n  \"name\": \"Opening window\",\n  \"description\": \"A type screen hands over to the one great photograph: the picture first shows as a window about 45% of the width in the middle of a held stage and opens to full-bleed over about one screen of scroll, while the image inside settles from 1.15 scale. Scroll-linked and linear, so the reader sets the pace; it is fully open after three quarters of the hold and rests a moment before the page moves on. Use it once, for the picture that carries the subject. Where scroll timelines are unsupported, or under reduced motion, the picture is simply a full-bleed screen. Recipe: 'Opening window' in references/motion.md.\"\n },\n {\n  \"id\": \"ink-fill\",\n  \"name\": \"Ink-fill statement\",\n  \"description\": \"One statement of three to five lines at 32px or more starts at 45% ink and fills to full ink line by line as it rises from three quarters of the way down the screen to just past half way, so the reading pace follows the scroll. Every word is readable before it fills; the fill only sets the rhythm. Once per page, never on body copy, never on a headline the visitor needs at once. Full ink without scroll timelines or under reduced motion. Recipe: 'Ink fill' in references/motion.md.\"\n },\n {\n  \"id\": \"sheet-over\",\n  \"name\": \"Sheet over a held picture\",\n  \"description\": \"A full-bleed photograph holds its place for one screen and the next chapter, an opaque sheet in the page ground carrying its heading at the top edge, slides up over it like a page being turned. The chapter change is read, not just seen, and nothing is hijacked: the photograph is a 100svh figure with position: sticky; top: 0, followed by a section with its own background and a higher stacking order. Hold for one screen at most, use it at one or two chapter changes, and give each held photograph a caption so the held screen carries a line of text.\"\n },\n {\n  \"id\": \"sideways-gallery\",\n  \"name\": \"Sideways gallery\",\n  \"description\": \"A short set of pictures (eight or fewer: rooms, kitchens, pieces) moves sideways while the vertical scroll holds the stage, one pixel of scroll for one pixel of travel, and the hold ends the moment the last picture reaches the margin. Only on wide screens with motion allowed and only when the row is under three screens long; phones, reduced motion and longer rows get the native drag row with snapping. Focusing a link scrolls its picture into view, and the only copy of a call to action never sits inside the moving row. Recipe: 'Sideways gallery' in references/motion.md.\"\n },\n {\n  \"id\": \"pushed-line\",\n  \"name\": \"Pushed line\",\n  \"description\": \"One line of very large type, the name or the claim, is pushed sideways by the scroll rather than by a clock: it travels from 12% right to 12% left of its place while it crosses the screen, linear and locked to the scrollbar, and reads whole at the middle of its run. One per page, never across running text, and the words must never be cropped at the moment the line sits in the middle of the screen. Build with animation-timeline: view() on the line and a translateX keyframe; static where scroll timelines are unsupported and under reduced motion.\"\n },\n {\n  \"id\": \"rolling-figures\",\n  \"name\": \"Rolling figures\",\n  \"description\": \"For a page whose case is a handful of numbers (a report, a fund, a practice with a founding year): three or four figures at display size roll each digit up to its value once as they come into view, about 1.1 seconds on a strong ease-out, the columns 70ms apart. Tabular figures, the real number kept in the text for screen readers and search, never in running text and never for a value that changes after load. Set at its value under reduced motion. Recipe: 'Rolling figures' in references/motion.md.\"\n },\n {\n  \"id\": \"carried-picture\",\n  \"name\": \"Carried picture\",\n  \"description\": \"Between the index and a case page, the picture the visitor clicked travels into place as the new page's hero while the old page fades out in 200ms and the new one rises in, all within 480ms, using the browser's own cross-document view transitions with no library and no full-screen curtain. Give the card picture and the hero the same view-transition-name; each name appears once per page. Browsers without view transitions simply navigate; reduced motion turns it off. Recipe: 'Page to page' in references/motion.md.\"\n }\n]\n","skills/taste-skill/library/palettes.json":"[\n {\n  \"id\": \"white-link-blue\",\n  \"name\": \"Sheet and biro\",\n  \"tags\": [\n   \"light-neutral\",\n   \"mono-accent\"\n  ],\n  \"bg\": \"#ffffff\",\n  \"surface\": \"#f4f4f4\",\n  \"ink\": \"#111111\",\n  \"muted\": \"#6b6b6b\",\n  \"accent\": \"#1a4be0\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#111111\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"White holds the whole page with black type, one grey for secondary lines and a pale grey step for tiles and inputs; the footer may invert to black. Blue is the colour of text links and the one button, and nothing else is tinted.\",\n  \"seenIn\": [\n   \"opl-shawn-golden\",\n   \"opl-lovably\",\n   \"aww-bleibtgleich26\"\n  ]\n },\n {\n  \"id\": \"cool-white-slate\",\n  \"name\": \"Frost and slate\",\n  \"tags\": [\n   \"light-neutral\"\n  ],\n  \"bg\": \"#f7f9fa\",\n  \"surface\": \"#ecf0f2\",\n  \"ink\": \"#1f3038\",\n  \"muted\": \"#5d6b72\",\n  \"accent\": \"#0d7480\",\n  \"accentInk\": \"#ffffff\",\n  \"note\": \"Cool white and one paler blue-grey step hold everything, with type in dark slate instead of black. Teal appears once per screen at most, as the primary button or one small detail beside the product photograph.\",\n  \"seenIn\": [\n   \"opl-aevion\",\n   \"aww-cominvi\"\n  ]\n },\n {\n  \"id\": \"rose-grey-green\",\n  \"name\": \"Rose grey, green\",\n  \"tags\": [\n   \"light-neutral\"\n  ],\n  \"bg\": \"#ebe5e3\",\n  \"surface\": \"#e1dad7\",\n  \"ink\": \"#2b2622\",\n  \"muted\": \"#6a615d\",\n  \"accent\": \"#0f7d45\",\n  \"accentInk\": \"#ffffff\",\n  \"note\": \"A single rosy grey covers the page from top to bottom with brown-black text and grey secondary lines; images are kept greyscale. Green appears only on the current-page link and on one button in the footer.\",\n  \"seenIn\": [\n   \"opl-the-queue\"\n  ]\n },\n {\n  \"id\": \"paper-grey-brass\",\n  \"name\": \"Newsprint and brass\",\n  \"tags\": [\n   \"light-neutral\"\n  ],\n  \"bg\": \"#e8e8e3\",\n  \"surface\": \"#dcdcd6\",\n  \"ink\": \"#181715\",\n  \"muted\": \"#63625c\",\n  \"accent\": \"#bfb21a\",\n  \"accentInk\": \"#181715\",\n  \"fields\": [\n   {\n    \"bg\": \"#181715\",\n    \"ink\": \"#e8e8e3\"\n   }\n  ],\n  \"note\": \"Warm paper grey with near-black type holds the upper page, then whole sections flip to near-black with paper-grey type; no section is tinted. Brass yellow marks one small detail per screen, such as the button or a single word.\",\n  \"seenIn\": [\n   \"aww-monolog\"\n  ]\n },\n {\n  \"id\": \"stone-blueprint\",\n  \"name\": \"Stone and blueprint\",\n  \"tags\": [\n   \"light-neutral\"\n  ],\n  \"bg\": \"#dfdedb\",\n  \"surface\": \"#d3d2ce\",\n  \"ink\": \"#26251e\",\n  \"muted\": \"#5f5d55\",\n  \"accent\": \"#2456d6\",\n  \"accentInk\": \"#ffffff\",\n  \"note\": \"Stone paper carries the whole page with near-black and grey text. One image at a time is printed in the accent blue as its only ink, and the same blue fills the single button.\",\n  \"seenIn\": [\n   \"opl-compile\"\n  ]\n },\n {\n  \"id\": \"white-navy-tab\",\n  \"name\": \"Navy on white\",\n  \"tags\": [\n   \"light-neutral\",\n   \"photographic-neutral\"\n  ],\n  \"bg\": \"#ffffff\",\n  \"surface\": \"#f4f4f2\",\n  \"ink\": \"#1f2b4d\",\n  \"muted\": \"#6a7186\",\n  \"accent\": \"#f7941d\",\n  \"accentInk\": \"#1f2b4d\",\n  \"fields\": [\n   {\n    \"bg\": \"#05070a\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#e3e1dc\",\n    \"ink\": \"#1f2b4d\"\n   }\n  ],\n  \"note\": \"Pure white pages with navy type sit between full-bleed photographs, opening on near-black and closing on a warm grey footer. Tangerine is one small tab or button, never larger than a thumbnail.\",\n  \"seenIn\": [\n   \"aww-white-desert\",\n   \"aww-realevate\"\n  ]\n },\n {\n  \"id\": \"three-stones\",\n  \"name\": \"Three stones\",\n  \"tags\": [\n   \"light-neutral\",\n   \"photographic-neutral\"\n  ],\n  \"bg\": \"#eeecea\",\n  \"surface\": \"#e4e1dd\",\n  \"ink\": \"#333231\",\n  \"muted\": \"#6b6763\",\n  \"accent\": \"#5c6b54\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#cdc3b6\",\n    \"ink\": \"#333231\"\n   }\n  ],\n  \"note\": \"Three close stone tones share the interface: the lightest for the page, the middle one for panels, the darkest for a single band, all with charcoal type. Saturated colour is left to the photographs and their backdrops; the grey-green fills the button only.\",\n  \"seenIn\": [\n   \"aww-noho\",\n   \"aww-vero-new-york\"\n  ]\n },\n {\n  \"id\": \"putty-black-teal\",\n  \"name\": \"Putty and black\",\n  \"tags\": [\n   \"light-neutral\",\n   \"photographic-neutral\"\n  ],\n  \"bg\": \"#dedad3\",\n  \"surface\": \"#d3cec6\",\n  \"ink\": \"#0a0a0a\",\n  \"muted\": \"#5c5852\",\n  \"accent\": \"#256f82\",\n  \"accentInk\": \"#ffffff\",\n  \"note\": \"Warm putty covers the page and pure black handles all type and the main shapes. The only tint in the interface is teal, used for the one button or a single marker placed near the photographs.\",\n  \"seenIn\": [\n   \"aww-colonia-zacamil\",\n   \"opl-archiv\"\n  ]\n },\n {\n  \"id\": \"moss-sand\",\n  \"name\": \"Sand and moss\",\n  \"tags\": [\n   \"light-neutral\",\n   \"earth\"\n  ],\n  \"bg\": \"#ddd6c6\",\n  \"surface\": \"#d2cab8\",\n  \"ink\": \"#2a2a26\",\n  \"muted\": \"#59574e\",\n  \"accent\": \"#4f6238\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#3f5a2a\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"Sand grey holds the page with charcoal type, and one deep leaf-green band may close it. Moss green is reserved for buttons; brighter greens and blues arrive only through photographs.\",\n  \"seenIn\": [\n   \"opl-vestris\",\n   \"aww-izanami\"\n  ]\n },\n {\n  \"id\": \"green-mat-chocolate\",\n  \"name\": \"Bone, green, chocolate\",\n  \"tags\": [\n   \"light-neutral\",\n   \"earth\"\n  ],\n  \"bg\": \"#e5e1d8\",\n  \"surface\": \"#dad5ca\",\n  \"ink\": \"#2a1d17\",\n  \"muted\": \"#6b5b51\",\n  \"accent\": \"#456f3a\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#456f3a\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"Bone ground with chocolate-brown text takes most of the page. The green is spent on one large flat block, about a third of a screen, and on the button; all other colour comes from photographs.\",\n  \"seenIn\": [\n   \"opl-davesocozy\",\n   \"opl-mat\"\n  ]\n },\n {\n  \"id\": \"lunar-grey-bronze\",\n  \"name\": \"Lunar and bronze\",\n  \"tags\": [\n   \"dark-neutral\"\n  ],\n  \"bg\": \"#111111\",\n  \"surface\": \"#1c1c1c\",\n  \"ink\": \"#f2f2f2\",\n  \"muted\": \"#8f8f8f\",\n  \"accent\": \"#a08672\",\n  \"accentInk\": \"#111111\",\n  \"note\": \"Soft black holds the page with panels one step lighter, white text and grey secondary lines, so photographs supply all the colour. Muted bronze goes on small markers and the one button only.\",\n  \"seenIn\": [\n   \"aww-21-hrs-on-the-moon\",\n   \"opl-dialkit\",\n   \"opl-lorenzo-bocchi-photography\"\n  ]\n },\n {\n  \"id\": \"blue-black-cornflower\",\n  \"name\": \"Night and cornflower\",\n  \"tags\": [\n   \"dark-neutral\"\n  ],\n  \"bg\": \"#0a0d14\",\n  \"surface\": \"#131824\",\n  \"ink\": \"#e9edf3\",\n  \"muted\": \"#8891a1\",\n  \"accent\": \"#5a9bfc\",\n  \"accentInk\": \"#0a0d14\",\n  \"note\": \"Blue-black ground and slate panels with silver-white text fill the page; no section changes colour. Cornflower blue marks the buttons and at most one word in a heading.\",\n  \"seenIn\": [\n   \"opl-viewport-2\",\n   \"aww-moto-finance\",\n   \"opl-rafael-derolez-2026\"\n  ]\n },\n {\n  \"id\": \"green-black-bone\",\n  \"name\": \"Green-black and bone\",\n  \"tags\": [\n   \"dark-neutral\",\n   \"earth\"\n  ],\n  \"bg\": \"#161c1a\",\n  \"surface\": \"#1f2725\",\n  \"ink\": \"#e3e2da\",\n  \"muted\": \"#8e948d\",\n  \"accent\": \"#9fc7b8\",\n  \"accentInk\": \"#161c1a\",\n  \"note\": \"Bone type on green-black from top to bottom, with panels and drawn details barely lighter than the ground so photographs supply the colour. Pale jade is for the booking or contact button alone.\",\n  \"seenIn\": [\n   \"opl-kereliott\",\n   \"aww-lama-lama-2\"\n  ]\n },\n {\n  \"id\": \"black-crimson\",\n  \"name\": \"Black and crimson\",\n  \"tags\": [\n   \"dark-neutral\",\n   \"mono-accent\"\n  ],\n  \"bg\": \"#0a0a0a\",\n  \"surface\": \"#151515\",\n  \"ink\": \"#efefef\",\n  \"muted\": \"#8c8c8c\",\n  \"accent\": \"#b11226\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#efefef\",\n    \"ink\": \"#0a0a0a\"\n   }\n  ],\n  \"note\": \"Black with off-white text and mid-grey texture takes nearly the whole page, and the last sections may invert to off-white with black type. Deep crimson is scattered sparingly: a few characters in a heading, a slider fill, the one button.\",\n  \"seenIn\": [\n   \"opl-textmode-overlay\"\n  ]\n },\n {\n  \"id\": \"forest-pale-lime\",\n  \"name\": \"Forest and lime\",\n  \"tags\": [\n   \"dark-neutral\",\n   \"earth\"\n  ],\n  \"bg\": \"#0f1f10\",\n  \"surface\": \"#162a17\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#9aa39a\",\n  \"accent\": \"#c6f19d\",\n  \"accentInk\": \"#0f1f10\",\n  \"fields\": [\n   {\n    \"bg\": \"#000000\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#ffffff\",\n    \"ink\": \"#0f1f10\"\n   }\n  ],\n  \"note\": \"Forest green, black and white sections alternate, with forest green holding the most; photographs stay in moss greens and stone browns. Pale lime sits on small squares only, such as arrow buttons and the closing wordmark.\",\n  \"seenIn\": [\n   \"aww-alethia\"\n  ]\n },\n {\n  \"id\": \"charcoal-room-sage\",\n  \"name\": \"Charcoal and sage\",\n  \"tags\": [\n   \"dark-neutral\",\n   \"photographic-neutral\"\n  ],\n  \"bg\": \"#1c1c1c\",\n  \"surface\": \"#262626\",\n  \"ink\": \"#f1f1ef\",\n  \"muted\": \"#9a9b96\",\n  \"accent\": \"#8fa68e\",\n  \"accentInk\": \"#1c1c1c\",\n  \"fields\": [\n   {\n    \"bg\": \"#c8c5ba\",\n    \"ink\": \"#1c1c1c\"\n   }\n  ],\n  \"note\": \"Charcoal holds the page with off-white text, and one section may flip to a pale concrete tone with dark text. Colour comes from the photographs; grey sage is used for the single button and the active state of a control.\",\n  \"seenIn\": [\n   \"opl-transport\",\n   \"opl-amanda-guo-design\"\n  ]\n },\n {\n  \"id\": \"warm-black-gold\",\n  \"name\": \"Warm black, gold\",\n  \"tags\": [\n   \"dark-neutral\",\n   \"photographic-neutral\"\n  ],\n  \"bg\": \"#0c0a08\",\n  \"surface\": \"#181512\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#8f8a84\",\n  \"accent\": \"#c9a45a\",\n  \"accentInk\": \"#0c0a08\",\n  \"note\": \"Warm near-black fills the page and photographs sit bright against it, with pure white small type; panels warm to a brown-black. Gold is for one text link or small button per screen, never a field.\",\n  \"seenIn\": [\n   \"aww-cipher\",\n   \"opl-hebbia\"\n  ]\n },\n {\n  \"id\": \"graphite-safety-orange\",\n  \"name\": \"Graphite and orange\",\n  \"tags\": [\n   \"mono-accent\",\n   \"dark-neutral\"\n  ],\n  \"bg\": \"#18191b\",\n  \"surface\": \"#222427\",\n  \"ink\": \"#eff0f1\",\n  \"muted\": \"#9c9ea3\",\n  \"accent\": \"#ff4a1f\",\n  \"accentInk\": \"#18191b\",\n  \"fields\": [\n   {\n    \"bg\": \"#eff0f1\",\n    \"ink\": \"#18191b\"\n   }\n  ],\n  \"note\": \"Graphite and cool light-grey sections alternate, graphite taking about two thirds, and photographs are desaturated so nothing competes. Safety orange marks the buttons, one thick solid bar across the top of the page and the highlighted item in a list or chart.\",\n  \"seenIn\": [\n   \"aww-sstr-friction-reduction\",\n   \"aww-boc-studio\",\n   \"aww-dragonfly-redux\"\n  ]\n },\n {\n  \"id\": \"soot-pale-lime\",\n  \"name\": \"Soot and lime\",\n  \"tags\": [\n   \"mono-accent\",\n   \"dark-neutral\"\n  ],\n  \"bg\": \"#0f0f0f\",\n  \"surface\": \"#1a1a1a\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#8f8f8f\",\n  \"accent\": \"#dafa9c\",\n  \"accentInk\": \"#0f0f0f\",\n  \"fields\": [\n   {\n    \"bg\": \"#ffffff\",\n    \"ink\": \"#0f0f0f\"\n   },\n   {\n    \"bg\": \"#dafa9c\",\n    \"ink\": \"#0f0f0f\"\n   }\n  ],\n  \"note\": \"A soot-black opening and close bracket white middle sections, all in black, white and grey. Pale lime is the single action colour: every button, and at most one headline set in it on the dark ground.\",\n  \"seenIn\": [\n   \"opl-builders-table\",\n   \"aww-made-with-gsap-1\",\n   \"aww-hilden-kaira\"\n  ]\n },\n {\n  \"id\": \"plum-black-pink\",\n  \"name\": \"Plum-black and pink\",\n  \"tags\": [\n   \"mono-accent\",\n   \"dark-neutral\"\n  ],\n  \"bg\": \"#0d060b\",\n  \"surface\": \"#1b0e17\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#9a8f97\",\n  \"accent\": \"#ff488b\",\n  \"accentInk\": \"#0d060b\",\n  \"fields\": [\n   {\n    \"bg\": \"#470c35\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#ffffff\",\n    \"ink\": \"#101421\"\n   }\n  ],\n  \"note\": \"Near-black and plum at the top and bottom bracket a white middle with navy-black text. Hot pink is reserved for primary buttons, bars in charts and map markers; it never fills a section.\",\n  \"seenIn\": [\n   \"aww-cerebrium\"\n  ]\n },\n {\n  \"id\": \"white-signal-red\",\n  \"name\": \"Signal red, white\",\n  \"tags\": [\n   \"mono-accent\"\n  ],\n  \"bg\": \"#ffffff\",\n  \"surface\": \"#f2f2f2\",\n  \"ink\": \"#0a0a0a\",\n  \"muted\": \"#6b6b6b\",\n  \"accent\": \"#d92b21\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#000000\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"White ground, black text and paper grey for filled panels, with one full black band allowed. Signal red is the only colour in the interface: one word in a headline, a few solid blocks, or the button.\",\n  \"seenIn\": [\n   \"opl-rsquad\",\n   \"aww-serotoninn\",\n   \"opl-estacion-venenta\"\n  ]\n },\n {\n  \"id\": \"white-mint-tiles\",\n  \"name\": \"Greys and mint\",\n  \"tags\": [\n   \"mono-accent\"\n  ],\n  \"bg\": \"#ffffff\",\n  \"surface\": \"#f3f3f3\",\n  \"ink\": \"#232323\",\n  \"muted\": \"#6e6e6e\",\n  \"accent\": \"#a1ffcb\",\n  \"accentInk\": \"#232323\",\n  \"fields\": [\n   {\n    \"bg\": \"#a1ffcb\",\n    \"ink\": \"#232323\"\n   },\n   {\n    \"bg\": \"#232323\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"White, near-black and two greys fill a board of flat tiles. Mint floods a few whole tiles (one statement, one figure, the closing call to action) and appears nowhere else.\",\n  \"seenIn\": [\n   \"aww-aspen-search\"\n  ]\n },\n {\n  \"id\": \"cool-grey-cobalt\",\n  \"name\": \"Cool grey, cobalt\",\n  \"tags\": [\n   \"mono-accent\"\n  ],\n  \"bg\": \"#eef0f3\",\n  \"surface\": \"#e2e5ea\",\n  \"ink\": \"#0b0c0e\",\n  \"muted\": \"#5d6470\",\n  \"accent\": \"#1f2de6\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#1f2de6\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"Cool pale grey holds the page with near-black type and nothing else tinted. Cobalt starts as the button and one highlighted sentence, takes one whole section as a flat field with white text, then returns as a single button block.\",\n  \"seenIn\": [\n   \"opl-vessa\",\n   \"opl-specia1ne\",\n   \"opl-brikkenco\"\n  ]\n },\n {\n  \"id\": \"offwhite-bottle-yellow\",\n  \"name\": \"Bottle ink, yellow\",\n  \"tags\": [\n   \"mono-accent\"\n  ],\n  \"bg\": \"#f7f7f7\",\n  \"surface\": \"#ebebeb\",\n  \"ink\": \"#0d2a1c\",\n  \"muted\": \"#5f6b64\",\n  \"accent\": \"#f6e016\",\n  \"accentInk\": \"#0d2a1c\",\n  \"fields\": [\n   {\n    \"bg\": \"#f6e016\",\n    \"ink\": \"#0d2a1c\"\n   }\n  ],\n  \"note\": \"Off-white ground with all type in a near-black bottle green instead of black. Yellow is the only saturated note: the button or one small object on most screens, and one later section that turns fully yellow.\",\n  \"seenIn\": [\n   \"aww-leo-parpeix-portfolio-2026\",\n   \"opl-wild-as\"\n  ]\n },\n {\n  \"id\": \"teal-on-paper\",\n  \"name\": \"Teal on paper\",\n  \"tags\": [\n   \"two-tone\"\n  ],\n  \"bg\": \"#f7f9f8\",\n  \"surface\": \"#ebf0ee\",\n  \"ink\": \"#06525c\",\n  \"muted\": \"#2f737d\",\n  \"accent\": \"#06525c\",\n  \"accentInk\": \"#f7f9f8\",\n  \"fields\": [\n   {\n    \"bg\": \"#06525c\",\n    \"ink\": \"#f7f9f8\"\n   }\n  ],\n  \"note\": \"Cool white paper and a single teal used for every word, shape and button, with no black anywhere. The accent is that same teal filled solid, for the button and for one inverted band with paper-coloured type.\",\n  \"seenIn\": [\n   \"opl-le-petit-bleu\"\n  ]\n },\n {\n  \"id\": \"navy-pink\",\n  \"name\": \"Navy and pink\",\n  \"tags\": [\n   \"two-tone\",\n   \"single-field\"\n  ],\n  \"bg\": \"#1a2039\",\n  \"surface\": \"#212846\",\n  \"ink\": \"#f9a3c0\",\n  \"muted\": \"#b9879c\",\n  \"accent\": \"#f9a3c0\",\n  \"accentInk\": \"#1a2039\",\n  \"note\": \"One navy field runs the entire page. Pink does everything else, from the name and headings to body text, and fills one solid button.\",\n  \"seenIn\": [\n   \"aww-trevor-noah\"\n  ]\n },\n {\n  \"id\": \"blush-aubergine\",\n  \"name\": \"Blush and aubergine\",\n  \"tags\": [\n   \"two-tone\"\n  ],\n  \"bg\": \"#edccbe\",\n  \"surface\": \"#e8c2b2\",\n  \"ink\": \"#351a2b\",\n  \"muted\": \"#6c4857\",\n  \"accent\": \"#351a2b\",\n  \"accentInk\": \"#edccbe\",\n  \"fields\": [\n   {\n    \"bg\": \"#351a2b\",\n    \"ink\": \"#edccbe\"\n   }\n  ],\n  \"note\": \"Blush pink and dark aubergine alternate as full fields and serve as each other's text colour, in roughly equal shares. There is no third colour: the button is a solid block of whichever of the two is not the ground.\",\n  \"seenIn\": [\n   \"aww-house-of-honey-1\",\n   \"opl-sarah-matt-wedding\"\n  ]\n },\n {\n  \"id\": \"cobalt-on-sand\",\n  \"name\": \"Cobalt on sand\",\n  \"tags\": [\n   \"two-tone\"\n  ],\n  \"bg\": \"#e6dbc7\",\n  \"surface\": \"#ddd0b9\",\n  \"ink\": \"#062b8a\",\n  \"muted\": \"#3a5aa8\",\n  \"accent\": \"#062b8a\",\n  \"accentInk\": \"#e6dbc7\",\n  \"note\": \"Sand paper and one cobalt do everything: text, drawings and solid shapes are all the same blue. The button is a cobalt block with sand-coloured type, and no black or second hue is used.\",\n  \"seenIn\": [\n   \"aww-illoca\"\n  ]\n },\n {\n  \"id\": \"oxblood-grey\",\n  \"name\": \"Oxblood and grey\",\n  \"tags\": [\n   \"two-tone\"\n  ],\n  \"bg\": \"#e2e2e2\",\n  \"surface\": \"#d6d6d6\",\n  \"ink\": \"#7d0c14\",\n  \"muted\": \"#7a4a4e\",\n  \"accent\": \"#7d0c14\",\n  \"accentInk\": \"#e2e2e2\",\n  \"fields\": [\n   {\n    \"bg\": \"#7d0c14\",\n    \"ink\": \"#e2e2e2\"\n   }\n  ],\n  \"note\": \"Deep red text on grey paper holds most of the page, then pale grey text on a solid red field takes one long section and the footer. Photographs are desaturated so nothing breaks the pair, and the button is a solid red block.\",\n  \"seenIn\": [\n   \"opl-belgrade-architecture\"\n  ]\n },\n {\n  \"id\": \"olive-on-bone\",\n  \"name\": \"Olive on bone\",\n  \"tags\": [\n   \"two-tone\",\n   \"earth\"\n  ],\n  \"bg\": \"#ecebe7\",\n  \"surface\": \"#e1dfd9\",\n  \"ink\": \"#38450f\",\n  \"muted\": \"#5d683a\",\n  \"accent\": \"#38450f\",\n  \"accentInk\": \"#ecebe7\",\n  \"fields\": [\n   {\n    \"bg\": \"#38450f\",\n    \"ink\": \"#ecebe7\"\n   }\n  ],\n  \"note\": \"A bone page with every word, large or small, in one olive green; the footer inverts to a solid olive field with bone text. Photography supplies all other colour, and the button is the same olive, filled.\",\n  \"seenIn\": [\n   \"aww-tengile-malamala-collection\"\n  ]\n },\n {\n  \"id\": \"burgundy-bubblegum\",\n  \"name\": \"Burgundy and bubblegum\",\n  \"tags\": [\n   \"two-tone\"\n  ],\n  \"bg\": \"#3d0012\",\n  \"surface\": \"#4d0519\",\n  \"ink\": \"#ff99d3\",\n  \"muted\": \"#c77aa0\",\n  \"accent\": \"#ff99d3\",\n  \"accentInk\": \"#3d0012\",\n  \"note\": \"Deep burgundy is the ground for the whole page and bubblegum pink sets every word on it. The button and the active state of a control are solid pink with burgundy type; product photographs supply any other colour.\",\n  \"seenIn\": [\n   \"opl-madie\"\n  ]\n },\n {\n  \"id\": \"bottle-green-gold\",\n  \"name\": \"Bottle green, gold\",\n  \"tags\": [\n   \"two-tone\",\n   \"earth\"\n  ],\n  \"bg\": \"#133621\",\n  \"surface\": \"#1a4429\",\n  \"ink\": \"#f4d96c\",\n  \"muted\": \"#b3a55e\",\n  \"accent\": \"#f4d96c\",\n  \"accentInk\": \"#133621\",\n  \"note\": \"Bottle green covers the page and warm gold sets all the type, with panels one step lighter than the ground. The button is solid gold with green text, and photographs are kept dark and warm so the pair is not disturbed.\",\n  \"seenIn\": [\n   \"aww-lacoste-ace-breaker\"\n  ]\n },\n {\n  \"id\": \"cobalt-field\",\n  \"name\": \"Cobalt field\",\n  \"tags\": [\n   \"single-field\"\n  ],\n  \"bg\": \"#0034eb\",\n  \"surface\": \"#002fd6\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#c5d0ff\",\n  \"accent\": \"#e9e34a\",\n  \"accentInk\": \"#111111\",\n  \"note\": \"One electric cobalt fills everything, with white and pale-blue type; photographs are tinted into blue monotone or kept as small thumbnails. A single yellow dot or button is the only other colour on the page.\",\n  \"seenIn\": [\n   \"opl-george-wood\",\n   \"aww-studio-k95-3\"\n  ]\n },\n {\n  \"id\": \"mustard-field\",\n  \"name\": \"Mustard and black\",\n  \"tags\": [\n   \"single-field\"\n  ],\n  \"bg\": \"#e1ac10\",\n  \"surface\": \"#cd9d0f\",\n  \"ink\": \"#0b0b0b\",\n  \"muted\": \"#4d3d0a\",\n  \"accent\": \"#24338f\",\n  \"accentInk\": \"#ffffff\",\n  \"note\": \"One warm mustard field for the whole page with black ink only. Royal blue is the single interruption, kept to a sliver along one edge or one small button.\",\n  \"seenIn\": [\n   \"opl-beige-force\"\n  ]\n },\n {\n  \"id\": \"carmine-field\",\n  \"name\": \"Carmine field\",\n  \"tags\": [\n   \"single-field\"\n  ],\n  \"bg\": \"#9c1220\",\n  \"surface\": \"#8a101c\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#f0b9bd\",\n  \"accent\": \"#ffd9dc\",\n  \"accentInk\": \"#9c1220\",\n  \"fields\": [\n   {\n    \"bg\": \"#2a2a2a\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"A deep red field bookends or fills the page, with white type and pale pink secondary lines; work shown in between sits on flat charcoal so it keeps its own colours. The button is a pale pink block with red type.\",\n  \"seenIn\": [\n   \"opl-marina-rachello\",\n   \"opl-belgrade-architecture\"\n  ]\n },\n {\n  \"id\": \"pink-field-lime\",\n  \"name\": \"Bubblegum and lime\",\n  \"tags\": [\n   \"single-field\"\n  ],\n  \"bg\": \"#ff87ab\",\n  \"surface\": \"#ff739d\",\n  \"ink\": \"#0a0a0a\",\n  \"muted\": \"#6b1f3a\",\n  \"accent\": \"#def915\",\n  \"accentInk\": \"#0a0a0a\",\n  \"fields\": [\n   {\n    \"bg\": \"#0a0a0a\",\n    \"ink\": \"#ff87ab\"\n   }\n  ],\n  \"note\": \"A flat bubblegum pink field with black type from top to bottom. Fluorescent lime is the action colour only: the menu button, one highlighter swipe behind a word and the main button.\",\n  \"seenIn\": [\n   \"opl-nodeck\",\n   \"aww-decathlon-yestalgia\"\n  ]\n },\n {\n  \"id\": \"sky-field-navy\",\n  \"name\": \"Sky and navy\",\n  \"tags\": [\n   \"single-field\"\n  ],\n  \"bg\": \"#6bb4ee\",\n  \"surface\": \"#7dbdf0\",\n  \"ink\": \"#0e1822\",\n  \"muted\": \"#1b3d5c\",\n  \"accent\": \"#ff5a1f\",\n  \"accentInk\": \"#0e1822\",\n  \"fields\": [\n   {\n    \"bg\": \"#ffffff\",\n    \"ink\": \"#0e1822\"\n   },\n   {\n    \"bg\": \"#0e1822\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"Sky blue sits behind everything, white cards lie on top of it, and navy handles all text and the footer. Orange is for buttons and one highlighted word, so orange against blue is the single clash on the page.\",\n  \"seenIn\": [\n   \"opl-ohhmydesign\",\n   \"opl-anidachi\"\n  ]\n },\n {\n  \"id\": \"orange-field-black\",\n  \"name\": \"Orange and black\",\n  \"tags\": [\n   \"single-field\",\n   \"two-tone\"\n  ],\n  \"bg\": \"#ff7a1f\",\n  \"surface\": \"#ff8633\",\n  \"ink\": \"#050f16\",\n  \"muted\": \"#5a2306\",\n  \"accent\": \"#050f16\",\n  \"accentInk\": \"#ff7a1f\",\n  \"fields\": [\n   {\n    \"bg\": \"#ffffff\",\n    \"ink\": \"#050f16\"\n   }\n  ],\n  \"note\": \"Hot orange is the page: one flat field with blue-black type, flipping at a hard horizontal seam to a white section when the content needs a rest. The button is a solid block of the same blue-black with orange text, and every other colour comes from the objects shown.\",\n  \"seenIn\": [\n   \"opl-postaway\",\n   \"opl-the-new-industrials\"\n  ]\n },\n {\n  \"id\": \"tobacco-olive\",\n  \"name\": \"Tobacco and olive\",\n  \"tags\": [\n   \"single-field\",\n   \"earth\"\n  ],\n  \"bg\": \"#472913\",\n  \"surface\": \"#55321a\",\n  \"ink\": \"#e4e0cf\",\n  \"muted\": \"#b39f84\",\n  \"accent\": \"#525e1b\",\n  \"accentInk\": \"#e4e0cf\",\n  \"fields\": [\n   {\n    \"bg\": \"#c79a3e\",\n    \"ink\": \"#2b170a\"\n   },\n   {\n    \"bg\": \"#525e1b\",\n    \"ink\": \"#e4e0cf\"\n   }\n  ],\n  \"note\": \"Tobacco brown fills the page with bone type, and photographs stay in browns and ochre. One olive block holds the main text or the button, and a single ochre band may break the brown once.\",\n  \"seenIn\": [\n   \"aww-the-tuscan-journey-begins\"\n  ]\n },\n {\n  \"id\": \"poster-chapters\",\n  \"name\": \"Poster chapters\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#e6e0d2\",\n  \"surface\": \"#dcd5c5\",\n  \"ink\": \"#1a1a1a\",\n  \"muted\": \"#5f5b52\",\n  \"accent\": \"#18bc42\",\n  \"accentInk\": \"#1a1a1a\",\n  \"fields\": [\n   {\n    \"bg\": \"#ed4b44\",\n    \"ink\": \"#0f0f0f\"\n   },\n   {\n    \"bg\": \"#1a1a1a\",\n    \"ink\": \"#e6e0d2\"\n   },\n   {\n    \"bg\": \"#18bc42\",\n    \"ink\": \"#1a1a1a\"\n   },\n   {\n    \"bg\": \"#f2c21a\",\n    \"ink\": \"#1a1a1a\"\n   },\n   {\n    \"bg\": \"#e6e0d2\",\n    \"ink\": \"#1a1a1a\"\n   }\n  ],\n  \"note\": \"Each chapter takes one flat field in turn (coral red, near-black, bone, green, yellow) with black or bone type and no tints between them. Green doubles as the accent for the one button when the ground is bone or black.\",\n  \"seenIn\": [\n   \"aww-pp-neue-montreal\"\n  ]\n },\n {\n  \"id\": \"blue-red-black\",\n  \"name\": \"Blue, red, black\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#ffffff\",\n  \"surface\": \"#f3f3f3\",\n  \"ink\": \"#0a0a0a\",\n  \"muted\": \"#6b6b6b\",\n  \"accent\": \"#2436ff\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#2436ff\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#ff3b1f\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#0a0a0a\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#050a5c\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"Three flat poster colours each own whole sections: electric blue, red-orange and black, with white for the areas that show the product. No tints sit between them, and blue is the button colour on white.\",\n  \"seenIn\": [\n   \"opl-juggle\"\n  ]\n },\n {\n  \"id\": \"charcoal-primaries\",\n  \"name\": \"Charcoal and primaries\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#191919\",\n  \"surface\": \"#242424\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#9a9a9a\",\n  \"accent\": \"#0c7866\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#d71e1e\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#1e4bd7\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#0c7866\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#ffe927\",\n    \"ink\": \"#111111\"\n   }\n  ],\n  \"note\": \"A charcoal ground holds flat poster primaries assigned to whole panels: red, blue, teal green and yellow, each placed against a different one. Type is white, or black on yellow; teal green is the button colour on charcoal.\",\n  \"seenIn\": [\n   \"aww-mosbys-files\"\n  ]\n },\n {\n  \"id\": \"ultramarine-yellow\",\n  \"name\": \"Ultramarine and yellow\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#1423b8\",\n  \"surface\": \"#1220a6\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#b4bcf0\",\n  \"accent\": \"#1fc27a\",\n  \"accentInk\": \"#0a0a0a\",\n  \"fields\": [\n   {\n    \"bg\": \"#1423b8\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#000000\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#f7dd47\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#e9479f\",\n    \"ink\": \"#000000\"\n   }\n  ],\n  \"note\": \"Each section is one flat field in sequence: ultramarine, black, yellow, then ultramarine again, with white type on blue and black, and black type on yellow. Green is the only small accent and never grows larger than a button.\",\n  \"seenIn\": [\n   \"aww-warm-fuzzy\",\n   \"aww-px-push\"\n  ]\n },\n {\n  \"id\": \"candy-chapters\",\n  \"name\": \"Candy chapters\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#ffd249\",\n  \"surface\": \"#f5c63c\",\n  \"ink\": \"#0a0a0a\",\n  \"muted\": \"#5e4a0a\",\n  \"accent\": \"#f53fd6\",\n  \"accentInk\": \"#0a0a0a\",\n  \"fields\": [\n   {\n    \"bg\": \"#ffd249\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#ffffff\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#ffc4ef\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#a4f6f8\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#f9a21f\",\n    \"ink\": \"#0a0a0a\"\n   }\n  ],\n  \"note\": \"Each section owns one flat candy colour: yellow first, then white, pink, cyan and orange, with all type in black. Magenta is kept for buttons alone.\",\n  \"seenIn\": [\n   \"aww-aardvark-book-club\"\n  ]\n },\n {\n  \"id\": \"orange-sky-lime\",\n  \"name\": \"Orange, sky, lime\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#ff8126\",\n  \"surface\": \"#ff8d3a\",\n  \"ink\": \"#111111\",\n  \"muted\": \"#5c2a05\",\n  \"accent\": \"#de194b\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#ff8126\",\n    \"ink\": \"#111111\"\n   },\n   {\n    \"bg\": \"#4db3ff\",\n    \"ink\": \"#111111\"\n   },\n   {\n    \"bg\": \"#c5f53d\",\n    \"ink\": \"#111111\"\n   },\n   {\n    \"bg\": \"#161615\",\n    \"ink\": \"#f2f2f2\"\n   }\n  ],\n  \"note\": \"The page ground changes as you read: orange first, then sky blue, then acid lime at the end, with one near-black band between; type stays black on all three colours. Crimson is one small button per field.\",\n  \"seenIn\": [\n   \"opl-the-new-industrials\",\n   \"opl-anidachi\"\n  ]\n },\n {\n  \"id\": \"post-red-mustard\",\n  \"name\": \"Post red, mustard\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#e2dccf\",\n  \"surface\": \"#d7d0c1\",\n  \"ink\": \"#2a1110\",\n  \"muted\": \"#6b524c\",\n  \"accent\": \"#4a6f84\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#dc1928\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#952625\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#e0a912\",\n    \"ink\": \"#2a1110\"\n   },\n   {\n    \"bg\": \"#4a6f84\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#e2dccf\",\n    \"ink\": \"#2a1110\"\n   }\n  ],\n  \"note\": \"Post red and bone alternate as full section fields, with red holding the opening and the close. Mustard, slate blue and maroon are kept for whole card frames, and slate blue also fills the one button.\",\n  \"seenIn\": [\n   \"opl-locker-land\"\n  ]\n },\n {\n  \"id\": \"mint-orange-grey\",\n  \"name\": \"Grey, mint, orange\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#ffffff\",\n  \"surface\": \"#f5f5f5\",\n  \"ink\": \"#000000\",\n  \"muted\": \"#666666\",\n  \"accent\": \"#a7ff9c\",\n  \"accentInk\": \"#000000\",\n  \"fields\": [\n   {\n    \"bg\": \"#c5c5c5\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#a7ff9c\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#ff6831\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#000000\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"Black on white to start, then whole sections flood with flat mid-grey, acid mint and orange in turn. Photographs inside a flooded section are shown in black-and-white, and mint is also the button colour on white and black.\",\n  \"seenIn\": [\n   \"aww-paul-kalkbrenner\"\n  ]\n },\n {\n  \"id\": \"report-blocks\",\n  \"name\": \"Report blocks\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#ffffff\",\n  \"surface\": \"#f6f6f6\",\n  \"ink\": \"#000000\",\n  \"muted\": \"#5f5f5f\",\n  \"accent\": \"#fe7141\",\n  \"accentInk\": \"#000000\",\n  \"fields\": [\n   {\n    \"bg\": \"#fe7141\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#d1ddd3\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#f0ff1c\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#000000\",\n    \"ink\": \"#f4f4f4\"\n   }\n  ],\n  \"note\": \"A white base with flat blocks of orange, sage, acid yellow and black assigned to whole modules: figure tiles, quote panels and chapter bands. Text is black on every colour and off-white on black, and orange is also the button colour.\",\n  \"seenIn\": [\n   \"aww-ai-in-design-report-2026\"\n  ]\n },\n {\n  \"id\": \"card-pastels\",\n  \"name\": \"Card pastels\",\n  \"tags\": [\n   \"pastel-fields\"\n  ],\n  \"bg\": \"#f7f7f5\",\n  \"surface\": \"#ebebe8\",\n  \"ink\": \"#000000\",\n  \"muted\": \"#666662\",\n  \"accent\": \"#d0106f\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#97aaf6\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#bbf697\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#fed878\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#6ef8fb\",\n    \"ink\": \"#000000\"\n   }\n  ],\n  \"note\": \"Neutral paper ground and black type, with each card or tile given its own flat pastel (periwinkle, lime, amber or cyan), never two alike side by side. Magenta is reserved for the logo, the email address and text links.\",\n  \"seenIn\": [\n   \"opl-medium-rare\"\n  ]\n },\n {\n  \"id\": \"mint-pink-accounts\",\n  \"name\": \"Mint and pink\",\n  \"tags\": [\n   \"pastel-fields\"\n  ],\n  \"bg\": \"#f8f8f8\",\n  \"surface\": \"#eeeeee\",\n  \"ink\": \"#0a0a0a\",\n  \"muted\": \"#6a6a6a\",\n  \"accent\": \"#1f6b3a\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#c3edce\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#f8c7c9\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#ffffff\",\n    \"ink\": \"#0a0a0a\"\n   }\n  ],\n  \"note\": \"Near-white base with black type; mint and pink are the only two colours and each stands for one side of the product. They first appear as small circles, then as full-screen section fields, and deep green is used only for the button.\",\n  \"seenIn\": [\n   \"opl-tara\"\n  ]\n },\n {\n  \"id\": \"swap-pastels\",\n  \"name\": \"Swapping pastels\",\n  \"tags\": [\n   \"pastel-fields\"\n  ],\n  \"bg\": \"#c3cbe5\",\n  \"surface\": \"#d0d6eb\",\n  \"ink\": \"#141414\",\n  \"muted\": \"#4a5068\",\n  \"accent\": \"#0f5257\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#c3cbe5\",\n    \"ink\": \"#141414\"\n   },\n   {\n    \"bg\": \"#efd3da\",\n    \"ink\": \"#141414\"\n   },\n   {\n    \"bg\": \"#e6dccd\",\n    \"ink\": \"#141414\"\n   },\n   {\n    \"bg\": \"#cfd3cb\",\n    \"ink\": \"#141414\"\n   },\n   {\n    \"bg\": \"#f9cdbd\",\n    \"ink\": \"#141414\"\n   }\n  ],\n  \"note\": \"One flat pastel is the whole background and it swaps per project or chapter: periwinkle, pink, sand, sage, peach. Type and one solid box stay near-black on all five, and dark teal is only for the button.\",\n  \"seenIn\": [\n   \"opl-belen-jones\"\n  ]\n },\n {\n  \"id\": \"blush-sage-slate\",\n  \"name\": \"Blush, sage, slate\",\n  \"tags\": [\n   \"pastel-fields\",\n   \"earth\"\n  ],\n  \"bg\": \"#a6b3bc\",\n  \"surface\": \"#b2bdc5\",\n  \"ink\": \"#1c1c1c\",\n  \"muted\": \"#38424a\",\n  \"accent\": \"#2c3620\",\n  \"accentInk\": \"#e3e2da\",\n  \"fields\": [\n   {\n    \"bg\": \"#a6b3bc\",\n    \"ink\": \"#1c1c1c\"\n   },\n   {\n    \"bg\": \"#b7c8be\",\n    \"ink\": \"#1c1c1c\"\n   },\n   {\n    \"bg\": \"#d6c4b8\",\n    \"ink\": \"#1c1c1c\"\n   },\n   {\n    \"bg\": \"#2c3620\",\n    \"ink\": \"#e3e2da\"\n   }\n  ],\n  \"note\": \"Slate blue-grey, sage and blush share the page as soft flat blocks, one per chapter or menu tile, with dark type; one deep olive block anchors the close with pale type. Olive is also the button colour, and photographs of sea and sky do the rest.\",\n  \"seenIn\": [\n   \"aww-seasats\",\n   \"opl-nia-creative\"\n  ]\n },\n {\n  \"id\": \"candy-on-black\",\n  \"name\": \"Candy on black\",\n  \"tags\": [\n   \"pastel-fields\"\n  ],\n  \"bg\": \"#000000\",\n  \"surface\": \"#0d0d0d\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#999999\",\n  \"accent\": \"#93f1f7\",\n  \"accentInk\": \"#000000\",\n  \"fields\": [\n   {\n    \"bg\": \"#9ae187\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#93f1f7\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#f3ea7a\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#fbb65c\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#b9c8ff\",\n    \"ink\": \"#000000\"\n   }\n  ],\n  \"note\": \"Black ground and dark photographs take nearly all of the surface. The only flat colour is a solid block behind each title, which takes a new candy pastel per project (mint, cyan, lemon, orange, cornflower); cyan is the default for the button.\",\n  \"seenIn\": [\n   \"aww-glitch-grit\"\n  ]\n },\n {\n  \"id\": \"sky-sand\",\n  \"name\": \"Sky and sand\",\n  \"tags\": [\n   \"pastel-fields\"\n  ],\n  \"bg\": \"#cbe4f2\",\n  \"surface\": \"#bcdcee\",\n  \"ink\": \"#0a0a0a\",\n  \"muted\": \"#44606e\",\n  \"accent\": \"#b0298f\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#cbe4f2\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#f1e3b5\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#ffc013\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#0a0a0a\",\n    \"ink\": \"#f2f2f2\"\n   }\n  ],\n  \"note\": \"Sky blue and sand yellow are the constant ground, each holding whole sections, with black text throughout. Saturated colour arrives only as small solid objects, and magenta is kept for the contact card and its button.\",\n  \"seenIn\": [\n   \"opl-applied-imagination\"\n  ]\n },\n {\n  \"id\": \"studio-grey\",\n  \"name\": \"Studio grey\",\n  \"tags\": [\n   \"photographic-neutral\"\n  ],\n  \"bg\": \"#a8a8aa\",\n  \"surface\": \"#b4b4b6\",\n  \"ink\": \"#0e0e0e\",\n  \"muted\": \"#3a3a3c\",\n  \"accent\": \"#1f5c49\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#1b1b1c\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"One mid grey serves as both page and studio backdrop, so the photographed object seems to stand on the page itself; type is black and one black band comes late. Colour comes only from the product, and racing green is for the single button.\",\n  \"seenIn\": [\n   \"aww-longbow\",\n   \"aww-l-i-s-a\"\n  ]\n },\n {\n  \"id\": \"walnut-tan\",\n  \"name\": \"Walnut and tan\",\n  \"tags\": [\n   \"photographic-neutral\",\n   \"earth\"\n  ],\n  \"bg\": \"#2b2216\",\n  \"surface\": \"#382d1e\",\n  \"ink\": \"#e4e2da\",\n  \"muted\": \"#a39a8b\",\n  \"accent\": \"#bda38b\",\n  \"accentInk\": \"#2b2216\",\n  \"fields\": [\n   {\n    \"bg\": \"#bda38b\",\n    \"ink\": \"#1c150d\"\n   }\n  ],\n  \"note\": \"Dark walnut holds the opening and the close with bone type, and the middle of the page may turn to flat tan around honey-lit photographs. There is no bright accent: tan is the fill for the one button on walnut.\",\n  \"seenIn\": [\n   \"opl-the-deep-end\"\n  ]\n }\n]","skills/taste-skill/library/photos.json":"{\n \"source\": \"Lorem Picsum (https://picsum.photos): photographs from Unsplash, used under the Unsplash licence\",\n \"url\": \"https://picsum.photos/id/{id}/{width}/{height}\",\n \"sets\": {\n  \"fog-and-quiet\": {\n   \"title\": \"Fog and quiet\",\n   \"note\": \"misty, muted, minimal landscapes and empty horizons; calm areas for text\",\n   \"sectors\": [\n    \"hospitality\",\n    \"health\",\n    \"fashion\",\n    \"agency\",\n    \"studio-portfolio\",\n    \"personal-portfolio\",\n    \"saas\",\n    \"ai-product\",\n    \"finance\",\n    \"architecture\",\n    \"real-estate\",\n    \"other\",\n    \"nonprofit\",\n    \"culture\"\n   ],\n   \"keywords\": [\n    \"fog\",\n    \"mist\",\n    \"quiet\",\n    \"calm\",\n    \"minimal\",\n    \"silence\",\n    \"retreat\",\n    \"wellness\",\n    \"spa\",\n    \"meditation\",\n    \"slow\"\n   ],\n   \"primary\": [\n    \"health\"\n   ],\n   \"photos\": [\n    {\n     \"id\": 70,\n     \"alt\": \"Road lined with tall trees fading into thick fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"centre\",\n     \"quality\": 5,\n     \"ratio\": 1.51,\n     \"by\": \"Dorothy Lin\",\n     \"page\": \"https://unsplash.com/photos/OokBLPrkCNk\"\n    },\n    {\n     \"id\": 172,\n     \"alt\": \"Stone jetty stretching into still water and dense grey fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"warm grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.51,\n     \"by\": \"Aleksi Tappura\",\n     \"page\": \"https://unsplash.com/photos/TQeX8khR54I\"\n    },\n    {\n     \"id\": 194,\n     \"alt\": \"Wooden deck and a single rock disappearing into thick fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"cool grey\",\n      \"weathered brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.51,\n     \"by\": \"Aleksi Tappura\",\n     \"page\": \"https://unsplash.com/photos/hVOv8me9ue8\"\n    },\n    {\n     \"id\": 228,\n     \"alt\": \"Single round hay bale in a field under dense fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey green\",\n      \"golden tan\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.33,\n     \"by\": \"Michal Kubicek\",\n     \"page\": \"https://unsplash.com/photos/0AbVUUorULU\"\n    },\n    {\n     \"id\": 255,\n     \"alt\": \"Gravel path leading to a cluster of bare trees on a hill\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"olive green\",\n      \"pale grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Jon Ottosson\",\n     \"page\": \"https://unsplash.com/photos/Xg1e5bR_bL4\"\n    },\n    {\n     \"id\": 266,\n     \"alt\": \"Three ships on a distant horizon across a calm blue sea\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"pale blue\",\n      \"deep blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"all\",\n     \"quality\": 5,\n     \"ratio\": 1.78,\n     \"by\": \"John Maravelakis\",\n     \"page\": \"https://unsplash.com/photos/Vosp2wlY3Bs\"\n    },\n    {\n     \"id\": 269,\n     \"alt\": \"Gulls perched on a concrete wall beside a pale still sea\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"pale blue\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Jill Heyer\",\n     \"page\": \"https://unsplash.com/photos/bbV7QzDUJus\"\n    },\n    {\n     \"id\": 279,\n     \"alt\": \"Still misty water fading into a soft pink-grey sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"dusty pink\",\n      \"slate grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"all\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Taylor Leopold\",\n     \"page\": \"https://unsplash.com/photos/OHS0yA7OkrQ\"\n    },\n    {\n     \"id\": 302,\n     \"alt\": \"Lone marker post standing in still water wrapped in fog\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"all\",\n     \"quality\": 5,\n     \"ratio\": 1.6,\n     \"by\": \"Billy Lam\",\n     \"page\": \"https://unsplash.com/photos/O3rmGgNYLKo\"\n    },\n    {\n     \"id\": 353,\n     \"alt\": \"Low cloud drifting over dark green forested hills\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"deep green\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.78,\n     \"by\": \"Forrest Cavale\",\n     \"page\": \"https://unsplash.com/photos/qfmd9bu7IgA\"\n    },\n    {\n     \"id\": 465,\n     \"alt\": \"Dark rocky peak emerging from thick white cloud\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"charcoal\",\n      \"pale grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 5,\n     \"ratio\": 1.51,\n     \"by\": \"Paula Vermeulen\",\n     \"page\": \"https://unsplash.com/photos/_f2m3mEkaaU\"\n    },\n    {\n     \"id\": 510,\n     \"alt\": \"Small red-roofed church below a mountain under a blank white sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"olive brown\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.33,\n     \"by\": \"Jeff Sheldon\",\n     \"page\": \"https://unsplash.com/photos/4IPe3tnBKK0\"\n    },\n    {\n     \"id\": 544,\n     \"alt\": \"Layered hill ridges fading into warm beige mist\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"beige\",\n      \"warm brown\",\n      \"cream\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Francesco Gallarotti\",\n     \"page\": \"https://unsplash.com/photos/-HkuuUSY1pE\"\n    },\n    {\n     \"id\": 552,\n     \"alt\": \"Tiny sailboat on a calm sea with distant hills, black and white\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"white\",\n      \"black\"\n     ],\n     \"mono\": true,\n     \"calm\": \"all\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Hugo Kerr\",\n     \"page\": \"https://unsplash.com/photos/Ke96snCJ1m0\"\n    },\n    {\n     \"id\": 594,\n     \"alt\": \"Small boathouse at the end of a jetty on dark water at night\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"black\",\n      \"deep purple\",\n      \"warm white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Aurélien bellanger\",\n     \"page\": \"https://unsplash.com/photos/uoSEDUu8F-I\"\n    },\n    {\n     \"id\": 634,\n     \"alt\": \"Pine forest dissolving into fog beneath a pale pink sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"dark green\",\n      \"pale pink\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Jay Mantri\",\n     \"page\": \"https://unsplash.com/photos/TFyi0QOx08c\"\n    },\n    {\n     \"id\": 813,\n     \"alt\": \"Still blue lake with a faint distant shoreline in haze\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"slate blue\",\n      \"powder blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"all\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Roger Burkhard\",\n     \"page\": \"https://unsplash.com/photos/rlX9J28Pd9g\"\n    },\n    {\n     \"id\": 842,\n     \"alt\": \"Wooden steps with railings descending into pale pink fog\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"blush pink\",\n      \"pale grey\",\n      \"slate\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 0.75,\n     \"by\": \"Joe Beck\",\n     \"page\": \"https://unsplash.com/photos/NbUokuw0BQI\"\n    },\n    {\n     \"id\": 922,\n     \"alt\": \"Dark treeline dissolving upward into pale fog, black and white\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"charcoal\",\n      \"grey\",\n      \"white\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.8,\n     \"by\": \"Patrick Hendry\",\n     \"page\": \"https://unsplash.com/photos/37ZuGYD3JOk\"\n    },\n    {\n     \"id\": 926,\n     \"alt\": \"Lone figure standing on a hilltop in thick beige fog\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"warm beige\",\n      \"olive grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.78,\n     \"by\": \"Harman Abiwardani\",\n     \"page\": \"https://unsplash.com/photos/mU_aX6JBYmg\"\n    },\n    {\n     \"id\": 941,\n     \"alt\": \"Small island on a pale, glassy sea beneath soft clouds\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale blue\",\n      \"soft white\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Ivan Slade\",\n     \"page\": \"https://unsplash.com/photos/RdyMe8KQAV0\"\n    },\n    {\n     \"id\": 989,\n     \"alt\": \"Low cloud covering a forested lakeshore under a pale sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"dark teal\",\n      \"soft blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Paul Jarvis\",\n     \"page\": \"https://unsplash.com/photos/eBDdgbM5dSo\"\n    },\n    {\n     \"id\": 994,\n     \"alt\": \"Silky long-exposure sea beneath a blue and orange sunset sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"soft blue\",\n      \"peach\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"all\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Jonathan Bean\",\n     \"page\": \"https://unsplash.com/photos/ywnnwzcdR5o\"\n    },\n    {\n     \"id\": 11,\n     \"alt\": \"Misty river winding through a grassy valley between forested slopes\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"pale green\",\n      \"grey green\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Paul Jarvis\",\n     \"page\": \"https://unsplash.com/photos/Cm7oKel-X2Q\"\n    },\n    {\n     \"id\": 93,\n     \"alt\": \"Marshland with scattered pine trees under a soft pastel sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"moss green\",\n      \"pale blue\",\n      \"soft pink\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Caroline Sada\",\n     \"page\": \"https://unsplash.com/photos/r1XwWjI4PyE\"\n    },\n    {\n     \"id\": 130,\n     \"alt\": \"Single seagull gliding over a grey sea beneath pale clouds\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"white\"\n     ],\n     \"mono\": true,\n     \"calm\": \"all\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Ryan Jacques\",\n     \"page\": \"https://unsplash.com/photos/ywiAen4L4qA\"\n    },\n    {\n     \"id\": 131,\n     \"alt\": \"Tiny figure on a pier under a vast pale yellow sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale yellow\",\n      \"sand beige\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.48,\n     \"by\": \"Charlie Foster\",\n     \"page\": \"https://unsplash.com/photos/yPaskTQiNjA\"\n    },\n    {\n     \"id\": 135,\n     \"alt\": \"Dark choppy sea fading into dense blue-grey fog\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"indigo\",\n      \"slate blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.33,\n     \"by\": \"Yuriy Khimanin\",\n     \"page\": \"https://unsplash.com/photos/o4H20aIIAt8\"\n    },\n    {\n     \"id\": 213,\n     \"alt\": \"Soft orange sunset sky above a calm misty sea\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"peach orange\",\n      \"slate blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"all\",\n     \"quality\": 4,\n     \"ratio\": 1.51,\n     \"by\": \"Kelly Sikkema\",\n     \"page\": \"https://unsplash.com/photos/X7dy114KWs4\"\n    },\n    {\n     \"id\": 227,\n     \"alt\": \"Railway tracks curving into a misty forest of bare trees\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"dark teal\",\n      \"grey green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"centre\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Andrea Boldizsar\",\n     \"page\": \"https://unsplash.com/photos/1iP1dozVO8I\"\n    },\n    {\n     \"id\": 264,\n     \"alt\": \"Wooden post standing among stones beside still misty water\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"warm beige\",\n      \"grey\",\n      \"tan\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Jon Phillips\",\n     \"page\": \"https://unsplash.com/photos/XsPM2CBTTpI\"\n    },\n    {\n     \"id\": 282,\n     \"alt\": \"Wooden railing overlooking a pine forest covered by low fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"muted brown\",\n      \"dark green\",\n      \"warm grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Taylor Leopold\",\n     \"page\": \"https://unsplash.com/photos/9dw0xLlxw1s\"\n    },\n    {\n     \"id\": 291,\n     \"alt\": \"Two figures standing in a misty blue field at dusk\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"deep blue\",\n      \"muted rust\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Caleb George\",\n     \"page\": \"https://unsplash.com/photos/zdjOYZeJj3w\"\n    },\n    {\n     \"id\": 300,\n     \"alt\": \"Hay bales scattered across a pale field under white sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"light grey\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Pavel Voinov\",\n     \"page\": \"https://unsplash.com/photos/2f_CnEeZsVg\"\n    },\n    {\n     \"id\": 313,\n     \"alt\": \"Distant clump of trees in a foggy field at dusk\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"dusty mauve\",\n      \"slate blue\",\n      \"dark olive\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Sonja Langford\",\n     \"page\": \"https://unsplash.com/photos/4xYgBTYC2-Q\"\n    },\n    {\n     \"id\": 385,\n     \"alt\": \"Calm sea stretching to a thin glowing horizon at dusk\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"slate blue\",\n      \"teal\",\n      \"soft orange\"\n     ],\n     \"mono\": false,\n     \"calm\": \"all\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Griffin Keller\",\n     \"page\": \"https://unsplash.com/photos/7oS_26cb1Wo\"\n    },\n    {\n     \"id\": 406,\n     \"alt\": \"Low clouds drifting across steep forested mountain slopes\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"white\",\n      \"dark green\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.51,\n     \"by\": \"Roland Batke-Mutschler\",\n     \"page\": \"https://unsplash.com/photos/SmhN4FejPFs\"\n    },\n    {\n     \"id\": 443,\n     \"alt\": \"Mist and cloud hanging over dark pine-covered mountains\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"dark green\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Tim Mossholder\",\n     \"page\": \"https://unsplash.com/photos/p3kpqGBRPok\"\n    },\n    {\n     \"id\": 457,\n     \"alt\": \"Faint ships on a pale foggy sea with almost no horizon\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"pale grey\"\n     ],\n     \"mono\": true,\n     \"calm\": \"all\",\n     \"quality\": 4,\n     \"ratio\": 1.77,\n     \"by\": \"Volkan Olmez\",\n     \"page\": \"https://unsplash.com/photos/ccPpd02Spe0\"\n    },\n    {\n     \"id\": 467,\n     \"alt\": \"Dark sea fading into white fog in black and white\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"white\",\n      \"grey\",\n      \"charcoal\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Taylor Leopold\",\n     \"page\": \"https://unsplash.com/photos/COE-CIGj8VA\"\n    },\n    {\n     \"id\": 472,\n     \"alt\": \"Small wooded island wrapped in fog on a dark lake\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"dark green\",\n      \"grey\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Dustin Scarpitti\",\n     \"page\": \"https://unsplash.com/photos/gR_zHJqbtzo\"\n    },\n    {\n     \"id\": 481,\n     \"alt\": \"Still lake at dusk with mist and dark conifers along the shore\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"teal grey\",\n      \"slate\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Dustin Scarpitti\",\n     \"page\": \"https://unsplash.com/photos/RdF3apSExR0\"\n    },\n    {\n     \"id\": 722,\n     \"alt\": \"Tree silhouettes in thick golden fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"ochre\",\n      \"olive brown\",\n      \"pale gold\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 0.67,\n     \"by\": \"Sebastian Kostrubala\",\n     \"page\": \"https://unsplash.com/photos/4yDg-dDX9uM\"\n    },\n    {\n     \"id\": 727,\n     \"alt\": \"Sandy mound with dark shrubs beneath a blank foggy sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"ochre\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.33,\n     \"by\": \"Devan Freeman\",\n     \"page\": \"https://unsplash.com/photos/HrUbyeQvL_w\"\n    },\n    {\n     \"id\": 731,\n     \"alt\": \"Grassy rocky mountain ridge emerging from thick grey mist\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"mist grey\",\n      \"olive green\",\n      \"dark brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.33,\n     \"by\": \"Rob Bye\",\n     \"page\": \"https://unsplash.com/photos/61XW8CMNX6A\"\n    },\n    {\n     \"id\": 807,\n     \"alt\": \"Lone tree on a grassy slope disappearing into thick fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"moss green\",\n      \"mist grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.78,\n     \"by\": \"Tiago Aguiar\",\n     \"page\": \"https://unsplash.com/photos/FtVQIQ9rDFI\"\n    },\n    {\n     \"id\": 886,\n     \"alt\": \"Flat grassy field vanishing into pale yellow fog\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"straw yellow\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.33,\n     \"by\": \"Glen Carrie\",\n     \"page\": \"https://unsplash.com/photos/p62O--o1x-U\"\n    },\n    {\n     \"id\": 925,\n     \"alt\": \"Conifer trees fading into dense grey fog on a hillside\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"mist grey\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"right\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Patrick Fore\",\n     \"page\": \"https://unsplash.com/photos/vpAKO21abME\"\n    },\n    {\n     \"id\": 965,\n     \"alt\": \"Long bridge disappearing into thick grey fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"mist grey\",\n      \"slate\",\n      \"pale green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Liane Metzler\",\n     \"page\": \"https://unsplash.com/photos/c5uShPcKLAE\"\n    },\n    {\n     \"id\": 966,\n     \"alt\": \"Forested mountainside sloping diagonally beneath white fog\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"olive green\",\n      \"brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Alberto Restifo\",\n     \"page\": \"https://unsplash.com/photos/kKrfPaKgE1c\"\n    },\n    {\n     \"id\": 991,\n     \"alt\": \"Hazy sun above layered dark hills in sepia tones\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"sepia\",\n      \"dark brown\",\n      \"pale gold\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Fritz Bielmeier\",\n     \"page\": \"https://unsplash.com/photos/ooJi3CJQRa8\"\n    },\n    {\n     \"id\": 1028,\n     \"alt\": \"Bare dead trees standing in dry ground under sepia haze\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"sepia\",\n      \"tan\",\n      \"dark brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Dikaseva\",\n     \"page\": \"https://unsplash.com/photos/zvf7cZ0PC20\"\n    }\n   ]\n  },\n  \"coast\": {\n   \"title\": \"Coast\",\n   \"note\": \"sea, shoreline, cliffs, piers and beaches\",\n   \"sectors\": [\n    \"hospitality\",\n    \"health\",\n    \"real-estate\",\n    \"restaurant\",\n    \"event\",\n    \"fashion\",\n    \"other\"\n   ],\n   \"keywords\": [\n    \"coast\",\n    \"sea\",\n    \"ocean\",\n    \"beach\",\n    \"surf\",\n    \"island\",\n    \"harbour\",\n    \"harbor\",\n    \"seaside\",\n    \"sail\",\n    \"boat\",\n    \"fish\",\n    \"marine\",\n    \"cliff\",\n    \"guesthouse\",\n    \"shore\",\n    \"bay\",\n    \"atlantic\",\n    \"lookout\"\n   ],\n   \"primary\": [\n    \"hospitality\"\n   ],\n   \"photos\": [\n    {\n     \"id\": 77,\n     \"alt\": \"Wooden jetty leading to a small pavilion over calm sea\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"warm tan\",\n      \"pale teal\",\n      \"soft grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.48,\n     \"by\": \"May Pamintuan\",\n     \"page\": \"https://unsplash.com/photos/j9nfqTi5T5o\"\n    },\n    {\n     \"id\": 626,\n     \"alt\": \"Red and white lighthouse in turquoise sea below a chalk cliff\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"turquoise\",\n      \"white\",\n      \"grass green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Nick Diamantidis\",\n     \"page\": \"https://unsplash.com/photos/jkPKQWK1sKU\"\n    },\n    {\n     \"id\": 640,\n     \"alt\": \"Aerial view of turquoise surf breaking onto golden sand\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"sand\",\n      \"turquoise\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Sarah Bürvenich\",\n     \"page\": \"https://unsplash.com/photos/vigsqYux_-8\"\n    },\n    {\n     \"id\": 641,\n     \"alt\": \"Empty lifeguard chair on a beach at pastel dusk\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"peach\",\n      \"slate blue\",\n      \"dusty teal\"\n     ],\n     \"mono\": false,\n     \"calm\": \"right\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Fré Sonneveld\",\n     \"page\": \"https://unsplash.com/photos/2qLT_Rq-2tk\"\n    },\n    {\n     \"id\": 853,\n     \"alt\": \"Lone rock in a calm blue sea beneath a pastel sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"sea blue\",\n      \"peach\",\n      \"pale pink\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.51,\n     \"by\": \"Stephen Radford\",\n     \"page\": \"https://unsplash.com/photos/674bDNKmnIk\"\n    },\n    {\n     \"id\": 1049,\n     \"alt\": \"Rock island reflected on a wet beach under a pale sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"soft white\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.25,\n     \"by\": \"Rosan Harmens\",\n     \"page\": \"https://unsplash.com/photos/Sd8O2SgKDJA\"\n    },\n    {\n     \"id\": 1052,\n     \"alt\": \"Black sea stacks off a dark beach with white surf under a pale sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"black\",\n      \"white\",\n      \"pale grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Annie Spratt\",\n     \"page\": \"https://unsplash.com/photos/x8R2oSWZRSE\"\n    },\n    {\n     \"id\": 12,\n     \"alt\": \"Dark rocks on a sandy beach with calm sea and islands\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"sand beige\",\n      \"dark brown\",\n      \"pale grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Paul Jarvis\",\n     \"page\": \"https://unsplash.com/photos/I_9ILwtsl_k\"\n    },\n    {\n     \"id\": 14,\n     \"alt\": \"Rocky shoreline meeting a calm pale sea under hazy sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"pale blue\",\n      \"warm brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Paul Jarvis\",\n     \"page\": \"https://unsplash.com/photos/IQ1kOQTJrOQ\"\n    },\n    {\n     \"id\": 16,\n     \"alt\": \"Blue sea and distant islands seen over a rocky driftwood shore\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"sky blue\",\n      \"deep blue\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Paul Jarvis\",\n     \"page\": \"https://unsplash.com/photos/gkT4FfgHO5o\"\n    },\n    {\n     \"id\": 27,\n     \"alt\": \"Person standing on a rocky shore watching misty waves at sunset\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"warm orange\",\n      \"brown\",\n      \"pale gold\"\n     ],\n     \"mono\": false,\n     \"calm\": \"right\",\n     \"quality\": 4,\n     \"ratio\": 1.78,\n     \"by\": \"Yoni Kaplan-Nadel\",\n     \"page\": \"https://unsplash.com/photos/iJnZwLBOB1I\"\n    },\n    {\n     \"id\": 47,\n     \"alt\": \"Long wooden pier over misty surf in black and white\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"light grey\",\n      \"charcoal\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Christopher Sardegna\",\n     \"page\": \"https://unsplash.com/photos/uDUiRS8YroY\"\n    },\n    {\n     \"id\": 68,\n     \"alt\": \"Curving pier with a railing, lamp post and weather vane\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"light grey\",\n      \"charcoal\"\n     ],\n     \"mono\": true,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Cristian Moscoso\",\n     \"page\": \"https://unsplash.com/photos/2SfRAWkinpU\"\n    },\n    {\n     \"id\": 108,\n     \"alt\": \"Palm trees silhouetted against a bright washed-out sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"soft pink\",\n      \"dark brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Florian Klauer\",\n     \"page\": \"https://unsplash.com/photos/t1mqA3V3-7g\"\n    },\n    {\n     \"id\": 144,\n     \"alt\": \"Pavilion at the end of a pier over waves, monochrome\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"black\",\n      \"white\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.78,\n     \"by\": \"Mouly Kumar\",\n     \"page\": \"https://unsplash.com/photos/TuOiIpkIea8\"\n    },\n    {\n     \"id\": 154,\n     \"alt\": \"Hazy beach at dusk with distant walkers and soft surf\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"dusty pink\",\n      \"muted purple\",\n      \"pale blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Christopher Sardegna\",\n     \"page\": \"https://unsplash.com/photos/x_jTtMOOMd4\"\n    },\n    {\n     \"id\": 162,\n     \"alt\": \"Aerial view of a coastline with turquoise sea and patchwork fields\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"turquoise\",\n      \"sand brown\",\n      \"deep blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Dillon McIntosh\",\n     \"page\": \"https://unsplash.com/photos/SlGVAKyP20U\"\n    },\n    {\n     \"id\": 179,\n     \"alt\": \"Waves breaking around dark rocks on a misty shoreline\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"slate grey\",\n      \"white\",\n      \"warm brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Angelina Odemchuk\",\n     \"page\": \"https://unsplash.com/photos/lp0IFw6YqZg\"\n    },\n    {\n     \"id\": 215,\n     \"alt\": \"Wide empty sandy beach with palm trees and blue sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale sand\",\n      \"sky blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 4,\n     \"ratio\": 1.33,\n     \"by\": \"Paula Borowska\",\n     \"page\": \"https://unsplash.com/photos/04paG2PxKGs\"\n    },\n    {\n     \"id\": 218,\n     \"alt\": \"Calm turquoise bay between two limestone cliffs under storm clouds\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"turquoise\",\n      \"slate grey\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"centre\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Monika Majkowska\",\n     \"page\": \"https://unsplash.com/photos/Nq8LdWC7HnM\"\n    },\n    {\n     \"id\": 268,\n     \"alt\": \"White lifeguard chair standing in dune grass under overcast sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"straw yellow\",\n      \"green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.52,\n     \"by\": \"davide ragusa\",\n     \"page\": \"https://unsplash.com/photos/vc3ZOCf5BN8\"\n    },\n    {\n     \"id\": 317,\n     \"alt\": \"Long wooden pier with railings reaching toward a pastel horizon\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"weathered brown\",\n      \"pale peach\",\n      \"soft blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.78,\n     \"by\": \"Paula Borowska\",\n     \"page\": \"https://unsplash.com/photos/cKYgt4K0g5w\"\n    },\n    {\n     \"id\": 323,\n     \"alt\": \"Steep green headlands dropping into a deep blue bay\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"deep blue\",\n      \"olive green\",\n      \"tan\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Paweł Wojciechowski\",\n     \"page\": \"https://unsplash.com/photos/QYAojSRu82c\"\n    },\n    {\n     \"id\": 347,\n     \"alt\": \"Dune grass bending in wind beneath a wide white sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"straw gold\",\n      \"grey blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Alex Talmon\",\n     \"page\": \"https://unsplash.com/photos/umq-jgTjr28\"\n    },\n    {\n     \"id\": 356,\n     \"alt\": \"Lone surfer walking along a misty beach in black and white\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"charcoal\",\n      \"silver grey\",\n      \"white\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.33,\n     \"by\": \"Daniel Ruswick\",\n     \"page\": \"https://unsplash.com/photos/fqtOAqbbnJg\"\n    },\n    {\n     \"id\": 372,\n     \"alt\": \"Lifeguard tower on an empty sandy beach under a hazy sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale blue\",\n      \"sand\",\n      \"soft grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Gabriel Santiago\",\n     \"page\": \"https://unsplash.com/photos/KWkMiUIxcD0\"\n    },\n    {\n     \"id\": 374,\n     \"alt\": \"Coastline with green headlands, a curving beach and turquoise sea\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"turquoise\",\n      \"deep green\",\n      \"sky blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Ma. Alejandra\",\n     \"page\": \"https://unsplash.com/photos/TDahcrcPhhA\"\n    },\n    {\n     \"id\": 404,\n     \"alt\": \"Waves breaking in white foam around a rugged brown rock\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey blue\",\n      \"white\",\n      \"rust brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Cole Patrick\",\n     \"page\": \"https://unsplash.com/photos/H28ODcp4EUk\"\n    },\n    {\n     \"id\": 440,\n     \"alt\": \"Rugged coastal headlands in soft backlit haze at sunset\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"pale gold\",\n      \"warm brown\",\n      \"cream\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Artur Pokusin\",\n     \"page\": \"https://unsplash.com/photos/0nv-h04oPhM\"\n    },\n    {\n     \"id\": 483,\n     \"alt\": \"Dark sea cliffs and rocks with white surf breaking below\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"charcoal\",\n      \"teal\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.78,\n     \"by\": \"Paulo Simões Mendes\",\n     \"page\": \"https://unsplash.com/photos/hrcRtexM7M0\"\n    },\n    {\n     \"id\": 485,\n     \"alt\": \"White chalk cliffs above a curved beach in sea mist\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"turquoise\",\n      \"sand\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.51,\n     \"by\": \"David Marcu\",\n     \"page\": \"https://unsplash.com/photos/DNXWtB33WWE\"\n    },\n    {\n     \"id\": 574,\n     \"alt\": \"Grassy cliff and black sand beach with sea stacks offshore\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"green\",\n      \"charcoal\",\n      \"pale blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"right\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Julien Lavallée\",\n     \"page\": \"https://unsplash.com/photos/lVtlz3JRV6o\"\n    },\n    {\n     \"id\": 606,\n     \"alt\": \"Wooden boardwalk winding through grassy dunes toward the sea\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"sage green\",\n      \"sand\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Aleksandra Boguslawska\",\n     \"page\": \"https://unsplash.com/photos/MS7KD9Ti7FQ\"\n    },\n    {\n     \"id\": 614,\n     \"alt\": \"Aerial view of white surf washing over a dark rocky shore\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"charcoal\",\n      \"white\",\n      \"dark brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Josefa Holland-Merten\",\n     \"page\": \"https://unsplash.com/photos/GnP5Kfg5ebU\"\n    },\n    {\n     \"id\": 732,\n     \"alt\": \"Dark rocky shoreline beside a calm sea under a pale cloudy sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale blue\",\n      \"soft grey\",\n      \"charcoal\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Dominik Schröder\",\n     \"page\": \"https://unsplash.com/photos/ivieBAESVWM\"\n    },\n    {\n     \"id\": 851,\n     \"alt\": \"Aerial view of turquoise sea meeting a curved reddish coastline\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"turquoise\",\n      \"teal\",\n      \"rust brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.66,\n     \"by\": \"Tiago Aguiar\",\n     \"page\": \"https://unsplash.com/photos/uXzNVOZT5no\"\n    },\n    {\n     \"id\": 969,\n     \"alt\": \"Wet rocky shore with sea stacks under a bright sky, black and white\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"black\",\n      \"grey\",\n      \"silver\"\n     ],\n     \"mono\": true,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Lee Miller\",\n     \"page\": \"https://unsplash.com/photos/_rsGm7nob3w\"\n    },\n    {\n     \"id\": 997,\n     \"alt\": \"Aerial view of a forested headland beside deep blue sea\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"deep blue\",\n      \"forest green\",\n      \"yellow green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 0.68,\n     \"by\": \"Mickey O'neil\",\n     \"page\": \"https://unsplash.com/photos/GSzD6vGIWKM\"\n    },\n    {\n     \"id\": 1055,\n     \"alt\": \"Wide wet sand flat with a distant shoreline under a pale sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"warm brown\",\n      \"sand\",\n      \"off-white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Neil Thomas\",\n     \"page\": \"https://unsplash.com/photos/12rzbJhQ89E\"\n    }\n   ]\n  },\n  \"mountain\": {\n   \"title\": \"Mountain\",\n   \"note\": \"peaks, alpine valleys, snow and rock\",\n   \"sectors\": [\n    \"hospitality\",\n    \"health\",\n    \"event\",\n    \"physical-product\",\n    \"nonprofit\",\n    \"other\",\n    \"education\"\n   ],\n   \"keywords\": [\n    \"mountain\",\n    \"alpine\",\n    \"peak\",\n    \"summit\",\n    \"hike\",\n    \"hiking\",\n    \"climb\",\n    \"outdoor\",\n    \"lodge\",\n    \"chalet\",\n    \"trail\",\n    \"expedition\"\n   ],\n   \"photos\": [\n    {\n     \"id\": 235,\n     \"alt\": \"Snow-covered peak rising above dark forested slopes and a lake\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"slate blue\",\n      \"white\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Paul E. Harrer\",\n     \"page\": \"https://unsplash.com/photos/TI-B-TNYJMU\"\n    },\n    {\n     \"id\": 260,\n     \"alt\": \"Snowy mountain peak framed by dark pine trees in mist\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"pale grey\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"centre\",\n     \"quality\": 5,\n     \"ratio\": 0.67,\n     \"by\": \"Sylwia Bartyzel\",\n     \"page\": \"https://unsplash.com/photos/OdAqbedkfiA\"\n    },\n    {\n     \"id\": 830,\n     \"alt\": \"Layered blue mountain ridges receding into haze\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"cobalt blue\",\n      \"pale blue\",\n      \"navy\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Luca Zanon\",\n     \"page\": \"https://unsplash.com/photos/X0OoHrPvgXE\"\n    },\n    {\n     \"id\": 906,\n     \"alt\": \"Sunlit snowy pyramid peak against a clear blue sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"sky blue\",\n      \"white\",\n      \"dark slate\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.33,\n     \"by\": \"Andras Toth\",\n     \"page\": \"https://unsplash.com/photos/E9CrQou9K0Y\"\n    },\n    {\n     \"id\": 931,\n     \"alt\": \"Layered mountain slopes fading into blue haze\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"steel blue\",\n      \"pale blue\",\n      \"dark teal\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.51,\n     \"by\": \"Paul Earle\",\n     \"page\": \"https://unsplash.com/photos/xJ2tjuUHD9M\"\n    },\n    {\n     \"id\": 1018,\n     \"alt\": \"Green cliffs and a winding road under low mist\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"moss green\",\n      \"mist grey\",\n      \"dark brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.33,\n     \"by\": \"Andrew Ridley\",\n     \"page\": \"https://unsplash.com/photos/Kt5hRENuotI\"\n    },\n    {\n     \"id\": 29,\n     \"alt\": \"Rocky ridges and snow-covered peaks in a high mountain range\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"slate grey\",\n      \"white\",\n      \"blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Go Wild\",\n     \"page\": \"https://unsplash.com/photos/V0yAek6BgGk\"\n    },\n    {\n     \"id\": 66,\n     \"alt\": \"Lone mountain peak beyond open grassland under heavy grey cloud\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"olive green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.33,\n     \"by\": \"Nicholas Swanson\",\n     \"page\": \"https://unsplash.com/photos/agnhLQWqr1Q\"\n    },\n    {\n     \"id\": 121,\n     \"alt\": \"Hazy mountain gorge with steep slopes in black and white\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"black\",\n      \"white\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Radio Pink\",\n     \"page\": \"https://unsplash.com/photos/p-bkdO43shE\"\n    },\n    {\n     \"id\": 166,\n     \"alt\": \"Moody valley with a river, dark hills and a foreground boulder\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"charcoal\",\n      \"grey\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.78,\n     \"by\": \"Romain Briaux\",\n     \"page\": \"https://unsplash.com/photos/yD3PXDV7Sjc\"\n    },\n    {\n     \"id\": 296,\n     \"alt\": \"Snow-capped mountain range beneath a deep blue sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"deep blue\",\n      \"white\",\n      \"dark brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Greg Shield\",\n     \"page\": \"https://unsplash.com/photos/Du30R57aCyM\"\n    },\n    {\n     \"id\": 327,\n     \"alt\": \"Snow-covered mountain range under a clear teal sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"teal\",\n      \"white\",\n      \"rust brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Ryan Schroeder\",\n     \"page\": \"https://unsplash.com/photos/Gg7uKdHFb_c\"\n    },\n    {\n     \"id\": 368,\n     \"alt\": \"Sheer granite cliffs above a hazy valley in warm evening light\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"peach\",\n      \"warm grey\",\n      \"slate\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Tyssul Patel\",\n     \"page\": \"https://unsplash.com/photos/o-zOatT4kQw\"\n    },\n    {\n     \"id\": 377,\n     \"alt\": \"Snow-capped mountain range under a dark blue evening sky\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"navy\",\n      \"slate blue\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Martin Staněk\",\n     \"page\": \"https://unsplash.com/photos/8WClaa1CmZ0\"\n    },\n    {\n     \"id\": 393,\n     \"alt\": \"Green mountain streaked with snow rising above a dark gravel plain\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"moss green\",\n      \"charcoal\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Alex Talmon\",\n     \"page\": \"https://unsplash.com/photos/UFskvng2OMU\"\n    },\n    {\n     \"id\": 426,\n     \"alt\": \"Layered blue mountains and a hazy valley under streaked clouds\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"slate blue\",\n      \"teal\",\n      \"pale grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Ales Krivec\",\n     \"page\": \"https://unsplash.com/photos/01ZeHnK3F_4\"\n    },\n    {\n     \"id\": 450,\n     \"alt\": \"Turquoise lake in a forested valley between snow-dusted mountains\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"turquoise\",\n      \"slate grey\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.51,\n     \"by\": \"Tanvi Malik\",\n     \"page\": \"https://unsplash.com/photos/OeC1wIsKNpk\"\n    },\n    {\n     \"id\": 523,\n     \"alt\": \"Volcanic crater rising from a hazy plain beneath a teal sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"teal\",\n      \"tan\",\n      \"brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 2.21,\n     \"by\": \"Harman Abiwardani\",\n     \"page\": \"https://unsplash.com/photos/WLUHO9A_xik\"\n    },\n    {\n     \"id\": 538,\n     \"alt\": \"Bird soaring above snowy mountain ridges in black and white\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"white\",\n      \"black\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.51,\n     \"by\": \"Julia Revitt\",\n     \"page\": \"https://unsplash.com/photos/yypv2Tu-mxU\"\n    },\n    {\n     \"id\": 565,\n     \"alt\": \"Snowy peak veiled in cloud with birds crossing a white sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"pale grey\",\n      \"dark brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"René Reichelt\",\n     \"page\": \"https://unsplash.com/photos/HzaT5l4Fzqc\"\n    },\n    {\n     \"id\": 591,\n     \"alt\": \"Jagged rock pinnacle rising through swirling white cloud\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"grey\",\n      \"tan\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 0.75,\n     \"by\": \"Billy Onjea\",\n     \"page\": \"https://unsplash.com/photos/_qGq1Z2Bk6c\"\n    },\n    {\n     \"id\": 684,\n     \"alt\": \"Jagged snow-covered peaks under a dark blue sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"navy\",\n      \"white\",\n      \"slate blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.78,\n     \"by\": \"Lee Roylland\",\n     \"page\": \"https://unsplash.com/photos/dfZbts6B4yw\"\n    },\n    {\n     \"id\": 735,\n     \"alt\": \"Steep dark cliffs with fog drifting through the gap between them\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"charcoal\",\n      \"mist grey\",\n      \"deep green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"centre\",\n     \"quality\": 4,\n     \"ratio\": 0.62,\n     \"by\": \"wyman H\",\n     \"page\": \"https://unsplash.com/photos/ZQeRH1XD4Tc\"\n    },\n    {\n     \"id\": 809,\n     \"alt\": \"Rocky mountain peak breaking through thick white clouds\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"slate grey\",\n      \"blue grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Namphuong Van\",\n     \"page\": \"https://unsplash.com/photos/sP4UZnpSiN4\"\n    },\n    {\n     \"id\": 814,\n     \"alt\": \"Jagged rocky peaks under a soft pink and violet dusk sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"dusty violet\",\n      \"soft pink\",\n      \"slate grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.53,\n     \"by\": \"Ales Krivec\",\n     \"page\": \"https://unsplash.com/photos/duoMdMm3aY0\"\n    },\n    {\n     \"id\": 827,\n     \"alt\": \"Conical mountain silhouette above a still lake under a starry dusk sky\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"indigo\",\n      \"dusky violet\",\n      \"navy\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 0.67,\n     \"by\": \"kazuend\",\n     \"page\": \"https://unsplash.com/photos/2KXEb_8G5vo\"\n    },\n    {\n     \"id\": 866,\n     \"alt\": \"Snowy mountain peak behind a snow slope under pink-tinted clouds\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"dusky blue\",\n      \"soft pink\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Samuel Zeller\",\n     \"page\": \"https://unsplash.com/photos/9RqA6tnT0gA\"\n    },\n    {\n     \"id\": 873,\n     \"alt\": \"Turquoise lake between steep rocky mountains with distant snow\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"teal\",\n      \"slate grey\",\n      \"pale cream\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 0.67,\n     \"by\": \"Daniel Roe\",\n     \"page\": \"https://unsplash.com/photos/lpjb_UMOyx8\"\n    },\n    {\n     \"id\": 918,\n     \"alt\": \"Rocky peak wrapped in sunlit cloud above a forested valley\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"warm gold\",\n      \"dark green\",\n      \"grey brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.51,\n     \"by\": \"David Marcu\",\n     \"page\": \"https://unsplash.com/photos/CaQ_KITtnVY\"\n    },\n    {\n     \"id\": 929,\n     \"alt\": \"Green cliff face rising out of dense white mist\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"moss green\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Tiago Muraro\",\n     \"page\": \"https://unsplash.com/photos/1kEHpwZdmtc\"\n    }\n   ]\n  },\n  \"forest\": {\n   \"title\": \"Forest\",\n   \"note\": \"woodland, paths between trees, moss and filtered light\",\n   \"sectors\": [\n    \"hospitality\",\n    \"health\",\n    \"nonprofit\",\n    \"education\",\n    \"physical-product\",\n    \"other\"\n   ],\n   \"keywords\": [\n    \"forest\",\n    \"wood\",\n    \"tree\",\n    \"cabin\",\n    \"nature\",\n    \"green\",\n    \"organic\",\n    \"sustainable\",\n    \"timber\",\n    \"garden\"\n   ],\n   \"photos\": [\n    {\n     \"id\": 229,\n     \"alt\": \"Path through tall pine trees fading into blue-grey fog\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"blue grey\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Orlova Maria\",\n     \"page\": \"https://unsplash.com/photos/7FLh300YONc\"\n    },\n    {\n     \"id\": 10,\n     \"alt\": \"Dense evergreen forest with a blue lake and distant hills beyond\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"deep green\",\n      \"teal blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Paul Jarvis\",\n     \"page\": \"https://unsplash.com/photos/6J--NXulQCs\"\n    },\n    {\n     \"id\": 190,\n     \"alt\": \"Path winding between rows of tall pine trunks\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"dark brown\",\n      \"moss green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"James Forbes\",\n     \"page\": \"https://unsplash.com/photos/jrzvClypPq8\"\n    },\n    {\n     \"id\": 216,\n     \"alt\": \"Narrow dirt trail through mossy green woodland\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"moss green\",\n      \"brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Paul Jarvis\",\n     \"page\": \"https://unsplash.com/photos/9702xTENR-M\"\n    },\n    {\n     \"id\": 243,\n     \"alt\": \"Autumn larch forest on a foggy hillside with a footpath\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"rust brown\",\n      \"pale grey\",\n      \"olive green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Orlova Maria\",\n     \"page\": \"https://unsplash.com/photos/DYW1s0AfLwo\"\n    },\n    {\n     \"id\": 423,\n     \"alt\": \"Snow-laden fir trees fading into pale winter fog\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"pale blue\",\n      \"grey green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"centre\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Gabriel Santiago\",\n     \"page\": \"https://unsplash.com/photos/pTgTMVxQE_k\"\n    },\n    {\n     \"id\": 476,\n     \"alt\": \"Sunlight bursting between tall redwood trunks in a shaded forest\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"dark brown\",\n      \"deep green\",\n      \"gold\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Mr. Marco\",\n     \"page\": \"https://unsplash.com/photos/QP1dUyQ8WsI\"\n    },\n    {\n     \"id\": 498,\n     \"alt\": \"Upward view of towering redwood trunks converging toward the canopy\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"green\",\n      \"reddish brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Kim Daniel\",\n     \"page\": \"https://unsplash.com/photos/JsqAqevX6lg\"\n    },\n    {\n     \"id\": 559,\n     \"alt\": \"Snow-covered lane lined with bare frosted trees\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"grey brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 4,\n     \"ratio\": 1.51,\n     \"by\": \"Ali Inay\",\n     \"page\": \"https://unsplash.com/photos/yNaGxHqjOuw\"\n    },\n    {\n     \"id\": 600,\n     \"alt\": \"Sunbeams streaming through tall conifers in a dark forest\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"dark green\",\n      \"pale gold\",\n      \"black\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Dustin Scarpitti\",\n     \"page\": \"https://unsplash.com/photos/eWBseWsTEpA\"\n    },\n    {\n     \"id\": 704,\n     \"alt\": \"Upward view of tall bamboo stems converging in a green canopy\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"dark green\",\n      \"green\",\n      \"black\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Ståle Grut\",\n     \"page\": \"https://unsplash.com/photos/NUgw97CVdAk\"\n    },\n    {\n     \"id\": 730,\n     \"alt\": \"Snow-dusted conifer forest fading into pale winter fog\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"frost white\",\n      \"pale grey\",\n      \"slate green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Ryan Pohanic\",\n     \"page\": \"https://unsplash.com/photos/W3V2tQAZxPA\"\n    },\n    {\n     \"id\": 805,\n     \"alt\": \"Band of dark conifer forest between a meadow and a blank white sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"white\",\n      \"dark green\",\n      \"olive brown\"\n     ],\n     \"mono\": false,\n     \"calm\"\n\n<!-- [TRUNCATED AT 50KB] -->","skills/taste-skill/library/sections.json":"[\n {\n  \"id\": \"features-capabilities-at-poster-scale\",\n  \"role\": \"features\",\n  \"name\": \"Capabilities at poster scale\",\n  \"shape\": \"list\",\n  \"tags\": [\n   \"type-led\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"type-only-statement\",\n   \"hero-object\",\n   \"loud-flat-poster\",\n   \"borrowed-category\",\n   \"colour-chapters\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"No images. The heading, two to four words, is the first line of the list itself, set at the same size as the items but in the soft ink, so no separate title sits above. Five to eight capability names follow, one per line, at clamp(40px, 5.2vw, 84px), medium to heavy weight, leading 1.0, tight tracking, flush left on the page margin across columns 1–8 of 12. Each name's one-sentence description is set at 16–18px in columns 9–12, its first baseline aligned with the name's baseline (CSS grid, align-items: first baseline). Rows are separated by 0.35em of space and nothing else. On hover one row keeps full ink while the others fall to 35% opacity. Leave 18–22vh of empty ground above and below; nothing else shares the section.\",\n  \"mobile\": \"Names drop to 11vw and stay one per line; a name that will not fit breaks onto a second line with a hanging indent. Each description sits directly under its name at 16px, indented one margin width, with 28px before the next name. The soft-ink heading line stays as the first row. All rows at full ink.\",\n  \"seenIn\": [\n   \"aww-cominvi\",\n   \"aww-cerebrium\",\n   \"opl-specia1ne\"\n  ]\n },\n {\n  \"id\": \"features-pinned-heading-passing-rows\",\n  \"role\": \"features\",\n  \"name\": \"Pinned heading, passing rows\",\n  \"shape\": \"pinned\",\n  \"tags\": [\n   \"colour-field\",\n   \"type-led\"\n  ],\n  \"directions\": [\n   \"pinned-poster\",\n   \"loud-flat-poster\",\n   \"colour-chapters\",\n   \"split-stage\",\n   \"editorial-report\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One flat saturated field, full-bleed, as tall as its content. Columns 1–5: the heading, two or three words, at clamp(56px, 6.6vw, 104px) in the heaviest weight, position: sticky; top: 32px, so it holds while the right side travels. Columns 7–12: four to six capability blocks stacked with 120px between them. Each block is a title at 28px bold, then a two-part row: a portrait photograph at 3:4, 180–220px wide with square corners, and beside it, top-aligned, a plain list of four to six short lines at 18px with 14px between lines. Photographs alternate between the left and the right of their list, so the column does not read as a ladder. One ink colour, chosen for contrast on the field. The heading releases when the bottom of the last block reaches it.\",\n  \"mobile\": \"The heading becomes a sticky bar at the top of the section: one line at 9vw on the field colour with 12px padding, holding while blocks pass under it. Each block stacks its title, a full-width 4:3 photograph, then the list at 17px. 72px between blocks.\",\n  \"seenIn\": [\n   \"opl-protip-marketing\",\n   \"aww-cerebrium\",\n   \"aww-sharplink\"\n  ]\n },\n {\n  \"id\": \"features-one-scene-stepping-statements\",\n  \"role\": \"features\",\n  \"name\": \"One scene, stepping statements\",\n  \"shape\": \"full-bleed\",\n  \"tags\": [\n   \"photo-led\"\n  ],\n  \"directions\": [\n   \"place-carries-it\",\n   \"pinned-poster\",\n   \"dark-room\",\n   \"hero-object\",\n   \"uneven-photographs\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A wrapper 350–450vh tall holds a sticky full-bleed photograph (100vw by 100svh) with a calm, symmetrical subject and a clear upper third; a neutral dark scrim covers only that upper third. At top centre, five or six short statements of two to five words are stacked at 18–20px with 10px between them; the first of them is the section's heading. One statement is at full white and the rest at 45% opacity; the active line steps down the stack as the reader scrolls (IntersectionObserver on invisible 70vh markers). For each statement, two small photographs with square corners, 160–240px wide and of different ratios, fade in left and right of the centre line at different heights, then leave when the next pair arrives. No other text. A low-key image on a deep ground works equally well.\",\n  \"mobile\": \"The photograph stays sticky at 100svh, cropped to its centre. The statement stack moves to the bottom third over a scrim, at 17px, left-aligned on the margin. Each statement brings one small photograph only, 44vw wide, placed in the top-right corner with a 16px margin.\",\n  \"seenIn\": [\n   \"aww-seasats\",\n   \"opl-eagles-nest\"\n  ]\n },\n {\n  \"id\": \"features-stacking-colour-sheets\",\n  \"role\": \"features\",\n  \"name\": \"Stacking colour sheets\",\n  \"shape\": \"stack\",\n  \"tags\": [\n   \"colour-field\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"colour-chapters\",\n   \"page-is-the-object\",\n   \"pinned-poster\",\n   \"loud-flat-poster\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Three to five capabilities, each a full-width flat colour sheet about 86svh tall with only its top corners rounded at 28px. Every sheet is position: sticky, with top offsets rising by 72px from one sheet to the next, so each new sheet slides up over the last and leaves the previous sheet's title band showing, like tabbed folders in a drawer. Inside a sheet: the capability name top-left at clamp(28px, 3vw, 44px), sitting within that 72px band; a paragraph of up to 40ch at 18px bottom-left; and in columns 7–12 one photograph filling the sheet from below the band to the bottom edge, square corners, no inset. Sheet colours follow the palette in a fixed order, with ink chosen per sheet. The heading, two to four words at clamp(40px, 5vw, 80px), sits on the ground above the stack with 48px beneath and scrolls away normally.\",\n  \"mobile\": \"Sheets stay sticky but the offset shrinks to 52px and the name drops to 22px so it fits the visible band. Inside each sheet the photograph comes first at 4:3 and full width, then the paragraph at 17px with 20px padding. Sheets are as tall as their content, 70svh at least.\",\n  \"seenIn\": [\n   \"aww-hilden-kaira\",\n   \"opl-nia-creative\",\n   \"opl-april-leihuanani-evangelista\",\n   \"aww-mosbys-files\"\n  ]\n },\n {\n  \"id\": \"features-mosaic-of-unlike-tiles\",\n  \"role\": \"features\",\n  \"name\": \"Mosaic of unlike tiles\",\n  \"shape\": \"mosaic\",\n  \"tags\": [\n   \"dense\",\n   \"colour-field\"\n  ],\n  \"directions\": [\n   \"dense-tiles\",\n   \"editorial-report\",\n   \"colour-chapters\",\n   \"specimen-catalogue\",\n   \"loud-flat-poster\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A 12-column grid with 8px gaps and rows of 96px, filled with no empty cells and no outlines. Six to eight filled tiles in four sizes only: 6×5, 6×3, 3×3 and 3×2 (columns × rows). The rule that keeps it from being a card grid: no two neighbouring tiles hold the same kind of thing. One tile is the heading alone, two to four words at 4vw, top-left. One is a photograph covering its tile. One is a single figure at 6vw with a caption. One is a short list of four lines at 20px. The others are a single sentence each at 28–32px. Text sits top-left with 24px padding; tiles holding one sentence leave their lower half empty. Tile fills: the ground one tone darker, two palette colours, and photographs. One corner radius everywhere, either 0 or 8px.\",\n  \"mobile\": \"Two columns with 6px gaps. The heading tile and the photograph tile span both columns; sentence tiles span both at their natural height; the figure and list tiles sit side by side as a pair of squares. Order: heading, photograph, pair, sentence, sentence.\",\n  \"seenIn\": [\n   \"opl-sand-studio\",\n   \"opl-builders-table\",\n   \"aww-cominvi\",\n   \"opl-uglycash\"\n  ]\n },\n {\n  \"id\": \"features-statement-cell-dark-rows\",\n  \"role\": \"features\",\n  \"name\": \"Statement cell, dark rows\",\n  \"shape\": \"split\",\n  \"tags\": [\n   \"type-led\",\n   \"dense\"\n  ],\n  \"directions\": [\n   \"dense-tiles\",\n   \"editorial-report\",\n   \"type-only-statement\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Two halves butted together, each 50vw wide and at least 90svh tall, with no gap. Left half, in a pale tone: the heading in three short lines at clamp(36px, 4.2vw, 68px), its middle line pushed flush right while the first and third stay flush left (text-align set per line), so the block zigzags inside the cell. A two-sentence paragraph of 30ch sits at the bottom-left and the single action at the bottom-right on the same baseline. Right half, in the darkest tone: four or five rows of equal height filling it, told apart by alternating two near-black tones, not by lines. Each row is a three-part grid: a title at 28px (5 parts), a short paragraph at 16px (4 parts) and a plain list of three terms at 15px (3 parts), all top-aligned with 28px padding. No images anywhere in the section.\",\n  \"mobile\": \"The halves stack. The light cell comes first at 70svh with the zigzag heading at 10vw and the paragraph at its foot. The dark rows follow at full width; each row stacks its title and paragraph, and its three terms run inline as one sentence separated by commas. Rows keep the alternating tones.\",\n  \"seenIn\": [\n   \"aww-aspen-search\"\n  ]\n },\n {\n  \"id\": \"features-staggered-fragment-cells\",\n  \"role\": \"features\",\n  \"name\": \"Staggered fragment cells\",\n  \"shape\": \"grid\",\n  \"tags\": [\n   \"ui-led\",\n   \"dense\"\n  ],\n  \"directions\": [\n   \"product-performs\",\n   \"dense-tiles\",\n   \"quiet-instrument\"\n  ],\n  \"needs\": [\n   \"product-ui\"\n  ],\n  \"blueprint\": \"A three-column grid of six filled cells with 8px gaps, each cell 420–460px tall and filled one tone off the ground, no outlines. Every cell has two parts: a text part (a title at 17px medium and three lines at 15px in the soft ink, 24px padding) and a real fragment of the interface at true size (a control, a menu, a table slice, a swatch strip) docked flush against the opposite edge of the cell and cropped by it. The stagger is the idea: across the first row cells run text-top, fragment-top, text-top; the second row runs the reverse, so fragments form a checkerboard. Fragments differ in shape and size on purpose. The heading, two to four words at 32–40px, sits left-aligned above the grid with 56px beneath it and no supporting line.\",\n  \"mobile\": \"One column of cells at their natural height with 6px gaps. Every cell runs text first, fragment second, but fragments alternate between docking to the left edge and the right edge, and they are allowed to run off the side of the cell at true size instead of shrinking.\",\n  \"seenIn\": [\n   \"opl-dabbit\",\n   \"opl-woblo\"\n  ]\n },\n {\n  \"id\": \"features-small-proof-beside-text\",\n  \"role\": \"features\",\n  \"name\": \"Small proof beside text\",\n  \"shape\": \"list\",\n  \"tags\": [\n   \"quiet\",\n   \"ui-led\"\n  ],\n  \"directions\": [\n   \"quiet-instrument\",\n   \"product-performs\",\n   \"split-stage\",\n   \"name-as-monument\",\n   \"contact-sheet\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One narrow module repeated four to six times down the page, never alternating sides. Each module is 640px wide at most and starts on the page's text margin (at about 22% of the viewport on an understated page). Left part: a flat panel 360px wide and 120 to 200px tall, one tone off the ground, radius 8px, holding one small exact demonstration: a cropped interface fragment at true size, or a tightly cropped photograph covering the panel. Right part, 20px away and top-aligned: a heading of one or two lines at 18px medium and two short paragraphs at 15px in the soft ink, in a column 250px wide. Panel heights vary with their content; text always hangs from the panel's top edge. 96–120px of empty ground between modules. The section heading is 24–28px, on the same left edge, 64px above the first module. In a column under 600px the text moves beneath its panel.\",\n  \"mobile\": \"Each module stacks: the panel at full width and natural height, then heading and paragraphs 16px below on the same left edge, at 17px and 15px. 64px between modules. Panels keep their true-size contents and crop from the right instead of scaling down.\",\n  \"seenIn\": [\n   \"opl-rows\"\n  ]\n },\n {\n  \"id\": \"features-comparison-set-as-text\",\n  \"role\": \"features\",\n  \"name\": \"Comparison set as text\",\n  \"shape\": \"table\",\n  \"tags\": [\n   \"type-led\",\n   \"quiet\"\n  ],\n  \"directions\": [\n   \"type-only-statement\",\n   \"editorial-report\",\n   \"product-performs\",\n   \"quiet-instrument\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A comparison table with no lines and no tick marks. A CSS grid: capability names in columns 1–5 of 12 at 22–24px medium, then three answer columns of equal width (plans, methods, or this against the usual way). Every cell answers in words at 17px: 'Yes, unlimited', 'Up to five', 'Not yet', never a symbol. Seven to ten rows, each 64–72px tall, with every other row on a ground one tone darker so the eye tracks across; rows touch. The column that matters is one filled block in the accent or ink colour running the full height of the table behind its cells and rising 24px above the first row, with its text reversed. Column names sit in the top row at 17px bold. The heading, two to four words at 40–48px, hangs top-left above column 1 with 48px beneath.\",\n  \"mobile\": \"The table turns on its side: one block per capability. The name at 20px bold, then three lines beneath, each giving a column name and its answer at 16px; the featured column's line is set on the filled colour at full width. Blocks alternate the two ground tones.\",\n  \"seenIn\": [\n   \"aww-pp-neue-montreal\"\n  ]\n },\n {\n  \"id\": \"features-one-size-name-columns\",\n  \"role\": \"features\",\n  \"name\": \"One-size name columns\",\n  \"shape\": \"index\",\n  \"tags\": [\n   \"quiet\",\n   \"type-led\",\n   \"dense\"\n  ],\n  \"directions\": [\n   \"contact-sheet\",\n   \"quiet-instrument\",\n   \"name-as-monument\",\n   \"dark-room\",\n   \"uneven-photographs\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Pure text at one size. Three columns start on columns 1, 4 and 7 of the 12-column grid, leaving columns 10–12 empty on purpose. Each column opens with a group name in full ink and continues with a tight stack of six to ten capability names in the soft ink, all at 16–17px, regular weight, line-height 1.25, no bullets and no symbols; one blank line separates group name from stack. Hovering a name brings it to full ink and shows a one-line description in a fixed spot: the top of the empty columns 10–12, at the same size. The heading is no larger than 28px; two or three words, alone on column 1, 96px above the columns. Give the section 20vh of empty ground above and below, so the smallness reads as decided. Works on light or deep grounds.\",\n  \"mobile\": \"Columns stack with 40px between groups; text rises to 18px with line-height 1.4 for touch. Group names stay in full ink. Hover descriptions are dropped; each group ends instead with one sentence in the soft ink that sums it up. The heading is 24px, 48px above.\",\n  \"seenIn\": [\n   \"aww-revelatio-studio\",\n   \"aww-pp-neue-montreal\",\n   \"aww-lama-lama-2\"\n  ]\n },\n {\n  \"id\": \"features-specimens-on-colour-tiles\",\n  \"role\": \"features\",\n  \"name\": \"Specimens on colour tiles\",\n  \"shape\": \"grid\",\n  \"tags\": [\n   \"object-led\",\n   \"colour-field\"\n  ],\n  \"directions\": [\n   \"specimen-catalogue\",\n   \"hero-object\",\n   \"one-motif\",\n   \"colour-chapters\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Each capability is represented by one object photographed alone and shown on a flat colour tile. Columns 1–3 hold the heading (two to four words at 40–52px), top-aligned, with a 30ch sentence beneath and nothing else down the rest of that column. Columns 4–12 hold a grid of five or six tiles in two rows with 10px gaps: tiles are 4:5 except one, which is double width at 8:5 and placed second in the first row. Tile colours rotate through three palette fields. Each photograph is centred at about 70% of its tile's height; on light tiles use mix-blend-mode: multiply so a white studio background disappears. Under each tile, outside it and aligned to its left edge: the capability name at 20px medium and one fact at 16px in the soft ink. No text on the tiles and no hover lift.\",\n  \"mobile\": \"The heading and its sentence sit on top at full width. Tiles become a two-column grid with 8px gaps; the double tile spans both columns at 8:5 and comes first. Names shrink to 17px and facts to 15px, still under each tile.\",\n  \"seenIn\": [\n   \"aww-noho\",\n   \"aww-coffeetech-r\",\n   \"opl-when-you-wish-upon-a-starboy\"\n  ]\n },\n {\n  \"id\": \"features-statements-on-colour-fields\",\n  \"role\": \"features\",\n  \"name\": \"Statements on colour fields\",\n  \"shape\": \"statement\",\n  \"tags\": [\n   \"colour-field\",\n   \"poster\",\n   \"type-led\"\n  ],\n  \"directions\": [\n   \"colour-chapters\",\n   \"loud-flat-poster\",\n   \"type-only-statement\",\n   \"sentence-as-layout\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Three or four full-bleed flat colour fields, each 72–80svh tall, butted together with no gap. Each field holds one benefit and is almost empty. The benefit is a phrase of two to four words at clamp(56px, 9vw, 150px), heavy, leading 0.9, on two lines at most, hugging the bottom-left corner with 28px margins. Its explanation is three lines at 17–18px, 30ch wide, placed near the top at column 8, so the eye travels the diagonal from small text to big phrase. On alternate fields the arrangement mirrors: phrase bottom-right and right-aligned, paragraph top-left at column 2. Text on each field is ink or paper, whichever contrasts more. There is no separate section heading: the first field's phrase is the heading. Nothing else appears on the fields: no images, shapes or buttons.\",\n  \"mobile\": \"Fields are 64svh tall. The paragraph sits top-left at 16px across 80% of the width; the phrase sits bottom-left at 13vw on two lines. Mirroring is dropped; alternate fields right-align the paragraph only, keeping the phrase on the left margin.\",\n  \"seenIn\": [\n   \"opl-anidachi\",\n   \"aww-px-push\"\n  ]\n },\n {\n  \"id\": \"features-rows-with-margin-photographs\",\n  \"role\": \"features\",\n  \"name\": \"Rows with margin photographs\",\n  \"shape\": \"list\",\n  \"tags\": [\n   \"type-led\",\n   \"photo-led\"\n  ],\n  \"directions\": [\n   \"editorial-report\",\n   \"uneven-photographs\",\n   \"place-carries-it\",\n   \"sentence-as-layout\",\n   \"colour-chapters\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Everything hangs from one vertical axis at column 5, about 35% of the width. First the heading: a statement of up to five words at clamp(40px, 5vw, 80px) starting on the axis, vertically centred in an otherwise empty 70svh of ground. Then four or five benefit rows, each starting on the same axis: a title at clamp(28px, 3vw, 48px) and under it a paragraph of 34ch at 17px. Columns 1–4 stay empty. At the right margin each row carries one photograph, top-aligned with its title and deliberately unequal: 240px wide at 4:5 in one row, 320px at 3:2 in the next, 180px square after that. Rows are separated by 96–120px of space, not lines. On a saturated field, set all type in one pale ink and leave the photographs ungraded.\",\n  \"mobile\": \"The axis collapses to the left margin. The statement sits at 9vw in 50svh of empty ground. Each row stacks its title at 26px, the paragraph, then its photograph at alternating widths: 100%, 70% flush right, 55% flush left. 64px between rows.\",\n  \"seenIn\": [\n   \"aww-px-push\"\n  ]\n },\n {\n  \"id\": \"features-paragraph-with-picture-words\",\n  \"role\": \"features\",\n  \"name\": \"Paragraph with picture words\",\n  \"shape\": \"statement\",\n  \"tags\": [\n   \"type-led\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"sentence-as-layout\",\n   \"one-motif\",\n   \"product-performs\",\n   \"editorial-report\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One paragraph does the work of a feature grid. Three or four sentences, 35–50 words in total, set at clamp(30px, 3.6vw, 60px), leading 1.18, medium weight, across columns 1–11, left-aligned. Each sentence names one capability, and directly after that capability's key noun sits an inline slot: an inline-block frame 1em tall and 1.9em wide, radius 0.18em, dropped 0.12em below the baseline, holding a tight photograph crop (object-fit: cover) or a real interface control at readable size. Four slots at most, never two on one line. The nouns keep the weight and colour of the rest; the slots are the only emphasis. Mark it up as a paragraph and give the section a visually hidden heading of two or three words; nothing visible sits above. 72px lower, starting at column 7, one supporting sentence at 18px and the action.\",\n  \"mobile\": \"The paragraph drops to 7vw with leading 1.22 and fills the width. Slots stay inline at 1em tall but narrow to 1.5em wide. If a slot lands alone at the start of a line, let it; do not shrink the type. The supporting sentence and the action follow at full width.\",\n  \"seenIn\": [\n   \"aww-monolog\",\n   \"opl-uncle-rudy\",\n   \"aww-cominvi\",\n   \"opl-midnight-2\"\n  ]\n },\n {\n  \"id\": \"features-capabilities-as-a-menu\",\n  \"role\": \"features\",\n  \"name\": \"Capabilities as a menu\",\n  \"shape\": \"table\",\n  \"tags\": [\n   \"object-led\",\n   \"type-led\"\n  ],\n  \"directions\": [\n   \"page-is-the-object\",\n   \"split-stage\",\n   \"borrowed-category\",\n   \"type-only-statement\",\n   \"quiet-instrument\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"The capabilities are set as a printed menu or price list. One paper-coloured sheet, 520–600px wide and taller than it is wide, sits on a contrasting flat ground, centred or starting at column 2; its top and bottom edges are cut into shallow scallops or a zigzag with clip-path, its sides straight. On it, centred at the top, the heading: two or three words at 44–56px, then 40px of space. Below, items in two or three groups; each group opens with its name at 20px bold. Each item is a row: the name at 19px on the left, a short value on the right (a price, a time, a quantity, 'included'), and between them a leader of round 4px dots (border-bottom: 4px dotted, sitting on the baseline). A description at 15px in the soft ink sits under the name, at most 34ch. 18px between items, 44px between groups.\",\n  \"mobile\": \"The sheet fills the width minus 12px margins and keeps its cut top and bottom edges. Names stay left and values right on one line with the dot leader between; descriptions wrap beneath at 15px. Group names drop to 18px. Padding inside the sheet is 20px.\",\n  \"seenIn\": [\n   \"opl-the-content-architecture\",\n   \"aww-pensatori-irrazionali\"\n  ]\n },\n {\n  \"id\": \"features-shape-marked-small-points\",\n  \"role\": \"features\",\n  \"name\": \"Shape-marked small points\",\n  \"shape\": \"split\",\n  \"tags\": [\n   \"object-led\",\n   \"quiet\"\n  ],\n  \"directions\": [\n   \"one-motif\",\n   \"hero-object\",\n   \"product-performs\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"For the many minor points that do not deserve a row each. Columns 1–5: one photograph inside a single large shape taken from the subject's own geometry (a circle, an arch, a chamfered block), made with clip-path or border-radius, about 78svh tall and pushed 12% past the section's left edge so the viewport crops it. Columns 7–12: the heading, two to four words at 40–48px, then 56px lower a grid of eight to twelve points in three columns with 40px column gaps and 44px row gaps, no cells and no fills. Each point is a title at 17px medium preceded by the same shape drawn at cap height (0.7em, flat fill, inline SVG or a styled span), then two lines at 15px in the soft ink. The small shapes take a different palette colour per column, which is the only colour on the right side.\",\n  \"mobile\": \"The shaped photograph comes first, 82vw wide, cropped by the left edge and no taller than 60svh. The heading follows at 30px. Points become one column with 28px between them; the small shape hangs in the margin to the left of each title, so titles and text share one edge.\",\n  \"seenIn\": [\n   \"opl-dabbit\",\n   \"aww-sstr-friction-reduction\"\n  ]\n },\n {\n  \"id\": \"showcase-two-giant-words-compared\",\n  \"role\": \"showcase\",\n  \"name\": \"Two giant words compared\",\n  \"shape\": \"statement\",\n  \"tags\": [\n   \"type-led\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"type-only-statement\",\n   \"editorial-report\",\n   \"loud-flat-poster\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"No photographs: the thing shown is a pair of words, characters or figures that make the point by comparison (before and after, input and output, ours and the usual). At the top of the section, on one row: the heading, two to four words at 28–36px, at the left margin, and a paragraph of up to 60 words at 17px starting at column 7. Then 12vh of space. Below, two specimens side by side, one starting on column 1 and one on column 7, each set at clamp(180px, 34vw, 520px) with leading 0.8, so each fills about half the viewport's width. The section has a fixed height and overflow: hidden, so its bottom edge cuts both specimens at roughly 60% of their height. One short caption at 16px sits above the top-left of each specimen, naming it. Both specimens share one ink; the difference is in the letterforms or values, not in colour.\",\n  \"mobile\": \"Heading first, then the paragraph, at full width. The two specimens stack, each at 62vw type size in its own 38svh box with overflow hidden so the lower part is cut. Captions sit above each box at 15px. The second box takes the inverse colours of the first.\",\n  \"seenIn\": [\n   \"aww-pp-neue-montreal\"\n  ]\n },\n {\n  \"id\": \"showcase-two-objects-two-fields\",\n  \"role\": \"showcase\",\n  \"name\": \"Two objects, two fields\",\n  \"shape\": \"split\",\n  \"tags\": [\n   \"object-led\",\n   \"colour-field\"\n  ],\n  \"directions\": [\n   \"specimen-catalogue\",\n   \"hero-object\",\n   \"colour-chapters\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Two panels side by side, each 50vw wide and 92svh tall, in two different flat tones from the palette, meeting on a clean vertical edge with no gap. Each panel is dominated by one cut-out object photograph scaled to 130–150% of the panel's width and positioned so the panel's top edge crops it: the reader sees the lower two-thirds of the object, very close. On light panels use mix-blend-mode: multiply to lose a white studio background. Along the bottom of each panel, 28px in from the edges, one row: the name at 20px medium and a price or fact at 17px on the left; on the right, two small rectangular actions, one filled with ink and one with paper. Nothing sits in the middle of a panel. The heading, two to four words at 32–40px, is set at the top-left of the first panel only, in the empty corner beside the object.\",\n  \"mobile\": \"Panels stack, each 78svh tall, the object scaled to 150% of the width and cut by the top and right edges. The bottom row becomes two lines: name and fact, then the two actions side by side at full width. The heading sits top-left on the first panel at 26px.\",\n  \"seenIn\": [\n   \"aww-noho\"\n  ]\n },\n {\n  \"id\": \"showcase-object-in-front-of-type\",\n  \"role\": \"showcase\",\n  \"name\": \"Object in front of type\",\n  \"shape\": \"statement\",\n  \"tags\": [\n   \"object-led\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"hero-object\",\n   \"borrowed-category\",\n   \"loud-flat-poster\",\n   \"sentence-as-layout\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Type and object share one space instead of sitting side by side. Three or four lines of display type, one or two words each, are stacked flush left at clamp(72px, 9vw, 150px) with leading 0.88, starting on the left margin and allowed to leave the right edge (white-space: nowrap; overflow: hidden on the section). The lines step through tones of one ink: one at 45%, one at full strength, the rest at 18%. The object photograph, a cut-out or a studio shot blended with multiply, is absolutely positioned over the upper right of the stack at 40–46vw wide, rotated no more than 6 degrees and above the type in the stacking order, so it hides parts of three or four letters. Under the stack, in columns 8–12, a two-paragraph block at 20px gives the facts. The full-strength line is the heading; nothing sits above it.\",\n  \"mobile\": \"Type drops to 15vw and still runs off the right edge. The object sits at 78vw wide, overlapping the last two lines from below instead of from the right, and is cropped by the right edge. The facts block follows at full width and 17px.\",\n  \"seenIn\": [\n   \"aww-the-watch\",\n   \"opl-aevion\",\n   \"aww-coffeetech-r\"\n  ]\n },\n {\n  \"id\": \"showcase-band-of-unequal-panels\",\n  \"role\": \"showcase\",\n  \"name\": \"Band of unequal panels\",\n  \"shape\": \"strip\",\n  \"tags\": [\n   \"photo-led\"\n  ],\n  \"directions\": [\n   \"place-carries-it\",\n   \"uneven-photographs\",\n   \"name-as-monument\",\n   \"editorial-report\",\n   \"dark-room\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A modest heading, then one wide band of pictures. The heading, two to four words at 36–44px, starts at column 3, left of centre, with 64px beneath it. The band spans the full viewport width edge to edge and is 68svh tall: four photographs standing side by side with no gaps and deliberately unequal widths, a flex row with flex-grow values of 5, 2, 3 and 2. Each panel is cropped with object-fit: cover to a tall slice, so the band reads as one folded view. The first panel carries a two-line title at 28px in paper colour at its top-left, 24px in, over a neutral scrim that covers only that corner. Hovering a panel raises its flex-grow to 6 over 500ms while the others give way; without hover the widths simply stay. One caption line at 16px sits under the band at the left margin.\",\n  \"mobile\": \"The heading sits on the margin at 28px. The band becomes a two-by-two block with no gaps, 84svh tall in total: the first row split 64/36 and the second 36/64, so the slices stay unequal. The title stays on the first panel. No hover behaviour.\",\n  \"seenIn\": [\n   \"aww-white-desert\",\n   \"aww-tengile-malamala-collection\"\n  ]\n },\n {\n  \"id\": \"showcase-close-up-with-column-card\",\n  \"role\": \"showcase\",\n  \"name\": \"Close-up with column card\",\n  \"shape\": \"full-bleed\",\n  \"tags\": [\n   \"photo-led\",\n   \"object-led\"\n  ],\n  \"directions\": [\n   \"hero-object\",\n   \"place-carries-it\",\n   \"dark-room\",\n   \"borrowed-category\",\n   \"pinned-poster\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A full-bleed close-up photograph, 100vw by 100svh, with nothing over most of it. A four-column grid lies on top. One solid card in the ink colour, exactly one grid column wide (about 22vw) and 52svh tall, sits in the second column, vertically centred. Inside it, centred: the item's name at 30–36px, a variant line at 17px, the price or key fact at 17px, a small 3:2 photograph of the whole object (the card shows the whole, the background shows the detail), and at the foot a square-cornered action filling the card's width. The card is opaque, radius 0–6px, with no blur. When the section presents two or three items, each gets its own full-bleed frame and its card moves one column to the right each time, so position carries the sequence. The first card's name is the section heading.\",\n  \"mobile\": \"The photograph fills 100svh, cropped to its most detailed area. The card becomes a full-width block docked to the bottom, 46svh tall, left-aligned inside with 20px padding; the small whole-object photograph sits to the right of the name at 96px wide.\",\n  \"seenIn\": [\n   \"aww-longbow\"\n  ]\n },\n {\n  \"id\": \"showcase-live-demo-with-controls\",\n  \"role\": \"showcase\",\n  \"name\": \"Live demo with controls\",\n  \"shape\": \"split\",\n  \"tags\": [\n   \"ui-led\",\n   \"quiet\"\n  ],\n  \"directions\": [\n   \"product-performs\",\n   \"quiet-instrument\",\n   \"dense-tiles\"\n  ],\n  \"needs\": [\n   \"product-ui\"\n  ],\n  \"blueprint\": \"One filled panel, 680–760px wide and about 640px tall, radius 12px, in a tone clearly darker or lighter than the ground, placed on the text column's left edge or centred, with at least 15vh of empty ground above and below. The panel is split 62/38 into two flat areas that differ by one tone. Left area: the product doing its job on real content at true size. Right area: a narrow column of working controls, six to nine stacked rows 44px tall, each with a name at 14px on the left and a slider, toggle or value on the right; changing one changes the demonstration at once. A text link sits in the panel's bottom-left corner. The heading, two to four words at 24–32px, sits above the panel on its left edge with one sentence at 16px; under the panel, one line of start instruction.\",\n  \"mobile\": \"The panel fills the width. The demonstration takes the top at 4:3; the controls follow beneath as full-width rows 52px tall, only the four most telling ones, with a text link that reveals the rest. Heading and sentence sit above at 24px and 16px.\",\n  \"seenIn\": [\n   \"opl-dialkit\",\n   \"opl-textmode-overlay\"\n  ]\n },\n {\n  \"id\": \"showcase-one-frame-three-distances\",\n  \"role\": \"showcase\",\n  \"name\": \"One frame, three distances\",\n  \"shape\": \"pinned\",\n  \"tags\": [\n   \"photo-led\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"pinned-poster\",\n   \"hero-object\",\n   \"dark-room\",\n   \"sentence-as-layout\",\n   \"place-carries-it\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A wrapper 300vh tall holds a sticky stage of 100svh. On the stage one frame is centred: 30vw wide at 4:5, square corners, overflow hidden. Inside it the same photograph is shown at three distances as the reader scrolls: the whole subject, then scaled to 180% toward one detail, then to 320% on a second detail (transform: scale with a transform-origin per stage, 700ms ease, switched by IntersectionObserver on three invisible markers). The sentence is delivered in halves: its first two or three words sit above the frame at clamp(56px, 8vw, 130px), centred; the last words arrive below the frame at the second stage, overlapping the frame's bottom edge by 0.3em. At the third stage one caption of 28ch at 17px appears to the right of the frame, top-aligned. The two halves together are the heading and stay within two lines.\",\n  \"mobile\": \"The frame grows to 70vw at 4:5 and stays sticky at centre. The first half of the sentence sits above it at 13vw, the second half below it at the same size. The third-stage caption appears under the sentence at 16px, centred.\",\n  \"seenIn\": [\n   \"aww-vero-new-york\",\n   \"aww-illoca\",\n   \"opl-screentune\"\n  ]\n },\n {\n  \"id\": \"showcase-one-image-across-tiles\",\n  \"role\": \"showcase\",\n  \"name\": \"One image across tiles\",\n  \"shape\": \"mosaic\",\n  \"tags\": [\n   \"photo-led\",\n   \"dense\"\n  ],\n  \"directions\": [\n   \"dense-tiles\",\n   \"contact-sheet\",\n   \"editorial-report\",\n   \"colour-chapters\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One photograph is cut across a board of tiles. A grid of six columns and four rows with 8px gaps spans the full width between 12px margins; every tile is square (aspect-ratio: 1). Each tile shows its own piece of the same image: set the photograph as every tile's background at background-size: 600% 400% and step background-position by column and row, so the picture reads whole through the gaps. Five of the twenty-four tiles are swapped for flat colour tiles from the palette, never two adjacent: one holds the heading (two to four words at 2.6vw, top-left, 16px padding), three hold one fact each at 18px, one holds the action. On hover a tile's piece scales to 108% inside its own clip. Choose a photograph with one clear subject, so the board is legible at a glance.\",\n  \"mobile\": \"Three columns by six rows with 6px gaps, the photograph re-cut at background-size 300% 600% from a portrait crop. Four colour tiles only; the heading tile spans two columns in the top row with the heading at 6vw. Facts drop to 15px.\",\n  \"seenIn\": [\n   \"aww-produx-design\",\n   \"aww-ai-in-design-report-2026\"\n  ]\n },\n {\n  \"id\": \"showcase-frame-run-one-lifted\",\n  \"role\": \"showcase\",\n  \"name\": \"Frame run, one lifted\",\n  \"shape\": \"strip\",\n  \"tags\": [\n   \"photo-led\",\n   \"quiet\"\n  ],\n  \"directions\": [\n   \"contact-sheet\",\n   \"uneven-photographs\",\n   \"specimen-catalogue\",\n   \"quiet-instrument\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Columns 1–3 are a nearly empty column: the heading (two to four words at 24–28px) at the top, a link under it, and one or two short notes at 15px much further down, each level with the frame it describes. Columns 4–12 hold a run of six to eight frames of the same subject at one fixed height of 30vh, with natural widths and 6px gaps: the whole view, a tight crop of the same thing, a detail, the reverse side. The run is allowed to leave the right edge. One frame is lifted out of the row: shown at 2.2 times the row height with its bottom aligned to the row's bottom (flex row, align-items: end), so it stands above the others. Under each frame, at 15px: a name on the left and a single fact on the right. Square corners, no captions on the images.\",\n  \"mobile\": \"The heading and link sit on top. The lifted frame comes first at full width. The rest of the run scrolls sideways beneath it at a fixed height of 34vw with 4px gaps and scroll-snap, bleeding off the right edge. Notes are listed under the run at 15px.\",\n  \"seenIn\": [\n   \"aww-serotoninn\",\n   \"aww-butter\",\n   \"aww-no-art\"\n  ]\n },\n {\n  \"id\": \"showcase-output-slips-along-the-edge\",\n  \"role\": \"showcase\",\n  \"name\": \"Output slips along the edge\",\n  \"shape\": \"full-bleed\",\n  \"tags\": [\n   \"photo-led\",\n   \"object-led\"\n  ],\n  \"directions\": [\n   \"page-is-the-object\",\n   \"borrowed-category\",\n   \"place-carries-it\",\n   \"loud-flat-poster\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"For subjects whose result is a piece of text or paper: a receipt, a note, a ticket, a written line. A full-bleed photograph, 100vw by 96svh, sets the scene. In the upper centre, left-aligned in a column starting at 18% of the width, two short paragraphs in paper colour at 28–32px, the first opening with the heading's two to four words; a neutral scrim sits behind that column only. Along the bottom, six paper-coloured slips stand side by side across the full width with 12px gaps, each a filled rectangle of a different height (between 26 and 44svh), their lower ends cut off by the section's bottom edge. Two or three of the slips, not all, are tilted by 1–2 degrees. Each slip carries a sample of real output in the text face at 15px: a bold first line, a divider made of typed characters, then four to eight lines.\",\n  \"mobile\": \"The photograph is 100svh. The paragraphs sit in the top third at 22px. Only three slips show, each 30vw wide, standing along the bottom at different heights, and the row scrolls sideways to reveal the rest. Slip text stays at 14px; do not scale it down.\",\n  \"seenIn\": [\n   \"opl-poetry-camera\"\n  ]\n },\n {\n  \"id\": \"showcase-object-on-a-disc\",\n  \"role\": \"showcase\",\n  \"name\": \"Object on a disc\",\n  \"shape\": \"index\",\n  \"tags\": [\n   \"object-led\",\n   \"colour-field\"\n  ],\n  \"directions\": [\n   \"one-motif\",\n   \"specimen-catalogue\",\n   \"hero-object\",\n   \"colour-chapters\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One section about a viewport tall on a plain ground. A flat filled disc 64vh across, in one palette colour, sits with its centre at 58% of the width; swap the disc for the subject's own shape if it has one. A cut-out object photograph stands in front of it, centred on it, about 78% of the disc's height and breaking the disc's outline at the top. Bottom-left, starting on the margin and ending level with the disc's lower edge: a vertical list of four to six item names at clamp(28px, 2.9vw, 44px), leading 1.15. The selected name is in full ink and the rest at 25%; choosing a name swaps the object (300ms crossfade) and the disc's colour. The heading, two to four words at the same size as the names but in the soft ink, is the first line of that list. One fact about the selected item sits at the disc's right edge at 17px.\",\n  \"mobile\": \"The disc comes first, 86vw across and centred, with the object in front. The names follow as a single sideways-scrolling line at 26px with 24px gaps, the selected one in full ink. The fact sits under the names at 16px.\",\n  \"seenIn\": [\n   \"aww-cominvi\",\n   \"opl-tara\"\n  ]\n },\n {\n  \"id\": \"showcase-square-plate-spare-text\",\n  \"role\": \"showcase\",\n  \"name\": \"Square plate, spare text\",\n  \"shape\": \"split\",\n  \"tags\": [\n   \"colour-field\",\n   \"photo-led\"\n  ],\n  \"directions\": [\n   \"split-stage\",\n   \"page-is-the-object\",\n   \"colour-chapters\",\n   \"editorial-report\",\n   \"one-motif\",\n   \"name-as-monument\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One flat field split 50/50, at least 88svh tall. Left half: a single square photograph filling the half's width minus 40px margins, vertically centred, square corners. A large simple shape may be laid over it to turn the photograph into the object it stands for: a ring 86% of its width with a 6px stroke and a small solid dot at the centre makes a record; a notch cut by clip-path makes a ticket stub. Right half, a flex column with space-between: at the top a row of three plain text tabs at 18px (editions, years, variants), the active one in full ink and the others at 40%; in the middle the title, two to four words at 32–40px bold, with a 34ch description 48px below; along the bottom two filled rectangular cells side by side, each half the column wide and 72px tall, acting as the two actions, one in ink and one a tone off the field.\",\n  \"mobile\": \"The square photograph comes first at full width with 16px margins. The tabs sit under it as one row at 17px. Then the title at 28px, the description, and the two action cells stacked, each full width and 60px tall.\",\n  \"seenIn\": [\n   \"aww-paul-kalkbrenner\"\n  ]\n },\n {\n  \"id\": \"how-it-works-lines-that-step-across\",\n  \"role\": \"how-it-works\",\n  \"name\": \"Lines that step across\",\n  \"shape\": \"statement\",\n  \"tags\": [\n   \"type-led\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"type-only-statement\",\n   \"sentence-as-layout\",\n   \"loud-flat-poster\",\n   \"editorial-report\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"The sequence is written, not counted. Four lines of display type, one stage per line, each a complete short clause that begins with its order word: 'First you send it.' 'Then we take it apart.' 'You choose one.' 'It ships on Friday.' Set at clamp(36px, 4.6vw, 76px), leading 1.0, one line each. The first line starts on column 1 and each following line starts two columns further right (grid-column-start 1, 3, 5, 7), so the block descends as a staircase and the eye follows the diagonal. Under each line, on that line's own left edge and 12px below, a sentence of up to 34ch at 17px in the soft ink. 56px between stages. The last line may take the accent colour as the single emphasis. The first line serves as the heading; there is no title above. Leave the columns to the left of the final stage empty.\",\n  \"mobile\": \"Lines drop to 8.4vw and may wrap onto a second line. The staircase becomes a smaller indent of 6vw per stage, so the fourth line starts 18vw in. Each sentence sits under its line at 16px on the same indent. 40px between stages.\",\n  \"seenIn\": [\n   \"opl-rendez-vous-franceclat\"\n  ]\n },\n {\n  \"id\": \"how-it-works-photographs-down-a-diagonal\",\n  \"role\": \"how-it-works\",\n  \"name\": \"Photographs down a diagonal\",\n  \"shape\": \"stack\",\n  \"tags\": [\n   \"photo-led\",\n   \"quiet\"\n  ],\n  \"directions\": [\n   \"uneven-photographs\",\n   \"place-carries-it\",\n   \"dark-room\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Three stages, three photographs of different sizes placed along a falling diagonal on the 12-column grid. Stage one: a 3:4 portrait in columns 1–4. Stage two: a 1:1 square in columns 6–8, its top edge 220px lower than the first photograph's top. Stage three: a 16:10 landscape in columns 8–12, starting 180px below the bottom of the second. Each stage's text sits in the gap the stagger leaves: a paragraph of up to 36ch at 17px, top-aligned with its photograph and placed in the columns to its right (to its left for the third). Each paragraph opens with a bold run-in phrase that carries the order: 'On the first day', 'A week later', 'By the end'. Square corners; no arrows or connecting marks. The heading, two to four words at clamp(36px, 4vw, 64px) in a light weight, sits alone in columns 7–12 at the very top, level with the first photograph's top edge.\",\n  \"mobile\": \"The diagonal becomes alternating widths: the first photograph at 100%, the second at 62% flush right, the third at 78% flush left. Each paragraph follows its photograph on that photograph's left edge at 16px. 56px between stages. The heading sits above at 30px.\",\n  \"seenIn\": [\n   \"opl-fynza\",\n   \"opl-the-queue\"\n  ]\n },\n {\n  \"id\": \"how-it-works-drag-row-of-moments\",\n  \"role\": \"how-it-works\",\n  \"name\": \"Drag row of moments\",\n  \"shape\": \"carousel\",\n  \"tags\": [\n   \"photo-led\"\n  ],\n  \"directions\": [\n   \"contact-sheet\",\n   \"place-carries-it\",\n   \"uneven-photographs\",\n   \"page-is-the-object\",\n   \"dark-room\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A story told left to right. Top row: the heading, two to four words at 28–36px, at the left margin; at the right margin two solid square buttons, 48px each, for back and forward. Directly beneath, a solid bar 6px tall spans the full width in a soft tone, with a full-ink segment showing how far the row has been scrolled. Then the row itself: six to nine columns, each 280px wide with 32px gaps, in a horizontally scrolling flex container with scroll-snap that bleeds off both viewport edges. Every column reads top to bottom: a one-line caption at 18px bold that carries the order in words ('We met', 'Two winters on', 'The move'), three lines at 15px in the soft ink, then 80–140px of empty space that varies per column, then a 4:5 portrait photograph. Because the spaces vary, the photographs' top edges rise and fall along the row.\",\n  \"mobile\": \"Columns are 72vw wide with 16px gaps, so the next one always shows at the right edge. The buttons are dropped; the 6px progress bar stays under the heading. The empty space inside columns shrinks to 32–64px but still varies from column to column.\",\n  \"seenIn\": [\n   \"opl-sarah-matt-wedding\",\n   \"aww-no-art\"\n  ]\n },\n {\n  \"id\": \"how-it-works-pinned-fragment-changing-state\",\n  \"role\": \"how-it-works\",\n  \"name\": \"Pinned fragment, changing state\",\n  \"shape\": \"pinned\",\n  \"tags\": [\n   \"ui-led\",\n   \"quiet\"\n  ],\n  \"directions\": [\n   \"product-performs\",\n   \"quiet-instrument\",\n   \"split-stage\",\n   \"pinned-poster\"\n  ],\n  \"needs\": [\n   \"product-ui\"\n  ],\n  \"blueprint\": \"Two columns. Right, columns 7–12: a stage that is position: sticky; top: 14vh, holding one fragment of the real interface at true size on a single flat stage colour, about 520px square. Left, columns 1–5: three statements, each in its own block 80vh tall, so one is in view at a time. A statement is a two-line sentence at 28–32px that begins with its order word ('Paste a link.', 'Then pick the parts you want.', 'Share it when it looks right.') plus one supporting line at 16px. The statement nearest the viewport's centre is in full ink; the others sit at 30%. As each statement becomes active the fragment changes to the matching state: an empty field, a filled list with two rows selected, a finished result with its confirmation. Build the states in HTML and switch a class; do not swap screenshots. The heading, two to four words at 24–28px, sits above the first statement.\",\n  \"mobile\": \"The stage is sticky at the top, 46svh tall, the fragment fitted by cropping to its active region, not by shrinking its text. Statements scroll beneath it in blocks 60svh tall at 22px. The stage releases after the third statement.\",\n  \"seenIn\": [\n   \"opl-juggle\",\n   \"aww-cerebrium\",\n   \"opl-vessa\"\n  ]\n },\n {\n  \"id\": \"how-it-works-itinerary-on-a-slip\",\n  \"role\": \"how-it-works\",\n  \"name\": \"Itinerary on a slip\",\n  \"shape\": \"table\",\n  \"tags\": [\n   \"object-led\",\n   \"type-led\"\n  ],\n  \"directions\": [\n   \"page-is-the-object\",\n   \"type-only-statement\",\n   \"split-stage\",\n   \"quiet-instrument\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"The process is printed as an itinerary or receipt. One paper-coloured slip 420–480px wide stands on a contrasting flat ground at columns 7–11; its bottom edge is a zigzag cut with clip-path and its top edge is straight. The heading, two to four words at clamp(40px, 4.4vw, 68px), sits in columns 1–5 with a 30ch paragraph, top-aligned with the slip. On the slip, in the text face at 16px with tabular figures: stages grouped under time headings that carry the order ('Monday', 'Midweek', 'Friday'), each heading in bold with 28px above it. Under a heading, two to four rows; each row has what happens on the left, a duration or time on the right, and a leader of round 4px dots between. The final row is inverted, paper-coloured text on a full-width ink bar 44px tall, and states the result: what the reader holds at the end and the total time.\",\n  \"mobile\": \"The heading and paragraph come first. The slip follows at full width minus 16px margins, keeping its zigzag bottom edge. Rows keep left text, dots and right value on one line; long descriptions wrap under the left text. The inverted final row stays full width.\",\n  \"seenIn\": [\n   \"opl-the-content-architecture\",\n   \"opl-lennys-newsletter-product-pass\"\n  ]\n },\n {\n  \"id\": \"how-it-works-accordion-of-tinted-panels\",\n  \"role\": \"how-it-works\",\n  \"name\": \"Accordion of tinted panels\",\n  \"shape\": \"strip\",\n  \"tags\": [\n   \"colour-field\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"colour-chapters\",\n   \"one-motif\",\n   \"loud-flat-poster\",\n   \"dense-tiles\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A two-column introduction, then one horizontal accordion. Introduction: the heading, two to four words at clamp(36px, 4vw, 60px), in columns 1–5; one paragraph at 18px in columns 7–11. 64px below, a flex row across columns 1–12, 520px tall, of four to six panels with no gaps. The open stage is a panel taking about 58% of the width; the rest are vertical slivers sharing what remains. Order is carried by colour: the first stage is the darkest tone of one hue and each later stage is a lighter flat tint of it, so the row reads dark to light from left to right. A sliver shows only its stage name, rotated 90 degrees and reading upward, at 20px bold, anchored to its bottom-left. The open panel shows the name at 40px top-left, a 36ch paragraph at 18px bottom-left and, optionally, one photograph in its right half. Clicking a sliver opens it (flex-basis transition, 450ms).\",\n  \"mobile\": \"The accordion turns vertical: stages stack at full width as bars 64px tall in the same dark-to-light order, names set horizontally at 18px. The open stage expands to its content height with the paragraph at 17px. The first stage is open by default.\",\n  \"seenIn\": [\n   \"aww-white-desert\"\n  ]\n },\n {\n  \"id\": \"how-it-works-tiles-that-grow\",\n  \"role\": \"how-it-\n\n<!-- [TRUNCATED AT 50KB] -->","skills/taste-skill/library/sites.json":"[\n {\n  \"id\": \"aww-pp-neue-montreal\",\n  \"name\": \"PP Neue Montreal\",\n  \"url\": \"https://neuemontreal.com/\",\n  \"source\": \"Awwwards Site of the Day\",\n  \"kind\": \"other\",\n  \"score\": 8.6,\n  \"idea\": \"A typeface specimen dressed as a vintage city travel guide: the font named after Montreal is sold through guidebook titling, postcards and old tourist footage.\",\n  \"mood\": [\n   \"bold\",\n   \"playful\",\n   \"retro-modernist\",\n   \"typographic\",\n   \"confident\"\n  ],\n  \"archetype\": \"giant-wordmark\",\n  \"hero\": \"Grainy coral-red field. Top row: a monogram in a pale pill at left, a pale-grey pill nav with seven links centred, a black pill button at right. Below at the left margin, a two-line white bold title at about 4.5vw; opposite it, a ring of repeated monograms set around a circle like a stamp. Three full-width black hairlines cut the field into bands: a two-line intro sentence at ~1.6vw sits in the second, and the typeface name fills the third in black bold at ~17vw, two lines, tight leading, 60% of the width. A 4:3 clip of 1960s street footage is inset bottom-right, 29% wide, bottom-aligned with the name.\",\n  \"type\": \"PP Neue Montreal only: Bold for display with -0.01em tracking and leading near 0.9, Text Regular 16px for body and lists. Sizes leap from 16px to 144px headings to a ~240px name; one section enlarges a single lowercase letter to viewport height.\",\n  \"colour\": \"#ed4b44 #1a1a1a #f0e7d4 #18bc42 #b5b5b5 #f2c21a — Each chapter takes a flat field (coral red, near-black, cream, green) with black or cream type; one headline colours every word differently. Warm, print-poster feel with visible grain.\",\n  \"imagery\": \"Archive 1960s city footage, saturated vintage postcards, a handwritten postcard back, and rotated specimen posters and stamp sheets scattered around a headline. All square-cornered and inset, never full-bleed.\",\n  \"layout\": \"24px side margins and full-width hairlines marking bands. Content is left-anchored in three or four columns split by vertical hairlines; chapters alternate between tabular lists, a scattered collage, a centred statement and a giant glyph comparison. A pill nav stays pinned.\",\n  \"sections\": [\n   {\n    \"role\": \"intro\",\n    \"description\": \"Near-black screen split by a vertical hairline at about 75% width. Left: a three-line small heading at the top margin, then a five-line bold oblique headline at ~6vw in which each line is indented further right like a staircase and each word takes its own colour (green, cream, grey, yellow, blue, orange). Right narrow column: two stacked postcards, one saturated photo card and one cream handwritten card with a stamp. A tiny section label sits bottom-left.\"\n   },\n   {\n    \"role\": \"other\",\n    \"description\": \"A dark band of pure tabular type. A body paragraph occupies column one; weight names stack as tight single-line lists in two further columns divided by vertical hairlines. Below, a small label over a full-width rule introduces a two-column timeline: years stacked at the left margin, release notes stacked from the centre line behind a short vertical rule. One text size, leading near 1.0, no decoration at all.\"\n   },\n   {\n    \"role\": \"gallery\",\n    \"description\": \"Dark full-viewport stage with a three-line cream headline at ~4vw placed dead centre. Around it eight or nine specimen artefacts (a stamp sheet, a green poster with a blue numeral, a grey flag chart, a rainbow ticket grid, concentric colour squares) are each rotated 10 to 30 degrees and arranged on a loose ring, several cropped by the viewport edge, as if tossed on a table.\"\n   },\n   {\n    \"role\": \"showcase\",\n    \"description\": \"Cream field. A caption row at the top: a two-line label at the left margin and a five-line paragraph starting at about 55% width. Then a full-width rule carrying a tiny label at each end naming the two cuts. Below it, two black lowercase letters, each roughly half the viewport wide and cropped by the bottom edge, one from each cut, so the reader compares shapes at poster scale.\"\n   }\n  ],\n  \"steal\": [\n   \"Give a product page a borrowed genre (here a tourist guidebook) and let that genre dictate titles, imagery and chapter names.\",\n   \"Cut a flat colour hero into bands with full-width hairlines and set the name at ~17vw in the bottom band beside a small inset film clip.\",\n   \"Scatter rotated print artefacts on a loose ring around a centred headline and let several crop off the viewport.\"\n  ],\n  \"media\": \"The hero is a red printed cover with paper grain; the real media is small, a 418x316 looping 1960s street clip at the bottom right (about 10% of the viewport) beside a wordmark filling about 60% of the width. Later: a postcard pair in the right half of a split, rotated ephemera orbiting a centred statement, full-bleed photo panels that slide up over the previous chapter, a spine accordion, and a full-bleed vintage photograph overscanned 72px each side; square corners, one video.\",\n  \"motion\": \"Black, then a turning seal of logo letters, then the cover by 4.5s; four hero groups rise 25px and fade over 400ms cubic-bezier(0.44,0,0.56,1) at 200ms steps, settling at about 5.5s though the page loaded in 2.5s. Lenis drives a chain of sticky full-screen chapters: ephemera fly off as a photo panel slides up, a headline steps through weights of the variable cut on scroll, and a single glyph rotates and zooms for about 5 screens; about 390 appear fades run over 400ms on a spring-shaped linear() curve, with no reduced-motion rule.\"\n },\n {\n  \"id\": \"aww-seasats\",\n  \"name\": \"Seasats\",\n  \"url\": \"https://www.seasats.com/\",\n  \"source\": \"Awwwards Site of the Day\",\n  \"kind\": \"physical-product\",\n  \"score\": 8.4,\n  \"idea\": \"Calm, dusk-lit seascapes sell autonomous boats as serene instruments, and the navigation is a column of stacked colour swatches taken from that sea-and-sand palette.\",\n  \"mood\": [\n   \"serene\",\n   \"cinematic\",\n   \"engineered\",\n   \"assured\"\n  ],\n  \"archetype\": \"fullbleed-media-overlay\",\n  \"hero\": \"A 10px white frame surrounds everything. The left 84% is one rounded media panel: a dusk scene of a low, solar-decked vessel centred on mirror-flat water, with two larger hulls cropped by the panel's left and right edges. The headline is centred in the panel's upper third, two lines of white light-weight flared serif at 124px (8.6vw). A wordmark in custom wide techno lettering sits top-left; a white rounded button with mono caps and a dark-green square arrow sits bottom-centre. The right 14% is the menu: a full-height column of stacked flat colour blocks (blush, sage, then four darkening olives), each holding left-aligned 15px links, sub-items numbered 01 to 04.\",\n  \"type\": \"seasonMix, a low-contrast serif-sans hybrid, light weight, sentence case, near-zero tracking, at 124px for the headline and about 40px for statements; seasonSans 16px for body and menu; supplyMono uppercase at 9 to 12px for buttons, tags and footer data.\",\n  \"colour\": \"#a6b3bc #232323 #b7c8be #d6c4b8 #2c3620 #e2832a — Slate blues and lilac greys from the seascapes dominate; the menu adds blush, sage and olive blocks; the footer flips to a burnt-orange and rust scene. Text stays white.\",\n  \"imagery\": \"Photoreal rendered footage of autonomous boats on glassy water at dusk: symmetrical, low horizon, lots of sky, full-bleed after the hero. Small square-cornered inset stills with mono tag labels float over the scene.\",\n  \"layout\": \"Mostly full-viewport scenes with one centred text block each, at top or bottom, and the wordmark fixed top-left. Only the hero uses the framed panel-plus-menu split. A thin vertical progress line runs down the right edge.\",\n  \"sections\": [\n   {\n    \"role\": \"features\",\n    \"description\": \"A pinned full-bleed scene shot from the boat's deck: the hull forms a dark symmetrical wedge rising from the bottom edge to a mast at centre, horizon at one-third. At top-centre six short statements are stacked, centred, at 16px; one is white and the others half opacity, and the highlight steps down the list on scroll. For each, small photo cards (150 to 220px wide, square corners, mono tag on the top edge) appear left and right of the mast.\"\n   },\n   {\n    \"role\": \"intro\",\n    \"description\": \"A full-bleed aerial view of dark teal water with several small vessels scattered across the lower half and a faint horizon near the top. A single two-line statement in the light serif at about 40px sits centred near the bottom edge. Nothing else is on screen except the wordmark top-left and the thin progress line at right.\"\n   },\n   {\n    \"role\": \"footer\",\n    \"description\": \"Colour inverts to a burnt-orange haze over rust-red terrain, with black silhouettes of hulls and a keel hanging from the top edge as if seen from below the surface. Mid-height: mono readouts at left reporting distance scrolled in metres and scroll speed in knots with a one-line quip; a link list at 16px in the centre; mono contact details at right. The wordmark fills the full width at the bottom, white, about 130px tall.\"\n   }\n  ],\n  \"steal\": [\n   \"Build the menu as a full-height column of stacked flat colour blocks sampled from the imagery, grouping links by block colour instead of by rules or headings.\",\n   \"List every claim at once, centred and dimmed, and move a single full-opacity highlight through the list on scroll while supporting images appear around a fixed subject.\",\n   \"Give the footer its own opposite-temperature scene and a live readout of how far and how fast the visitor scrolled, in the product's own units.\"\n  ],\n  \"media\": \"A dusk render of the vessel on still water, as a still, a 3s muted loop and a canvas layered together, fills an inset card at about 84% of the width beside a colour-band nav panel and goes full bleed once scrolled. Then a scroll-scrubbed frame sequence on a sticky stage with labelled photo cards floating at depth, small video thumbnails that grow into full-bleed chapter loops, a WebGL globe rising as a half-sphere from the bottom edge, and sticky product renders that turn with the scroll; 18 images, 6 videos, 8px corners on the hero frame and cards.\",\n  \"motion\": \"The preloader wordmark's seven letters slide up out of their masks at 50ms steps, the framed hero arrives at 1.2s and the title fades in softly, settling after about 5s, and smooth scroll then runs 34 sticky elements with no pins: the flythrough is a scrubbed image sequence, a fixed background layer changes the ground per chapter, and the nav collapses to a slim right-edge rail. Title characters rise on cubic-bezier(.215,.61,.355,1) (the house ease, 17 uses) with durations that shorten by 12ms per character, so the end of a word catches up with its start.\"\n },\n {\n  \"id\": \"aww-ai-in-design-report-2026\",\n  \"name\": \"Ai in Design Report 2026\",\n  \"url\": \"https://stateofaidesign.com/\",\n  \"source\": \"Awwwards Site of the Day\",\n  \"kind\": \"other\",\n  \"score\": 8.4,\n  \"idea\": \"A research report laid out like a colour-blocked print annual: a thermal-blurred video collage on top, an oversized tight grotesk title, and flat orange, lilac, sage and black blocks carrying stats, quotes and chapters.\",\n  \"mood\": [\n   \"editorial\",\n   \"bold\",\n   \"colour-blocked\",\n   \"assured\",\n   \"contemporary\"\n  ],\n  \"archetype\": \"editorial-masthead\",\n  \"hero\": \"The top 53% is a full-width video band: blurred, heat-map-like abstract footage in orange, lilac and sage, overlaid with four or five hard-edged rectangles of the same footage in grey or green, two tagged with tiny mono labels in white boxes. The header sits flush on top: a black logo block at far left, an orange link tab running to 40% of the width, two plain links at right. Below the band, on white: a two-line deck at about 1.4vw on a 1% left margin, and from 42% across a two-line title at 8.3vw, medium weight, tracking -0.06em. Bottom row: mono credit left, scroll cue and arrow aligned to the title column.\",\n  \"type\": \"Beausite Classic, a grotesk with some stroke contrast, in Medium for titles and Regular for text; sentence case, tracking -0.06em at display size. Geist Mono for small uppercase labels. Steps: 8.3vw title, about 5.5vw numerals, about 3vw statements, 16px body, 10px mono. Footer wordmark near 96vw.\",\n  \"colour\": \"#ffffff #000000 #fe7141 #cdabfe #d1ddd3 #f0ff1c — White base with flat blocks of orange, lilac, sage and black assigned to whole modules (stat tiles, quote panels, chapter bands), all drawn from the hero footage. Text is black, or off-white on black.\",\n  \"imagery\": \"Hero: abstract blurred video with a heat-map grade, cut into overlapping rectangles. Body: warm documentary photos and clips of people at desks in wood-lined rooms, square-cornered, butted directly against flat colour blocks with no gap.\",\n  \"layout\": \"1% margins and a recurring column line at about 42% where most headings and text begin. Open white text passages ruled by hairlines alternate with tight mosaics in which photos and colour blocks share edges. Each chapter opens with a full-width colour band.\",\n  \"sections\": [\n   {\n    \"role\": \"proof\",\n    \"description\": \"A full-width hairline, a tiny mono label at the left, then seven black partner logos evenly spaced across the full width in one row with generous padding above and below, closed by a second hairline. Immediately beneath, another mono label and a three-line statement at about 3vw, flush left and occupying only the left half, followed by a full-width photo strip.\"\n   },\n   {\n    \"role\": \"stats\",\n    \"description\": \"A mosaic with no gutters. A photo of two people at a laptop fills the left two-thirds at roughly 1:1; the right third is split into two stacked flat tiles, lilac above and sage below. Each tile carries a large numeral with a plus sign at about 5.5vw in its top-left corner and a two-line caption directly beneath; the rest of the tile is empty colour.\"\n   },\n   {\n    \"role\": \"testimonial\",\n    \"description\": \"Quote module as two abutting blocks: a black block on the left 40% holding only a small name and a mono role caption, and a sage block on the right 60% with the quotation at about 3vw, top-left aligned with empty sage beneath. Directly below, a full-width orange band opens a chapter: hairline at top, a large two-digit number with the chapter word under it at left, a two-line title and small paragraph starting at the 42% column.\"\n   },\n   {\n    \"role\": \"footer\",\n    \"description\": \"Black footer. A row of three small source counts along the top, separated by vertical hairlines, then the report name in off-white heavy type at nearly full viewport width with a trademark sign at its top-right, then the year at the same size right-aligned on a second line. Two small link columns with mono headings sit lower left beside the year; a hairline and one row of credits and partner logos close it.\"\n   }\n  ],\n  \"steal\": [\n   \"Start most headings and text at a fixed column line about 42% across, leaving the left for small decks, credits and chapter numbers.\",\n   \"Butt flat colour tiles directly against a photograph with no gutter and put one large numeral plus two caption lines in each tile's top-left corner.\",\n   \"Take the page's flat block colours from the hero footage so the abstract video and the layout read as one palette.\"\n  ],\n  \"media\": \"A video collage covers 100% of the screen at load and lifts to the top ~53% to uncover the title on white. Below, a documentary photograph two thirds wide in a sticky frame beside stacked colour stat blocks, a pinned deck of colour cards each with a 10s clip docked bottom-left, and a carousel of equal stills running off the right edge: 12 images and 6 muted videos, all square-cornered.\",\n  \"motion\": \"No preloader, but the collage re-cuts itself for about 4s before the title lands. Framer drives the sticky stacking (a 1350px photo frame and three 900px chapter cards that peel away to uncover the next); there is no split text, links change colour over .2s cubic-bezier(.44,0,.56,1), and one panel slides 610px in over 500ms cubic-bezier(0.44,0,0.37,1).\"\n },\n {\n  \"id\": \"aww-house-of-honey-1\",\n  \"name\": \"House of Honey\",\n  \"url\": \"https://www.houseofhoney.com/\",\n  \"source\": \"Awwwards Site of the Day\",\n  \"kind\": \"studio-portfolio\",\n  \"score\": 8.4,\n  \"idea\": \"A block-heavy wordmark pierced by a hairline script: the bold-against-delicate contrast is repeated at every scale, with giant pink script behind quiet serif statements.\",\n  \"mood\": [\n   \"glamorous\",\n   \"warm\",\n   \"playful\",\n   \"editorial\",\n   \"confident\"\n  ],\n  \"archetype\": \"giant-wordmark\",\n  \"hero\": \"Top 42% is a flat blush-pink band; the bottom 58% is a full-bleed photograph of a bright living room, arched window on the centre axis, butting against the band with no margin. A tiny nav row sits at the very top with 8px side margins: block logo glyph and five links left, contact link with a small square arrow box far right. The wordmark fills the width edge to edge: two words in ultra-black extended caps, about 120px cap height, dark aubergine, with a hairline script 'of' 230px tall between them, overshooting above and below. Directly beneath, two two-line serif uppercase taglines at 31px, one flush left, one flush right.\",\n  \"type\": \"Wordmark in ultra-black extended caps; statements in noeText serif, uppercase, 31–40px, tight tracking; nav and captions in neueHaasGrotesk around 14px; 'canora' hairline script for the connecting word and for cropped background words at 37vw. Three contrasting voices, each with one job.\",\n  \"colour\": \"#edccbe #331917 #0e0e0e #f26fcb #ffffff — Blush pink and dark aubergine-brown alternate as full fields and as each other's text colour. Hot pink appears only in the oversized script and a 2px divider. Photographs bring saturated colour.\",\n  \"imagery\": \"Editorial interior photography, saturated and daylight-lit. Hero is a full-bleed landscape crop; projects are portrait crops about 5:6 in a three-column grid with 4px gutters and square corners.\",\n  \"layout\": \"Edge-to-edge with 8px outer margins. Typographic sections (small centred label, serif statement, cropped giant script) alternate with a three-column image grid. Blush and brown fields swap each section; hairline link rows close blocks. The footer is a full-width logo glyph.\",\n  \"sections\": [\n   {\n    \"role\": \"intro\",\n    \"description\": \"Dark aubergine field under the hero photo, separated by a 2px hot-pink line. A small sans label centred, then a three-line centred serif uppercase statement at about 31px in blush, 45% of the width. Behind it a hot-pink script phrase set near 37vw runs off both sides and is cut by the section's bottom edge, its ascenders rising into the statement. A smaller serif line follows.\"\n   },\n   {\n    \"role\": \"other\",\n    \"description\": \"Title card before the project grid. Blush field, nearly empty screen. A small label and a one-line serif uppercase heading about 40px sit centred at 55% height. The giant pink script returns, cropped by the bottom edge so only its top half shows and running off both sides.\"\n   },\n   {\n    \"role\": \"work\",\n    \"description\": \"Three columns edge to edge with 4px gutters and 8px outer margins. Portrait photos about 500×580px, square corners. Under each: an uppercase sans title at 14px and a grey line of GPS coordinates. Two rows, then a full-width hairline row with a text link left and a small square arrow box at the far right.\"\n   },\n   {\n    \"role\": \"footer\",\n    \"description\": \"Brown field. The logo glyph is enlarged to full width and about a third of the screen: blush rectangles and quarter-circle arcs with 4px gaps, forming an abstract monogram. Below: four columns of small links, a hairline, two addresses in the first two columns, another hairline, then copyright left and a small blush button right.\"\n   }\n  ],\n  \"steal\": [\n   \"Set a wordmark edge to edge in ultra-heavy extended caps and thread a hairline script connecting word through it that overshoots the cap height both ways.\",\n   \"Use an oversized script word in one hot accent colour as a cropped background layer behind small, calm serif statements.\",\n   \"Split a tagline into two halves, flush left and flush right on the same baseline under the wordmark, instead of centring it.\"\n  ],\n  \"media\": \"The lower 58% of the fold is a full-bleed interior photograph that continues for one full viewport as a five-image crossfading slideshow with a pink progress line on its bottom edge. Below: a three-up grid of 4:5 project tiles with 8px gutters sliding over a giant script marquee, a full-bleed tinted feature photograph with its title docked bottom-left, a full-bleed photograph with an inset colour card, and one giant cropped letterform as the footer's picture, the photographs oversized to 110-170% of their frames for drift and no video anywhere.\",\n  \"motion\": \"There is no visible preloader and the page is whole at 400ms; under Lenis, blocks rise 8px and fade in over 800ms ease-out at 0-260ms staggers (39 WAAPI calls), slideshow crossfades take 600ms cubic-bezier(0.7,0,0.25,1), the oversized photographs drift, and script marquees run on CSS time (90-122s per pair). Page changes use a 1s view transition on the same curve; nothing pins, and there is one reduced-motion rule.\"\n },\n {\n  \"id\": \"aww-white-desert\",\n  \"name\": \"White Desert\",\n  \"url\": \"https://white-desert.com/\",\n  \"source\": \"Awwwards Site of the Day\",\n  \"kind\": \"hospitality\",\n  \"score\": 8.4,\n  \"idea\": \"One word, the destination, set a third of the screen tall over footage like a film title card; sheer scale stands in for remoteness.\",\n  \"mood\": [\n   \"cinematic\",\n   \"epic\",\n   \"luxurious\",\n   \"cold\",\n   \"restrained\"\n  ],\n  \"archetype\": \"bottom-anchored-type\",\n  \"hero\": \"Full-bleed video (the view from an aircraft window over an ice shelf, darkly vignetted by the window frame) fills the viewport. Faint vertical hairlines divide it into six columns. Top-left, three outlined rectangular nav buttons about 120 by 40px with 6px gaps; top-right, two more; between them a small white mountain logo over a condensed caps name. One condensed uppercase word spans almost the full width at 17.8vw, white, centred, anchored so its baseline sits about 35px above the bottom edge. At mid-height a two-line italic serif tagline at about 16px hangs on the first column line at left, and a film-play label sits between two hairlines at right.\",\n  \"type\": \"Three voices: Oswald 400 uppercase for the giant word and footer wordmark (up to 22vw); Cardinal Classic Long, a light high-contrast serif, for caps statements near 32px and italic taglines; Inter Tight 14px for nav and body. Body to display is roughly an 18x jump.\",\n  \"colour\": \"#040608 #ffffff #e9e7e1 #1f2b4d #f5821f #95979a — Footage and near-black open the page; content sections flip to pure white with navy serif type and end on a warm grey footer. One small orange tab is the only accent. Cool overall.\",\n  \"imagery\": \"Aerial and wildlife footage and stills of ice, penguins and rust-coloured rock peaks, natural cool grade, always full-bleed with square corners; trips appear as tall vertical image slices set side by side with no gaps.\",\n  \"layout\": \"A six-column grid made visible by faint full-height hairlines runs through every section. Text blocks are small and hung off column lines, often starting at column two or three, with large voids around them. Full-bleed image screens alternate with nearly empty white text screens.\",\n  \"sections\": [\n   {\n    \"role\": \"intro\",\n    \"description\": \"A white screen with the six vertical hairlines still showing. A serif caps paragraph at about 32px, navy, light weight and tight leading, occupies only columns two to four, left-aligned with its first line indented by half the measure. Above its top-left sits a small italic label ringed by a loose hand-drawn pen scribble. An orange vertical tab with rotated text is fixed to the right edge.\"\n   },\n   {\n    \"role\": \"gallery\",\n    \"description\": \"Leaving the hero, the giant word blurs and dissolves into white mist that becomes the next section's background. Later a full-viewport photograph of jagged rock peaks in snow bleeds to all four edges, with a narrow 13px paragraph from the white section above overlapping its top edge at a column line, so text and image interlock rather than stack.\"\n   },\n   {\n    \"role\": \"showcase\",\n    \"description\": \"A serif caps heading at about 40px sits left of centre with a long pencil-like scribble underline that extends well past the words on both sides. Below, a full-width band of four vertical image panels with no gaps and unequal widths, like an accordion; the first panel carries a two-line italic serif title in white at its top-left.\"\n   },\n   {\n    \"role\": \"footer\",\n    \"description\": \"Warm grey field. The top row holds a small logo, three columns of grey link lists with italic serif group headings and, at right, a stack of square-cornered off-white tiles (a video thumbnail, two half-width buttons, one full-width). Beneath, the brand name in navy condensed caps runs edge to edge at about 22vw. A final strip has award badges left, a centred italic quotation and legal links right.\"\n   }\n  ],\n  \"steal\": [\n   \"Set a single place name in condensed caps at about 18vw, centred and anchored to the bottom edge of full-bleed footage, with everything else on screen at 14-16px.\",\n   \"Leave the column grid visible as faint full-height hairlines across video, white and footer sections, and hang small text blocks off those lines.\",\n   \"Ring or underline small serif labels with a loose hand-drawn pen scribble to put one human mark into an otherwise strict layout.\"\n  ],\n  \"media\": \"An 18s muted aerial and ice-cave clip covers the whole first screen under a scrim, with the title docked along the bottom edge. Later pictures dissolve into the white page through fog-like fades, a horizontal accordion opens one trip panel at half width beside blurred slivers, vertical ice strips wipe across the previous photograph, and a long pinned track of inset cards floats on a full-bleed texture ground before a closing photo panel carrying a quotation; 20 images, one video, square corners and a high-key cold grade.\",\n  \"motion\": \"There is no entrance choreography and footage plays from the first frame; under Lenis the hero title blurs and is swallowed by a sticky fog layer growing from 390 to 900px tall, statement lines fill from grey to navy, the camps heading scrubs from 140px down to 60px, and a pinned horizontal track moves the cards at about 0.56px per scrolled pixel over an 8,328px runway. Blocks rise 20rem with opacity over 1.4s cubic-bezier(.16,1,.3,1), and hovers run .3s cubic-bezier(.5,1,.89,1).\"\n },\n {\n  \"id\": \"opl-applied-imagination\",\n  \"name\": \"Applied Imagination\",\n  \"url\": \"https://applied-imagination.gpc.consulting\",\n  \"source\": \"One Page Love\",\n  \"kind\": \"other\",\n  \"score\": 8.3,\n  \"idea\": \"An essay conceived on a flight is read as a descent: an altimeter ticks from 30,000 ft to zero while you scroll down through halftone clouds to mountains at ground level.\",\n  \"mood\": [\n   \"airy\",\n   \"witty\",\n   \"editorial\",\n   \"dreamlike\"\n  ],\n  \"archetype\": \"type-poster\",\n  \"hero\": \"A pale blue sky fading to warm cream fills the viewport, with white clouds shaded in halftone dots. A tiny serif logotype sits top-centre; no nav. The title, two centred lines of black wedge-serif at 8.9vw, occupies the middle half of the screen and about 73% of its width; a cloud layer passes in front of the second line's baseline so the feet of the letters dissolve into dots. A two-line centred deck at 24px sits beneath. A mono byline strip is centred on the bottom edge with a scroll cue bottom-right. On the left edge at mid-height, a short vertical rule carries a two-line mono altitude readout.\",\n  \"type\": \"fsKim, a sturdy wedge-serif display face, regular weight at 128px with -0.01em tracking for the title and pull quotes; gtAmerica at 24px for the deck and about 16px for essay body; gtAmericaMono uppercase around 11px with wide tracking for byline, altitude and tape labels.\",\n  \"colour\": \"#cbe4f2 #f1e3b5 #0a0a0a #ffc013 #8e2f8f #f04e23 — Sky blue melting into sand yellow is the constant ground and text is black. Saturated magenta, orange and yellow arrive only in collage objects, tape labels and the footer contact card.\",\n  \"imagery\": \"Photo-collage cut-outs (parachutes carrying a treasure chest and a burning dumpster, a pair of legs, mountains) given a coarse halftone dot screen, layered in front of and behind the type against painted clouds.\",\n  \"layout\": \"A narrow text column about 38% wide for essay passages, interrupted by full-width display pull quotes and collage objects floating at the edges. One continuous sky instead of sections, with a fixed left-edge altimeter. Nearly 23 screens, ending on a ground-level landscape.\",\n  \"sections\": [\n   {\n    \"role\": \"intro\",\n    \"description\": \"Sky background, no container. A three-line pull quote in black wedge-serif at about 7vw is centred and tightly leaded. Two cut-out parachutes hang over it: a magenta one from the top-left carrying a chest spilling coins, an orange one at lower right carrying a burning dumpster, each overlapping letterforms. Small mono labels on tilted strips of coloured tape are stuck to the objects. Words in the quote turn from grey to black as they are reached.\"\n   },\n   {\n    \"role\": \"other\",\n    \"description\": \"Running essay text in about 16px grotesk, black, in a single column roughly 38% of the viewport wide, positioned left of centre with large sky margins on both sides. Paragraphs are separated by a blank line; serif sub-statements at about 28px introduce passages. The next display quote is seen rising from below, its letters partly hidden behind cloud and blurred.\"\n   },\n   {\n    \"role\": \"contact\",\n    \"description\": \"Ground level: halftone-screened mountains in green and brown rise from both sides, and the title returns at huge scale, cropped by the top edge and tucked behind the peaks. Centred below is a square-cornered two-panel card: a cream left panel with a short form of two fields and a small orange button, and a magenta right panel with a round portrait, name and a yellow subscribe button. Yellow tape-strip credits sit on the bottom edge.\"\n   }\n  ],\n  \"steal\": [\n   \"Tie a persistent numeric readout to scroll position (altitude falling to zero) so the reader's progress becomes part of the story.\",\n   \"Layer an illustration element in front of the bottom of a giant title so the letters sink into the scene instead of sitting on top.\",\n   \"Apply one coarse halftone dot screen to every photo cut-out so collage pieces from different sources read as one illustration set.\"\n  ]\n },\n {\n  \"id\": \"opl-compile\",\n  \"name\": \"Cursor Compile\",\n  \"url\": \"https://cursor.com/compile\",\n  \"source\": \"One Page Love\",\n  \"kind\": \"event\",\n  \"score\": 8.3,\n  \"idea\": \"The event name drawn as seven looping one-line curves in seven colours, more signature than logotype, on an otherwise whisper-quiet off-white page whose images are re-rendered as rows of coloured characters.\",\n  \"mood\": [\n   \"quiet\",\n   \"hand-drawn\",\n   \"warm\",\n   \"technical\",\n   \"restrained\"\n  ],\n  \"archetype\": \"giant-wordmark\",\n  \"hero\": \"Warm off-white field with no header or navigation. Starting about 23% down, a line-drawn wordmark spans from 8% to 92% of the width and about 29% of the height: each letter is a single 2px stroke looping like a Lissajous figure, each in a different colour (orange, green, olive, lilac, black, brown, blue), overlapping its neighbours. Directly beneath, two 14px captions, one flush left in ink and one flush right in grey. After a gap of about 20% of the viewport, three equal columns sit at the bottom, each topped by a hairline: an 18px statement, a grey 14px paragraph, and an email field over a full-width near-black rectangular button.\",\n  \"type\": \"The only large lettering is the drawn wordmark. All real text is CursorGothic regular in two sizes, 18px and 14px (the largest text on the page is 1.8vw), sentence case, with hierarchy made by ink versus mid-grey rather than by size or weight.\",\n  \"colour\": \"#edece8 #26251e #f07a1f #2e9e3a #2f6bf0 #9b8ff0 — Warm paper ground with near-black and grey text. The wordmark's colours return one at a time as the single ink of each character-rendered image (lilac, teal, green, orange). Event photos are dark and warm.\",\n  \"imagery\": \"Two kinds: landmarks and speaker portraits redrawn as rows of tiny characters in one saturated colour on a tint of the same colour; and dark, warm documentary event photos. All are square-cornered rectangles in strict rows.\",\n  \"layout\": \"About 7% side margins on a three-column grid. Each section has a small two-line heading at left (title in ink, subtitle in grey), then a row or carousel of equal tiles with one-line captions beneath. Very large vertical gaps between sections; a denser photo grid near the end.\",\n  \"sections\": [\n   {\n    \"role\": \"list\",\n    \"description\": \"Tour dates as a three-column grid of 3:2 tiles. Each tile is a city landmark rendered entirely in rows of small characters in one colour on a pale tint of that colour: lilac, teal, green, orange. Under each tile, one caption line: city name in ink, date in grey straight after it, and a status word flush right. A fourth tile wraps alone to the left of a second row, leaving two columns empty.\"\n   },\n   {\n    \"role\": \"gallery\",\n    \"description\": \"Session recordings as stacked carousels. A small heading and grey subtitle, then per stage a tiny label at left with two arrow glyphs at far right and a row of 16:9 dark photo tiles, two full tiles visible and a third cropped by the margin. Each tile has a small white event tag in its bottom-left corner. Caption beneath: speaker name in ink followed by the talk title in grey on the same line.\"\n   },\n   {\n    \"role\": \"about\",\n    \"description\": \"Speaker row: one-line heading at left, arrows at right, then four near-square portrait tiles with 8px gaps, each a face drawn in horizontal rows of characters in one colour on its tint (orange, green, lilac, teal). Some tiles show only plain stripes with the face barely emerging, so portraits appear to resolve from lines as they load or on hover.\"\n   },\n   {\n    \"role\": \"cta\",\n    \"description\": \"After a three-column photo grid with mixed landscape and portrait crops and 8px gaps, the page ends on an empty off-white screen holding one centred sentence at 18px and a small dark pill button beneath it. There are no footer columns, links or legal rows.\"\n   }\n  ],\n  \"steal\": [\n   \"Draw the name as one continuous thin looping stroke per letter, each in a different colour, and let it be the only large element on the page.\",\n   \"Keep all text at two small sizes and build hierarchy from ink versus grey on the same line (name in ink, detail in grey right after it).\",\n   \"Re-render photographs as rows of tiny characters in a single saturated colour on a tint of that colour, one colour per tile.\"\n  ]\n },\n {\n  \"id\": \"opl-the-new-industrials\",\n  \"name\": \"The New Industrials\",\n  \"url\": \"https://thenewindustrials.com/\",\n  \"source\": \"One Page Love\",\n  \"kind\": \"other\",\n  \"score\": 8.3,\n  \"idea\": \"A long-read essay laid out inside a visible drafting grid, where colour fields shift as you read and 3D machine parts drift through the margins and finally assemble into the publisher's initials.\",\n  \"mood\": [\n   \"bold\",\n   \"playful\",\n   \"editorial\",\n   \"engineered\",\n   \"saturated\"\n  ],\n  \"archetype\": \"editorial-masthead\",\n  \"hero\": \"A saturated orange page framed by black hairlines 24px from each edge. Top strip: a monogram logo left, a black pill with orange monospaced title centred, a boxed year right. Under it a row of eight empty outlined cells, 62px tall, like a ruler. A cream panel then fills the remaining width and height. Inside, a WebGL scene of pastel low-poly machine parts with visible wireframes sits behind a two-line uppercase title in a tall condensed slab serif, glyphs about 210px high, spanning 83% of the width. Small monospaced uppercase credits flank it at mid-height; reading time is centred below, with two boxed share links on the bottom edge.\",\n  \"type\": \"Title in a tall condensed slab serif at roughly 14vw cap height, black, uppercase. Essay in Albra Book serif: 34px lead paragraph, 18px running text with generous leading. Supply Mono in tiny uppercase for credits and box labels; a narrow typewriter-like face for the pull quote.\",\n  \"colour\": \"#ff8126 #f1ead8 #161615 #4db3ff #c5f53d #ff5fc0 — The page background changes as you read: orange, then a gradient through lilac into sky blue, then acid lime at the end. Type and hairlines stay black; the 3D parts carry rainbow gradients.\",\n  \"imagery\": \"Real-time 3D machine components (cylinders, gears, polyhedra) in matte pastel with coloured wireframe edges and neon gradient caps; they overlap the title, float into text margins and form letters in the footer.\",\n  \"layout\": \"Black hairlines divide the whole page into cells: one wide text cell flanked by narrow empty ones, each chapter tagged with a small numbered box at its corner. The lead paragraph spans the cell, running text is indented into a narrower column, and full-width quote screens interrupt.\",\n  \"sections\": [\n   {\n    \"role\": \"intro\",\n    \"description\": \"On orange, a ruled cell with a small numbered square at its top-right corner. The opening paragraph is set in serif at about 34px, seven lines, filling the cell with 60px padding. A horizontal hairline closes the cell; the next one indents its text by about 180px and drops to 18px, with a vertical rule marking the indent. The side cells stay empty, so the grid reads as margin furniture.\"\n   },\n   {\n    \"role\": \"other\",\n    \"description\": \"Pull quote: a full-viewport interruption where the grid lines stop. The background becomes a vertical gradient from orange through dusty lilac to sky blue. Centred, five lines of a narrow, widely tracked typewriter-style face at about 48px in dark olive-brown, each letter trailing a soft red vertical smear downward like wet ink. The next cell resumes on the blue that the gradient ended on.\"\n   },\n   {\n    \"role\": \"other\",\n    \"description\": \"Body screens: a single serif column about 960px wide between two vertical hairlines, paragraphs separated by a blank line. One 3D object per screen (a grey-green polyhedron with green edges, an orange hexagonal nut) sits half outside the column, crossing the vertical rule and the page edge at a different height each time, so every screen of text has one sculptural interruption.\"\n   },\n   {\n    \"role\": \"footer\",\n    \"description\": \"Acid-lime field. The publisher's three initials are built as a sculpture from the 3D parts seen earlier, about 60% of the viewport tall and spanning nearly the full width, each letter a different assembly of pipes, gears and blocks in clashing gradients. Below, hairlines form two cells holding monospaced uppercase credits at 10px, aligned to the cells' left padding.\"\n   }\n  ],\n  \"steal\": [\n   \"Draw the layout grid as visible black hairlines, including a row of empty cells, and tag each text block with a small numbered box.\",\n   \"Change the page background colour between chapters of a long read so progress is felt as a shift of colour.\",\n   \"Let one family of 3D objects recur at three scales: behind the title, in the margins, and assembled into a monogram at the end.\"\n  ]\n },\n {\n  \"id\": \"opl-wild-as\",\n  \"name\": \"wild\",\n  \"url\": \"https://craft.wild.as\",\n  \"source\": \"One Page Love\",\n  \"kind\": \"agency\",\n  \"score\": 8.3,\n  \"idea\": \"A studio essay on craft versus AI in which everything decorative is drawn on one square-pixel grid: the hero heatmap, the icons, the diagrams, the marquee lettering and the footer equaliser.\",\n  \"mood\": [\n   \"precise\",\n   \"playful\",\n   \"technical\",\n   \"bright\",\n   \"editorial\"\n  ],\n  \"archetype\": \"editorial-masthead\",\n  \"hero\": \"White page with a barely visible graph-paper grid. The top 22% is a masthead band split by a vertical hairline at 60%: at left, a two-line uppercase headline in a light grotesk at 5.2vw, tight leading, starting 9% from the left and nearly touching the top edge; at right, a two-line uppercase tagline with words spread to justify the column, then a pixel logo and a small right-aligned description. Below, a full-bleed canvas about 45% of the viewport tall: thousands of small squares in yellow, red, lime, cobalt and navy form a heatmap that erodes into white along its lower edge. A 3vw intro paragraph begins at the fold.\",\n  \"type\": \"Sneak in one regular-to-light weight does everything: uppercase 75px headline at -0.035em, a 44px sentence-case intro, section headings near 30px, 13px body. Tiny SF Mono uppercase captions with wide tracking sit under headings. A bitmap pixel face appears once, in the closing marquee. No bold anywhere.\",\n  \"colour\": \"#ffffff #0a0a0a #f2b90f #3b55d9 #1e2340 #e8452c — White page, black type, black buttons. Colour lives only inside the pixel graphics, in a fixed set of yellow, cobalt, navy, red and lime, so every illustration looks related. No section changes background.\",\n  \"imagery\": \"Canvas-drawn square-pixel fields: a heatmap band, particle streams that tighten from scattered dots into a dense ribbon, pixel smiley faces, an equaliser strip. Client work appears once, as three plain square-cornered photo cards.\",\n  \"layout\": \"Content runs from 9% to 91% with a constant split: heading in the left third, body in the right two-thirds, a tiny mono caption under the heading. Full-bleed pixel canvases interrupt the text. A small fixed mono link sits top-right; the ending is centred.\",\n  \"sections\": [\n   {\n    \"role\": \"work\",\n    \"description\": \"Three equal cards in one row, each a 6:5 image with square corners (laptop mock-up, product photo, flat illustration) followed by a centred project name at about 20px and a centred two-line description in small text. No borders, shadows or tags; a small round black arrow button overlaps the right edge of the third image to advance the row. Large white space above and below.\"\n   },\n   {\n    \"role\": \"intro\",\n    \"description\": \"Essay rows: a two- or three-line heading at about 2.2vw in the left third with a tiny wide-tracked mono caption below it; in the right two-thirds, two short justified paragraphs at 13px. Under one row, two pixel-art faces built from black squares (a smile and a frown, about 30px) sit side by side, each over a mono label and a three-line centred caption, forming a two-column comparison.\"\n   },\n   {\n    \"role\": \"how-it-works\",\n    \"description\": \"A four-word heading on two lines and a short paragraph at the left, then a wide canvas diagram: scattered pale-blue and navy squares at the left converge into a tight horizontal ribbon in the middle and fan out again in yellow at the right, a pixel funnel. Below it four narrow columns, each with a small round dark marker, a bold one-word label and two lines of small text.\"\n   },\n   {\n    \"role\": \"cta\",\n    \"description\": \"A single line of bitmap lettering scrolls across the full width, each glyph assembled from yellow squares flecked with red, navy and lime. Centred beneath: a black button with stepped pixel corners, two short grey centred paragraphs and an email line. The page ends with a full-width strip of coloured pixel bars like an audio equaliser, a small black play button centred above it.\"\n   }\n  ],\n  \"steal\": [\n   \"Pick one drawing primitive, a square on a fixed grid, and render every non-text element with it (hero art, icons, diagrams, display lettering, footer) in one five-colour set.\",\n   \"Split a masthead band 60/40 with a vertical hairline: oversized light-weight uppercase headline at left, a word-spaced justified tagline and tiny descriptor at right.\",\n   \"Lay out long copy as rows with the heading in the left third and body in the right two-thirds, and put the tiny mono caption under each heading instead of an eyebrow above it.\"\n  ]\n },\n {\n  \"id\": \"aww-hilden-kaira\",\n  \"name\": \"Hildén & Kaira\",\n  \"url\": \"https://www.hildenkaira.fi/\",\n  \"source\": \"Awwwards Site of the Day\",\n  \"kind\": \"agency\",\n  \"score\": 8.3,\n  \"idea\": \"The agency name is cast in liquid chrome across the full width, and the same chrome becomes emoji that float through the page, tying a social-media pitch to one material.\",\n  \"mood\": [\n   \"brash\",\n   \"glossy\",\n   \"editorial\",\n   \"witty\"\n  ],\n  \"archetype\": \"giant-wordmark\",\n  \"hero\": \"Warm light-grey field. The lowercase serif wordmark, rendered as polished chrome 3D letters with a molten ampersand, runs edge to edge across the top quarter (about 220px tall, 16px side margins). A tilted portrait video roughly 180 by 220px covers two of its letters. Directly under the wordmark, four small nav links centred. Then 300px of nothing, with one chrome flame emoji floating at the far left. The headline sits in the bottom third: three centred lines of narrow display serif at 4.4vw, leading so tight that descenders touch ascenders, a two-line 15px sans sub, and two square-cornered buttons, black and pale lime.\",\n  \"type\": \"PP Editorial New 400 for headlines at 63px, -0.02em tracking and leading near 0.9; PP Neue Montreal 13px for nav, body and buttons. The jump is roughly 5:1 with nothing in between. Stat numerals use the sans at about 60px.\",\n  \"colour\": \"#eae9e6 #181818 #ecfdad #b5b5b5 #ffffff #3aa57a — Warm grey and near-black alternate by section. Pale lime is the single accent: secondary buttons, headline text on dark, stat tiles and service cards. Chrome silver recurs as a material.\",\n  \"imagery\": \"Chrome 3D-rendered lettering and emoji objects (flame, heart, dove, microphone, wink) floating free; vertical phone videos of client content shown as fanned, slightly rotated stacks with white borders. Square corners throughout.\",\n  \"layout\": \"Centred statements with large voids, alternating light and dark full-width bands. Content arrives as square-cornered slabs: a white case card on grey, lime service cards stacking over each other on black. Chrome objects break the grid at the edges.\",\n  \"sections\": [\n   {\n    \"role\": \"testimonial\",\n    \"description\": \"Full-viewport near-black band. A two-line centred serif statement in pale lime at about 4vw sits in the upper third with nothing near it. Two small testimonials are pushed to the bottom-left and bottom-right corners: five tiny stars, two lines of 11px sans, name and title, each centred in its own narrow block. The centre bottom is left empty.\"\n   },\n   {\n    \"role\": \"work\",\n    \"description\": \"Horizontal carousel of wide white slabs on the grey ground, the next slide peeking at the right edge. Left half: a two-line serif title top-left, then far below a red-dot label over a thin rule and two flat tiles side by side, a wide lime one and a narrower brushed-chrome one, each with a tiny caption and a 60px sans numeral. Right half: a grey panel with three vertical videos fanned like playing cards.\"\n   },\n   {\n    \"role\": \"features\",\n    \"description\": \"On black, a centred serif section title, then service cards that pin and stack: a lime slab about 55% wide with serif title top-left, grey serif index number top-right, a small paragraph and black button bottom-left and a vertical video inset bottom-right. White and green slabs peek out beneath it, offset downward, and the top card tilts a degree or two as it scrolls.\"\n   },\n   {\n    \"role\": \"footer\",\n    \"description\": \"A full brushed-silver gradient field. The chrome wordmark repeats at full width across the top. Bottom-left, a small serif label over two short link columns; bottom-right, two square translucent tiles each holding a chrome object (microphone, heart) with a serif label above and three tiny square social buttons below. A hairline and a legal row close it.\"\n   }\n  ],\n  \"steal\": [\n   \"Render the wordmark in one physical material and reuse that material for small floating objects, so decoration and logo are the same thing.\",\n   \"Leave a third of the hero empty between a top-edge wordmark and a bottom-third headline; the gap makes both read.\",\n   \"Set a display serif with leading under 1.0 so lines interlock, and pair it with 13px sans for everything else.\"\n  ]\n },\n {\n  \"id\": \"aww-px-push\",\n  \"name\": \"PX PUSH\",\n  \"url\": \"https://pxpush.com/\",\n  \"source\": \"Awwwards Site of the Day\",\n  \"kind\": \"agency\",\n  \"score\": 8.2,\n  \"idea\": \"A design subscription presented as a retro broadcast: the entire site is seen through a CRT screen, with a chrome logo token floating in the sky as its mascot.\",\n  \"mood\": [\n   \"retro-futurist\",\n   \"cool\",\n   \"technical\",\n   \"cinematic\",\n   \"confident\"\n  ],\n  \"archetype\": \"product-object-centre\",\n  \"hero\": \"Full-bleed photograph of deep-blue sky over a cloud bank, the whole viewport under a CRT treatment: horizontal scanlines, slight blur, dark vignette with rounded corners. Top row with 43px margins: thin techno wordmark left; three links and a start link with a green dot right, split by a vertical hairline; full-width hairline beneath. Then one marquee line at 12vw (173px) in off-white grotesk, cropped at both edges, words separated by a solid dot, closed by a second hairline. Dead centre: a chrome 3D ring token about 400px wide. Bottom-left: a 216×144px royal-blue rounded thumbnail with a two-line mono caption. Bottom-right: a four-line mono uppercase paragraph 450px wide.\",\n  \"type\": \"A semi-condensed grotesk (digest name 'SemiSqueezed') at regular weight carries the 173px marquee, 28px paragraphs and 5vw statements; an uppercase monospace at 11–17px handles tags, captions and link rows. Ten-to-one jump between display and labels; no bold anywhere.\",\n  \"colour\": \"#03049c #71737d #1a1a1a #788ca4 #d9dde6 #c8f31d — Each section is a full colour field: sky photo, mid grey, near-black, then saturated royal blue. Text is off-white or pale lavender; acid lime appears only in small thumbnails, green only as a status dot.\",\n  \"imagery\": \"Sky photograph, a chrome 3D logo token, and client work shown as phone UIs on a blue ground and a poster photographed in a street lightbox. Everything sits under the same scanline filter; tiles have small radii.\",\n  \"layout\": \"A narrow left rail (about 17% wide) carries a bullet, a mono section tag and a small pinne\n\n<!-- [TRUNCATED AT 50KB] -->","skills/taste-skill/library/type.json":"[\n {\n  \"id\": \"switzer-semibold\",\n  \"name\": \"Switzer\",\n  \"class\": \"grotesk-tight\",\n  \"display\": {\n   \"family\": \"Switzer\",\n   \"source\": \"fontshare\",\n   \"slug\": \"switzer\",\n   \"weights\": [\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 600 · tracking -0.04em · leading 0.95 · sentence case; charcoal rather than pure black\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=switzer@400,500,600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Switzer\",\n   \"source\": \"fontshare\",\n   \"slug\": \"switzer\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking -0.005em\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=switzer@400,500,600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Suisse Intl\",\n   \"Neue Haas Grotesk\"\n  ],\n  \"note\": \"One neo-grotesk doing everything: semibold headings pulled tight, small regular text, no capitals and no second voice. Suits software, hardware and studio pages that want to look exact and unshowy.\",\n  \"seenIn\": [\n   \"aww-noho\",\n   \"opl-vessa\",\n   \"aww-aspen-search\",\n   \"opl-rows\"\n  ],\n  \"links\": [\n   \"https://api.fontshare.com/v2/css?f[]=switzer@400,500,600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"general-sans-bold\",\n  \"name\": \"General Sans\",\n  \"class\": \"grotesk-tight\",\n  \"display\": {\n   \"family\": \"General Sans\",\n   \"source\": \"fontshare\",\n   \"slug\": \"general-sans\",\n   \"weights\": [\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 700 · tracking -0.02em · leading 0.9 · sentence case; sizes jump straight from 16px text to 10vw and larger\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=general-sans@400,500,700&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"General Sans\",\n   \"source\": \"fontshare\",\n   \"slug\": \"general-sans\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body and lists, 500 for emphasis · leading 1.45 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=general-sans@400,500,700&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"PP Neue Montreal\",\n   \"Aeonik\"\n  ],\n  \"note\": \"A grotesk with slightly geometric bowls, set bold and very large against plain 16px text with nothing in between. Suits studios, type and product launches, and finance or tech brands that lead with the name.\",\n  \"seenIn\": [\n   \"aww-pp-neue-montreal\",\n   \"aww-moto-finance\",\n   \"opl-brikkenco\",\n   \"aww-nothin\"\n  ],\n  \"links\": [\n   \"https://api.fontshare.com/v2/css?f[]=general-sans@400,500,700&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"schibsted-heavy\",\n  \"name\": \"Schibsted Grotesk\",\n  \"class\": \"grotesk-tight\",\n  \"display\": {\n   \"family\": \"Schibsted Grotesk\",\n   \"source\": \"google\",\n   \"weights\": [\n    800\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 800 · tracking -0.05em · leading 0.88 · sentence case or all lowercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Schibsted+Grotesk:wght@400;600;800&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Schibsted Grotesk\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for paragraphs, 600 for navigation and other functional text · leading 1.4 · tracking -0.01em\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Schibsted+Grotesk:wght@400;600;800&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"ABC Diatype\",\n   \"Khteka\"\n  ],\n  \"note\": \"A compact, warm grotesk set heavy with letters almost touching; small text stays in the same family at semibold. Suits music, events and culture pages where the type is the image.\",\n  \"seenIn\": [\n   \"aww-paul-kalkbrenner\",\n   \"opl-rendez-vous-franceclat\",\n   \"aww-monolog\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Schibsted+Grotesk:wght@400;600;800&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"hanken-medium\",\n  \"name\": \"Hanken Grotesk\",\n  \"class\": \"grotesk-tight\",\n  \"display\": {\n   \"family\": \"Hanken Grotesk\",\n   \"source\": \"google\",\n   \"weights\": [\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 500 · tracking -0.05em · leading 0.9 · sentence case; one statement size (about 6vw) used for every heading\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Hanken+Grotesk:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Hanken Grotesk\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.45 · tracking -0.005em\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Hanken+Grotesk:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Akzidenz Grotesk\",\n   \"LayGrotesk\"\n  ],\n  \"note\": \"Medium-weight grotesk statements at one large size against caption-size text: a two-size system with no bold. Suits portfolios, agencies and tools that speak in short declarative lines.\",\n  \"seenIn\": [\n   \"aww-bleibtgleich26\",\n   \"aww-made-with-gsap-1\",\n   \"opl-locker-land\",\n   \"opl-builders-table\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Hanken+Grotesk:wght@400;500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"bricolage-contrast\",\n  \"name\": \"Bricolage Grotesque\",\n  \"class\": \"grotesk-tight\",\n  \"display\": {\n   \"family\": \"Bricolage Grotesque\",\n   \"source\": \"google\",\n   \"weights\": [\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 600 · tracking -0.04em · leading 0.92 · sentence case; leave optical sizing on so large sizes tighten and gain contrast\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:wght@400;500;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Bricolage Grotesque\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:wght@400;500;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Beausite Classic\",\n   \"F37 Analog\"\n  ],\n  \"note\": \"A grotesk with visible stroke contrast and slightly irregular curves, so headings look drawn rather than engineered. Suits reports, consultancies and design-led software that want warmth without a serif.\",\n  \"seenIn\": [\n   \"aww-ai-in-design-report-2026\",\n   \"aww-illoca\",\n   \"opl-ohhmydesign\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:wght@400;500;600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"franklin-source\",\n  \"name\": \"Libre Franklin / Source Serif 4\",\n  \"class\": \"grotesk-tight\",\n  \"display\": {\n   \"family\": \"Libre Franklin\",\n   \"source\": \"google\",\n   \"weights\": [\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 700 · tracking -0.035em · leading 0.92 · uppercase for the title, sentence case for section headings\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Libre+Franklin:wght@700&family=Source+Serif+4:ital,wght@0,400;0,600;1,400;1,600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Source Serif 4\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    600\n   ],\n   \"italic\": true,\n   \"settings\": \"400 for body, 600 for emphasis, italic for quotations · leading 1.55 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Libre+Franklin:wght@700&family=Source+Serif+4:ital,wght@0,400;0,600;1,400;1,600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Founders Grotesk\",\n   \"Die Grotesk\",\n   \"NON Natural Grotesk\"\n  ],\n  \"note\": \"An American gothic for headings over a sober transitional serif for reading, the pairing of a newspaper front page. Suits essays, annual reports, archives and finance pages that have real paragraphs.\",\n  \"seenIn\": [\n   \"aww-dragonfly-redux\",\n   \"aww-trevor-noah\",\n   \"aww-mosbys-files\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Libre+Franklin:wght@700&family=Source+Serif+4:ital,wght@0,400;0,600;1,400;1,600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"switzer-roman\",\n  \"name\": \"Switzer\",\n  \"class\": \"grotesk-light\",\n  \"display\": {\n   \"family\": \"Switzer\",\n   \"source\": \"fontshare\",\n   \"slug\": \"switzer\",\n   \"weights\": [\n    400\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 400 · tracking -0.03em · leading 1.1 · sentence case; headings stay small (28–40px) and at most one line jumps to 5vw\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=switzer@400,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Switzer\",\n   \"source\": \"fontshare\",\n   \"slug\": \"switzer\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for everything, 500 only for names and links · leading 1.45 · tracking -0.01em; hierarchy by ink against mid-grey\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=switzer@400,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Neue Haas Grotesk 55 Roman\",\n   \"Helvetica Now\"\n  ],\n  \"note\": \"A single roman weight of a Swiss neo-grotesk at two or three modest sizes; position and grey value do the work that size and bold usually do. Suits architects, galleries, studios and any quiet page where photographs carry the scale.\",\n  \"seenIn\": [\n   \"aww-revelatio-studio\",\n   \"opl-spatial\",\n   \"aww-pensatori-irrazionali\",\n   \"opl-compile\"\n  ],\n  \"links\": [\n   \"https://api.fontshare.com/v2/css?f[]=switzer@400,500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"archivo-regular\",\n  \"name\": \"Archivo\",\n  \"class\": \"grotesk-light\",\n  \"display\": {\n   \"family\": \"Archivo\",\n   \"source\": \"google\",\n   \"weights\": [\n    400\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 400 · tracking -0.02em · leading 1.0 · sentence case; never bold, inactive items fade to grey\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Archivo:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Archivo\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 600 for buttons and short emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Archivo:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Scto Grotesk A\",\n   \"Cash Sans\"\n  ],\n  \"note\": \"A sturdy grotesque kept at regular weight even at 88px, so the page reads as composed rather than loud. Suits finance, infrastructure and research pages that need to look sober and current.\",\n  \"seenIn\": [\n   \"aww-sharplink\",\n   \"opl-plastic\",\n   \"opl-lovably\",\n   \"opl-berd\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Archivo:wght@400;600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"clash-grotesk-regular\",\n  \"name\": \"Clash Grotesk\",\n  \"class\": \"grotesk-light\",\n  \"display\": {\n   \"family\": \"Clash Grotesk\",\n   \"source\": \"fontshare\",\n   \"slug\": \"clash-grotesk\",\n   \"weights\": [\n    400\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 400 · tracking -0.03em · leading 0.95 · sentence case, or uppercase for one statement\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=clash-grotesk@400,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Clash Grotesk\",\n   \"source\": \"fontshare\",\n   \"slug\": \"clash-grotesk\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.4 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=clash-grotesk@400,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Sneak\",\n   \"ABC Monument Grotesk\"\n  ],\n  \"note\": \"A slightly narrow neo-grotesk with closed apertures, used at regular weight from marquee size down to paragraphs. Suits agencies and digital studios that want large type without heaviness.\",\n  \"seenIn\": [\n   \"aww-px-push\",\n   \"opl-wild-as\",\n   \"aww-sstr-friction-reduction\"\n  ],\n  \"links\": [\n   \"https://api.fontshare.com/v2/css?f[]=clash-grotesk@400,500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"work-sans-light\",\n  \"name\": \"Work Sans\",\n  \"class\": \"grotesk-light\",\n  \"display\": {\n   \"family\": \"Work Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    300\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 300 · tracking -0.035em · leading 1.0 · sentence case\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Work+Sans:wght@300;400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Work Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.55 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Work+Sans:wght@300;400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"ABC Favorit\",\n   \"Clarkson Light\",\n   \"PP Mori\"\n  ],\n  \"note\": \"A light grotesque with open, slightly old-fashioned shapes; large headings look airy and the text weight beneath stays easy to read. Suits AI and research products, fashion houses and calm brand sites.\",\n  \"seenIn\": [\n   \"aww-cerebrium\",\n   \"aww-squarespace-foundations\",\n   \"aww-boc-studio\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Work+Sans:wght@300;400;500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"anton-work\",\n  \"name\": \"Anton / Work Sans\",\n  \"class\": \"condensed-heavy\",\n  \"display\": {\n   \"family\": \"Anton\",\n   \"source\": \"google\",\n   \"weights\": [\n    400\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 400 (single heavy cut) · tracking -0.01em · leading 0.86 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Anton:wght@400&family=Work+Sans:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Work Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 600 for links and short emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Anton:wght@400&family=Work+Sans:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Druk\",\n   \"Thunder\",\n   \"Acme Gothic\"\n  ],\n  \"note\": \"Compressed heavy capitals stacked tight, with a neutral grotesque kept small beneath. Suits fashion drops, sport, nightlife and any page built as a poster.\",\n  \"seenIn\": [\n   \"aww-serotoninn\",\n   \"opl-juggle\",\n   \"opl-lorenzo-bocchi-photography\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Anton:wght@400&family=Work+Sans:wght@400;600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"big-shoulders-public\",\n  \"name\": \"Big Shoulders / Public Sans\",\n  \"class\": \"condensed-heavy\",\n  \"display\": {\n   \"family\": \"Big Shoulders\",\n   \"source\": \"google\",\n   \"weights\": [\n    800\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 800 · tracking -0.005em · leading 0.88 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Big+Shoulders:wght@800&family=Public+Sans:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Public Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 600 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Big+Shoulders:wght@800&family=Public+Sans:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Founders Grotesk Condensed\",\n   \"PP Neue York\",\n   \"Knockout\"\n  ],\n  \"note\": \"A tall American gothic taken from city signage, blunt and civic, over a plain public-service sans. Suits culture indexes, community projects, bars, sport clubs and local campaigns.\",\n  \"seenIn\": [\n   \"aww-mosbys-files\",\n   \"opl-the-sapphic-bar-index\",\n   \"opl-the-deep-end\",\n   \"aww-colonia-zacamil\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Big+Shoulders:wght@800&family=Public+Sans:wght@400;600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"archivo-compressed\",\n  \"name\": \"Archivo\",\n  \"class\": \"condensed-heavy\",\n  \"display\": {\n   \"family\": \"Archivo\",\n   \"source\": \"google\",\n   \"weights\": [\n    800\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 800 at font-stretch 62% (load the wdth axis and use its narrowest setting) · tracking -0.01em · leading 0.86 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Archivo:wdth,wght@62..125,100..900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Archivo\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"normal width · 400 for body, 500 for buttons and emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Archivo:wdth,wght@62..125,100..900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Helvetica Now Display Condensed\"\n  ],\n  \"note\": \"One variable family pushed to its narrowest, heaviest setting for headlines and relaxed to normal width for text, so display and body share a skeleton. Suits sportswear, campaigns and fintech pages that speak in capitals.\",\n  \"seenIn\": [\n   \"aww-decathlon-yestalgia\",\n   \"opl-uglycash\",\n   \"opl-juggle\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Archivo:wdth,wght@62..125,100..900&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"bebas-garamond\",\n  \"name\": \"Bebas Neue / EB Garamond\",\n  \"class\": \"condensed-heavy\",\n  \"display\": {\n   \"family\": \"Bebas Neue\",\n   \"source\": \"google\",\n   \"weights\": [\n    400\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 400 (single cut, capitals only) · tracking -0.02em, tightening to -0.06em above 15vw · leading 0.85 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Bebas+Neue:wght@400&family=EB+Garamond:ital,wght@0,400;0,500;1,400;1,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"EB Garamond\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": true,\n   \"settings\": \"leading 1.45 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Bebas+Neue:wght@400&family=EB+Garamond:ital,wght@0,400;0,500;1,400;1,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Founders Grotesk Condensed\",\n   \"Cardinal Classic Long\",\n   \"Signifier\"\n  ],\n  \"note\": \"Huge condensed capitals against a light old-style serif with italics: an industrial voice and a literary one, with a twenty-fold size gap between them. Suits crafted physical products, spirits, outdoor goods and hospitality.\",\n  \"seenIn\": [\n   \"aww-longbow\",\n   \"aww-white-desert\",\n   \"aww-mosbys-files\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Bebas+Neue:wght@400&family=EB+Garamond:ital,wght@0,400;0,500;1,400;1,500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"barlow-condensed\",\n  \"name\": \"Barlow Condensed / Barlow\",\n  \"class\": \"condensed-heavy\",\n  \"display\": {\n   \"family\": \"Barlow Condensed\",\n   \"source\": \"google\",\n   \"weights\": [\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 700 · tracking -0.02em · leading 0.9 · uppercase for statements, mixed case for item titles\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@700&family=Barlow:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Barlow\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@700&family=Barlow:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"FF DIN Condensed\",\n   \"Helvetica Now Display Condensed\"\n  ],\n  \"note\": \"Road-sign condensed type with squared curves, bold but not compressed into a wall, with its normal-width sibling for text. Suits logistics, motorsport, hardware and directories with many short titles.\",\n  \"seenIn\": [\n   \"aww-julien-calot\",\n   \"opl-medium-rare\",\n   \"opl-uglycash\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@700&family=Barlow:wght@400;500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"panchang-switzer\",\n  \"name\": \"Panchang / Switzer\",\n  \"class\": \"extended-heavy\",\n  \"display\": {\n   \"family\": \"Panchang\",\n   \"source\": \"fontshare\",\n   \"slug\": \"panchang\",\n   \"weights\": [\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 700 · tracking -0.02em · leading 1.0 · uppercase; four words or fewer per line because the face is very wide\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=panchang@700&display=swap\\\" rel=\\\"stylesheet\\\">\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=switzer@400,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Switzer\",\n   \"source\": \"fontshare\",\n   \"slug\": \"switzer\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=panchang@700&display=swap\\\" rel=\\\"stylesheet\\\">\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=switzer@400,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Monument Extended\",\n   \"Owners Wide\",\n   \"Nimbus Sans Extended\"\n  ],\n  \"note\": \"A flat-sided extended grotesk in heavy capitals, wide enough that two words fill the screen, with a neutral sans kept small. Suits portfolios, real estate, travel and brand sites that want a broad, confident wordmark.\",\n  \"seenIn\": [\n   \"opl-belen-jones\",\n   \"aww-lxl-creative\",\n   \"aww-realevate\",\n   \"aww-the-tuscan-journey-begins\"\n  ],\n  \"links\": [\n   \"https://api.fontshare.com/v2/css?f[]=panchang@700&display=swap\",\n   \"https://api.fontshare.com/v2/css?f[]=switzer@400,500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"tiktok-sans-wide\",\n  \"name\": \"TikTok Sans\",\n  \"class\": \"extended-heavy\",\n  \"display\": {\n   \"family\": \"TikTok Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    800\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 800 at font-stretch 150% (load the wdth axis and use its widest setting) · tracking -0.01em · leading 1.0 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=TikTok+Sans:wdth,wght@75..150,300..900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"TikTok Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"normal width · 400 for body, 500 for emphasis · leading 1.45 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=TikTok+Sans:wdth,wght@75..150,300..900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Herokid Wide\",\n   \"At Aero\",\n   \"Wintyr\"\n  ],\n  \"note\": \"One variable grotesk stretched wide and bold for the headline and the closing statement, then returned to normal width for reading. Suits personal portfolios, apps and tech brands that want width without a second family.\",\n  \"seenIn\": [\n   \"aww-haoqi-design\",\n   \"opl-tara\",\n   \"aww-produx-design\",\n   \"opl-proooof\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=TikTok+Sans:wdth,wght@75..150,300..900&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"unbounded-onest\",\n  \"name\": \"Unbounded / Onest\",\n  \"class\": \"extended-heavy\",\n  \"display\": {\n   \"family\": \"Unbounded\",\n   \"source\": \"google\",\n   \"weights\": [\n    800\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 800 · tracking -0.03em · leading 1.0 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Unbounded:wght@800&family=Onest:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Onest\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Unbounded:wght@800&family=Onest:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"IntraNet\",\n   \"Nekst\",\n   \"Owners Wide\"\n  ],\n  \"note\": \"A wide display sans built from rounded squares, heavy and a little architectural, beside a clean text grotesk. Suits architecture indexes, watches, mobility and events that want a title with a constructed feel.\",\n  \"seenIn\": [\n   \"opl-belgrade-architecture\",\n   \"aww-the-watch\",\n   \"aww-risk\",\n   \"aww-house-of-honey-1\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Unbounded:wght@800&family=Onest:wght@400;500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"chivo-black\",\n  \"name\": \"Chivo\",\n  \"class\": \"heavy-black\",\n  \"display\": {\n   \"family\": \"Chivo\",\n   \"source\": \"google\",\n   \"weights\": [\n    900\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 900 · tracking -0.05em · leading 0.88 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Chivo:wght@400;700;900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Chivo\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for paragraphs, 700 for navigation, tags and links · leading 1.35 · tracking -0.01em\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Chivo:wght@400;700;900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Elza\",\n   \"ABC Diatype Heavy\",\n   \"Suisse Intl Black\"\n  ],\n  \"note\": \"A black grotesque in capitals with letters nearly colliding, and only two sizes on the page: enormous and small. Suits agencies, city and culture projects and musicians who want the type to land like a headline.\",\n  \"seenIn\": [\n   \"aww-glitch-grit\",\n   \"opl-city-of-angels\",\n   \"aww-warm-fuzzy\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Chivo:wght@400;700;900&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"cabinet-grotesk-black\",\n  \"name\": \"Cabinet Grotesk\",\n  \"class\": \"heavy-black\",\n  \"display\": {\n   \"family\": \"Cabinet Grotesk\",\n   \"source\": \"fontshare\",\n   \"slug\": \"cabinet-grotesk\",\n   \"weights\": [\n    800\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 800 · tracking -0.035em · leading 0.9 · lowercase or sentence case, one or two words per line\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=cabinet-grotesk@400,500,800&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Cabinet Grotesk\",\n   \"source\": \"fontshare\",\n   \"slug\": \"cabinet-grotesk\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=cabinet-grotesk@400,500,800&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Champ\",\n   \"Uncut Sans\"\n  ],\n  \"note\": \"A heavy sans with tight joins and an eccentric lowercase, friendly but loud. Suits bookshops, food, consumer subscriptions and marketing studios.\",\n  \"seenIn\": [\n   \"aww-aardvark-book-club\",\n   \"opl-protip-marketing\",\n   \"opl-rendez-vous-franceclat\"\n  ],\n  \"links\": [\n   \"https://api.fontshare.com/v2/css?f[]=cabinet-grotesk@400,500,800&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"epilogue-black\",\n  \"name\": \"Epilogue\",\n  \"class\": \"heavy-black\",\n  \"display\": {\n   \"family\": \"Epilogue\",\n   \"source\": \"google\",\n   \"weights\": [\n    900\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 900 · tracking -0.04em · leading 0.9 · sentence case or title case\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Epilogue:wght@400;500;900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Epilogue\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Epilogue:wght@400;500;900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Die Grotesk D\",\n   \"Acme Gothic\",\n   \"FH Oscar\"\n  ],\n  \"note\": \"A broad black grotesque with a slightly uneven rhythm, at its best as a name set very large in mixed case. Suits entertainers, podcasts, consumer apps and blunt SaaS pages; emphasis comes from colour, not from a change of weight.\",\n  \"seenIn\": [\n   \"aww-trevor-noah\",\n   \"opl-juggle\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Epilogue:wght@400;500;900&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"red-hat-black\",\n  \"name\": \"Red Hat Display / Red Hat Text\",\n  \"class\": \"heavy-black\",\n  \"display\": {\n   \"family\": \"Red Hat Display\",\n   \"source\": \"google\",\n   \"weights\": [\n    900\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 900 · tracking -0.03em · leading 0.92 · uppercase; centred three-line stacks work well\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Red+Hat+Display:wght@900&family=Red+Hat+Text:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Red Hat Text\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Red+Hat+Display:wght@900&family=Red+Hat+Text:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"FH Oscar\",\n   \"Futura Bold\"\n  ],\n  \"note\": \"A geometric black with round bowls and flat terminals, cleaner and more even than a grotesque at the same weight. Suits fintech, apps and portfolios that want heavy type with a tidy, technical finish.\",\n  \"seenIn\": [\n   \"aww-risk\",\n   \"aww-leo-parpeix-portfolio-2026\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Red+Hat+Display:wght@900&family=Red+Hat+Text:wght@400;500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"jost-caps\",\n  \"name\": \"Jost\",\n  \"class\": \"geometric\",\n  \"display\": {\n   \"family\": \"Jost\",\n   \"source\": \"google\",\n   \"weights\": [\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 700 · tracking -0.03em · leading 0.9 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Jost:wght@400;500;700&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Jost\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Jost:wght@400;500;700&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Futura Std Bold\",\n   \"Futura PT\"\n  ],\n  \"note\": \"The pointed, circular geometry of the 1920s in bold capitals, with the same family at reading size. Suits space, science, museums, architecture and anything that should feel like a mid-century poster.\",\n  \"seenIn\": [\n   \"aww-21-hrs-on-the-moon\",\n   \"aww-leo-parpeix-portfolio-2026\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Jost:wght@400;500;700&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"stack-sans-light\",\n  \"name\": \"Stack Sans Headline / Stack Sans Text\",\n  \"class\": \"geometric\",\n  \"display\": {\n   \"family\": \"Stack Sans Headline\",\n   \"source\": \"google\",\n   \"weights\": [\n    300\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 300 · tracking -0.022em · leading 1.05 · sentence case; a heading may be two-tone, grey then full ink\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Stack+Sans+Headline:wght@300&family=Stack+Sans+Text:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Stack Sans Text\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Stack+Sans+Headline:wght@300&family=Stack+Sans+Text:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Mluvka\",\n   \"Roobert\"\n  ],\n  \"note\": \"A geometric sans in a light weight at large size, soft and exact at once, with its text cut underneath. Suits consumer apps, utilities and developer tools that want to feel calm and modern.\",\n  \"seenIn\": [\n   \"opl-screentune\",\n   \"opl-dialkit\",\n   \"opl-typewave\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Stack+Sans+Headline:wght@300&family=Stack+Sans+Text:wght@400;500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"albert-sans-semibold\",\n  \"name\": \"Albert Sans\",\n  \"class\": \"geometric\",\n  \"display\": {\n   \"family\": \"Albert Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 600 · tracking -0.035em · leading 1.0 · sentence case\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Albert+Sans:wght@400;500;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Albert Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Albert+Sans:wght@400;500;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"BT Steinhart\",\n   \"TT Norms Pro\",\n   \"Objektiv\"\n  ],\n  \"note\": \"A geometric grotesque with Scandinavian restraint: round letters, even colour, nothing decorative. Suits logistics, health, property and corporate sites that need to look clear and dependable.\",\n  \"seenIn\": [\n   \"aww-united-carriers\",\n   \"aww-likova\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Albert+Sans:wght@400;500;600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"spartan-figtree\",\n  \"name\": \"League Spartan / Figtree\",\n  \"class\": \"geometric\",\n  \"display\": {\n   \"family\": \"League Spartan\",\n   \"source\": \"google\",\n   \"weights\": [\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 700 · tracking -0.04em · leading 0.88 · lowercase or sentence case\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=League+Spartan:wght@700&family=Figtree:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Figtree\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 600 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=League+Spartan:wght@700&family=Figtree:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Degular\",\n   \"Roobert\"\n  ],\n  \"note\": \"A compact bold geometric with a low waist, punchy in short lowercase lines, over a friendly open text sans. Suits newsletters, consumer products, creators and small shops.\",\n  \"seenIn\": [\n   \"opl-lennys-newsletter-product-pass\",\n   \"opl-near\",\n   \"opl-sand-studio\",\n   \"aww-aardvark-book-club\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=League+Spartan:wght@700&family=Figtree:wght@400;600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"pilcrow-rounded\",\n  \"name\": \"Pilcrow Rounded\",\n  \"class\": \"rounded-friendly\",\n  \"display\": {\n   \"family\": \"Pilcrow Rounded\",\n   \"source\": \"fontshare\",\n   \"slug\": \"pilcrow-rounded\",\n   \"weights\": [\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 700 · tracking -0.05em · leading 0.9 · all lowercase, one or two words per line\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=pilcrow-rounded@400,500,700&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Pilcrow Rounded\",\n   \"source\": \"fontshare\",\n   \"slug\": \"pilcrow-rounded\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0; lowercase throughout is fine\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=pilcrow-rounded@400,500,700&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Milling Triplex\",\n   \"Ease\"\n  ],\n  \"note\": \"A sturdy sans with fully rounded stroke ends, set bold and tight in lowercase with one small size for everything else. Suits toys, gadgets, cosmetics and other objects with soft moulded edges.\",\n  \"seenIn\": [\n   \"opl-when-you-wish-upon-a-starboy\",\n   \"opl-anidachi\",\n   \"aww-artem-shcherbakov\"\n  ],\n  \"links\": [\n   \"https://api.fontshare.com/v2/css?f[]=pilcrow-rounded@400,500,700&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw,\n\n<!-- [TRUNCATED AT 50KB] -->","skills/taste-skill/references/app-screens.md":"# App screens\n\nDashboards, admin, analytics, settings, inboxes, wallets and builders: the screens people work in.\nRead this file whole before you start one. The page run in `SKILL.md` does not apply to them.\n\nA generated dashboard is the average of every dashboard template: a dark or tinted sidebar with a\ncoloured pill on the active item, \"Welcome back\" and a waving hand, four KPI cards each with an icon\nin a tinted circle, a green \"+12.5%\" and a sparkline, a gradient area chart, a zebra table under\nuppercase headers. Nothing in it is wrong and none of it was decided.\n\nThis chapter is distilled from a study of 23 real product screens chosen by the owner: 17 products,\n17 light screens and 6 dark, all at desktop width (1440 or 1512px). Each screen was measured from its\npixels and noted for what works and what fails; the numbers below are those measurements and their\nmedians. The products are not named. What separates these screens from the generated kind, in order\nof how much it shows:\n\n1. **Colour goes on data, not chrome.** The median screen has about 3% coloured pixels; 17 of 23 stay\n   at 5% or less. 12 have no filled primary button at all.\n2. **KPIs are type, not tiles.** No screen puts an icon in a coloured circle on a KPI, and none draws a\n   sparkline on one.\n3. **Surfaces are flat.** 17 of 23 give their cards no shadow; separation is a 1px line or one tone\n   step.\n4. **There is no hero header.** 9 screens have no heading over 16px; where there is one, its median is\n   24px.\n5. **Charts carry almost no chrome.** A single series has no legend; gridlines are 3-7 faint lines or\n   none.\n6. **Navigation recedes.** The active item is a neutral grey pill or a change of text colour; a\n   coloured left bar appears once.\n7. **Tables are rules and alignment.** No zebra striping, no header bands, numbers right-aligned.\n8. **Data states are honest.** Zeros print as zeros, missing values as a grey dash, and an empty\n   section keeps its frame.\n\nTaking the template's devices away is half the job, as it is on a page. The other half is substance:\nthe product's real data, a screen that answers its one question first, and a grid whose arithmetic\ncloses.\n\n**A warning learned in testing.** In the first blind round, screens built with this chapter were\nclean, quiet and correct, and they lost to richer screens built without it. The judges' reasons were\nthe same every time, and each is now a rule below:\n\n- **The first screen was thin.** One large chart of a flat line filled it, and half the blocks the\n  brief asked for started below the fold. On a 1440×900 screen, every block the brief names shows its\n  header and its first rows (§2.2).\n- **The product was missing.** No name, no workspace, no mark: the screen could have belonged to\n  anyone. The shell names the product and the scope (§3.2).\n- **Restraint hid meaning.** A latency rise and a request rise were the same grey. Colour on a change\n  says good or bad, not up or down (§5).\n- **There was nothing to do.** No control for the job the screen exists for. The most frequent job is\n  one click from the first screen (§2.2).\n- **Rows ended ragged** and **a style's move was over-applied** (a tray around every card, an icon\n  rail where people needed labels). Keep the move to where it carries meaning.\n\nQuiet is the starting point, not the goal. A screen that a person would trust shows more of the\nproduct than a template does: its people, its objects, its numbers and the one thing to do next.\n\n**Give the product a face.** After four rounds the judges' top complaint was the same on most\nscreens: \"a well-applied kit, not a product with its own identity\" (stock Geist or Inter, a #f8f8f8\nground, white 12px cards, lime on black). The style's tokens make a screen correct; these make it\nthis product's, and choosing them is a step of the run, not a finish (§2.3):\n\n- **One face from the sheet, chosen before you build.** Each style lists two or three ways it takes a\n  face from the brief: a ground tinted from the product's world, a figure face with character, the\n  brand's hue on the main data element. Choose one, write it in your notes next to the screen's\n  question, and check that it shows on the first screenshot.\n- **The dealt typeface, really loaded.** A build that fell back to the default face landed on the\n  default look; the inspector now fails it.\n- **The product's mark and name** at the top of the shell, drawn for this product (a simple\n  monogram or symbol in the accent, from its name or its object), never a black square with a letter.\n- **One element only this product has**, built from its own things: an energy home's power flow, a\n  bakery's sell-out strip, a leave planner's cover against the minimum, the pace groups of a running\n  club as a unit chart, the couple as three lanes, a deploy's commit as the hero of the overview. The\n  sheet lists the library's signature elements whose words appear in the brief; otherwise invent one.\n  Name it in your notes next to the screen's question.\n- **The one chart hue on the main data element**: today's line, the booked bars, the current period,\n  the margin that breaks. A screen whose only hue is a delta reads as a kit, and the inspector warns\n  when a screen with charts carries no hue on its data (`no-data-hue`).\n- **Its people and objects as themselves**: each person gets a stable initial and a pale tint of their\n  own hue, with people listed next to each other at least 60 degrees apart. These tints are identity,\n  not data: they stay pale and out of the chart legends. Products show their thumbnails, cover art\n  shows the cover.\n- **Words of the trade** in labels and empty states (\"Waiting on the customer\", \"Off sick\", \"Due\n  on the 28th\"), never the generic noun of a template (\"Items\", \"Records\", \"Status\").\n\n**Calendars and timelines** (house rule, from testing; the study has none). People down the left on a\nfixed 160-220px column, grouped under a team subheader rather than repeating the team on every row;\ndays across with faint 1px day lines, weekends one tone step darker, and today marked by a 1px line\nin the one data hue with its date in ink. Bars are 20-24px tall at radius 4. One-line names sit on a\n32px pitch; a name with a subline (team, office) needs 40-44px, or the subline touches the next name.\n**Every kind of booking has its own mark**, so sickness reads apart from a holiday at a glance:\nholiday a pale fill, off sick a 1px diagonal hatch, long leave a darker grey step, working away an\noutline, a pending request a dashed outline. A style with a hue budget may add a 3px left edge in the\nhue for the kind the screen is about. Full colour is only for what needs a decision (a request that\nbreaks cover). A label sits inside its bar; a bar too short for it shows the kind's code inside and\nthe full label in its tooltip, or the label after the bar's end, never over the days before it.\nHoliday markers name their office in a multi-office product. Every swatch in the legend is the mark\nitself, scaled down, and lists only kinds on screen: `Charts.timeline(el, rows, kinds)` draws the bars\nand returns that legend from the same kinds map.\n\n## Contents\n\n1. When this applies\n2. The run for an app screen\n3. The shell\n4. The canvas and the page title\n5. KPIs\n6. Charts\n7. Tables and lists\n8. Forms and settings\n9. Type and colour\n10. Density\n11. Empty, zero, loading and error states\n12. The phone\n13. House rules for app screens\n14. Tells of generated dashboards\n\n## 1. When this applies\n\nAn app screen is worked in rather than read. This chapter covers:\n\n- dashboards and overviews: a seller's day, a project's health, a publication's growth;\n- admin and back office: members, orders, events, a catalogue;\n- analytics and reports, including a generated report with no app around it;\n- settings and billing;\n- list screens to work through: inboxes, queues, tables with filters;\n- wallets and finance homes;\n- builders and editors: flow, form and page builders, canvases;\n- the detail page of one object: an event, a deployment, a customer.\n\nA product site that shows its interface is a page; the interface fragments on it follow these rules\nfor their insides (mark each fragment's root with `data-ui`). When a request holds both, build each\nwith its own run and share one palette and one typeface.\n\nThe study is 23 desktop screens. It has no phone screens, no loading or error states, one settings\npage, no inbox and no dense operations table (the densest screen shows about 120 data points). Where a\nrule below goes past the study, it says **house rule**.\n\n## 2. The run for an app screen\n\nDo these in order. The first three steps decide whether the screen is any good.\n\n### 2.1 Inventory the data and the jobs\n\nThe page run inventories the subject's world; an app screen inventories its data. Write in your notes,\nin 8 to 12 lines:\n\n- **the objects** the screen shows (deployments, invoices, members, events, conversations) and their\n  fields, with units;\n- **realistic magnitudes**: how many objects, a typical amount, the range of a rate, how values move\n  over a day, a month, a year, and for a new account how small they really are;\n- **the people**: who opens this screen, how often (a glance once a day, or an eight-hour session),\n  on what device;\n- **the jobs**: what they do next from here (approve, reply, pay, ship, invite), and which job comes\n  up most;\n- **the product's own things**: its name and mark, the workspace or account it is scoped to, the people\n  in it (two partners, a team of six, the club's members), and the objects people recognise by sight\n  (product photographs in a shop, cover art in a media tool, a map of the route). These are what make\n  a screen belong to this product instead of to a template; plan where each one appears.\n\nThen write the data itself: a small dataset in a JSON or JS file that the screen renders from, with\nbelievable names, amounts that add up to their totals, dates in order and a unit on every figure.\nTotals are computed from the rows, never typed in separately. Small numbers stay small: the studied\nscreens show new accounts with 1, 6 or 9 of something, drawn honestly at their real size. Write the\nfigures that must agree as assertions in the data file (`console.assert(sold - cancelled === rsvps)`,\nthe bins sum to the total, the parts to the whole) and read the console: in testing, a ticket table\nthat did not reconcile with its own KPI cost a judge's trust in the whole screen. Checks that need\ncomputed values (allowance after a request, cover per day) go in the script that computes them.\n\n**Data that tells the truth** (house rules, from testing; judges checked every one of these):\n\n- **A fact shown twice is one variable.** A time window, a total or a state that appears in two cards\n  (the battery full 13:30-16:30 in the KPI label, the shaded span and the battery card) is one value in\n  the data file, and the copy and the chart annotation are both built from it. Two cards that\n  disagree by half an hour cost more trust than a missing card.\n- **Totals and deltas come from the parts as shown.** Sum the rounded pennies the screen displays,\n  never round the unrounded total separately: £21.68 + £8.34 − £3.81 is £26.21, and a screen that\n  says £26.22 is caught. A change is the difference of the two values on screen (£5.28 against\n  £5.22 is +£0.06, not +£0.07).\n- **Every relative figure names its baseline** in the same phrase: \"3 h 40 m before close\", \"45 m\n  earlier than last Sunday\", \"+5 on the usual Monday\". \"Early\", \"up\" or a bare \"+5\" next to another\n  time or figure reads as measured against that one.\n- **One name per time.** Shops close at 15:00 and the tills are cashed up at 15:12; the header and\n  the card use the same words for the same moment, and an error state rewrites the status line.\n- **If a caption has to say which bars are which, encode it in the chart instead**: a marked period in\n  a second tone with its own legend entry, a signed axis, a label on the mark.\n\n### 2.2 Name the screen's one question\n\nEvery screen answers one question first: \"Did today's sales come in?\", \"Which deploy broke?\", \"Who is\nwaiting for a reply?\", \"How much of this month's plan is left?\". Write it in one line. It decides\nthree things:\n\n- **what is biggest.** In the study the largest block is always the one that carries the screen's\n  question, whatever form it takes (a chart, a plan, a ring, a list). The same holds for figures:\n  the largest figure on the screen answers the question the title row's sentence answers. In testing,\n  an 88% sun ratio at 32px out-shouted the 24px charging window the title led with;\n- **what comes first** in the reading order;\n- **what is left out.** The studied settings page shows three usage numbers and links to the\n  analytics screen instead of drawing a chart; four screens draw no chart at all because a few\n  numbers say it.\n\nThen name the screen's **one finding**: the fact in today's data that most needs attention (\"9 no-shows\nwhile 8 people waited for a place\", \"the 23:28 deploy doubled the error rate\", \"eating out is £36 over\").\nPut it where it is read first, as the line under the title or the subline of the headline figure,\nnext to the action it drives. In testing, the finding that mattered sat in a 14px caption at the\nbottom of a card and the screen read as flat.\n\n**Do not rebuild a studied screen.** When the product is of the same kind as a screen in the study (a\nfinance home, a deploy overview), its arrangement is the trap: judges recognised the copies at once.\nTake the structure from the product's own things instead: for a couple's budget, Mia, Joint and Tom\nas three columns running through accounts, plan and bills; for a running club, the pace groups.\n\nThen list the screen's blocks as the answers to its next questions, one line each, the way the page\nrun lists claims. A block with no question is deleted. This is how you avoid the stock order of KPI\nrow, big chart, two small charts, table.\n\nThree more lines, each tested:\n\n- **Everything the brief names is on the first screen.** At 1440×900, every block the brief asks for\n  shows its header and its first rows or its figure. Size the headline block to the question (about\n  200-360px tall), cap long lists at 4-6 rows with \"View all\", and put time-sensitive blocks (bills\n  due, SLAs running out, a failed deploy) before long tables. A chart whose line is flat for most of\n  the window does not get the full width: give it two-thirds and put the next answer beside it.\n- **The most frequent job is one click away.** Name it (\"pack the orders due today\", \"reply to the\n  oldest breach\", \"redeploy the failed build\") and put its control where the answer shows: a primary\n  button in the title row, an action on the row that needs it, a \"View logs\" on the failed item. A\n  screen with no control for its main job reads as a report, not as a tool.\n- **Show the evidence beside the answer.** A judge trusts \"Error rate 0.28%\" more with its spike\n  annotated (\"peaked at 3.9% after the 23:28 deploy, reverted\") than with the number alone. One line\n  of explanation on the event that matters is worth more than a second chart.\n\n### 2.3 Choose a style\n\n```bash\nnode <skill>/scripts/draw.mjs --app --kind <kind> --brief \"<one line about the product>\" \\\n  --screens <screens> [--theme light|dark] [--keep palette,type] --options 3\n```\n\nThis deals up to three styles from `library/app.json` (fewer when only two suit the kind and the\ntheme). `draw.mjs --app --list kinds` (or `styles`, `screens` or `signatures`) prints the choices; the\nscreens are `overview`, `analytics`, `list`, `detail`, `settings`, `wallet`,\n`builder`, `inbox`, `home` and `report`. The library holds seven styles, each distilled from the\nstudied screens that share its move:\n\n| Style | Theme | For | The move |\n| --- | --- | --- | --- |\n| `achromatic-ledger` | light | money homes, reports, settings with usage | No colour in the chrome; charts in ink; one small signal where a figure changed |\n| `framed-sheet` | light | B2B analytics, developer platforms, builders | One tinted L-frame; the page on a white sheet inset 8px, no shadow |\n| `accent-ladder` | light | creator and small-business admin with plans | The full hue on small marks only; its pale tints on every area |\n| `editorial-greeting` | light | team and personal homes | The greeting as the h1 in a centred 12-column column; every figure at regular weight |\n| `pastel-consumer` | light | wallets, budgeting | Pale same-hue tiles under one large radius; quiet money polarity |\n| `true-black-flat` | dark | community, events, media | Elevation by lightness alone; colour only on data |\n| `data-terminal` | dark | markets, monitoring | Every selection is the same 1px accent line; signs, not colour, on numbers |\n\nChoose by how the product is used (long sessions or a quick look, money or media, a team or one\nperson, day or night), not by what is most familiar, and write one line on why. Then deal the sheet:\n\n```bash\nnode <skill>/scripts/draw.mjs --app <the same arguments, without --options> --style <id>\n```\n\nThe sheet gives the style's tokens and type, its shell and one pattern for each screen you named.\nKeep the style's one move intact and take every other value from the defaults in this file. Redraw\n(`--redraw style | shell | screen:<name>`) only for a reason you can state: it contradicts the brand,\nor the product is used in a way the style does not suit. With an existing brand, pass\n`--keep palette,type`, map its colours onto the roles in §9 and keep the style's colour budget.\n\n**Then choose its face, before any markup.** The sheet's \"Its face\" list gives two or three ways this\nstyle takes a face from the brief, and \"Signature elements\" lists the library's elements whose words\nappear in the brief (a power flow for an energy home, a sell-out strip for a bakery, a cover matrix\nand a kind-encoded timeline for a leave planner). Write in your notes, next to the screen's question:\nthe face you chose, the signature element (from the sheet, or your own built from the product's\nthings), and where each appears on the first screen. A style dealt to two products must not give them\nthe same face: in four rounds, the screens that skipped this step were scored as the same kit.\n\n### 2.4 Build the shell\n\nBuild the frame first, empty: the sidebar or rail, the top bar if the shell has one, the canvas with\nits gutters, the title row (§3 and §4). `<skill>/assets/app.css` is a neutral start for all of it:\ncopy it into the project and put the sheet's tokens in its `:root`. Look at it at 1440 and at 390 before any data goes in. Do the\ngrid arithmetic now and write it in a comment: the column count, the gutter, and the sum that proves\nthe cards land on the canvas edges.\n\n### 2.5 Put in the data\n\nRender every block from the dataset; draw the charts from it too, with `<skill>/assets/charts.js`\n(`Charts.line`, `Charts.bars`, `Charts.diverging`, `Charts.ring`, `Charts.barList`, `Charts.plan`,\n`Charts.bullet`, `Charts.timeline`, `Charts.matrix`, `Charts.timeStrip`; the file's header lists their\noptions) or your own SVG to the rules of §6, never a chart library's defaults and never a picture of a\nchart. The newer helpers return `{ svg, legend }`: put that legend in the card's header rather than\ndrawing your own, so each swatch is the mark it explains. Format every figure by §7.4: separators, fixed decimals per\nmetric, a sign on every change, units as smaller grey suffixes, tabular figures, right alignment in\ncolumns. Use the product's own words for labels. No placeholder data: the inspector fails lorem ipsum,\nAcme, John Doe and their kind. Proof is not invented here either: no vanity totals, no \"+12%\" on an\naccount that is a week old.\n\n### 2.6 Build the states\n\nFor every block, build its empty, zero, loading and error state (§11); for every row and control, its\nhover, selected, focus and disabled state. Look at each one in the browser. A screen that only works\nwith full data is half built.\n\n### 2.7 The check\n\n```bash\nnode <skill>/scripts/lint.mjs --app <source files or folder>\nnode <skill>/scripts/inspect.mjs --app <url or path/to/index.html>\n```\n\nA sheet dealt with `--app` switches both tools to the app rules by itself. The inspector opens the\nscreen at 1440, 768 and 390 and measures what this chapter asks for: an h1 (and reports it as the\nscreen's hero); a sidebar that folds on the phone; the canvas used to its right edge; panel shadows\nand borders; the number of corner radii; cards in one row that end apart, where a column of cards\nstacked with the gutter counts as one block (`ragged-row`); a blank band inside a card of over 40px,\nor over 64px before a new section's heading (`panel-void`); icons in tinted squares; numeric alignment and tabular figures; chart hues; colour\nshare, and a screen with charts but no hue on its data (`no-data-hue`); placeholder data; text under\n11px; and the page rules that still hold (contrast, gradients, the banned palettes, emoji). Fix every\n`FAIL`. Treat each `WARN` as wrong unless you can defend it to a designer in one sentence.\n\nThen look at the screenshots, every width, and answer these in writing. This is the critique for an\napp screen: the caps in `critique.md` for pictures, motion and the page's live element are page rules\nand do not apply here.\n\n1. Is the screen's question answered by the biggest thing on it, and is that read first? Is the\n   largest figure the one that answers the title row's sentence?\n2. Does every block share the screen's edges? Is there a dead strip on one side, a card stopping\n   short, an orphan cell, a stretched card with a blank band (a legend pinned to its foot, four rows\n   in a card kept at its neighbour's height)?\n3. Is colour only on data, on status and on the one primary action, and does the main data element\n   carry the one hue? Does the face you chose show on the first screen?\n4. Do the numbers add up, and do they line up digit for digit? List every fact that appears twice\n   and check that the copies agree; recompute each total and change from the values as displayed;\n   check that every relative figure names what it is against.\n5. Does every zero look like a zero and every missing value like a dash? Does every count badge sit\n   on a queue that needs action, with its noun clear from the label?\n6. Does every legend swatch match the mark it explains, and does any caption have to say which bars\n   are which (then encode it in the chart)? Does any label collide with a line or another label?\n7. On the phone, is the navigation folded away, and does each block still answer its question?\n\nFix the worst three, inspect again, look again. Three rounds at most. Judge the pictures: if a problem\nshows in a screenshot, it is real, whatever the code says.\n\n### 2.8 Report\n\nTell the user, briefly: the style dealt (name and seed) and any redraws with their reasons; the face\nyou chose and the signature element; each screen's one question; any check you allowed and why (for example `--allow icon-chips` for node-type\ntiles in a builder); and the sample data that must be replaced with real data, listed so it can be\nfound.\n\nApp screens have no motion floor. Motion is feedback: press, hover, focus, a menu or a sheet opening,\na row arriving. Nothing on the screen performs an entrance (house rule).\n\n## 3. The shell\n\n### 3.1 Five archetypes\n\n| Shell | In the study | What it is |\n| --- | --- | --- |\n| **Open plane** | 5 screens | A labelled sidebar on the page ground (or within 1-2% of it), separated by nothing or by one 1px hairline. No top bar: the header and the cards sit on the ground. The canvas is fluid with a 24-64px gutter, or a centred column. |\n| **Tinted frame, white sheet** | 8 screens | Sidebar and top bar share one tinted ground (#f6f6f6-#f9fbfc) with no rule between them; the page sits on a white sheet inset 8px from the window's right and bottom edges, radius 10-16 (median 16), a 1px #eaeaea-#ededed edge and no shadow. Variants: a flush L-frame, the inset sheet, and floating panels inset 8-12px with a 12px gap. |\n| **Ruled T-frame** | 4 screens | A 210-240px sidebar and a 64px top bar on one ground, divided only by 1px rules. The workspace switcher sits at the top bar's right end behind a full-height divider. Three of the four are dark. |\n| **Icon rail** | 3 screens | An unlabelled rail 50-60px wide (median 55); 15-18px icons on a 34-49px pitch; the active item marked by colour or by a 2% tint band; groups split by 20px hairlines. It saves about 180px of width. |\n| **No sidebar** | 3 screens | A 46-48px top bar over a centred 1088-1208px column with 152-212px gutters; the logo sits on the column's left edge. For reports, viewers and products with few destinations. |\n\nAll six dark screens use one ground everywhere, divided by 1px rules of #161616-#232323 or by nothing.\nNo screen in the study puts a dark or saturated sidebar against a light canvas (0 of 17).\n\n### 3.2 Sidebar\n\n- **Width.** Labelled sidebars run 210-292px; the median is 230 and most sit at 224-240. One floating\n  sidebar card appears (280px wide, 40px in from the window edge).\n- **Rows.** A 32px hit area on a 34px pitch is the mode (7 screens); the roomy versions run 40-52px on\n  a 42-60px pitch. Icons are 14-20px, median 16, outline at about 1.5px stroke on 14 of 16 screens.\n  Labels are 14px at 400 on 12 of 16, in ink or in a grey of #4b4d4f-#63666e, about 8-10px after the\n  icon, with the label column at x 36-48.\n- **Active item.** A neutral grey pill with the label unchanged, on 8 screens: radius 4-16 (median 8),\n  inset 8-14px from the sidebar's edges, a fill of about #e9e9e9-#ededed. On dark, brightness alone:\n  the label goes from #bbb to #fff (3 screens). Colour alone on the icon or label (3, all of them\n  rails or a floating card). A tinted accent fill (3). A left accent bar once in 23. The weight\n  changes on 2. Default: the grey pill on light, brightness on dark.\n- **Groups.** Sentence-case grey labels at 12-13px, never uppercase (9 screens), with 22-56px of air\n  above and 13-33px to the first item; or hairlines instead (4). Utilities such as settings and help\n  pushed to the bottom (5).\n- **Top and bottom.** The workspace or account switcher at the top of the sidebar (7 screens), at its\n  bottom (2), or in the top bar. The bottom holds a user row (8) or one upsell (8); one of those\n  upsells is a filled accent button.\n- **The product is named** (house rule, from testing). The product's mark and name sit at the top of\n  the sidebar or rail, and the scope (workspace, team, project, account) is shown as a switcher or a\n  breadcrumb. A screen whose product cannot be named from the screenshot reads as a template.\n- **Counts on nav items** (house rule, from testing). A count appears only on a queue that needs\n  action, and its noun is clear from the label: \"Requests 5\", \"Price changes 3\". A bare \"Range and\n  prices 9\" left the judge asking nine of what.\n- **Labels by default.** A labelled sidebar unless the product has five destinations or fewer and the\n  screen needs the width (a research or monitoring view); an icon rail always carries the product's\n  mark at the top, a tooltip and an accessible name on every icon. Nav items are other screens, never\n  anchors into the current page (a sidebar that scroll-spies one long page was marked down twice).\n\n### 3.3 Top bar\n\n14 of 23 screens have one; the default is none. Heights fall into two groups: 44-51px (median about\n48) on light chrome, and 64px, usually with a 1px rule. A top bar must hold something real: search,\nthe workspace switcher, or the page or object name. Search sits centred on the window at 548x32 with\na shortcut hint (2 screens), or at 457-537x36 in a no-sidebar bar. The right cluster is inset 24-46px\nfrom the edge. Two screens leave about 1070px of their top bar blank; both are flagged for it.\n\n### 3.4 Right rail and pinned columns\n\nOne screen has a right rail: a fixed 384px column in a `1fr 384px` grid with a 24px gap, starting\nlevel with the first card rather than with the title, its section headings outside the cards and 8px\nabove each. Use one only for a stable secondary stream: recent items, the details of the selected\nobject, share links. A pinned left column appears once: a 306px accounts card at the viewport height\nminus 72px, so net worth stays in view while the rest of the screen scrolls.\n\nFive screens float a button (24-56px), and one of those buttons covers the content it sits on and is\nflagged. House rule: no floating button unless it is the screen's one primary action and covers\nnothing at any width.\n\n## 4. The canvas and the page title\n\n### 4.1 Width and gutters\n\n- **Fluid** (14 screens): side padding 17-64px, median 29, with 24 and 36-40 the common values;\n  content 1120-1312px wide, median about 1204.\n- **Centred** (8 screens): 624, 864, 1088, 1100, 1152, about 1190 and 1208px; median about 1126.\n  Data pages land at 1100-1250 either way. Only two personal homes go narrow (624 and 864), and both\n  are flagged for wasting the width.\n- **Top offset**, from the canvas top to the title: 20-88px, median about 36. Tools sit at 20-36;\n  greeting homes at 50-88.\n- **One gutter.** Use one gap value horizontally and vertically. Mixed gutters (12 against 16, 20\n  against 24, 16 against 12) are flagged on 8 screens.\n\n### 4.2 One left edge, one right edge\n\nThe strongest screens run a single left edge from the header to the last row. One indents its page\nheader by the cards' 24px padding, so the title, the card titles, the numbers and the chart all start\non one line. Row rules may bleed 7-8px past the text column while the text stays on it.\n\nThe grid's arithmetic closes: 3 x 372 + 2 x 17 = 2 x 568 + 16 = 1152; 12 x 77 + 11 x 16 = 1100;\n4 x 144 + 3 x 16 = 624; a second-row card exactly as wide as the two cards above it\n(251 + 24 + 515). Write your sum down.\n\nFailures to avoid, all from the study: cards stopping 120px short of the sheet's right edge; a 0px\nright gutter against a 40px left one; a column centred on the window instead of on the area beside\nthe sidebar (204px on its left, 444px on its right); a medallion 108px off the column's axis. The\ninspector warns when the content stops well short of the right edge.\n\n**Dead space from a grid that does not fit the data** is the commonest failure in the study (10\nscreens): four KPI tiles in a three-column grid, orphaning the fourth; one card alone in a\nthree-column row beside 810px of nothing; a card stretched to its neighbour's height with 250px of\nblank under its legend. Choose the column count from the number of items, let a lone card span, and\ndo not stretch a card's frame over empty space.\n\n**Cards that share a row share a bottom edge.** In testing, rows whose cards stopped 26-190px apart\nwere marked down every time, by judges and by the inspector (`ragged-row`). Balance the row by its\ncontent first: move a list's rows so the two columns hold the same number, cap both lists at the same\ncount, or pair blocks of similar height. Two cards stacked in one column beside a tall card count as\none block: they balance when the column ends level. Only when the contents cannot balance, stack the\ntwo blocks, or let the shorter card fill the row height with its content top-aligned and the footer\naction (a \"View all\", a total) pinned to its bottom so the extra height is not a hole.\n\n**A stretched card stretches only when it has content to fill.** Only an action or a total may be\npinned to a stretched card's foot; a legend or a note stays directly under its chart. In testing, a\ncover card stretched to its neighbour with its legend pinned to the bottom left 60px of blank under\nthe last row, and a sell-out card left 45px above its links. When the content is short, let the card\nkeep its own height (`align-items: start` on the row), move its footer link into its header, or give\nthe row a block of similar height. A filtered block shrinks to its rows, or keeps a fixed number of\nrows with one sentence in the empty ones; four rows over 270px of empty card is a hole. The inspector\nwarns on a blank band of over 40px inside a card (`panel-void`).\n\n**Narrow blocks do not span the canvas.** A table of five columns or fewer, or a list of six rows or\nfewer, runs to about 760px at 1440 and pairs with the next block; stretched to 1300px it leaves\n400-600px voids between a name and its first figure.\n\n### 4.3 The title\n\n- **Every screen has one h1**; the inspector fails a screen without one. 14 screens set it in the\n  canvas at 18-48px, median and mode 24, at 600-700 (700 on 8). The rest have nothing over 16px: a\n  breadcrumb or the top bar names the page. Then the breadcrumb's last item is the h1, at 16px, and\n  the screen's name is still the first thing read.\n- **A noun, not a greeting**: \"Analytics\", \"Overview\", the project's or the object's name. 3 of 23\n  greet, and one adds an emoji, which goes. A greeting suits a personal or team home only.\n- **An optional second line**: one 14-16px grey sentence about the data or the object (the finding,\n  the period, the scope), never about the interface (\"the filters narrow every block…\", \"this page\n  shows…\" read as instructions, not a product), or a 12px line\n  naming the data's source.\n- **Right of the title**: actions only when they are real (10 screens); otherwise nothing. A freshness\n  stamp (\"Updated Jul 27, 4:09 PM\", with a refresh button) on 6.\n- **The primary action.** 12 of 23 have no filled primary button; 5 make it near-black (#1d1f20,\n  #1f2937) or inverted white on dark; 4 fill it with the brand hue. One primary per screen.\n\n### 4.4 Tabs, filters and the date range\n\n- **The date range** at page level (7 screens) or on each card (7), never both. A card that states its\n  own period puts it in its header, right-aligned, in grey.\n- **Underline tabs** (8 screens) always sit on a full-width 1px rule; the indicator is 1-4px (median\n  2), as wide as the label or running 8-11px past it.\n- **A segmented track** once: 48px, #f3f4f6, a white 36px active pill, and the date select inside its\n  right end, so tabs and range read as one row. A segmented control is as wide as its options, and full\n  width only below about 480px: three options spread across a 680px tablet card read as a progress bar.\n- **Control height** in title and filter rows: 28-40px, median 34, clustering at 32 and 36.\n- **Order**: scope on the left (the date first, then the filters), utility and refresh on the right.\n- **Compound filters** that read as a sentence (\"Date | Jun 14 - Jul 13 | Daily\"), 28px tall and 8px\n  apart, once.\n- **To the first card**: 13-64px, median 24.\n\n## 5. KPIs\n\n- **No tile of its own.** 11 of the 20 screens with headline numbers give a KPI no tile: bare text on\n  the page or on a card (5), or one container split by 1px hairlines (6). 9 use one card per KPI,\n  61-147px tall (median about 108). The default is one container split by 1px dividers into equal\n  columns. 7 screens have no KPI row at all and put each headline number in the card that explains\n  it, which is often better.\n- **Count.** 1-6 per row, median 3-4. The count matches the grid: four KPIs get four columns.\n- **Size.** Values 16-40px, median 26, mode 24. Values in their own tile run larger (median 30) than\n  in a shared strip (median 24). Nothing at 48px or over. Labels 12-16px, median 14; the value is\n  about 1.7 times the label.\n- **Weight.** An even split: 400 on 8 screens, 600 on 6, 700-800 on 6. A large number at regular\n  weight under a semibold label is the common pattern. Bold for money only.\n- **Order.** Label above the value on 14 screens; labels grey (#6b6b6b-#aaa) on 13; sentence case.\n- **Nothing else.** No icon in a coloured circle (0 of 23), no sparkline (0 of 23), no tinted tile.\n  An info icon beside the label is fine (5 screens). Units are a smaller grey suffix: \"5 mins\" at 24\n  over 14, \"2 m 24 s\", \"5 /10\".\n- **The answer figure leads.** When one figure is the screen's answer (a balance, net worth, the\n  portfolio's value), it is 30-36px and at least 1.3 times its sibling figures (those at 18-24px). In\n  testing, a 24px portfolio value beside two 24px figures left the screen without a lead. No other\n  figure on the screen is larger: the biggest number answers the title row's sentence, so a\n  secondary ratio in another card stays at the siblings' size.\n- **One figure, one place.** A figure shown in the strip is not repeated in a legend beside it, and a\n  KPI strip whose every cell names a panel below (RSVPs, then an RSVPs panel) is dropped: lead each\n  panel with its own number instead.\n- **A second job.** KPIs may be the chart's series tabs or the list's type filter (the selected card\n  takes a 1.5px border). As tabs, the selected one carries a 2px rule or the active fill and an ink\n  label; the others keep a grey label and their value in ink, at 400 against the selected one's 500.\n  A grey value reads as disabled: in testing, three shops' takings set in grey because they were tabs\n  read as secondary, though they were the brief's first ask. When the tabs are the per-entity\n  breakdown the brief asks for, grey nothing and let the rule alone mark the selection. On a phone the\n  tabs become a 2-up grid with the selected cell filled, or a row that scrolls sideways; never an\n  underline floating inside the grid (`app.css` does both).\n\n### Deltas\n\n- Optional: 9 of the 20 KPI screens show one; 11 do not.\n- 10-15px (median 14), never larger than the label. Text or a small glyph on 6 screens; a pale pill\n  on 3.\n- **The window in words**: \"vs prior 30 days\", \"in the last 90 days\", \"from 0 (last 4 weeks)\" (7 of\n  the 9).\n- **Colour only the number**, or set the whole delta in grey.\n- **Colour says good or bad, not up or down** (house rule, from testing). Every metric has a good\n  direction: latency, error rate, cost, churn and time-to-reply are better when they fall. A change\n  in the bad direction puts `--negative` on the number (or a small down-pointing glyph in that\n  colour); a change in the good direction is `--positive` or grey. A judge read a 2.5× rise in errors\n  set in the same grey as a rise in visits as hiding the screen's only bad news.\n- **Zero or undefined change is grey.** The study's commonest KPI failure is a zero or undefined change\n  shown as a signal: three identical green \"up 100%\" pills grown from zero, a \">999%\", a bold red\n  \"0.00%\", a green \"+0\". When the prior period was zero, write \"+4 (new)\"; when there is nothing to\n  compare, a short grey dash where the delta would be.\n\n## 6. Charts\n\n### 6.1 Which chart for which question\n\n| Question | Form | In the study |\n| --- | --- | --- |\n| Is it moving over time? | One line; an area only with a fill of 15% or less | 9 screens |\n| How much per period? | Columns with square corners | 3 |\n| How is it distributed? | A histogram with equal bins | 1 (its unequal bins are flagged) |\n| Who ranks? | A sorted horizontal bar list, or the row's fill as the bar in a one-figure list | 3 |\n| What share? | A thin ring, or a 100% stacked bar with 2px seams; five parts at most | 5 |\n| How far to the target? | A progress bar, both ends labelled, the fill the true ratio | 4 |\n| How much of the plan is used? | A track as long as the plan, the spent part filled, what is already committed as a lighter segment, an overrun past the track's end in the negative colour (`Charts.plan`) | house rule |\n| Has it drifted from its target? | One row per part: the current share as a bar with a 1px tick at the target (`Charts.bullet`); never two stacked bars to compare | house rule |\n| Where? | A map with a list beside it; the list carries the magnitudes | 1 |\n| Per period, and the running total? | The two side by side at equal width, with the same dates | 1 |\n| Which way did it flow, and how much? | Columns above and below one zero line on one scale, the axis signed and captioned on each side (\"Sold\" above, \"Bought\" below), a marked period in a second tone with its own legend entry (`Charts.diverging`) | house rule |\n| Who is away when? | A timeline of people by day, each kind of booking its own mark (`Charts.timeline`) | house rule |\n| Is there enough cover? | A team-by-day matrix of slack against the minimum (+2, +1, 0, −1), one hue ramping toward the negative colour, the headcount on hover (`Charts.matrix`) | house rule |\n| When in the day, against last time? | One row per item on a shared opening-to-closing axis: a 2px grey track, an ink dot for today, a hollow tick for the comparison day (`Charts.timeStrip`) | house rule |\n\nThree more, from testing:\n\n- **The pair of per-period bars and the running total is used once per screen**, and only when the\n  total crosses a line that matters (capacity, a target). Three such pairs in six charts read as one\n  pattern stamped out.\n- **A series that is flat except for one event** gets at most two-thirds of the width and about 140px of\n  height, or a range capped at about twice its reference line with the off-scale peak labelled\n  (`Charts.line({ max })`). A full-width plot that is 85% empty was the biggest block on a first\n  screen and was marked down.\n- **A forecast is not a fact**: after today the line is dashed and the end value is labelled\n  (`Charts.line({ today, endLabel })`), with the gap to the target bracketed when there is one.\n- **What the brief asks to see over time is drawn on the first screen.** KPI cells may switch the chart\n  only between metrics the brief did not name.\n\nWhen there are only a few numbers, draw no chart: four screens skip it, and the settings page links\nto the analytics screen with \"View more\".\n\n### 6.2 One question, one series\n\nOne series per chart is the norm; three is the most any screen draws. To show another metric, switch\nit with a control (a segmented control, a dropdown, the KPIs as tabs) instead of overlaying lines.\nPlots run 112-264px tall (median about 195) and 316-1136px wide (median about 570), an aspect of 1.8\nto 5.2.\n\n### 6.3 Axes and gridlines\n\n- **Gridlines** run horizontally only on 7 of the 12 cartesian charts, both ways on 3, and not at all\n  on 2. Use 3-5 (the study runs 3-7, median 4-5): 1px, solid, about #e5e5e5 on light (range\n  #cfcfd2-#f2f2f2), #2b2b2b on #111. Dashed lines are allowed in chart grids (4 screens: 3/3, 4/4,\n  3/2.5) and nowhere else on the screen.\n- **No y-axis line.** The baseline is the one heavier line (2px on two screens, 1px on one); full axes\n  on one.\n- **Y ticks**: 4-7, median 5, at 11-16px (median 12) in grey (#5f5f5f-#6c6c6c), on the left (8\n  screens) or the right (2). Round, even steps (0/5/10/15%; 0-600 by 150), the top tick above the\n  maximum, integers for counts, and zero as the baseline for bars and counts.\n- **Never without a scale.** Two screens draw no y-scale and show magnitude only on hover; both are\n  flagged. So are uneven ticks (0/3/6/10), a 0.8 tick on a count, a top tick equal to the maximum so\n  the line hits the plot's edge, and a cumulative axis that starts at 1.\n- **Axis text no larger than the data.** 15-16px ticks beside 14px values are flagged as louder than\n  the numbers.\n- **X labels**: 4-8 per chart, flat, never rotated (40 degrees is flagged), the first and last pulled\n  inside the plot, on one step all the way: a forced closing label after 14:00 on a 90-minute step\n  left a short last gap that a judge measured. Choose a step that lands on the end (hourly from 08:00\n  to 15:00) or leave the end unlabelled. Labelling only the two ends hides when things happened. Irregular dates on a\n  categorical axis are flagged: time goes on a time scale.\n\n### 6.4 Marks\n\n- **Lines** 1-3px, median 2, in straight segments. Four screens smooth their lines, and one smoothed\n  curve invents values between daily totals (flagged), so draw straight segments. No point markers,\n  except a hover dot (8px on one screen).\n- **Fill**: none on 7 of 10 time charts. At most a flat tint of about 14%, or a fade from the line to\n  transparent over 150-200px.\n- **Bars** have square corners (4 screens), or at most a 4px top radius with a square bottom on the\n  baseline. Stacked segments are split by a 1-2px seam.\n- **Colour.** One hue per chart. The accent touches only data on 8 screens, and data ink is under 3%\n  of the pixels on most. Neutral series are fine and often better: a near-black line that turns pale\n  grey after the cursor; a white line against a red one; signs instead of colour (\"+$24,000,000\").\n  But the one hue, when the style has one, goes on the screen's main data element (today's series,\n  the booked bars, the current period, the margin that breaks), not on a secondary chart or a delta:\n  in testing, an all-ink screen with no hue on any of its data read as a kit.\n  One subject keeps one hue across the screen: the same subscribers drawn pink in one chart and indigo\n  in the next is flagged. Unrelated hues on one screen (three, five) are flagged every time. Status\n  colours are for status. The inspector warns over four hues and fails over six.\n- **Legends.** None for a single series (9 charts): the title or the dropdown names it. Otherwise five\n  items at most, as a 5-8px dot with a 12-14px grey label in the card's header, or as a small table\n  (dot, name, value, change) that makes the legend carry data. Never list a series that has no data\n  (flagged). Every swatch is the mark it explains, scaled down: the legend dot is the line's colour,\n  a hatched bar's swatch is hatched. A swatch drawn separately from the mark drifted from it in testing\n  (a black outline with a red edge explaining a red outline); the helpers return the legend built from\n  the same style object as the marks.\n- **Rings** only for three to five parts of a whole that are not already listed beside them (a ring\n  redrawing the spent, due and left figures of the tile next to it was marked redundant). Never\n  labelled on the slices; the total sits in the centre or beside the ring. The\n  screens noted for their rings use thin strokes: 3-5px on a 90-154px ring, 8px on 182px. Two others\n  use 28 and 37px.\n- **Progress bars** are 4-24px tall (median 8), fully rounded, with both ends labelled (\"Skilled 200\"\n  and \"Expert 2,000\"); the fill is the true ratio, so 303 on that scale fills 22px of 392. A zero has\n  no stub (a 6px stub at zero is flagged).\n- **Tooltips** are bare text or a plain box without an arrow: label and value on one line.\n- **Annotate the event that matters.** A step or a spike more than about three times the usual change\n  gets a 1px marker and a 12px label naming its cause (\"Deploy a3f09c1\", \"Newsletter featured\");\n  reference lines (a budget, an SLO, a start time) are 1px dashed with their label at the end. In\n  testing, an unexplained jump was the first thing a judge asked about. `Charts.line`,\n  `Charts.bars` and `Charts.diverging` take `annotations` and `reference`.\n- **Labels never collide.** Annotation labels sit in rows above the plot, each beside the top of its\n  own leader line, and no leader line runs through another label; the rows are reserved only when a\n  label exists, so a chart without one has no dead band above it. The \"Now\" label of a forecast goes\n  on whichever side of its line the series does not cross. Lay labels out after the fonts load, or\n  the label set changes between loads (it did in testing). The helpers do all of this; give a label\n  that may not fit a `short` form.\n- **Use the helper, then extend it.** Draw charts with `assets/charts.js` and add what a chart needs to\n  it, rather than writing new axis code: in testing, every chart written from scratch on a phone put\n  its y labels on top of its line.\n- **Short and empty histories are drawn honestly**: a flat zero line with one spike, missing bars for\n  empty periods, no padded y-range, no \"No data\" picture. Do not give one point the screen's largest\n  plot, though: a lone dot in a full-size grid reads as barren (flagged once).\n\n## 7. Tables and lists\n\n### 7.1 Rows\n\n- Single-line data rows: 36-53px, median 45.\n- Two-line rows with media: 56-92px, median 72. The pitch is the media's height plus 24-32px\n  (48 + 24, 48 + 32, 50 + 30).\n- Key-value and legend rows inside cards: 21-32px.\n- In a two-line cell, line 2 sits about 21px below line 1 (19-23), one size smaller (12-14px) and\n  grey. Two-line labels need a 40-44px pitch at least: on a 32px pitch a subline nearly touched the\n  next row's name and the list ran together (house rule, from testing).\n- Overview lists show 2-5 rows.\n\n### 7.2 Header\n\n- 11-14px, median 12, mostly regular weight, grey, sentence case (9 of the 11 headed tables). The one\n  uppercase header in the study is flagged as louder than the data.\n- **No fill band** (0 of 11) and **no rule under it** on 8 of 11. Where there is a rule, it is the\n  strongest line in the table (#e5e7eb over #f3f4f6 row rules).\n- Header row 36-40px.\n- Numeric headers are right-aligned and flush with their values; a header that stops 15px short of\n  its column is flagged. A header over a control aligns with the control it labels (centred over a\n  column of steppers), and a delta beside a stepper gets its own narrow unlabelled column; three\n  alignments in one header row were flagged.\n- A sort glyph on the active column only.\n\n### 7.3 Dividers\n\n- **No zebra striping** (0 of 23).\n- No row dividers on about half the lists; they rely on a 61-92px pitch or on 2-8px gaps between\n  filled rows.\n- When present: 1px, 3-7% darker than the surface (#ededed-#f4f4f4 on white; #161616 on #000,\n  #1b1a1f on #131217).\n- Extent: bleeding 8-9px past the text edge; starting at the text column and skipping the media; or\n  the full inner width. Pick one per screen.\n\n### 7.4 Figures and alignment\n\n- **Numbers right-aligned**, in tabular figures or a monospace. Every left-aligned numeric column and\n  every column of proportional digits in the study is flagged (durations \"00:00:12\" and \"00:00:04\"\n  that jitter, cents that drift).\n- **Fixed decimals per metric**: money 2, percentages 1 or 2, counts none. Thousands separators\n  everywhere (\"$16,531.54\"); abbreviate only in a capacity line (\"12.7k of 20.0k\"). A sign on ever\n\n<!-- [TRUNCATED AT 50KB] -->","skills/taste-skill/references/colour.md":"# Colour\n\nThe direction sheet deals a palette with named roles. This file is how to apply it so the page looks\ndecided rather than tinted.\n\n## Contents\n\n1. What the study measured\n2. The roles\n3. Proportion\n4. Surfaces without lines or shadows\n5. Colour fields\n6. Dark pages\n7. Colour and photographs\n8. Contrast\n9. Banned families, and what \"warm\" means here\n\n## 1. What the study measured\n\n- 41% of the studied pages are dark, 59% light. A quarter sit on pure white; 12% on pure black.\n- Schemes, as the panel classed them: monochrome plus one accent 23%, light neutral 22%, dark neutral\n  14%, several flat colours 13%, strictly two-tone 12%, colour carried by photographs 9%, one saturated\n  field 6%.\n- Buttons are neutral (black, white, grey) on 52% of sites. A coloured button is a choice, not a\n  requirement.\n- Gradient fills appear on 22% of the top-scored sites and 52% of the weak ones; gradient text on 2%\n  against 13%.\n- One site in 246 has a terracotta primary button and none has a violet one. Those are colours of\n  generated pages, not of the gallery. Warm off-white grounds do occur (32 sites), nearly always with\n  a dark or green ink rather than an orange accent.\n- Top-scored sites change the page's field colour between sections more often (a median of two section\n  grounds against one).\n\n## 2. The roles\n\n```css\n:root {\n  --bg: …;          /* the ground: most of the surface */\n  --surface: …;     /* one tone step from the ground: filled panels, form fields, tiles */\n  --ink: …;         /* main text and the strongest marks */\n  --muted: …;       /* secondary text; still passes contrast on --bg */\n  --accent: …;      /* the one accent */\n  --accent-ink: …;  /* text on the accent */\n  /* --field-1 … --field-n and their inks, when the palette has section fields */\n}\n```\n\nUse the tokens for every colour in the build. A raw hex in a component is a second palette starting.\nDo not add greys between the roles: if you need a quieter text, it is `--muted`; if you need a quieter\nsurface, it is `--surface`.\n\n## 3. Proportion\n\nDecide the shares before colouring anything and check them in the screenshot:\n\n- **Ground:** 70–90% of the page.\n- **Ink:** text and perhaps one inverted section (ink as ground, ground as ink).\n- **Accent:** under 5% of any screen. It marks the action and at most one other recurring thing. The\n  moment it appears in five places it stops meaning \"here\".\n\nPalettes with fields (flat-loud, pastel) work differently: each section is one field at full strength\nand the proportion rule applies inside each section (field, its ink, nothing else).\n\nThe accent is not for headings, icons, bullets, borders or underlines unless the direction sheet says\nso. A headline is ink.\n\n## 4. Surfaces without lines or shadows\n\nWith rules and shadows banned, a surface is told apart from the ground by tone alone:\n\n```css\n.panel { background: var(--surface); }          /* 2–6 lightness points from --bg */\n.field { background: var(--surface); border: 0; } /* inputs: filled, with a clear focus state */\n.field:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }\n```\n\n- One step is enough. If a panel does not read, increase padding or separate with space before\n  reaching for a second tone.\n- Do not nest a panel inside a panel.\n- Images do not need a frame. If a light photograph melts into a light ground, change the crop or set\n  it on `--surface`, do not outline it.\n- A thick bar (4px or more) in ink or accent is a graphic element, allowed where the direction uses\n  it. A 1px line is not.\n\n## 5. Colour fields\n\nA section that changes the whole ground colour is the strongest colour move available, and it replaces\ndividers, cards and background decoration at once.\n\n- Fields meet edge to edge with a hard line. Nothing fades.\n- Every field has its own assigned ink from the palette. Never put `--muted` on a coloured field; use\n  the field's ink at full strength, or at 70% opacity for secondary text if it still passes contrast.\n- Neighbouring fields should differ in lightness, not only in hue, or the page vibrates.\n- Order them like chapters: open strong, rest, surprise, close dark or very light.\n- The page's meta theme colour and the navigation follow the first field.\n\n## 6. Dark pages\n\n- Put `color-scheme: dark` on the root so form controls and scrollbars follow.\n- The ground is a deep tone with a slight tint from the palette, and the ink is a soft light, not\n  `#fff` on `#000`, unless the palette deals exactly that for a stark two-tone direction.\n- Secondary text is where dark pages fail: check `--muted` against the ground (4.5:1).\n- Depth on dark comes from a lighter surface step, never from glows or coloured light.\n- Use lighter font weights than you would on a light page.\n\n## 7. Colour and photographs\n\n- When photographs carry the colour, the interface stays neutral and takes its ink from the darkest\n  tone in the imagery.\n- Do not wash a photograph with the brand colour. Either leave it alone, or commit to a real treatment\n  for every image on the page (all greyscale, or all untouched).\n- Text over a photograph needs a calm region. If there is none, move the text off the image. A neutral\n  scrim (black or the ink colour, 30–55% opacity, flat or fading over the text area only) is the one\n  gradient the inspector allows.\n- A flat field sampled from a photograph (its sky, its shadow) makes a section sit with that image.\n\n## 8. Contrast\n\n- Body text 4.5:1 or better; display type and large numerals 3:1 or better; the dealt palettes meet\n  7:1 for ink on ground.\n- `inspect.mjs` computes contrast for text on flat grounds and fails anything under 2.6:1. It cannot\n  see text over photographs: check those in the screenshots yourself.\n- Do not lower opacity on text to make it \"soft\" unless you have checked the resulting ratio.\n- Focus states and hover states increase contrast, never reduce it.\n\n## 9. Banned families, and what \"warm\" means here\n\nThe inspector fails these:\n\n- **Cream with terracotta.** A yellow-cream ground (roughly hue 22–62, light and noticeably\n  saturated) with a rust, clay or burnt-orange accent is the house look of AI assistants and of the\n  pages they generate. Either half alone is suspect; together they are unmistakable.\n- **Violet and indigo.** The first wave of generated pages was purple; it still reads that way.\n\nIf the brief wants warmth, get it from a low-chroma stone, bone or putty ground (saturation under\nabout 15%), from a deep green, brown or oxblood ink, from photographs, or from a full warm field\n(mustard, tomato red, pink) used flat and with conviction. Warmth is not beige.\n\nIf the brand itself owns one of the banned colours, it is the brand's and you keep it: use\n`--keep palette`, pass `--allow palette-purple` (or the relevant rule) to the inspector, and note it in\nthe report.\n","skills/taste-skill/references/copy.md":"# Words\n\nCopy is the first design decision. A headline that needs four lines cannot be rescued by typography,\nand a page of slogans cannot be rescued by layout. Write the page as plain text before any markup.\n\n## Contents\n\n1. Write the argument first\n2. The two-line headline (with the character budget)\n3. Headline shapes that work\n4. Supporting line, body, buttons\n5. Proof without inventing it\n6. Things that read as generated\n7. Micro-typography\n\n## 1. Write the argument first\n\nAnswer in one line each, in a scratch note:\n\n- Who is reading, and what do they already know?\n- What is this, said the way its maker would say it to a friend?\n- What single thing should the reader believe after one screen?\n- What would make them believe it (a picture of the thing, a number, a name, a demonstration)?\n- What do they do next?\n\nThen list the page as claims, one per section, each with its proof:\n\n```\n1. It is a three-legged oak stool, made to order.             → the stool, large\n2. Each seat is cut from one board, so the grain is yours.    → three close-ups\n3. It takes six weeks, and you can follow it.                 → the stages, photographed\n4. It costs 240 and is delivered by the maker.                → price, button\n```\n\nA section with no claim is filler; delete it. This is also how you escape the stock order of\nhero, logos, features, testimonial, pricing, call to action: the order of the argument is the order of\nthe page.\n\n## 2. The two-line headline\n\nA headline is a title. It is held in one glance. On the studied gallery sites the hero headline has a\nmedian of 5 words and 70% sit on one or two lines at desktop width. Every headline on your page, at\nevery viewport, fits in **two lines or fewer**. `inspect.mjs` measures this at 1440, 768 and 390 pixels\nand fails the page otherwise.\n\nThe constraint is arithmetic, so do it before you fall in love with a sentence:\n\n```\ncharacters per line ≈ line width in px ÷ (font size in px × k)\n\nk ≈ 0.40  condensed faces\nk ≈ 0.50  most grotesks and serifs at display size, tight tracking\nk ≈ 0.58  wide / extended faces, all-caps settings\n```\n\n| Where | Line width | Size | Per line | Two-line budget |\n| --- | --- | --- | --- | --- |\n| Phone 390, 20px gutters | 350px | 44px | ~16 | **~32 characters** |\n| Phone 390, 20px gutters | 350px | 34px | ~21 | ~42 characters |\n| Tablet 768 | 690px | 64px | ~22 | ~44 characters |\n| Desktop, 12-col measure | 1100px | 104px | ~21 | ~42 characters |\n| Desktop, half width | 620px | 72px | ~17 | ~34 characters |\n\nSo a hero headline of **about 32 characters or fewer** (four to six words) survives everywhere at a\nconfident size. Up to about 42 works if the phone size comes down to the mid-30s. Past that you are\nwriting a sentence; move the rest into the supporting line.\n\nControlling the break:\n\n- Give the headline a `max-width` in `ch` so it breaks where you intend, and add\n  `text-wrap: balance` so two lines come out even.\n- Where the break matters (it usually does), author it: `Stools for<br> small kitchens`. Check the\n  phone screenshot; if an authored line wraps there, hide the `<br>` under a breakpoint or shorten.\n- Never fix a long headline only by shrinking it. A timid 28px headline of nine words is worse than\n  five words at 64px.\n- Avoid a single orphan word on line two. Rebalance by cutting a word, not by nudging the width.\n\nSection headings follow the same rule and are shorter: two to five words.\n\n**A statement is not a headline.** An intro sentence or a quotation set large (the manifesto line\nafter the hero, a testimonial) is a paragraph: mark it up as `<p>` or `<blockquote>`, keep it to about\n25 words, and set it at statement size, which the inspector takes as 36px or less on desktop, 32px on\na tablet and 24px on a phone. It may then run to about three lines (four on a phone). Set larger than\nthat, or marked up as a heading, or placed as the main line of the first screen, it is a headline and\ngets two lines. In blind judging, a sentence set big over three or more lines was read as a long\nheadline every time, whatever its markup; if the words matter that much, cut them to a two-line\nheadline instead.\n\n## 3. Headline shapes that work\n\nAll seen repeatedly on the gallery sites. Pick the plainest one that is true.\n\n- **The name.** The brand or the person, set very large, with a one-line description elsewhere.\n  Strongest when the name is short and the subject is visual (studios, restaurants, hotels, people).\n- **What it is.** \"A vinyl shelf in your pocket.\" \"Furniture for small rooms.\" Category, stated with\n  one specific word.\n- **The claim.** \"Your bank won't do this.\" One sentence a competitor could not sign.\n- **The instruction.** \"Understand your money.\" Verb first, short.\n- **The place or the moment.** \"Antarctica.\" \"Lisbon, since 1984.\" For hospitality, events, travel.\n\nShapes to avoid, because they are the average of every landing page:\n\n- The mad-lib: \"The AI-powered platform for modern teams\".\n- The tricolon: \"Fast. Simple. Secure.\" or \"Plan. Build. Ship.\"\n- The correction: \"It's not just a tool, it's a workflow\". Also \"More than a …\".\n- \"X, reimagined / redefined / made simple\". \"Welcome to …\". \"Meet …\" for a product nobody has met.\n- A question the reader did not ask.\n- A headline that needs its colon: \"Ledgerly: invoicing for freelancers\". Drop the name, it is in the\n  navigation.\n- One word of the headline styled differently (italic, serif, coloured, underlined, in a pill).\n\nSentence case. No full stop unless the direction's voice uses them everywhere.\n\n## 4. Supporting line, body, buttons\n\n**Supporting line.** One sentence, at most about 22 words, that says concretely what the thing is and\nwho it is for. It is where the detail cut from the headline goes. It never repeats the headline in\nother words.\n\n**Body.** Short paragraphs of plain statements. Prefer the specific noun and the real number: \"ships\nin a week\" over \"fast delivery\"; \"38 seats\" over \"intimate\". Read every sentence and ask whether a\ndifferent company could print it unchanged; if so, sharpen it or cut it.\n\n**Buttons.** Name the action or the thing: \"Book a table\", \"See the plans\", \"Download for Mac\".\nOne to three words. The primary action keeps one name everywhere on the page. One primary button per\nscreen; a second action is a plain text link. No arrow glyph on every link and button; at most one\narrow, on the primary action, if the direction uses arrows at all.\n\n**Navigation.** The wordmark, up to five plain links, one action. Link labels are single nouns.\n\n## 5. Proof without inventing it\n\nNever invent customers, quotes from named people, press logos, user counts, ratings or benchmarks.\nInvented proof is both dishonest and a recognised tell.\n\nWhen the brief supplies no proof, use what is true by construction:\n\n- Show the thing itself, large. A real demonstration outranks any quote.\n- State how it works, specifically.\n- Use facts from the brief (price, place, year, materials, what is included).\n- If a testimonial or logo section is explicitly requested and no real ones exist, build the section\n  with plainly fictional sample content and say so in your final report so it is replaced before\n  launch. Do not put real company names or real people in it.\n\n**Sample details are different from proof, and they are expected.** Where the brief gives the shape of\nthe content but not every detail (six rooms \"from €140\", \"a short menu\", twelve speakers), write the\nfull set of plausible details: each room with a name, a bed, a view and its own rate; each dish with\nits price; each speaker with a talk title. A design can only be judged at its real density, and a page\nthat shows one rate where six rooms exist looks unfinished. List every sample detail in the report so\nthe client confirms or replaces it.\n\n## 6. Things that read as generated\n\n`lint.mjs` flags most of these.\n\n- Verbs and adjectives of the genre: unlock, unleash, supercharge, elevate, empower, streamline,\n  seamless, effortless, robust, cutting-edge, next-generation, world-class, all-in-one, blazing fast.\n- Labels pretending to be editorial: \"Field notes\", \"The details\", \"Our philosophy\", \"Quietly trusted\n  by\". A section heading can simply be \"Pricing\".\n- Furniture text: locale or time strips, \"Est. 2024\", coordinates, version stamps, \"Scroll\", \"(Scroll\n  to explore)\", fake photo credits, status lines such as \"Available for work\" with a dot, strings of\n  words separated by middle dots or slashes.\n- The em dash as a habit. One or two on a page read as writing; ten read as a model. Use a full stop.\n- Explainer captions that narrate the design: \"A clean, minimal layout for…\".\n- Step labels that duplicate numbers: \"Step 1\", \"Phase 02\".\n- Three parallel items everywhere: three features, three stats, three steps. Use the number the\n  content has.\n\n## 7. Micro-typography\n\n- Curly quotes and apostrophes (“ ” ’), a real ellipsis (…), an en dash for ranges (9–5).\n- Non-breaking space between a number and its unit, and before the last short word of a headline\n  when it would otherwise orphan (`&nbsp;`).\n- `font-variant-numeric: tabular-nums` where numbers line up in columns (prices, tables).\n- `text-wrap: balance` on headings, `text-wrap: pretty` on paragraphs.\n- No all-caps for anything longer than three words; if you set caps, add 0.02–0.06em tracking.\n- No text under 13px. No centred paragraphs longer than three lines. No justified text.\n","skills/taste-skill/references/critique.md":"# Critique — judging the render\n\n`inspect.mjs` passing means nothing banned or broken was measured. It says nothing about whether the\npage is good. This file is how you find out. Use it on the screenshots, never on the code: you wrote\nthe code, so you will read your intentions into it. The pictures only show what is there.\n\n## Contents\n\n1. How to look (fourteen passes, a few minutes)\n2. The score\n3. Caps\n4. Writing the critique\n5. What to fix first\n6. When to stop\n\n## 1. How to look\n\nOpen `desktop-fold.jpg`, then the `desktop-page-*.jpg` sheets, then `mobile-fold.jpg` and the mobile\nsheets. Make each pass on its own; do not blend them.\n\n1. **One second, then five.** Glance and look away. What did you see? There should be exactly one\n   answer: a word, an image, an object. If the answer is \"a website\", there is no focal point. Then\n   give the first screen five seconds as a stranger: can you say what this is, who it is for and\n   what to do next? If the title only makes sense after scrolling, it is not a title.\n2. **Squint.** Blur your attention until text becomes grey bars. The page should reduce to two or\n   three large masses with clear size differences. Many small similar masses means everything is\n   medium and nothing leads.\n3. **Cover the logo.** Could this first screen belong to a competitor, or to a different industry?\n   If swapping the name and the noun in the headline would produce an equally valid page, the page has\n   no idea. Go back to the direction sheet; the idea is written there. Then scroll: does the idea reach\n   the pricing, the FAQ and the footer, or does the page turn into stock blocks after the first screen?\n4. **Edges.** Follow the left edge of every text block down the page. Count the distinct x positions.\n   A composed page has two or three, reused on purpose. Six means things were placed one at a time.\n5. **Space and frame.** Are related things close and unrelated things far? Is the gap between sections\n   clearly larger than any gap inside a section? Is any region empty by accident (a hole) rather than\n   by decision (a rest)? A hole usually sits beside a short column or under a removed decoration.\n   Then look at the frame: are the left and right margins of the page the same? Does any section keep\n   its text in one half and leave the other half empty? Is there a stretch of nothing taller than half\n   a screen? Readers name these first (\"it is pushed to the left\", \"random empty space\"), before any\n   detail; in the study of 100 Sites of the Day about 1 section in 100 left half the width empty.\n6. **Type.** Is the jump from body text to headline decisive (three times or more)? Do you see more\n   than five sizes? Any headline with one orphan word on its last line? Any paragraph wider than about\n   75 characters or centred over more than three lines?\n7. **Colour.** Name the proportions: which colour holds most of the surface, which supports, where is\n   the accent? An accent that appears in ten places means nothing. One that appears on the single\n   action and one detail means \"here\".\n8. **Images.** Count the real pictures: are there at least four, and is there a moving one? A page of\n   drawings only, or of type only, looks unfinished next to one with real photographs and footage.\n   Is every image doing a job (showing the thing, setting the place, proving the claim)?\n   Do the crops share ratios? Is anything a grey box, a stretched photo, a fake screen made of bars?\n   Does the photography share one light and one grade, or is it a stock mix?\n9. **Sameness.** Write one word for each section's layout (split, list, full-bleed, grid, statement,\n   index …). The same word twice in a row, or three times on the page, is the template showing.\n10. **Phone.** Is the mobile screen a composition of its own, with its own crop and its own line\n    breaks, or the desktop page squeezed? Is the first screen still one clear thing?\n11. **Fullness.** Go through the desktop sheets screen by screen. Is each screen a composed poster, or\n    is it a narrow column of small text with dead ground either side? Is any statement held on screen\n    for three screens? An austere page is not a restrained one: if the page could be mistaken for an\n    unfinished wireframe (grey shapes, grey text, one small column), it is underbuilt. A single motif or\n    drawing blown up to fill a whole screen with nothing to read is a hole too, however bold it looks.\n12. **Substance.** Does every section the brief asked for deliver its information completely and at a\n    readable size (the full menu, each room, every speaker, the price and what it includes)? Would the\n    visitor leave knowing what they came to find out? Is the primary action a real button on the first\n    screen?\n13. **Collisions.** Is anything lying on top of a headline, a statement or a button at any scroll\n    position? Does any element run off the edge of the phone screen? A row that scrolls sideways on\n    the phone reads as cut off in a screenshot and to most visitors; wrap it unless the cut is\n    plainly deliberate (a partial card showing at the edge).\n14. **The competitor and the live thing.** Put the nearest competitor's name on the page: does the\n    idea still work? Then name the one live thing (what the visitor can do or what differs each visit).\n    If either answer is weak, that is the first problem of the round, ahead of any detail.\n\nA note from testing: in blind comparisons a richer page full of template devices beat a cleaner page\nthat was thin, every time. The house rules remove the devices; passes 11–13 are where you make sure the\npage did not lose its substance with them.\n\n## 2. The score\n\nScore like an Awwwards juror: four criteria, 1–10 each, weighted **design 40%, usability 30%,\ncreativity 20%, content 10%**.\n\n**Design (40%)** — composition, typography, colour, imagery, craft.\n- 9–10: every screen holds as a poster. Nothing could be removed or moved.\n- 8: confident and coherent; one or two soft spots a designer would notice.\n- 7: clean and professional, a clear system, little tension.\n- 6: tidy but anonymous. Reads as a kit.\n- 5 or less: weak hierarchy, accidental spacing, default type, mismatched images.\n\n**Usability (30%)** — orientation in three seconds, readable text, obvious actions, honest mobile.\n- 9–10: you know what it is, who it is for and what to do without scrolling; flawless on a phone.\n- 8: clear and comfortable; minor friction (a long section, a small target).\n- 7: works, with one real problem (weak contrast somewhere, a cramped phone layout).\n- 6 or less: you have to hunt, or something breaks.\n\n**Creativity (20%)** — an idea you can state in a sentence, carried through.\n- 9–10: a concept specific to this subject that you have not seen applied this way.\n- 8: a clear idea with one memorable move.\n- 7: a tasteful execution of a known approach.\n- 6 or less: the category default.\n\n**Content (10%)** — words and pictures that are specific, true-sounding and edited.\n- 9–10: every line could only be about this subject; imagery is the subject.\n- 7–8: clear and concrete, some generic lines.\n- 6 or less: slogans, filler, stock.\n\n`overall = 0.4·design + 0.3·usability + 0.2·creativity + 0.1·content`\n\nFor calibration: real Sites of the Day land around 7.5–8.0 overall from the jury. An honest 8.5 is\nrare. If your first score for your own work is 9, score it again as the juror who did not build it.\n\n## 3. Caps\n\nThese override the arithmetic.\n\n- Any `FAIL` still reported by `inspect.mjs`: overall cannot exceed **6.0**.\n- A headline of three or more lines at any viewport, an eyebrow label, monospace labels, 01/02/03\n  numbering, a decorative gradient, a shadow on a resting element, or a decorative hairline visible in\n  a screenshot: overall cannot exceed **6.5**, whatever else is true.\n- Pass 3 fails (the page could belong to anyone): creativity cannot exceed **6**.\n- The idea passes for the nearest competitor (pass 14): creativity cannot exceed **7**.\n- Fewer than four real pictures (photographs, archival images, footage; drawings do not count):\n  design cannot exceed **6.5**.\n- A page that barely moves (the inspector's `still-page`), or motion that is one identical fade on\n  every block: design cannot exceed **7**.\n- No live thing (pass 14): creativity cannot exceed **7.5**.\n- Any placeholder (grey box, lorem, \"Image here\"): content cannot exceed **5**.\n- Two or more desktop screens that are mostly empty ground, or a page whose running text is small and\n  grey: design cannot exceed **6.5**.\n- A section the brief asked for that is missing or reduced to a few words: content cannot exceed **6**.\n- No real button for the primary action on the first screen: usability cannot exceed **7**.\n- The five-second pass fails (no clear title saying what this is on the first screen): usability\n  cannot exceed **6**.\n- Unequal page margins, a section huddled on one side with the other half empty, or a blank stretch\n  taller than half a screen: design cannot exceed **6.5**.\n- A section of running text with no heading naming it: usability cannot exceed **7**.\n- Anything covering a headline at any scroll position: usability cannot exceed **6**.\n- A blank band where a reveal did not fire, or content clipped off-screen: usability cannot exceed **5**.\n\n## 4. Writing the critique\n\nWrite it down; do not just think it. Use exactly this shape so rounds can be compared:\n\n```\nROUND n\nSeen in one second: …\nIdea (one sentence): …\nLive thing: …\nLayout words by section: hero=… / …=… / …\nScores: design _ · usability _ · creativity _ · content _ → overall _._\nCaps applied: …\nTop three problems (most visible first), each with the screenshot it shows in and the fix:\n1. …\n2. …\n3. …\n```\n\nName problems the way a designer would to a colleague: \"the supporting paragraph starts 40px left of\nthe headline's edge\", \"the testimonial section is the third split layout in a row\", \"the phone hero\ncrops the bottle out of frame\". \"Could be more polished\" is not a finding.\n\n## 5. What to fix first\n\nFix in this order; later items cannot rescue earlier ones.\n\n1. **The idea.** If pass 3 fails, change the hero concept, not the details.\n2. **Hierarchy.** One dominant element per screen. Make the big thing bigger and the small things\n   fewer before touching anything else.\n3. **Composition.** Shared edges, section spacing, variety of layout between sections, holes.\n4. **Typography.** Scale contrast, line breaks, measure, leading.\n5. **Imagery.** Replace weak pictures, unify crops and grade.\n6. **Colour.** Proportion and accent discipline.\n7. **Detail.** States, focus, small alignments, mobile refinements.\n8. **Motion.** Last.\n\nWhen removing something leaves a gap, do not refill it with an ornament. Close the gap, enlarge what\nremains, or let a picture or a colour field take the space.\n\n## 6. When to stop\n\nRun at most three rounds: critique → fix the top three → re-inspect → critique. Stop early when a round\nfinds no problem a stranger would notice. If round three still scores under 7.5, say so plainly in\nyour report, with the remaining problems listed; do not round up.\n","skills/taste-skill/references/imagery.md":"# Imagery\n\nPictures are where generated pages most obviously give up: a grey box, an icon in a square, a fake\ndashboard, an abstract blob. This file is how to decide what the pictures are, where to find real ones,\nhow to crop and place them, and what to do when there are none.\n\n## Contents\n\n1. What the study measured\n2. Decide what imagery exists\n3. Real pictures from the open collections\n4. The dealt photographs\n5. Cropping and placing\n6. Treatment\n7. Showing software\n8. Drawing the subject\n9. Type and colour alone\n10. Markup and credits\n11. Video\n12. Where pictures and footage go\n\n## 1. What the study measured\n\n- On 60% of the studied sites one piece of media covers at least half of the first screen; on half of\n  them it covers nearly all of it. Top-scored sites: 68% and 56%. Weak sites: 48% and 39%.\n- Only 15% of heroes have no media at all, and those are deliberate typographic statements.\n- Media has square corners on 73% of sites. Where corners are rounded the usual radius is about 12px,\n  applied to every image alike.\n- Top-scored pages carry far more imagery (a median of 37 images against 5 on weak pages): the strong\n  sites show, the weak ones tell.\n- What the imagery is, by the panel's classification: a mix of kinds 32%, photography 14%, generative\n  or WebGL scenes 13%, real product interface 12%, 3D renders 11%, illustration 9%, video 6%, type only\n  3%.\n- Among the 54 sites the panel scored under 6.8, legibility (text lost over a busy image, or too\n  little contrast) was named as a weakness in 13.\n- In the October 2026 study of 91 Awwwards Sites of the Day (section 12), the median page carries 7\n  pictures (top sites 8, the lowest 2) and footage appears on 42% of sites (half of the top ones, one\n  of the 16 lowest).\n- Pictures come in whole screens: 42% of scrolled screens hold none and 19% are 90% picture or more.\n- 94% of pictures have square corners, and on a typical site two ratios hold three-quarters of them.\n\n## 2. Decide what imagery exists\n\nIn order of preference:\n\n1. **The project's own images.** Product shots, the place, the people, the work. Even ordinary\n   photographs of the real thing beat beautiful photographs of something else. Ask what exists; look in\n   the repository.\n2. **Images you can generate** with an image tool in this session. Write prompts as a photographer's\n   brief: subject, angle, light, background, crop ratio, and \"no text\". Generate the hero first and\n   make the rest match its light.\n3. **Real pictures of the subject's world from the open collections** (section 3). Archives,\n   museums and photographers have published millions of pictures anyone may use with a credit: the\n   client's city and street in old postcards, maps of its neighbourhood, its materials, its trade in\n   engravings, museum objects of its kind. Whenever an honest one exists, it beats a drawing of the\n   same thing: it is real, it has detail no drawing in a page's budget reaches, and it carries history.\n   Honest means nobody could take it for the client's own product, room, dish, person or team.\n4. **Pictures you draw in code from the subject itself** (section 8), for what no honest picture\n   exists of: the product's own objects as flat shapes, the place's tiles and windows, a map of its\n   streets, the document a tool produces, the interface of a piece of software. In testing, pages that\n   drew their subject with care beat pages that borrowed unrelated photographs every time, and beat\n   pages that showed nothing.\n5. **The photographs dealt on the direction sheet.** Real photographs of places, light, texture and\n   weather. Use them only where an honestly generic picture fits (the open sea for a house on the sea,\n   fog for a quiet retreat). They cannot stand in for a specific product, dish, room, person or\n   screen: a foggy motorway on a restaurant page reads as stock at once, and jurors notice.\n6. **Type and colour alone,** done on purpose (section 9).\n\nTell `draw.mjs` the truth with `--have`. If you have no product photographs and no image tool, do not\npass `product-photo`; the draw will avoid the directions that depend on showing the object. Pictures\nfound in the open collections are not the project's own: do not pass `photography` for them.\n\n## 3. Real pictures from the open collections\n\n`scripts/assets.mjs` searches four open sources without keys and prints, for each find, a direct image\nURL, the page it comes from, its size, its creator, its licence and a credit line:\n\n- **Openverse**: one index over Flickr, Wikimedia Commons, museums and libraries.\n- **Wikimedia Commons**: archival photographs, old maps, scans of prints and books, places as they\n  look now.\n- **The Art Institute of Chicago** and **The Metropolitan Museum of Art**: public-domain paintings,\n  prints, drawings, photographs, textiles and objects, in large scans.\n\n```bash\nnode <skill>/scripts/assets.mjs \"ghent postcard\"\nnode <skill>/scripts/assets.mjs \"fig\" --source museums --orientation portrait\nnode <skill>/scripts/assets.mjs \"basalt texture\" --min-width 2400 --source openverse,commons\nnode <skill>/scripts/assets.mjs --get commons:36649959,met:707892     # download, record the credits\nnode <skill>/scripts/assets.mjs --credits                             # footer line and report list\n```\n\nBy default it keeps only licences that allow commercial use (CC0, public domain, CC BY, CC BY-SA) and\npictures at least 1000 pixels wide, and checks that every image it prints actually loads.\n`--license pd` keeps only pictures that need no credit; `--orientation`, `--min-width` and `--limit`\nnarrow the list; `--source` picks the sources; `--json` gives the raw results. Each result has a ref\n(`commons:36649959`) that `--get` takes.\n\n**What to search for.** The inventory (SKILL.md step 1), not the category: \"bakery\" finds other\npeople's bakeries. The subject's world is specific:\n\n- **Its place:** the city, the street, the harbour, the valley, in old postcards and photographs\n  (\"ghent postcard\", \"rotterdam harbour 1920\") and as it looks today (\"gent korenmarkt\").\n- **Its maps:** the street plan, the chart of its bay, the geology of its valley (\"ghent old map\",\n  \"nautical chart lisbon\").\n- **Its materials,** close enough to read as a surface: the stone of its quay, the grain of its oak,\n  its glaze, its tiles (\"azulejo tiles\", \"basalt cobblestones\", \"oak grain\").\n- **Its trade's history:** the old tools, the craft in engravings and trade catalogues, patent\n  drawings (\"bread oven engraving\", \"potter's wheel\", \"bicycle patent drawing\").\n- **Museum objects of its kind,** with `--source museums`: a coffee set from about 1810 for a studio\n  that makes coffee sets, a woodblock print of a wave for a surf school, a porcelain plate painted\n  with figs for a fig orchard.\n- **Scientific imagery:** botanical and zoological plates (\"botanical engraving fig\"), star charts,\n  microscope photographs, satellite views of its coast, geological sections.\n\nSearch in the place's own words (azulejo, not \"blue tile\"; Korenmarkt, not \"market square\"), add a\nmedium (postcard, engraving, old map, lithograph, aerial photograph) or a decade, and try two or three\nqueries per idea. The museum sources match best on one or two words (\"fig\", \"harbour\", \"teapot\").\n\n**What makes a good find.**\n\n- It belongs to this subject's world and would not fit the nearest competitor's page.\n- It still reads at the crop the slot needs. Look at it before deciding: `--get` downloads it, then\n  open the file. A title is not a picture.\n- It is large enough: twice the width it is shown at for anything full-bleed (the script prints the\n  largest size available). A 1024-pixel Flickr photograph is a half-width picture at most.\n- It belongs to one family with the others on the page: all engravings, or all photographs from one\n  era, or all close surfaces in one light. A 1900 postcard beside a modern stock photograph beside a\n  botanical plate reads as a scrapbook.\n- No watermark, no burned-in text or logo, no frame or scanner edge you cannot crop away, and no\n  recognisable living person who could be taken for the client's staff or customers.\n\n**Use it creatively.** Found pictures are material, not decoration:\n\n- **One archival photograph as the hero,** full-bleed: the street as it was a century ago, behind the\n  name of the business that stands in it today, with the year in the caption.\n- **A museum engraving enlarged until its line becomes texture,** cropped tight and returning at\n  different scales as the page's one motif (the whole fig plate in the hero, a single leaf of it\n  beside the menu).\n- **An engraving or a map on white paper set with `mix-blend-mode: multiply` on the page's colour\n  field,** so the ink sits on the ground (section 6).\n- **The real map of the street as the contact section,** the door marked, the north and the scale\n  taken from the original.\n- **A material close-up as a whole field:** the quay's stone behind the opening hours.\n- **A run of old postcards or plates as the gallery,** one size, one treatment.\n\nTreatments stay within section 6: untouched, greyscale for the whole set, or multiply on a field.\n\n**Stay honest.**\n\n- **A found picture is never the client's own.** It may show the client's city, its materials, its\n  history, the kind of thing it makes; it may never stand in for the client's product, room, dish,\n  person, team or customers. If a visitor could take it for the client's own (a bakery counter, a\n  plate of pasta, a smiling barista, a guest room), do not use it.\n- **Caption from the source** when a caption helps: what it is and when, as the archive describes it\n  (\"Gand, unloading a steamer, 1905\"). Never write a caption that ties it to the client.\n- **Record and credit every picture.** `--get` writes the source, creator, licence and page of each\n  download to `assets/credits.json`. CC BY and CC BY-SA require a credit with the title, the creator,\n  a link to the source and a link to the licence; `--credits` prints them as one line of HTML for\n  the footer (section 10). Public-domain pictures need no credit; give one anyway.\n- **Respect the licence.** CC BY-SA: an altered version (recoloured, combined with other pictures)\n  must be shared under the same licence. Non-commercial (NC) and no-derivatives (ND) licences are out\n  for a client's site, which is why the script leaves them out unless asked. Read the `note` lines:\n  some pictures carry personality rights or a trademark, are public domain only in the United States,\n  or come with an archive's statement instead of a licence.\n- **Download, do not hotlink.** Save what you use into the project: `--get` puts it in `assets/` at\n  1920 pixels wide (pass `--width 1280` for a picture shown at half the screen, `--width 3840` for a\n  very large hero where the source has it). The page then works offline, does not break when an\n  archive moves a file, and does not load from someone else's server. Every licence the script\n  allows by default permits copying.\n- **List them in the report:** file, title, creator, licence, source page, and where the credit sits.\n  `--credits` prints that list too.\n\nIf two or three honest queries per idea find nothing that fits, draw (section 8). A drawing made for\nthe subject is better than a found picture that is merely nearby. If the script cannot reach any\nsource (no network), draw, and say so in the report. For moving pictures, the same script searches\nreal footage with `--video` (section 11).\n\n## 4. The dealt photographs\n\n- The sheet lists eight from one set so they share a subject and a light. Use three to six.\n- Each line says where the calm area is. Put text there or keep text off the image.\n- More from the same or another set: `node scripts/draw.mjs --photos list`, `--photos <set>`, or\n  `--photos \"fog coast\"` to search descriptions.\n- URLs have the form `https://picsum.photos/id/<id>/<width>/<height>`. Request the exact pixel size you\n  render at twice the CSS size for sharpness, capped around 2400 wide. Add `?grayscale` for\n  black-and-white.\n- These are photographs from Unsplash served by Lorem Picsum under the Unsplash licence. List the ids\n  you used in your report; they are meant to be replaced by the project's own pictures.\n\n## 5. Cropping and placing\n\n- **Choose a small set of ratios and stick to them:** for example 4:5 for portraits, 16:10 for\n  landscapes and 1:1 for details. Random ratios look like a stock dump.\n- **Go large.** A photograph at full width, or at half the screen and full height, has presence. Six\n  small ones in a grid have none. If the image is good, give it the room; if it is not, cut it.\n- **Crop with intent.** Use `object-fit: cover` with an `object-position` chosen per image so the\n  subject sits where the composition needs it (off-centre, on a third, against the text side).\n- **Let images touch edges.** Full-bleed, or bleeding off one side, reads as designed. An image\n  floating with equal margins on all sides reads as placed by default.\n- **Overlap sparingly and on purpose:** a headline whose last line runs over the top edge of the\n  picture, a small image overlapping a large one by a fixed 40–80px. One overlap per screen at most.\n- **Square corners** unless the direction or the one-motif shape says otherwise. If rounded, one radius\n  for every image on the page.\n- **No frames:** no borders, no shadows, no device mock-ups, no browser chrome around pictures.\n- **Captions** are one short line in the small size and soft ink under the image, left-aligned to its\n  edge. Most images need none.\n- Where each picture goes on the page, how large, and what the phone does with it: section 12.\n\n## 6. Treatment\n\nOne treatment for the whole page:\n\n- **Untouched.** The default. Pick images whose light already agrees.\n- **Greyscale.** `filter: grayscale(1) contrast(1.05)`, or `?grayscale` on the URL. Unifies a mixed\n  set instantly and suits editorial and typographic directions. Apply to every image or none.\n- **Multiply on a field.** On a light flat ground, `mix-blend-mode: multiply` makes a white studio\n  background vanish so a product sits directly on the colour.\n- **Darkened for a dark page.** `filter: brightness(0.85) contrast(1.05)` so the image edges sink into\n  the ground.\n\nNot treatments: colour washes over photographs, duotone overlays, blur, grain overlays, vignettes,\ntilted \"polaroid\" frames with shadows.\n\nFor text on a photograph, a neutral scrim covering only the text area: a solid block at 40–55% black,\nor a fade from 55% black to transparent over the lower third. Never a coloured overlay.\n\n## 7. Showing software\n\n- Build a real fragment of the interface in HTML at its true size, with believable content, instead of\n  a shrunken screenshot or a decorative mock-up. Crop to the part that makes the point: one control,\n  one row, one panel.\n- Believable means real labels, real numbers that add up, one item hovered or selected, proper\n  alignment. Grey bars standing in for text are worse than no image.\n- Put the fragment directly on the page or on one flat stage colour. No laptop, no phone frame unless\n  the product is a phone app and the frame is a plain rounded rectangle.\n- Inside a fragment the product's own interface conventions apply (its small radii, its 1px control\n  borders, a shadow on its open menu). Put the attribute `data-ui` on the fragment's root element: the\n  inspector and the linter then leave what is inside alone, and hold the page around it to the house\n  rules. `data-ui` is for cropped fragments only; wrapping a heading or a whole section in it fails.\n  Write the fragment's CSS under a `[data-ui]` selector (`[data-ui] .row { … }`) so the linter can\n  tell it apart from page styles.\n- If the user supplies real screenshots, show them large and uncropped at least once.\n\n## 8. Drawing the subject\n\nWhen nothing real can be photographed and the open collections hold no honest picture of it, draw it,\nand draw it well. Inline SVG and CSS are enough. Drawings and found pictures can share a page: the\nfound ones show the world around the client, the drawings show the client's own things.\n\n- **Draw the subject's own things,** not decoration: the stool's three legs and the grain of its seat,\n  the enamel sign over the bakery door, the hut's two windows and its stove pipe, the street plan, the\n  invoice the tool produces, the festival's stage. If you cannot name what a drawing depicts in the subject's world, it is decoration.\n- **One graphic language for the whole page:** flat filled shapes, no outlines or one consistent\n  stroke weight, the same corner and curve vocabulary everywhere, drawn in the palette's real colours\n  (fields and accent at full strength, not greys). A set of drawings that obviously belong together\n  reads as an identity; a mix of styles reads as clip art.\n- **Colour is the material.** A product sold on its finish is drawn in that finish's colours; a sea house in the\n  sea's blues and the sand; never a page of grey placeholders.\n- **Draw with three levels of detail.** Jurors called simple drawings \"basic\" every time. Give each\n  drawing big shapes that read at a glance, middle shapes that describe the thing (the handle, the\n  window frame, the step), and small details that reward a second look (the maker's mark, the house\n  number, the chipped tile, the hinge, a bird on the roof). Make light with flat tone steps (a lit face\n  and a shaded face of each volume), not gradients. A drawing that would pass as a placeholder icon at\n  full size is not finished.\n- **Draw large and let it work:** the drawing is the hero's dominant element, a full-width band, a set\n  of tiles, the footer mark. Small doodles scattered around read as filler.\n- **Let it carry the idea through the page,** the way a motif does: the same drawn object returns at\n  different scales, the tile grid becomes the opening hours, the map becomes the booking section.\n- **Honesty:** say plainly, in small text near the first drawing or in the footer, that the pictures\n  are drawn until photographs exist, if the client might otherwise be taken to be showing real\n  products. In your report, list which drawings are placeholders for photography.\n- **Not this:** gradient-shaded 3D-looking blobs, isometric clip art, generic line illustrations of\n  people at laptops, abstract floating shapes, icons in squares. Those are the generated look.\n\n## 9. Type and colour alone\n\nThis is a legitimate design, not a gap to disguise. Only 7 of the studied sites use no imagery at all,\nand they hold their own: a median panel score of 7.5 against 7.2 for the whole set.\n\n- Make the typography the image: one statement at 10–14vw, a list set at 5vw, numerals at display size.\n- Use colour at scale: a full field, an inverted section, a two-field split.\n- Use the subject's own shape as one flat motif if the direction calls for it (a circle, an arc, a\n  notch), drawn in CSS, cropped by the viewport.\n- Do not add: icons in squares, abstract gradients, dot grids, wave dividers, floating shapes, emoji,\n  generic line illustrations, or an empty box where a picture \"will go\".\n\n## 10. Markup and credits\n\nA found picture, downloaded into the project with `--get`, used as the hero:\n\n```html\n<img src=\"assets/fig-engraving.jpg\" width=\"1920\" height=\"2807\" fetchpriority=\"high\" decoding=\"async\"\n     alt=\"Hand-coloured engraving of a fig cut open, with its flowers and seeds, in black, pink and green\">\n```\n\nA dealt photograph further down the page:\n\n```html\n<img src=\"https://picsum.photos/id/626/2400/1500\" width=\"2400\" height=\"1500\"\n     alt=\"Red and white lighthouse in a turquoise sea below a chalk cliff\" loading=\"lazy\" decoding=\"async\">\n```\n\nThe credits, as `--credits` prints them, in the footer:\n\n```html\n<p class=\"credits\">Pictures: <a href=\"https://commons.wikimedia.org/wiki/File:Fig_(Ficus_carica_L.);_57_segments_of_flowers_and_fruits_at_Wellcome_V0043000.jpg\">“Fig (Ficus carica L.): 57 segments of flowers and fruits”</a>, <a href=\"https://creativecommons.org/publicdomain/mark/1.0/\">public domain</a>, via Wikimedia Commons.</p>\n```\n\n- Always `width` and `height` (or `aspect-ratio` in CSS) so nothing jumps while loading.\n- `loading=\"lazy\"` on everything except the hero image, which gets `fetchpriority=\"high\"`.\n- `alt` describes the picture in plain words. Decorative repeats get `alt=\"\"`. The script's suggested\n  alt is the archive's title; rewrite it to say what the picture shows.\n- A coloured `background-color` on the image container (the ground or surface tone) so the layout is\n  whole before the image arrives.\n- The credit line is part of the footer's design, at full contrast, with its links. Set it at the body\n  size; one step smaller only on a page with plenty of running text, because a long credit line in\n  small type can become the page's most common text size and fail the inspector's body-size check.\n  One line for all pictures; no credit captions laid over the pictures themselves. Credit only the\n  pictures the page still uses.\n- A broken image fails the inspector. Check every picture in the screenshots.\n\n## 11. Video\n\nA moving picture of the subject's world can carry a section the way a photograph does: the river at\nthe end of the street, the roaster's drum turning, a timber frame going up. `assets.mjs --video`\nsearches real footage without keys: Wikimedia Commons (every video there comes with web-sized\ntranscodes; the best source for short clips), the Internet Archive's Prelinger Archives (industrial,\neducational, city and home films from the 1920s to the 1970s, mostly public domain and mostly long)\nand NASA (the Earth from orbit, launches, aircraft, laboratories). The rest of the Internet Archive is\nleft out: anyone can upload there, and the licence claims are unchecked.\n\n```bash\nnode <skill>/scripts/assets.mjs \"coffee roasting\" --video\nnode <skill>/scripts/assets.mjs \"river\" --video --source commons,nasa --orientation landscape\nnode <skill>/scripts/assets.mjs --get commons:49769620        # the clip, a poster frame, the credit\n```\n\nIt takes a rendition of 720p or smaller (`--res` changes that), lists short clips first, prints each\nclip's length and file size, and flags anything over 25 MB or longer than a minute. `--get` refuses a\nclip over 25 MB unless you pass `--max-mb`, and saves the source's still frame beside it as the\nposter (Commons and NASA; the archive's own stills are too small). An archive film of ten minutes is\ntoo heavy as it stands: trim a few seconds from it with ffmpeg if it is installed, or choose a\nshorter clip. Licences, credits and honesty work exactly as for pictures (section 3).\n\n**Choosing a clip.**\n\n- **Short:** 5 to 20 seconds that loop without a visible jump: water, smoke, a turning drum, traffic,\n  leaves, a crowd from far away. Watch it to the end before choosing.\n- **Light:** under about 5 MB for a section and 10 MB for a hero. In the study sources are 1920×1080\n  (the commonest) or 1280×720, median length 10 s; 720p is plenty behind type. For a full-bleed hero,\n  cut a tall 720×1280 version for the phone, or set `object-position` on the subject.\n- **Clean:** no slate, title card, logo, watermark or burned-in caption. NASA and archive films often\n  open with a slate, and the source's poster frame may be that slate. No recognisable person who could\n  be taken for the client's staff or customers.\n- **Never the client's own:** a found clip of a roastery is not this roastery.\n- **Found clips: one per page, two at most.** A found clip shows the world around the client; a\n  third makes a theme of it. The project's own footage can carry more: in the study a site with\n  footage carries a median of three or four clips. Either way, **one moving picture per screen**;\n  two loops running side by side are noise.\n\n**On the page.**\n\n- Muted, looping, inline, with a poster and a fixed size, as `--get` prints it:\n  `<video autoplay muted loop playsinline preload=\"metadata\" poster=\"assets/river-poster.jpg\"\n  width=\"854\" height=\"480\" aria-hidden=\"true\"><source src=\"assets/river.webm\" type=\"video/webm\"></video>`.\n  No sound and no controls on a decorative loop. `aria-hidden` because it is decoration: whatever the\n  clip says that matters belongs in the text beside it.\n- The poster shows before the clip plays, on slow connections and under reduced motion, so it must\n  work as a picture on its own. If the source's still is a slate or a blur, take a frame from the clip\n  yourself or use a found picture.\n- In the study only 31% of clips had a poster, and the panel recorded the blank and grey boxes\n  before they played as faults. Here every clip has one.\n- Play a clip only while it is in view, and none under `prefers-reduced-motion: reduce`, where the\n  poster shows instead:\n\n  ```html\n  <script>\n    const calm = matchMedia('(prefers-reduced-motion: reduce)');\n    const clips = [...document.querySelectorAll('video[autoplay]')];\n    const inView = new Set();\n    const sync = (v) => {\n      if (calm.matches) return;\n      if (inView.has(v)) v.play().catch(() => {}); else v.pause();\n    };\n    const settle = () => {\n      for (const v of clips) {\n        if (calm.matches) { v.removeAttribute('autoplay'); v.pause(); v.load(); }\n        else if (inView.has(v)) v.play().catch(() => {});\n      }\n    };\n    const watch = new IntersectionObserver((entries) => {\n      for (const e of entries) {\n        if (e.isIntersecting) inView.add(e.target); else inView.delete(e.target);\n        sync(e.target);\n      }\n    }, { threshold: 0.2 });\n    clips.forEach((v) => watch.observe(v));\n    settle();\n    calm.addEventListener('change', settle);\n  </script>\n  ```\n\n- Crop and place it like a photograph (sections 5 and 6): `object-fit: cover`, one ratio, square\n  corners, no frame, a ground-coloured `background-color` while it loads.\n- Never under body text. On a clip put a headline, one line and one action at most, and check the\n  contrast where they sit across the whole loop, not only on the poster: footage that is dark at\n  one second can be bright at the next. If any frame drops below 4.5:1 (3:1 for 24px and up), use the\n  scrim in section 6 or move the text off the clip. Nothing lies on top of a headline or a statement.\n- It is motion: let it be the page's one moving thing, or sit in a section where nothing else moves.\n- Credit it with the pictures: `--credits` prints one footer line for both (\"Pictures and footage:\")\n  and the list for the report, with each clip's length.\n- Where footage goes (hero background, inline loop, the frame that grows, a docked card), and what\n  the study measured about it: section 12. Nothing that matters plays on hover only, and a full film\n  with sound sits behind a play button that opens a player with controls.\n\n## 12. Where pictures and footage go\n\nWhat strong pages do with their pictures, measured on the latest 100 Awwwards Sites of the Day\n(10 July to 17 October 2026, captured at 1440×900 and 390×844). 91 were usable. A panel described where\nevery picture sat and scored each site the Awwwards way, and a script measured how much of each screen\nis picture. \"Top\" means a panel score of 7.5 or more (36 sites), \"lowest\" under 7.3 (16 sites). The\nscores sit close together (6.7 to 7.9) and a single score carries about half a point of noise, so read\nthe links between a placement and the score as leanings, not laws.\n\n### How much of each screen is picture\n\n- **All or nothing.** Counting photographs, footage and picture backgrounds (not canvases), the median\n  scrolled screen in the study is 16% picture, but few screens sit near it: 42% hold no picture and\n  19% are 90% picture or more. Only 19% fall between 20% and 60%. A picture either leads its screen or\n  stays out of it.\n- **About a third, with rests.** On the 67 sites that put pictures in the page, the average screen is\n  36% picture (middle half 18–69%). Top sites sit at 30% and leave 28% of their screens with no picture\n  at all: screens of type are the rests between picture screens.\n- **The first screen.** A picture covers at least half of it on 41% of the sites and nearly all of it\n  on 32%. A full-bleed photograph or film is the whole first screen on 29%; footage is the main hero\n  picture on about a quarter.\n- **A scene is not a picture.** 66 of the 91 keep a WebGL canvas over at least 30% of the screen, so\n  counting canvases the median screen is entirely covered. On the lowest-scored sites that canvas is\n  often all there is: the five lowest usable sites (6.7 to 7.0) draw everything in it and put two\n  pictures at most in the page.\n- **Text is small in area.** The median screen is 8% text. Type is set large and sparse around the\n  pictures, not packed beside them.\n- **Off-centre.** Measured per section across the crawled sites, pictures sit to the left or right\n  939 times, centred 273 times, and full-bleed or behind text 269 times.\n- **The phone carries more picture,** not less: 19% of a phone screen at the median, and 27% of the\n  first phone screen against 17% on desktop. Full-bleed pictures re-crop to portrait and fill the\n  screen; splits put the picture first at full width.\n\n### How many\n\n- **Seven pictures per page** at the median (middle half 1–25). Top sites 8 (middle half 4–27), lowest\n  2 (0–4). The floor in SKILL.md step 6, four and usually six to twelve, is the strong half of the\n  study.\n- **Footage on 42% of sites:** on half of the top sites and half of the middle band, and on one of the\n  16 lowest. A site with footage carries a median of three or four clips.\n- **Three to five placements.** Sites that use two or fewer of the placements below average 7.31;\n  sites that use three or more average about 7.5. The median top site uses four, the median lowest\n  site one. Where the pictures go changes from section to section on a designed page.\n\n### The placements, ranked\n\n| Placement | Sites (of 91) | Top (of 36) | Lowest (of 16) | Mean score with / without |\n| --- | --- | --- | --- | --- |\n| Split: picture in a half or two-thirds | 32 | 17 | 2 | 7.50 / 7.38 |\n| Horizontal gallery | 32 | 13 | 4 | 7.44 / 7.41 |\n| Full-bleed band between sections | 31 | 14 | 3 | 7.48 / 7.40 |\n| Full-bleed picture or film as the first screen | 26 | 10 | 3 | 7.45 / 7.41 |\n| Uneven mosaic | 25 | 11 | 1 | 7.49 / 7.40 |\n| Picture held while text scrolls | 23 | 12 | 1 | 7.52 / 7.39 |\n| Footage behind text | 22 | 8 | 2 | 7.46 / 7.41 |\n| Even grid | 20 | 11 | 2 | 7.48 / 7.41 |\n| Scattered collage | 19 | 6 | 3 | 7.47 / 7.41 |\n| Panel sliding over a held picture | 19 | 8 | 2 | 7.48 / 7.41 |\n| Inset frame that grows | 17 | 7 | 1 | 7.52 / 7.40 |\n| One picture centred on a field | 14 | 5 | 3 | 7.38 / 7.43 |\n| Cut-out object on a flat field | 13 | 7 | 1 | 7.57 / 7.40 |\n| Index with hover preview | 12 | 6 | 1 | 7.49 / 7.41 |\n| 3D gallery | 12 | 4 | 4 | 7.30 / 7.44 |\n| Small card docked in a corner | 11 | 5 | 1 | 7.47 / 7.42 |\n| Picture inside or in front of display type | 11 | 7 | 1 | 7.50 / 7.41 |\n| One small picture beside a statement | 8 | 5 | 0 | 7.56 / 7.41 |\n| Small pictures between words | 6 | 4 | 0 | 7.52 / 7.42 |\n\n- Found on top pages more than their share and almost never on the lowest: the split, the picture held\n  while text scrolls, the uneven mosaic, the inset frame that grows, the cut-out on a flat field, and\n  pictures set with the type (the last three rows together: 24 sites, 16 of them top, 1 lowest).\n- The horizontal gallery is common in every band and lifts nothing. Use it where browsing is the point.\n- The 3D gallery is the one placement that goes with lower scores, and with the lowest usability in the\n  table (5.9 against 6.35 for all sites).\n\n### Each placement\n\nEach entry gives when to use it, the geometry at 1440×900, the phone version and how it fails.\n\n**Split: picture in a half or two-thirds**\n\n- *When.* A claim and the picture that proves it. The commonest way strong pages pair words and a\n  picture.\n- *Geometry.* The picture takes 42% of the width at the median (middle half 33–49%), up to two-thirds,\n  at the full height of its section: 680×850 and 720×900 are typical. 38% of these pictures are\n  portrait, mostly 4:5 or 3:4. The text starts on the 50% line (x = 720) or on the line where the\n  picture ends, top-aligned or docked low, not centred in its half. Let the picture touch the viewport\n  on its outer side: only about 30% do in the study, and the ones with margin on every side read as\n  placed by default (section 5). Alternate sides only across three or more rows.\n- *Phone.* Picture first at full width (4:5, or 4:3 for a landscape), text under it.\n- *Fails.* The same split in three sections running; a picture floating in the middle of its half; a\n  text column narrower than about 30 characters.\n\n**Full-bleed band**\n\n- *When.* One picture carries a whole screen between type screens: the place, the work, the object at\n  full size. One every three or four screens at most.\n- *Geometry.* 100% wide and one to one and a half screens tall (median 900px at 1440×900, middle half\n  890–1,170px; ratios 1.4 to 1.9). For a slow parallax the picture is oversized in its frame by 4–10%\n  (32–72px a side in the study) and travels no further than that. Text is a headline and one line, or\n  nothing, docked 32–64px in from a corner over the calm part of the picture.\n- *Phone.* A portrait re-crop that fills the screen, with `object-position` set on the subject; the\n  text moves to the bottom quarter.\n- *Fails.* 11–14px white text over a bright area; three bands with nothing between them; a band that\n  only decorates.\n\n**Picture held while text scrolls**\n\n- *When.* A list, steps or a long paragraph that all belong to one picture. If the picture changes for\n  each item, it is the index with a preview, below.\n- *Geometry.* A 100vh sticky stage inside a section two to six screens long (runways of 1,800–5,400px\n  are typical in the study). The picture holds one half (685×880 is a typical portrait), two-thirds, or\n  the whole screen with the text passing over it on a solid panel. Text rows about 150px apart, so two\n  or three are in view at once.\n- *Phone.* Release the stick: picture first, text under it. If the picture swaps per item, keep it as\n  a band in the top 40% of the screen.\n- *Fails.* Long runways where the text has faded out and the held picture is all that is left (the\n  panel recorded several empty stages on phones); body copy set on the held picture.\n\n**Inset frame that grows**\n\n- *When.* Once per page, for the film or picture the page is about, as the move from type into\n  picture.\n- *Geometry.* The frame starts centred at 35–50% of the width (549×366, 710×480 and 864×540 in the\n  study) or as a 16px inset round a full screen, and grows to the full width and height over\n  720–2,700px of scroll. Any corner radius goes to 0 as it reaches the edges. A headline sits above it\n  before it starts; nothing else on the screen moves while it grows.\n- *Phone.* Start at full width inside the 16px margins and grow to a full-bleed portrait, or skip the\n  growth.\n- *Fails.* The growth is the only thing on screen for three scrolls; a loading spinner or a blank box\n  in the first frame (give it a poster, start loading before it enters); used twice.\n\n**Uneven mosaic**\n\n- *When.* A body of work, or one place seen several ways: five to twelve pictures.\n- *Geometry.* Two columns, or rows of three on a 24-column grid. Two or three picture widths (for\n  example 32%, 48% and 65% of the width, or 5, 7 and 12 columns), neighbours offset vertically by\n  120–190px, 130–450px between rows, one or two ratios, a caption under each.\n- *Phone.* One column alternating full width and about 70% width, or two columns of 120–180px tiles\n  that keep the offsets.\n- *Fails.* Random ratios with random offsets, which read as a stock dump. Captions in 9–12px mono with\n  index numbers, the award-site habit: here the caption is one line in the text face at body size, with\n  no number.\n\n**Horizontal gallery**\n\n- *When.* A set people browse in any order: products, rooms, events, a team.\n- *Geometry.* Cards 25–35% of the width (435×326 with 20px gaps at 1440: three in full and a fourth\n  cut by the edge), or a strip at one fixed height with mixed widths (576px tall in the study), or a\n  slider whose centre slide is about 73% of the width with 170–180px of each neighbour showing. Always\n  cut by the right edge so it reads as more. A marquee of pictures moves slowly: 60–120s per loop.\n- *Phone.* One card at 75–80% of the width (290–300px of 390) with the next one showing; swipe.\n- *Fails.* Arrows and no drag or swipe; a marquee of things people need to read; a carousel holding the\n  page's one important picture.\n\n**Panel sliding over a held picture**\n\n- *When.* A change of chapter: the picture holds, and the next section rises over it.\n- *Geometry.* The picture is sticky at 100vh; the next section's ground slides up over it at full width,\n  its top edge straight or shaped from the subject (the study has the arch of a building's windows).\n  Here it is a solid panel with square corners: no rounded sheet tops, no frosted glass.\n- *Phone.* Unchanged.\n- *Fails.* Decks of five or six cards whose earlier cards linger as slivers; stacking for its own sake.\n\n**Even grid**\n\n- *When.* An archive only (layout.md §5): a shop range, the team, a menu, the full list of work.\n- *Geometry.* Two, three or four across, equal cells, 8–16px gaps, one ratio (4:5 is the commonest),\n  the caption under each picture.\n- *Phone.* Two across for products, one for work and people.\n- *Fails.* Three equal cards as \"features\". Cards with a dark gradient at the foot so the label can sit\n  on the picture, common in the study: here the label goes under the picture.\n\n**Index with hover preview**\n\n- *When.* A list of eight or more projects or clients where the names matter as much as the pictures.\n- *Geometry.* Rows on a 45–80px pitch, names at 30–60px. One picture at a time, about a third of the\n  width at 16:9 or a portrait 300–450px tall, at a fixed place (the right half from the 50% line, or\n  the centre), swapped within 0.3s. A version that needs no mouse: the names scroll across a picture\n  fixed at the centre and the picture shows whichever name is crossing it. In the study the picture\n  sits on top of the names; here nothing lies on top of large type, so the names pass in front of it.\n- *Phone.* No hover. Give each row a thumbnail about 100px wide, or use the scroll version.\n- *Fails.* Pictures that never appear on a touch screen. Rows divided by hairlines, the award-site\n  habit: here rows are separated by space, and the active row by ink or a change of ground.\n\n**One picture on a field, or one small picture beside a statement**\n\n- *When.* A pause in the page: a single portrait or object. Or a small picture that gives a statement\n  a face.\n- *Geometry.* A single centred picture at 3:4 and 75% of the viewport height, on a ground taken from\n  the picture. Or a small picture 7–26% of the width (108–374px) beside, above or between the lines\n  of a 48–136px statement, aligned to one of its lines.\n- *Phone.* The picture above the statement at 60–100% of the width.\n- *Fails.* Used as the default for every picture: a picture with equal margins on all sides reads as\n  placed by default (section 5).\n\n**Small pictures between words**\n\n- *When.* A statement about the things themselves (materials, people, products), on a screen of its\n  own.\n- *Geometry.* Two to four chips in the statement, from the cap height to three-quarters of the type\n  size tall and one to one and a half times as wide (50×46px in a 60px line; 113×75px between the two\n  words of a 150px name), all from one shoot, square corners. Give them a width and height so the lines\n  do not jump while they load.\n- *Phone.* Keep them inline at the height of the text.\n- *Fails.* More than four; chips from different shoots; a chip that carries information the words do\n  not.\n\n**Picture inside or behind display type**\n\n- *When.* The object is the subject: a product, a building, a person.\n- *Geometry.* A small picture window sits inside a block of 150–200px display type and later opens\n  into the next screen; or the object stands behind the type, showing between and around the letters;\n  or it touches the edge of the word without covering a letter. In the study the object more often\n  stands in front and covers one or two letters, or a line of type runs behind a square picture; here\n  nothing lies on top of a headline (the inspector fails large text a fifth or more hidden), so the\n  type stays in front.\n- *Phone.* Keep it, with the type at about 15vw, and check the word still reads.\n- *Fails.* An object over the letters; type displaced or glitched by the picture.\n\n**Cut-out object on a flat field**\n\n- *When.* Products and objects. The highest mean score in the table, on 7 of the 36 top sites.\n- *Geometry.* The object at 35–60% of the width on a flat ground taken from its own colours, standing\n  on the bottom edge or running off one side, with the type behind or beside it.\n- *Phone.* The object at 80–90% of the width under the headline.\n- *Fails.* A render floating in a void with no ground; a drop shadow added to a cut-out (no resting\n  shadows here; keep a contact shadow only if it was photographed).\n\n**Scattered collage**\n\n- *When.* Archives, ephemera, a festival of many small things. Sparingly: it is about as common on the\n  lowest pages as on the top ones.\n- *Geometry.* Six to sixteen pictures of 100–300px at a few sizes around a centred heading, never over\n  it.\n- *Phone.* Re-stack as overlapping pairs in one column.\n- *Fails.* Tilted prints and stickers with offset shadows, common in the study and not a treatment\n  here (section 6); pictures crossing the text.\n\n**Small card docked in a corner**\n\n- *When.* A standing pointer to the reel or to the next thing.\n- *Geometry.* About 216×144 to 240×140, 30–43px from the corner; one per page.\n- *Phone.* Drop it, or move it into the flow.\n- *Fails.* Content scrolling under it; a second one.\n\n**3D gallery**\n\n- *What.* Pictures on a ring, sphere, helix or tunnel in a WebGL scene, turned by the wheel or by\n  dragging.\n- *In the study.* 12 sites, 4 of them among the 16 lowest; mean score 7.30 against 7.44, usability 5.9\n  against 6.35.\n- *Here.* Do not build one. Show the same pictures as an index with previews or a horizontal gallery.\n\n### Footage\n\n**What the study measured.**\n\n- Footage on 38 of 91 sites (42%): 18 of the 36 top sites, 19 of the 39 in the middle, 1 of the 16\n  lowest. A site with footage carries a median of three or four clips (middle half 1–8).\n- Footage covers at least half of the first screen on about a quarter of the sites, and is full-bleed\n  on nearly all of them.\n- Clips are short: median 10s, middle half 5–14s; 61% run 10s or less and 88% 20s or less.\n- Every decorative clip is muted, loops, plays inline and has no controls. The autoplay attribute is on\n  44% of clips; the rest are started by script, mostly as they come into view.\n- Only 31% of clips have a poster (13 of the 38 sites). The rest show a blank or grey box until they\n  play, and the panel recorded those as blank first paints. Here a poster is required (section 11).\n- Sources: 1920×1080 is the commonest, then 1280×720; tall clips at 450×800 or 540×960 for phones and\n  portrait tiles. Median source width 1,080px.\n- On the page: 16:9 41%, square 19%, portrait (4:5 to 9:16) 25%, 4:3 or 3:2 12%. Corners square on 75%\n  (the rest 8px or less, or 20–32px). `object-fit: cover` on 84%, contain on 16% (product strips, letterboxed\n  films).\n\n**Where it goes.**\n\n- **Hero background:** full-bleed, cover, often oversized by 1–25% so a drift or zoom never shows an\n  edge. Either one slow take or a montage cutting every second or two.\n- **Inline, as a picture:** in splits, tiles and cards, at about a third of the width (median 33%,\n  middle half 24–45%); a third of these clips are under a quarter of the width and fewer than one in\n  ten is full width. Slow, near-still subjects (water, skin, light, a turning object) read as living\n  photographs and sit well among stills.\n- **The frame that grows** (above), for a reel.\n- **A docked card** (above): one small clip in a corner.\n- **On hover:** only two or three sites play clips on hover, all of them in an index or list. Nothing\n  that matters should play on hover only; phones have no hover.\n- **Full films:** about ten sites offer a full film behind a play button that opens a player with\n  controls. None autoplays it.\n- **Sound:** six sites offer sound behind a toggle; no clip starts with sound.\n\n**How text sits on it.**\n\n- Of about 30 sites with a full-bleed picture or film behind text on the first screen, about 14 set the\n  type straight on it and rely on the footage being graded dark where the type sits; about 10 dim it\n  (to half brightness, under a 30–40% dark layer, or with a dark fade along the bottom 180–590px);\n  about 6 keep the text off the picture, above it or on a solid card.\n- What goes on footage in the study is the name or a headline at 47–136px and one short line, docked\n  bottom-left or centred. Where body text at 11–14px went on footage or a busy photograph, the panel\n  named it as a fault, on top-scored sites too.\n- Here: one headline, one line and one action on footage at most, and never body text. Check contrast\n  where the type sits across the whole loop, not only on the poster; if any frame drops below 4.5:1\n  (3:1 for type of 24px and up), use the scrim in section 6 or a solid band.\n\n**On the phone.** Footage re-crops to a full-screen portrait (a separate tall source, or\n`object-position` on the subject); inset frames go full-bleed. One site in the study adds a 40% scrim\non the phone only, where the type covers more of the picture.\n\n### Crops and treatment\n\n- **Ratios.** Of 1,356 pictures and clips measured: 4:5 21%, 16:9 19%, 1:1 16%, 16:10 10%, 3:2 7%, 2:3\n  5%, 4:3 5%, 5:4 4%, 3:4 3%, wider than 2:1 6%, 9:16 or taller 3%. Landscape 52%, portrait 33%,\n  square 15%.\n- **Two ratios do most of the work.** On sites with four pictures or more, the two commonest ratios\n  hold 76% of the pictures. The others (five ratios in all at the median) are exceptions with a reason:\n  one tall portrait in a run of landscapes, one wide band.\n- **Square corners** on 94% of pictures; 62 of the 68 sites with pictures in the page keep at least 80%\n  of them square. Where corners are rounded, it is 5px or less on two-thirds of them, or 20–32px on\n  card interfaces, one value per site.\n- **Cover.** `object-fit: cover` on 78%, contain on 10% (a product on a tile, a letterboxed film).\n- **Untouched.** CSS filters touch pictures on only 9 sites, mostly for hover states. A handful use\n  black-and-white photography as a set; two multiply scanned paper onto the ground. Several keep the\n  interface black, white and grey and let the photographs carry all the colour.\n- **Common in the study, not treatments here** (section 6): a fixed grain layer over the whole page\n  (about a third of the sites), duotone or tinted photographs, blurred copies behind a picture as a\n  glow, tilted prints and stickers with offset shadows.\n- **Oversize only by the distance it moves.** 22 sites move pictures with the scroll, oversizing them by\n  1–25%. Oversize by the travel and no more, on one picture per screen.\n- **Resolution.** The study serves pictures at a median 1.9 times their CSS width, but 17% are served\n  smaller than they are shown and full-width pictures at a median of only 1,440px. Here: twice the CSS\n  width, capped at about 2,400px (section 4).\n\n### Text over pictures\n\n- In the study, text sits on pictures often and is checked rarely: about 28 notes record text set\n  straight on a picture with no scrim, and the faults of 16 sites include text lost over pictures: 8–14px\n  labels and body over photographs, and navigation in a difference blend or with no backing passing\n  over them.\n- Where it works, the text is display size and sits over the calm part (sky, a dark wall, the shadow\n  side), docked in a corner or along one edge. Two other forms in the study: a solid card in the\n  ground colour inset over the photograph and carrying the heading, and text on the white of a picture\n  that fades into the page.\n- Here: on a picture put only display text, one short line and one action. Body text, captions and\n  labels go beside or under it. Measure contrast at the text's own position (4.5:1, or 3:1 for 24px and\n  up). If it fails, move the text to a calmer part, put it on a solid card in the ground colour, or use\n  the scrim in section 6. A fixed navigation that passes over pictures gets a solid band, or hides\n  while scrolling down.\n\n### Rules for a generator\n\n1. **About a third of the page is picture.** Across the scrolled screens, pictures fill 30–40% of the\n   area, and at least one screen in four carries no picture (top sites: 30% and 28%).\n2. **A picture leads its screen or stays small.** A leading picture takes at least 60% of its screen;\n   an accent stays under 10% of it. Avoid screen after screen of pictures at 20–40%: in the study 42% of\n   screens are 0% and 19% are 90% or more.\n3. **Three to five placements per page,** and no two neighbouring sections with the same one. Sites\n   with two or fewer average 7.31, sites with three or more about 7.5.\n4. **Six to twelve pictures, never fewer than four.** Study median 7; top sites 4–27; lowest 2.\n5. **Two ratios for at least 75% of the pictures** (76% in the study), a third only for a deliberate\n   exception. Defaults: 4:5 for portraits, 16:9 or 3:2 for landscapes.\n6. **Square corners on every picture** (94% in the study). If the direction rounds them, one radius of\n   4px for every picture and clip.\n7. **Split pictures take 42–50% of the width, or two-thirds,** at the full height of the section and\n   touching the viewport on their outer side; the text starts on the 50% line. On the phone the\n   picture goes first, full width.\n8. **Full-bleed bands are 100% wide and 100–150vh tall,** one every three or four screens, oversized by\n   10% at most for parallax, with text only in one corn\n\n<!-- [TRUNCATED AT 50KB] -->","skills/taste-skill/references/layout.md":"# Layout\n\nHow the page is put together: margins, the grid, where text sits, how sections differ, navigation,\nendings and the phone. The direction sheet gives the specific compositions; this file gives the habits\nbehind them, taken from the panel's notes on the 114 studied sites that scored 7.3 or higher (counts\nbelow are hand tallies from those notes, so read them as \"about\").\n\n## Contents\n\n1. What strong pages do\n2. Margins and the grid\n3. Where text sits\n4. Empty space\n5. The frame: margins, balance and titles\n6. Sections: carry the idea, vary the arrangement\n7. Navigation\n8. Endings\n9. The phone is a second composition\n10. How pages fail\n\n## 1. What strong pages do\n\n- **Tight margins, content to the edges.** About 45 of 114 use outer margins of 32px or less; only\n  about 8 use 80px or more. The centred 1100–1300px container is the minority among strong sites and\n  the usual frame of the ones the panel called stock.\n- **Text hangs from an off-centre line.** About 22 anchor text to one fixed line that is neither the\n  centre nor the margin: a third across, 42%, the midpoint.\n- **Two or three type sizes with nothing between** (about 30): one very large with one small, or\n  everything small with the scale given to the image.\n- **One thing per screen** (about 20): one statement, one object, one project.\n- **Sections told apart by their ground.** About 20 change the whole background colour at each\n  section; about 12 alternate light and dark; about 10 never change and separate by space alone.\n- **Sections recomposed, not repeated.** About 14 rearrange every section; about 12 alternate a\n  full-bleed image screen with a near-empty type screen.\n- **The system broken once, on purpose** (about 14): one centred line on a split page, one paper card\n  on a dark page, colour held back until the last screen.\n- **Often no navigation bar** (about 45), and endings that are a designed scene rather than link\n  columns.\n- **Few words.** Median 575 on the whole study; some of the best carry under 200.\n\n## 2. Margins and the grid\n\n```css\n:root {\n  --margin: clamp(1rem, 2.2vw, 2rem);   /* 16–32px: tight, so content reaches the edges */\n  --gutter: clamp(0.75rem, 1.4vw, 1.5rem);\n}\n.wrap { padding-inline: var(--margin); }\n.grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gutter); }\n```\n\n- One pair of margins and one grid for the whole page. Every left edge is a column line.\n- Do not wrap the page in a `max-width: 1200px; margin: auto` container by reflex. Let large things\n  (type, images, colour fields) run the full width, and constrain only the measure of running text\n  (`max-width` in `ch` on the paragraph, not on the page).\n- On very wide screens cap the layout at about 1760–1920px, or let type sized in `vw` stop growing with\n  a `clamp()`.\n- Directions that call for wide margins (uneven photographs, the quiet instrument) say so on the\n  sheet; follow the sheet.\n- Never draw the grid. Column lines, crosshairs and guides are banned ornaments here even though they\n  are fashionable; the grid is felt through alignment.\n\n## 3. Where text sits\n\n- **Pick the anchor line and reuse it.** If the hero headline starts at column 5, the section\n  headings, the pricing figure and the footer links start there too. Two or three anchor lines on a\n  whole page; six means nothing was decided.\n- **Off-centre beats centred.** A heading in the left third with its paragraph in the far-right\n  column on the same baseline and nothing between; a headline in the bottom third under a deliberate\n  void; text docked in corners with the middle given to the picture.\n- **Opposite ends.** Two short texts at opposite ends of one baseline (name left, one-line description\n  right) is the commonest alternative to the centred stack.\n- **Centred is a decision.** When a strong page centres, it uses one axis with wide empty flanks and a\n  single element per screen, not a centred stack of heading, paragraph and two buttons.\n- **Rows for long copy:** heading in the left third, body in the right two-thirds, the same split for\n  every row on the page.\n- Stagger sparingly: a second line indented by a third so a two-line headline steps across the screen.\n\n## 4. Empty space\n\nEmpty space is placed, not left over. In the study of 97 Sites of the Day captured in October 2026,\nreaders judged every large empty area either a rest, which something closes, or a hole, which nothing\ncloses. Strong sites have plenty of rests. About half of them still leave at least one hole, and the\nholes are what visitors name (\"big random blank spaces\").\n\n**A void is placed when something closes it.** In the readers' notes the closer is, most often:\n\n- the picture itself (sky, ground, the object, the film) with the type docked at its edge;\n- a picture across the void: the photograph at the far side of an empty band, the full-width row\n  rising under a statement, the opposite picture in a stagger;\n- the type: a headline large enough to span the space, or two short texts at the two ends of one\n  baseline;\n- on a one-screen page, the wordmark, the navigation and one fact in the corners, like a mount around\n  a print.\n\nAbout one closer in five in the study is a hairline or grid line. That device is banned here; close the\nvoid with the picture, the type, a step in ground tone or a field of flat colour.\n\n**Where holes come from.** In order of frequency in the study:\n\n1. A gap between sections stretched too far: bands of 250–760px of plain ground.\n2. Text in one half of a section and nothing in the other.\n3. Content that arrives late: a reveal not yet fired, so the visitor scrolls onto bare ground while the\n   words fade in.\n4. A short block stretched to a full screen: a footer padded to the viewport height, a section title\n   alone on a whole screen.\n5. A pinned scene that holds almost nothing for several screens.\n6. Pictures of different heights top-aligned in a row, leaving a hole under the short one.\n\n**Rules**\n\n- Decide where the void is and name what closes it. If nothing does, it is a hole: move the section's\n  picture into it, make the main element bigger, or take the space out.\n- Keep the void clean: no stray caption, no decorative shape, no faint watermark, no grid lines.\n- Sections sit 120–240px apart on desktop, counted from the last line of one to the first line of the\n  next (the median in the study is about 230–250px), and 72–112px on a phone. A change of ground\n  colour lets the gap be a little smaller. More than about 40% of a screen of plain ground between two\n  sections is a hole.\n- The gap between sections is clearly larger than any gap inside one. Related things sit close and\n  unrelated things far; a heading has at least twice as much space above it as below.\n- No stretch of the page taller than about half a screen holds nothing at all. In the study, runs of a\n  screen or more with nothing in the page were almost always scroll distance for a pinned scene; the\n  pinned stage must then hold something at every scroll position.\n- Content is in place on the first paint. An entrance moves what is already there (see `motion.md`);\n  it never leaves a screen of bare ground while the words arrive.\n- Size a section to its content. `min-height: 100vh` belongs to a section that fills the screen, not\n  to a footer or a lone heading.\n- In a row of pictures of different heights, align the bottoms or put something under the short one,\n  or crop the row to one ratio.\n- A rest is one thing on a screen: a single line, one object, one picture or a field of colour. Once\n  per page at most. A screen of nothing is never a rest, and the inspector fails two near-empty screens.\n- When a section looks empty, the answer is almost never \"add something\". Make the main element\n  bigger, or cut the section.\n\n## 5. The frame: margins, balance and titles\n\nThe frame is what readers judge before any detail: \"no good margin\", \"everything is shifted to one\nside\", \"no clear title\", \"random unclear sections\". The inspector measures each of these. The numbers\nare from the study of 97 Sites of the Day (October 2026).\n\n**One pair of equal margins.**\n\n- The left and right margins are the same, at every width. On the studied sites with scrolling\n  sections the two sides match to a few pixels: 16 and 16, 20 and 21, 32 and 32, 140 and 137. No\n  strong page in the study was pushed to one side.\n- The usual margin is tight: median about 28px at 1440, half the sites between about 18 and 45px, a\n  few at 80px or more. Here it is 16–32px (section 2), and never under 16px at any width, on the phone\n  included. About one award site in seven sets text 8–15px from the edge; that studio habit is\n  excluded here.\n- The navigation sits on the same margins as the content. The commonest small fault in the study is a\n  header on one inset and the page on another (40px against 20px, or 34px on the left against 10px on\n  the right).\n- A bleed is deliberate and starts from the margin: a row of pictures that runs off the right edge\n  begins on the left margin; a display line that bleeds starts or ends on one. A bleed never moves the\n  margin.\n- Asymmetry belongs inside the frame: an off-centre anchor line (a third across, 42%, the centre line)\n  on symmetric margins.\n\n**Use the width the page has set up.**\n\n- In the study about one text section in a hundred leaves half the width empty. Text that sits in one\n  half is common, in roughly one site in three, but the other half then holds the section's own\n  picture (most often), a full-bleed picture behind the text, a second column, a list or a figure.\n- When the text takes one side, put the picture, the second column, the list or the large number on\n  the other. Never leave the other half to plain ground.\n- The middle counts too: a card at the left edge and a lone button at the right with the middle third\n  empty is the same hole.\n- The first screen counts too. When the sentence and the button take the left third above a name\n  docked at the foot, the upper right holds something (the picture or film, one fact, the action) or\n  the name grows up to meet them; in testing, 60% of a first screen left as plain ground under the\n  navigation read as a hole, and the inspector now warns when one empty block takes 28% of the first\n  screen or more.\n- A display line fitted to the width is fitted by measurement (a small script that sets its size from\n  the content box, or SVG text with `textLength`), never by a size guessed for one face: a name that\n  starts on the margin and runs a few pixels off the other edge reads as a mistake.\n- A centred composition has one axis, equal flanks and one thing on it, not a stack of heading,\n  paragraph and two buttons.\n\n**A title that says what this is, on the first screen.**\n\n- Asked whether a stranger could say what the page is within five seconds, readers found that 40 of\n  the 97 first screens say it in words, 42 say it only through pictures, small print or a bare name,\n  and 15 do not say it at all. The last group lost usability and content points, not design points.\n- Size alone does not do it: 66 of the 97 first screens carry a display-size line, but 26 of those are\n  a name, a slogan or a place with nothing saying what is offered.\n- The first screen has one `h1`, at display size (32px or more on desktop; on the clear first\n  screens in the study mostly 50–150px), two lines at most, that says what this is: the name with\n  what it does, the product with what it is for, the event with its date and place. If the `h1` is\n  the name, the line under it, at 18px or more, says what the thing is.\n- It is there on the first paint. About a third of the studied pages still showed a loader or nothing readable 4.5\n  seconds.\n\n**A heading on every section.**\n\n- 82% of the text sections on the studied sites open with a heading: median 57px (40–96px for the\n  middle half), about three and a half times the body size, one or two lines.\n- Headings start on the outer margin or on the page's inner anchor line (in the study about a third\n  each) and in the same place for every section. About a quarter of the headings in the study are\n  centred; centre one moment per page here.\n- Where a studied section has no heading, the usual stand-in is a small label: caps, mono or a number\n  in brackets. All three are banned here. Put the label's words in a heading in the heading face at the\n  section size (\"The rooms\", \"How it works\", \"Prices\"), set them on the anchor line, and let the first\n  sentence carry the rest.\n- A statement can open a section as its heading only when it names what the section holds.\n\n## 6. Sections: carry the idea, vary the arrangement\n\nThe most common failure in every score band is a distinctive first screen followed by stock blocks:\nicon cards, a three-up row, an accordion, a link-column footer. About 25 of the studied sites lose\npoints this way, including several above 7.5.\n\n- **The idea survives to the last pixel.** Ask of each section, pricing and FAQ included: what does\n  the page's idea do here? If the page is a menu, the prices are menu lines. If the name is a\n  monument, the footer is the name again. If the object's shape is the motif, the button and the image\n  masks carry it.\n- **No two neighbours share a layout.** Use the shape of each dealt blueprint (list, split, statement,\n  full-bleed, mosaic, table, strip, pinned …). Count them in the screenshot; a shape used three times\n  is the template showing.\n- **Alternate dense and empty, image and type, light and dark** so the scroll has rhythm.\n- **A repeated module is for archives only** (a work index, a menu, a schedule). Anywhere else,\n  repetition reads as a kit.\n- **Break the system once.** After the page has established its rule, one planned exception (a single\n  centred line, one inverted section, one image at a different scale) is what makes the rule visible.\n- **Short pages are fine.** A quarter of the studied sites are one or two screens. Do not add sections\n  to seem complete; each one must carry a claim (see `copy.md` §1).\n\n## 7. Navigation\n\n- The plain form: the wordmark at one end, three to five text links, one action, all at text size on\n  the page ground with no bar, border or background. Median link count in the study is 3.\n- It is also normal to have less: small links in the corners, a single action, or the navigation\n  folded into the content (a list of section titles that is itself the index).\n- If it stays fixed, it must never sit on top of content: check every scroll position in the\n  screenshots, especially on the phone. Floating pill bars are where the panel most often recorded a\n  nav covering text.\n- On a phone: wordmark and one action in view; the links go in a simple full-screen sheet opened by a\n  text button (\"Menu\"), or move to the footer when there are only three.\n- Navigation is small furniture, however it is drawn. On desktop it takes no more than about a tenth\n  of the first screen; on a phone it is one row. A blueprint that builds the navigation as a column of\n  colour blocks or a stack of tabs gets that treatment on desktop only, and collapses to one row on\n  the phone so the headline, the supporting sentence and the action stay in the first screen. In\n  blind tests a nav that ate the hero cost a whole point of usability.\n\n## 8. Endings\n\n- The page should end on a designed scene. In the study: the name at full width (about 18 of 114), the\n  hero repeated in inverted colours (about 12), a closing scene of its own such as the one contact\n  fact set as a headline (about 14), or simply one quiet line (about 22). Link-column footers appear\n  in the panel's notes only as criticism.\n- The full-width name is strong but already a studio habit; use it when the direction is name-led,\n  otherwise prefer the blueprint dealt for the footer.\n- Put the practical facts (address, hours, email, legal line) in the text face at a readable size, on\n  the same anchor lines as the rest of the page.\n\n## 9. The phone is a second composition\n\nDesign the 390px screen as its own page, not the desktop page squeezed. Strong sites that neglect this\nlose usability points; weak ones are often just broken.\n\n- Each blueprint on the sheet has its own phone paragraph. Build it.\n- Keep one dominant thing on the first screen. A wordmark that was 20vw wide on desktop might stack on\n  two lines at 26vw on the phone and be even stronger.\n- Re-author line breaks; re-crop images to portrait (`object-position` per breakpoint, or a different\n  crop size in the image URL); keep unevenness with alternating widths rather than making everything\n  full width.\n- Margins 16–20px. Body text 16–18px. Touch targets at least 44px high.\n- Check 390px in the inspector's screenshots for every round: sideways scroll and three-line headlines\n  usually appear here first.\n\n## 10. How pages fail\n\nFrom the panel's notes on the 54 sites scoring under 6.8 (counts out of 54):\n\n- The whole page is the category's stock template; swap the logo and it could be any competitor\n  (about 20).\n- Centred headline, pill badge, two buttons, screenshot or tile grid below (about 9).\n- A distinctive hero, then stock modules in the usual order (about 8, and about 17 more in the middle\n  band).\n- A default typeface with no character (about 13).\n- Text too small or too low in contrast (about 13); legibility lost over busy photographs (about 9).\n- An undersized headline and no focal point (about 9).\n- The page never says what the thing is, or shows no work (about 12 and 7).\n- Thin content stretched over many screens, or a single gag (about 11).\n- Gates, preloaders and entry pop-ups before any content (about 9).\n- A phone layout that is the desktop shrunk, or broken (about 8).\n- Fixed elements sitting on content; careless details such as colliding lines (about 7 and 5).\n\nAnd the faults of the best sites, which are not to be copied: body text at 9–13px (about 24 of the 90\nsites at 7.5 or more), information hidden behind the concept (about 20), the idea running out\nmid-page (about 15), text over footage with no scrim (about 12), gates and blank first paints (about\n12), floating elements colliding with content (about 11), and a first screen with no statement of what\nthis is and no action (about 9). Say what the thing is, and offer the action, on the first screen.\n","skills/taste-skill/references/motion.md":"# Motion\n\nRead this before adding any animation. The static page must already be finished and passing\n`inspect.mjs`; motion is the last pass, never a way to rescue a weak layout.\n\n## Contents\n\n1. The budget\n2. What strong pages do with motion\n3. Four questions before any animation\n4. Tokens\n5. Scroll behaviours, ranked\n6. Recipes (copy, then adapt)\n7. Signature moves\n8. Reduced motion and performance\n9. What gives generated motion away\n10. Rules for motion\n\n## 1. The budget\n\nA page that does not move reads as a mock-up; the inspector counts what moves while the page loads and\nscrolls, and fails it under eight elements. The motion layer has five parts:\n\n- **Two or three scroll scenes:** the big, scroll-driven moments award sites are remembered for (a\n  camera flying through a field of pictures, a picture that grows from a window to the whole screen,\n  type that crosses a held stage, cards that deal out and stack). The direction sheet deals them from\n  `library/scenes.json` when the library has scenes for the brief; `references/scenes.md` says how to\n  fill and fit them. They are where the page is bold; everything else stays quiet so they land.\n\n- **One signature moment:** the thing a visitor would describe an hour later: the headline that rises\n  out of a mask, the image that opens like a shutter, the wordmark that scales with the scroll. The\n  direction sheet from `draw.mjs` names one. Build that one well; it is the only move allowed to be\n  loud.\n- **Section entrances, choreographed per section:** the parts of each section arrive in reading order\n  (heading, text, picture, details), staggered 60–90ms, rising 16–32px with opacity, once. Vary the\n  manner with the content instead of stamping one preset everywhere: a list arrives row by row, a\n  picture opens from a mask or settles from a slight scale, a figure counts up once, a statement rises\n  line by line.\n- **Feedback under the hand:** buttons that give on press, links that answer the pointer, cards and\n  pictures that respond on hover, a menu that opens from where it was clicked.\n- **One moving picture:** a found clip as a muted loop with a poster frame, a slow drift or scale on\n  a large photograph, or a scroll-linked move on the hero picture.\n\nWhat is still banned: the same fade-and-slide-up with the same timing on every block, which is the most\ncited motion tell of generated pages; motion that hides content until a script runs, with no fallback;\nbounce and elastic easing; anything that animates layout properties. Uniform motion says nobody decided\nanything; choreographed motion with one protected moment says somebody did.\n\n## 2. What strong pages do with motion\n\nMeasured on the latest 99 Awwwards Sites of the Day (July to October 2026), at 1440 and 390, with\nthe transitions, tweens and scroll triggers recorded while each page loaded and was scrolled. Where\nthe gallery does something the house rules ban, the house version follows.\n\n- **The stack.** Two in three use a smooth-scroll library and three in five ship Three.js; GSAP is\n  named on 56. The quiet layer below (reveals, line rises, the ink fill) needs none of it: CSS scroll\n  timelines and view transitions do that work, though only 3 and 6 of the sites use them. The big\n  scroll scenes are built on GSAP ScrollTrigger, as on the award sites, through the shared stage in\n  `assets/scenes/` (`references/scenes.md`).\n- **Curves.** The curves that really ran are strong ease-outs: expo out (`.16,1,.3,1` and\n  `.19,1,.22,1`) ran on 14 sites, cubic out on 13, quint out on 7, and by number of transitions the\n  quint and expo outs lead every chosen curve. In-out curves are kept for wipes and things that\n  travel (cubic and quart in-out, about 15 sites each). Ease-in appears only for exits, short, before\n  a slow arrival. Colour changes use plain `ease` (46 sites). Overshoot sits in 19 stylesheets and\n  ran on 2.\n- **Durations.** Hover colour 200-300 ms; small interface moves 300-450 ms; reveals and line rises\n  600-1,000 ms; picture openings and wipes 1,100-1,600 ms. The median of everything that ran on a\n  site is 420 ms.\n- **Staggers.** 20-40 ms between characters, 75-120 ms between lines, 50-100 ms between list items.\n- **Scroll-linked motion is locked to the scrollbar.** Of the sites that scrub, 14 of 18 lock it with\n  no smoothing; the other four smooth it by 0.1-3 s. Reveals fire when the element's top is 80-95% of the way\n  down the viewport, once.\n- **How much moves.** A median of 130 elements are moved by script on a page, but they come from a\n  few gestures: one split heading is 20-60 elements. The inspector's floor (8, warning under 16) is a\n  floor, not a target.\n- **Waiting is the most common cost.** 60 of 99 open on a loading screen, 26 of them with a counter.\n  Half the usable pages were still unreadable 2.5 s after the browser said the page had loaded, a\n  third at 4.5 s. The preloaders were not covering slow pages (their documents loaded faster than the\n  rest) and the readers' design marks were the same whatever the wait; only usability fell. House\n  version: no preloader, the message readable on the first frame, the load sequence over by 1.2 s.\n- **Pins cost length.** Two in three scrolling pages hold something sticky or pinned. Those pages\n  are twice as long (a median 16.6 screens against 7.5) for fewer words per screen (27 against 46).\n  House version: at most two held stages, about one screen per step, three screens per stage.\n- **Reduced motion is mostly missing.** 35 of 99 have any `prefers-reduced-motion` rule, 16 have\n  three or more; 5 of 26 scroll-scrubbed scenes have one. Every recipe here keeps the finished state\n  as the reduced state.\n\n## 3. Four questions before any animation\n\n1. **How often will someone see it?** Once per visit (hero load, a section reveal): it can take its\n   time. Many times per visit (hover, menu, accordion): fast and small. Hundreds of times (keyboard\n   actions, typing): no animation.\n2. **What is it for?** Valid answers: it shows where something came from, it confirms an action, it\n   keeps a change from being jarring, it explains how the product works, it is the signature moment.\n   \"It looks nice\" is only valid for the signature moment.\n3. **Which easing?** Entering or leaving: ease-out, so movement starts the instant the eye arrives.\n   Moving between two places on screen: ease-in-out. Colour and opacity on hover: `ease`. Constant\n   travel (marquee, progress): `linear`. `ease-in` makes interfaces feel slow because the first frames\n   barely move; do not use it. The CSS keyword curves are weak, so use the tokens below.\n4. **How long?** Press feedback 100–160ms. Hover 150–200ms. Menus and popovers 150–250ms. Dialogs and\n   drawers 250–450ms. Section and hero reveals 500–900ms. Leaving is quicker than arriving (about 70%).\n\n## 4. Tokens\n\n```css\n:root {\n  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);        /* entrances, moving hovers, UI under 600ms */\n  --ease-expo: cubic-bezier(0.16, 1, 0.3, 1);        /* new: reveals of 800ms and longer, line rises, openings */\n  --ease-in-out: cubic-bezier(0.76, 0, 0.24, 1);     /* wipes, panels, things that travel while visible */\n  --ease-soft: cubic-bezier(0.33, 1, 0.68, 1);       /* slow scale and drift on photographs */\n  --ease-exit: cubic-bezier(0.55, 0.055, 0.675, 0.19); /* new: something leaving for good, short */\n  --t-press: 140ms;\n  --t-hover: 180ms;\n  --t-ui: 240ms;\n  --t-reveal: 800ms;\n  --t-open: 1200ms;                                  /* new: picture openings and clip wipes */\n  --stagger-line: 90ms;                              /* new */\n  --stagger-item: 70ms;                              /* new */\n}\n```\n\nHow the study bears on each:\n\n- `--ease-out` (quint out) is in 28 stylesheets with its near twin and is the single most frequent\n  chosen curve among transitions that ran. Keep it.\n- `--ease-expo` is new. Expo out (`.16,1,.3,1` and `.19,1,.22,1`) is in 28 stylesheets and ran on 14\n  sites, more than any other chosen family, and it is the curve the long reveals use: line rises,\n  picture openings, card entrances of 0.9-1.6 s. Use it for anything at `--t-reveal` or longer; it\n  replaces `--ease-out` in the masked headline and the reveal-on-scroll recipes.\n- `--ease-in-out` (quart in-out) matches its family (14 stylesheets, 7 ran). Keep it for wipes,\n  shutters, menus and page transitions.\n- `--ease-soft` (cubic out) matches the cubic-out family (21 stylesheets, 13 ran), but the study uses it\n  for interface moves of 0.3-0.8 s, where `--ease-out` already serves. Narrow it to slow scale and\n  drift on photographs.\n- `--ease-exit` is new. Ease-in is right for exactly one job: something that leaves for good (an\n  outgoing caption, a replaced slide, a closing panel), short, at about 60-70% of the matching\n  entrance. Never for anything the visitor is waiting to see.\n- Not adopted: `.4,0,.2,1` (38 stylesheets) is a framework default, and overshoot curves (19) stay\n  banned on interface elements.\n- `--t-hover` stays at 180ms. The study's colour hovers run 200-300ms; a little quicker reads as\n  more exact. A hover that moves something (a label roll, an arrow) takes `--t-ui` to 400ms.\n\n## 5. Scroll behaviours, ranked\n\n| Behaviour | Pages of 99 | What it serves | House version |\n| --- | --- | --- | --- |\n| Smooth-scroll library | 67 | A feeling of weight; makes scrubbed scenes easier to build | Optional, through `Stage.smooth()`: Lenis at lerp 0.1-0.14, off for touch and reduced motion |\n| Held (sticky or pinned) stage | 44 | One picture or object carries several claims; chapters | Yes: the scroll scenes (`references/scenes.md`), two or three per page, one to four screens each; other sticky stages three screens at most |\n| Split text | 40 | Lines and words arriving as they are read; hover rolls | Lines for headings and statements; words only for the ink fill; characters only for a heading of one to three words |\n| Colour by chapter | 34 | Tells chapters apart without padding bands | Yes, as hard cuts at section edges; the header ink follows in 300ms |\n| Scroll-scrubbed scene (camera, object, image sequence) | 26 | Explains a product by moving it | Yes, from the scene library, built on the shared stage with a finished composition for reduced motion |\n| Parallax depth | 24 | Depth in collages; pictures drifting inside oversized frames | Travel under 8% of the element, pictures held at 106-110% in their frames |\n| Marquee | 21 | Life on a static band | Existing \"Edge-to-edge marquee\": one per page, pausable |\n| Masked line or word rise | 18 | Headings that arrive like set type | Yes: \"Masked line reveal\" on load, \"Lines that rise on scroll\" below the fold |\n| Wheel drives a scene, no page scroll | 16 | Browsing one object | Not used (see 2.6) |\n| Blur-in | 15 | Soft arrival | At most 8px of blur, 600ms, gone once settled; never on body text |\n| Picture from inset frame to full-bleed | 14 | The hand-over from a type screen to the big picture | Yes: \"Opening window\", about one screen of scroll |\n| Grey-to-ink text fill | 14 | Paces one statement | Yes, once per page, starting at 45% ink: \"Ink fill\" |\n| Sheet slides over a held layer | 11 | Page-turn rhythm between chapters | Yes: new move \"Sheet over a held picture\" |\n| Scramble or decode | 11 | A \"code\" voice | Not used (see 2.6) |\n| Header ink by chapter | 10 | The fixed header stays legible | Yes, with colour by chapter |\n| Horizontal track pinned to vertical scroll | 8 | Walking through rooms or a collection | Native drag row first; pinned only when the row is under three screens long, with keyboard support: \"Sideways gallery\" |\n| Curtain footer | 8 | The page ends as a scene | Existing move |\n| Rolling digits | 6 | Figures that arrive | Yes, for pages whose case is a handful of numbers: \"Rolling figures\" |\n| Index with hover preview | 5 | Navigating work by name | Existing move, upgraded recipe |\n\nText, split by unit: characters on about 20 pages, lines on about 14, words on about 11. Character\nsplits serve short headings and button rolls; on long statements they leave fragments mid-scroll.\n\n## 6. Recipes\n\nAll recipes keep the content visible when JavaScript is off, put every hidden state inside\n`prefers-reduced-motion: no-preference`, and use the tokens above. Two notes that apply to several:\n\n- **Scroll timelines need a scroller to watch.** `animation-timeline: view()` takes the nearest scroll\n  container, and `overflow: hidden` makes one. A picture inside an `overflow: hidden` frame therefore\n  never animates. Use `overflow: clip` on frames, or name the timeline on the section\n  (`view-timeline-name: --hero`) and point the children at that name. This also applies to the\n  existing \"Scroll-linked progress\" recipe.\n- **Scroll-linked means linear.** The scroll is the easing. 14 of the 18 scrubbing sites in the study\n  lock motion to the scrollbar, which is what CSS scroll timelines do.\n\nAll recipes keep content visible when JavaScript is off or slow: the hidden state only applies under\n`html.js`, which a one-line inline script sets.\n\n```html\n<script>document.documentElement.classList.add('js')</script>\n```\n\n### Load sequence in 1.2 seconds\n\nEverything is in the HTML and painted on the first frame; the sequence only adds arrival. Nothing\nwaits for the load event, and nothing in the navigation animates.\n\n```html\n<header class=\"hero\">\n  <h1 class=\"display lines\">\n    <span class=\"line\"><span data-line style=\"--i:0\">Stools for</span></span>\n    <span class=\"line\"><span data-line style=\"--i:1\">small kitchens</span></span>\n  </h1>\n  <p class=\"lead\" data-load style=\"--d:420ms\">…</p>\n  <a class=\"button\" data-load style=\"--d:480ms\" href=\"#stools\">See the stools</a>\n  <figure class=\"hero__picture\" data-open><img src=\"stool.jpg\" alt=\"…\" fetchpriority=\"high\"></figure>\n</header>\n```\n\n```css\n.hero__picture { overflow: clip; margin: 0; }\n@media (prefers-reduced-motion: no-preference) {\n  .js .hero [data-line] { transform: translateY(105%); animation: load-line 800ms var(--ease-expo) forwards; animation-delay: calc(100ms + var(--i) * var(--stagger-line)); }\n  .js .hero [data-load] { opacity: 0; transform: translateY(12px); animation: load-rise 500ms var(--ease-out) forwards; animation-delay: var(--d); }\n  .js .hero [data-open] { clip-path: inset(0 0 100% 0); animation: load-open 1000ms var(--ease-in-out) 150ms forwards; }\n  .js .hero [data-open] img { transform: scale(1.08); animation: load-settle 1100ms var(--ease-expo) 100ms forwards; }\n}\n@keyframes load-line { to { transform: none; } }\n@keyframes load-rise { to { opacity: 1; transform: none; } }\n@keyframes load-open { to { clip-path: inset(0); } }\n@keyframes load-settle { to { transform: none; } }\n```\n\nThe timeline: the headline's lines rise from 100 to 990 ms, the picture opens from 150 to 1,150 ms,\nthe sentence and the button arrive from 420 to 980 ms. All settled by 1.2 s, four things at most.\nPreload the display font (`<link rel=\"preload\" as=\"font\" type=\"font/woff2\" crossorigin>`) so the lines\nrise in the real face, and give the picture `fetchpriority=\"high\"` and a ground colour sampled from it,\nso a slow image opens onto its own colour rather than a blank box. Study: 22 of 91 pages were readable\nat the first intro frame and 11 more by 1.2 s; the intros the readers called respectful finished in\nabout 1-1.2 s; a third of the pages were still unreadable at 4.5 s.\n\n### Masked line reveal (the classic gallery headline)\n\nEach line slides up from behind its own baseline. Because headlines are capped at two lines, you set\nthe line breaks yourself and wrap each line.\n\n```html\n<h1 class=\"lines\">\n  <span class=\"line\"><span data-line style=\"--i:0\">Stools for</span></span>\n  <span class=\"line\"><span data-line style=\"--i:1\">small kitchens</span></span>\n</h1>\n```\n\n```css\n.lines .line { display: block; overflow: hidden; padding-bottom: 0.08em; margin-bottom: -0.08em; }\n.lines [data-line] { display: block; }\n@media (prefers-reduced-motion: no-preference) {\n  .js .lines [data-line] {\n    transform: translateY(105%);\n    animation: line-up 900ms var(--ease-out) forwards;\n    animation-delay: calc(var(--i) * 110ms + 150ms);\n  }\n}\n@keyframes line-up { to { transform: none; } }\n```\n\nThe `padding-bottom` / negative margin pair stops descenders (g, y, p) being clipped by the mask.\nOn a narrow phone the two authored lines may each wrap; check the mobile screenshot, and if they do,\nauthor a shorter mobile break with a `<br class=\"only-wide\">` pattern or reduce the size.\n\n### Reveal on scroll (once)\n\nFor the two or three sections that deserve it, not for every block.\n\n```css\n@media (prefers-reduced-motion: no-preference) {\n  .js [data-reveal] { opacity: 0; transform: translateY(24px); transition: opacity 700ms var(--ease-out), transform 900ms var(--ease-out); }\n  .js [data-reveal].is-in { opacity: 1; transform: none; }\n}\n```\n\n```js\nconst io = new IntersectionObserver((entries) => {\n  for (const e of entries) if (e.isIntersecting) { e.target.classList.add('is-in'); io.unobserve(e.target); }\n}, { rootMargin: '0px 0px -12% 0px', threshold: 0.1 });\ndocument.querySelectorAll('[data-reveal]').forEach((el) => io.observe(el));\n```\n\nNever attach reveals with a scroll listener, never replay them when the element re-enters, and never\nleave anything at `opacity: 0` if the observer fails to fire (the `html.js` gate handles no-JS; the\n`unobserve` handles replays).\n\n### Image shutter\n\nAn image opens from one edge while scaling down slightly inside its frame. Gallery staple; use it for\nthe one hero or showcase image.\n\n```css\n.shutter { overflow: hidden; }\n@media (prefers-reduced-motion: no-preference) {\n  .js .shutter { clip-path: inset(0 0 100% 0); transition: clip-path 1100ms var(--ease-in-out); }\n  .js .shutter img { transform: scale(1.12); transition: transform 1500ms var(--ease-soft); }\n  .js .shutter.is-in { clip-path: inset(0); }\n  .js .shutter.is-in img { transform: none; }\n}\n```\n\n### Press and hover\n\n```css\n.button { transition: transform var(--t-press) var(--ease-out), background-color var(--t-hover) ease, color var(--t-hover) ease; }\n.button:active { transform: scale(0.97); }\n.link { text-decoration: underline; text-decoration-color: transparent; text-underline-offset: 0.2em; text-decoration-thickness: 0.07em; transition: text-decoration-color var(--t-hover) ease; }\n@media (hover: hover) and (pointer: fine) {\n  .button:hover { background-color: var(--accent-strong); }\n  .link:hover { text-decoration-color: currentColor; }\n}\n```\n\nHover styles go behind `(hover: hover)` because touch devices fire hover on tap and leave it stuck.\nHover should raise contrast, never lower it. Do not change font weight on hover (the text reflows).\nDo not lift or scale every card on hover; one consistent, small response is enough.\n\n### Scroll-linked progress without JavaScript\n\nFor a wordmark that scales as the hero leaves, an image that drifts a few percent, or a progress bar.\nWrap in `@supports` so browsers without scroll timelines get the static state.\n\n```css\n@supports (animation-timeline: view()) {\n  @media (prefers-reduced-motion: no-preference) {\n    .drift { animation: drift linear both; animation-timeline: view(); animation-range: entry 0% exit 100%; }\n    @keyframes drift { from { transform: translateY(-4%); } to { transform: translateY(4%); } }\n  }\n}\n```\n\nKeep the travel small (under 8% of the element). Large parallax makes text hard to read and looks\ndated.\n\n### Pinned story\n\nA section whose heading stays put while items pass. Use `position: sticky`; do not hijack scrolling.\n\n```css\n.story { display: grid; grid-template-columns: 5fr 7fr; gap: var(--gutter); align-items: start; }\n.story__title { position: sticky; top: 18vh; }\n@media (max-width: 800px) { .story { grid-template-columns: 1fr; } .story__title { position: static; } }\n```\n\n### Index with preview, anchored to the row\n\nRows of names; pointing at a row or tabbing to it opens one frame level with that row. The frame\nfollows the row, never the pointer.\n\n```html\n<section class=\"index\">\n  <ul class=\"index__list\">\n    <li><a class=\"index__row\" href=\"/work/harbour-house\" data-preview=\"/img/harbour-house.jpg\">\n      <span class=\"index__name\">Harbour House</span><span class=\"index__year\">2025</span>\n      <img class=\"index__thumb\" src=\"/img/harbour-house-small.jpg\" alt=\"\" loading=\"lazy\" width=\"640\" height=\"400\">\n    </a></li>\n    <!-- … -->\n  </ul>\n  <div class=\"index__frame\" aria-hidden=\"true\"><img alt=\"\"></div>\n</section>\n```\n\n```css\n.index { position: relative; }\n.index__list { list-style: none; margin: 0; padding: 0; }\n.index__row { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: 0 var(--gutter); padding-block: 0.3em; font-size: var(--step-head); color: inherit; text-decoration: none; transition: opacity var(--t-hover) ease; }\n.index__thumb { order: -1; flex-basis: 100%; width: 100%; height: auto; margin-bottom: 0.4rem; }\n.index__frame { display: none; }\n@media (hover: hover) and (pointer: fine) {\n  .index__list { max-width: 62%; }\n  .index__thumb { display: none; }\n  .index__list:has(.index__row:hover, .index__row:focus-visible) .index__row:not(:hover, :focus-visible) { opacity: 0.4; }\n  .index__frame { display: block; position: absolute; top: 0; right: var(--margin); width: 30%; aspect-ratio: 4 / 3; z-index: 1; pointer-events: none; clip-path: inset(100% 0 0 0); transition: clip-path 320ms var(--ease-out), transform 360ms var(--ease-out); }\n  .index__frame.is-open { clip-path: inset(0); }\n  .index__frame img { width: 100%; height: 100%; object-fit: cover; }\n}\n@media (prefers-reduced-motion: reduce) { .index__frame { transition: none; } }\n```\n\n```js\n(() => {\n  const root = document.querySelector('.index');\n  if (!root) return;\n  const frame = root.querySelector('.index__frame');\n  const picture = frame.querySelector('img');\n  const fine = matchMedia('(hover: hover) and (pointer: fine)');\n  let warmed = false;\n  const show = (row) => {\n    if (!fine.matches) return;\n    if (!warmed) { warmed = true; root.querySelectorAll('[data-preview]').forEach((a) => { new Image().src = a.dataset.preview; }); }\n    picture.src = row.dataset.preview;\n    const y = row.offsetTop + row.offsetHeight / 2 - frame.offsetHeight / 2;\n    const max = root.offsetHeight - frame.offsetHeight;\n    const opening = !frame.classList.contains('is-open');\n    if (opening) frame.style.transitionProperty = 'clip-path';   // open in place, do not slide in from the top\n    frame.style.transform = `translateY(${Math.min(max, Math.max(0, y))}px)`;\n    if (opening) { frame.getBoundingClientRect(); frame.style.transitionProperty = ''; }\n    frame.classList.add('is-open');\n  };\n  const hide = () => frame.classList.remove('is-open');\n  root.querySelectorAll('.index__row').forEach((row) => {\n    row.addEventListener('pointerenter', () => show(row));\n    row.addEventListener('focus', () => show(row));\n  });\n  root.addEventListener('pointerleave', hide);\n  root.addEventListener('focusout', (e) => { if (!root.contains(e.relatedTarget)) hide(); });\n})();\n```\n\nOn touch screens each row shows its own picture above the name. Study: 5 pages navigate work this way;\nframes from about 470x270 to large plates behind the list; the other rows dimmed to about 0.3 (0.4 here, the floor for dimmed text). The\nimage trails and cursor-borne previews seen elsewhere in the study are the gimmick version.\n\n### Lines that rise on scroll\n\nFor a section heading or a statement whose line breaks you do not control. Splits after the fonts\nload, reveals once, then gives the plain text back so it rewraps normally. Plain text only (no links or\nemphasis inside).\n\n```html\n<h2 class=\"head\" data-lines>Turned by hand in one small workshop</h2>\n```\n\n```css\n[data-lines] .line { display: block; overflow: clip; padding-bottom: 0.12em; margin-bottom: -0.12em; }\n[data-lines] .line > span { display: block; }\n@media (prefers-reduced-motion: no-preference) {\n  .is-split .line > span { transform: translateY(110%); }\n  .is-split.is-in .line > span { transform: none; transition: transform 900ms var(--ease-expo) calc(var(--i) * var(--stagger-line)); }\n}\n```\n\n```js\n(() => {\n  const els = [...document.querySelectorAll('[data-lines]')];\n  if (!els.length || !('IntersectionObserver' in window) || matchMedia('(prefers-reduced-motion: reduce)').matches) return;\n  const restore = (el) => { el.textContent = el.dataset.text; el.classList.remove('is-split', 'is-in'); };\n  const split = (el) => {\n    const text = el.textContent.trim().replace(/\\s+/g, ' ');\n    el.dataset.text = text;\n    el.textContent = '';\n    const words = text.split(' ').map((word) => {\n      const s = document.createElement('span');\n      s.style.display = 'inline-block';\n      s.textContent = word;\n      el.append(s, ' ');\n      return s;\n    });\n    const lines = [];                                   // group the words by the line they landed on\n    for (const w of words) {\n      const last = lines.at(-1);\n      if (last && Math.abs(last.top - w.offsetTop) < 4) last.words.push(w.textContent);\n      else lines.push({ top: w.offsetTop, words: [w.textContent] });\n    }\n    el.textContent = '';\n    lines.forEach((line, i) => {\n      const mask = document.createElement('span');\n      const inner = document.createElement('span');\n      mask.className = 'line';\n      inner.style.setProperty('--i', i);\n      inner.textContent = line.words.join(' ');\n      mask.append(inner);\n      el.append(mask, ' ');\n    });\n    el.classList.add('is-split');\n  };\n  const io = new IntersectionObserver((entries) => {\n    for (const e of entries) {\n      if (!e.isIntersecting) continue;\n      io.unobserve(e.target);\n      e.target.classList.add('is-in');\n      e.target.querySelector('.line:last-of-type > span')\n        .addEventListener('transitionend', () => restore(e.target), { once: true });\n    }\n  }, { rootMargin: '0px 0px -12% 0px' });\n  document.fonts.ready.then(() => els.forEach((el) => { split(el); io.observe(el); }));\n  let width = innerWidth;                               // a width change before the reveal: give the text back\n  addEventListener('resize', () => {\n    if (innerWidth === width) return;\n    width = innerWidth;\n    els.filter((el) => el.matches('.is-split:not(.is-in)')).forEach((el) => { io.unobserve(el); restore(el); });\n  });\n})();\n```\n\nStudy: masked rises from 100-120% below the line, 0.6-1.2 s, 75-120 ms between lines, triggered when\nthe block's top is 80-95% down the viewport. Reduced motion: the script does not run; the text is plain.\n\n### Opening window\n\nThe hand-over from a type screen to the one big picture: the picture first shows as a window in the\nmiddle of a held stage and opens to full-bleed over about one screen of scroll.\n\n```html\n<section class=\"opening\">\n  <div class=\"opening__stage\">\n    <img src=\"workshop-wide.jpg\" alt=\"The workshop at first light, benches cleared\" width=\"2400\" height=\"1500\">\n  </div>\n</section>\n```\n\n```css\n.opening__stage { height: 100svh; overflow: clip; }\n.opening__stage img { display: block; width: 100%; height: 100%; object-fit: cover; }\n@supports (animation-timeline: view()) {\n  @media (prefers-reduced-motion: no-preference) {\n    .opening { height: 200svh; view-timeline-name: --opening; --inset-y: 20%; --inset-x: 28%; }\n    .opening__stage { position: sticky; top: 0; animation: opening-window linear both; animation-timeline: --opening; animation-range: contain 0% contain 75%; }\n    .opening__stage img { animation: opening-settle linear both; animation-timeline: --opening; animation-range: contain 0% contain 75%; }\n  }\n}\n@media (max-width: 700px) { .opening { --inset-y: 18%; --inset-x: 8%; } }\n@keyframes opening-window { from { clip-path: inset(var(--inset-y) var(--inset-x)); } to { clip-path: inset(0); } }\n@keyframes opening-settle { from { transform: scale(1.15); } to { transform: none; } }\n```\n\nThe section is two screens tall; the stage is held for one, and the window is fully open after three\nquarters of it, so the full-bleed picture rests for a moment before the page moves on. Study: 14 pages;\nstart windows 38-60% of the width; runways 600-1,800 px, and the readers asked for one to two screens.\nWithout scroll timelines, and under reduced motion, the picture is a full-bleed screen.\n\n### Held picture, passing captions\n\nThe pinned story built for photographs: the picture holds on one side while short captions pass on\nthe other; the caption at the middle of the screen is lit and its picture is shown.\n\n```html\n<section class=\"steps\">\n  <figure class=\"steps__media\">\n    <div class=\"steps__pictures\">\n      <img src=\"seasoning.jpg\" alt=\"Ash boards stacked to season\" class=\"is-on\">\n      <img src=\"turning.jpg\" alt=\"A leg being turned on the lathe\">\n      <img src=\"finish.jpg\" alt=\"Oil rubbed into a finished seat\">\n    </div>\n    <figcaption class=\"steps__count\" aria-hidden=\"true\"></figcaption>\n  </figure>\n  <ol class=\"steps__list\">\n    <li class=\"steps__item\"><h3>Seasoned for a year</h3><p>…</p></li>\n    <li class=\"steps__item\"><h3>Turned by hand</h3><p>…</p></li>\n    <li class=\"steps__item\"><h3>Finished with oil</h3><p>…</p></li>\n  </ol>\n</section>\n```\n\n```css\n.steps { display: grid; grid-template-columns: 7fr 5fr; column-gap: var(--gutter); }\n.steps__media { margin: 0; align-self: start; }           /* a stretched grid item cannot stick */\n.steps__pictures img { display: block; width: 100%; height: auto; }\n.steps__list { list-style: none; margin: 0; padding: 0; }\n.steps__item { min-height: 80svh; display: flex; flex-direction: column; justify-content: center; }\n.js .steps__media { position: sticky; top: 0; height: 100svh; display: flex; flex-direction: column; justify-content: center; gap: 0.75rem; }\n.js .steps__pictures { position: relative; aspect-ratio: 4 / 5; max-height: 80svh; }\n.js .steps__pictures img { position: absolute; inset: 0; height: 100%; object-fit: cover; opacity: 0; transition: opacity 500ms ease; }\n.js .steps__pictures img.is-on { opacity: 1; }\n.js .steps__item { opacity: 0.4; transition: opacity var(--t-ui) ease; }\n.js .steps__item.is-active { opacity: 1; }\n@media (max-width: 800px) {\n  .steps { display: block; }                               /* the section, not a grid area, contains the sticky picture */\n  .js .steps__media { height: auto; z-index: 1; background: var(--bg); padding-block: 0.5rem; }\n  .js .steps__pictures { aspect-ratio: 3 / 2; max-height: 42svh; }\n  .steps__item { min-height: 60svh; }\n}\n@media (prefers-reduced-motion: reduce) { .js .steps__pictures img, .js .steps__item { transition: none; } }\n```\n\n```js\n(() => {\n  const root = document.querySelector('.steps');\n  if (!root || !('IntersectionObserver' in window)) return;\n  const items = [...root.querySelectorAll('.steps__item')];\n  const pictures = [...root.querySelectorAll('.steps__pictures img')];\n  const count = root.querySelector('.steps__count');\n  const show = (i) => {\n    items.forEach((el, k) => el.classList.toggle('is-active', k === i));\n    pictures.forEach((el, k) => el.classList.toggle('is-on', k === i));\n    if (count) count.textContent = `${i + 1} of ${items.length}`;\n  };\n  const io = new IntersectionObserver((entries) => {\n    for (const e of entries) if (e.isIntersecting) show(items.indexOf(e.target));\n  }, { rootMargin: '-45% 0px -45% 0px' });                 // a band across the middle of the screen\n  items.forEach((el) => io.observe(el));\n  show(0);\n})();\n```\n\nWithout JavaScript the pictures and captions are two plain columns. Study: inactive items at 20-40%\n(dims of 10-15% read as missing text, so the floor here is 40%), crossfades of 400-600 ms, about one\nscreen per step; the readers asked for a visible count on any held sequence of more than two steps.\nThe count is a plain sentence in the body face, not a zero-padded numeral.\n\n### Sideways gallery\n\nA row of pictures that the vertical scroll moves sideways while the stage is held, for a short\ncollection (eight items or fewer). The native drag row is the base; the pinned version is added only\non wide screens with motion allowed, and only when the row is under three screens long.\n\n```html\n<section class=\"gallery\">\n  <div class=\"gallery__stage\">\n    <h2 class=\"head\">Eight kitchens, one stool</h2>\n    <ul class=\"gallery__track\">\n      <li class=\"gallery__item\"><a href=\"/kitchens/leith\"><img src=\"leith.jpg\" alt=\"A narrow galley kitchen in Leith\" width=\"1200\" height=\"1500\"><span>Leith</span></a></li>\n      <!-- … -->\n    </ul>\n  </div>\n</section>\n```\n\n```css\n.gallery__track { display: flex; gap: var(--gutter); list-style: none; margin: 0; padding: 0 var(--margin); overflow-x: auto; scroll-snap-type: x mandatory; scroll-padding-inline: var(--margin); }\n.gallery__item { flex: 0 0 min(72vw, 28rem); scroll-snap-align: start; }\n.gallery__item img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover; }\n.gallery.is-pinned .gallery__stage { position: sticky; top: 0; height: 100svh; display: flex; flex-direction: column; justify-content: center; gap: 2rem; overflow: clip; }\n.gallery.is-pinned .gallery__track { overflow: visible; scroll-snap-type: none; }\n.gallery.is-pinned .gallery__item { flex-basis: calc(62svh * 0.8); }\n```\n\n```js\n(() => {\n  const root = document.querySelector('.gallery');\n  if (!root) return;\n  const track = root.querySelector('.gallery__track');\n  const wide = matchMedia('(min-width: 900px) and (prefers-reduced-motion: no-preference)');\n  let dx = 0, queued = false;\n  const place = () => {\n    queued = false;\n    if (!root.classList.contains('is-pinned')) return;\n    const p = Math.min(1, Math.max(0, -root.getBoundingClientRect().top / dx));\n    track.style.transform = `translate3d(${(-p * dx).toFixed(1)}px, 0, 0)`;\n  };\n  const measure = () => {\n    root.classList.add('is-pinned');                     // measure the row as it would be when pinned\n    track.style.transform = '';\n    dx = track.scrollWidth - track.clientWidth;\n    const pin = wide.matches && dx > 0 && dx < innerHeight * 3;\n    root.classList.toggle('is-pinned', pin);\n    root.style.height = pin ? `${innerHeight + dx}px` : ''; // one pixel of scroll moves the row one pixel\n    place();\n  };\n  track.addEventListener('focusin', (e) => {             // keyboard: bring the focused item into view\n    if (!root.classList.contains('is-pinned')) return;\n    const item = e.target.closest('.gallery__item');\n    const x = Math.min(dx, Math.max(0, item.offsetLeft - parseFloat(getComputedStyle(track).paddingLeft)));\n    scrollTo({ top: root.getBoundingClientRect().top + scrollY + x, behavior: 'instant' });\n  });\n  addEventListener('scroll', () => { if (!queued) { queued = true; requestAnimationFrame(place); } }, { passive: true });\n  addEventListener('resize', measure);\n  addEventListener('load', measure);\n  wide.addEventListener('change', measure);\n  measure();\n})();\n```\n\nStudy: 8 pages pinned a horizontal track; their pages ran a median 25 screens, and the readers' worst\ncases spent 9 screens on three cards and 10,000-23,000 px of wheel on one track. Here the speed is 1:1\nand the hold ends when the last picture reaches the margin. Phones, narrow windows, reduced motion and\nlong rows all get the native row with snapping, which also works with touch, trackpads and the\nkeyboard. Never put the only copy of a call to action inside the moving row.\n\n### Receding hero\n\nAs the first screen leaves, its picture sinks a little and darkens while the words lift away a little\nfaster, so the hero recedes instead of simply scrolling off.\n\n```html\n<header class=\"hero\">\n  <img class=\"hero__picture\" src=\"kitchen.jpg\" alt=\"…\" width=\"2400\" height=\"1600\" fetchpriority=\"high\">\n  <div class=\"hero__copy\"><h1 class=\"display\">…</h1><p class=\"lead\">…</p></div>\n</header>\n```\n\n```css\n.hero { position: relative; min-height: 100svh; overflow: clip; display: grid; align-items: end; view-timeline-name: --hero; }\n.hero__picture { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }\n.hero::after { content: ''; position: absolute; inset: 0; background: var(--ink); opacity: 0; pointer-events: none; }\n.hero__copy { position: relative; z-index: 1; padding: var(--margin); }\n@supports (animation-timeline: view()) {\n  @media (prefers-reduced-motion: no-preference) {\n    .hero__picture { animation: hero-sink linear both; animation-timeline: --hero; animation-range: exit 0% exit 100%; }\n    .hero::after { animation: hero-dim linear both; animation-timeline: --hero; animation-range: exit 0% exit 100%; }\n    .hero__copy { animation: hero-lift linear both; animation-timeline: --hero; animation-range: exit 0% exit 70%; }\n  }\n}\n@keyframes hero-sink { to { transform: translateY(8%) scale(1.06); } }\n@keyframes hero-dim { to { opacity: 0.35; } }\n@keyframes hero-lift { to { transform: translateY(-6%); opacity: 0; } }\n```\n\nThe `exit` range runs from the moment the hero's top meets the top of the screen until its bottom\ndoes, which for a first screen is the first screen of scroll. Study: hero pictures that sink and dim as\nthey leave, a heading scrubbed from 140 to 60 px, a title card that scales down on the phone; the\nreaders called it quiet and the page \"one sheet\". Travel stays under 8%; the overlay is a flat ink at\nup to 35%, not a gradient. Static where unsupported or reduced.\n\n\n\n\n\n### Page to page\n\nNavigation between pages of the site with the browser's own view transitions: the old page fades\nquickly, the new one rises in, and the picture the visitor clicked travels into place as the new\npage's hero. No library, no full-screen curtain.\n\n```css\n/* on every page */\n@view-transition { navigation: auto; }\n@media (prefers-reduced-motion: reduce) { @view-transition { navigation: none; } }\n::view-transition-old(root) { animation: vt-leave 200ms var(--ease-exit) both; }\n::view-transition-new(root) { animation: vt-arrive 380ms var(--ease-out) 60ms both; }\n::view-transition-group(*) { animation-duration: 480ms; animation-timing-function: var(--ease-in-out); }\n::view-transition-image-pair(*.picture) { overflow: clip; }\n::view-transition-old(*.picture), ::view-transition-new(*.picture) { height: 100%; object-fit: cover; }\n@keyframes vt-leave { to { opacity: 0; } }\n@keyframes vt-arrive { from { opacity: 0; transform: translateY(16px); } }\n```\n\n```html\n<!-- on the index: the card picture of one project -->\n<img src=\"/img/leith.jpg\" alt=\"…\" style=\"view-transition-name: kitchen-leith; view-transition-class: picture\">\n<!-- on that project's page: its hero picture -->\n<img src=\"/img/leith-wide.jpg\" alt=\"…\" style=\"view-transition-name: kitchen-leith; view-transition-class: picture\">\n```\n\nEach name may appear once per page. Browsers without cross-document view transitions simply navigate.\nStudy: 16 pages load a page-transition library and run full-screen curtains of 0.7-2.4 s; 6 use view\ntransitions. The new page should be readable within half a second.\n\n### Ink fill\n\nOne statement that fills from part-ink to full ink as it rises through the screen, line by line. It is\nreadable before it fills; the fill only sets the pace.\n\n```html\n<p class=\"statement head\" data-fill>Nine people, one workshop, no catalogue: every stool is made for the kitchen it goes to.</p>\n```\n\n```css\n[data-fill] { --fill: var(--ink); color: var(--fill); }\n@supports (animation-timeline: view()) {\n  @media (prefers-reduced-motion: no-preference) {\n    .is-filling > span { display: inline-block; color: color-mix(in oklab, var(--fill) 45%, transparent); animation: ink-fill linear both; animation-timeline: view(); animation-range: cover 20% cover 45%; }\n  }\n}\n@keyframes ink-fill { to { color: var(--fill); } }\n```\n\n```js\n(() => {\n  if (!CSS.supports('animation-timeline: view()') || matchMedia('(prefers-reduced-motion: reduce)').matches) return;\n  document.querySelectorAll('[data-fill]').forEach((el) => {\n    const words = el.textContent.trim().split(/\\s+/);\n    el.textContent = '';\n    words.forEach((word, i) => {\n      const s = document.createElement('span');\n      s.textContent = word;\n      el.append(s, i < words.length - 1 ? ' ' : '');\n    });\n    el.classList.add('is-filling');\n  });\n})();\n```\n\nEach word watches its own position, so the words of a line fill together as the line moves from three\nquarters of the way down the screen to just past half way. Set `--fill` on a dark chapter to its ink.\nStudy: 14 pages scrub a statement from grey to ink; unread words started at about 25-30% and settled\nframes still caught statements half pale, which reads as disabled text. Here: one statement per page,\nthree to five lines, 32px or larger, starting at 45% (about 3:1 against the ground, enough for large\ntext). Full ink without scroll timelines or under reduced motion.\n\n### Rolling figures\n\nFor pages whose case is a handful of numbers: each digit rolls up to its value once, the columns a\nbeat apart. The real number stays in the text for screen readers and search.\n\n```html\n<p class=\"figure\"><span class=\"display\" data-roll>1987</span> the year the first stool was sold</p>\n```\n\n```css\n.roll__digits { display: inline-flex; font-variant-numeric: tabular-nums; line-height: 1; }\n.roll__col { display: inline-block; height: 1em; overflow: clip; }\n.roll__strip { display: flex; flex-direction: column; transform: translateY(calc(var(--d) * -1em)); }\n.roll__strip > span { height: 1em; }\n@media (prefers-reduced-motion: no-preference) {\n  .roll:not(.is-in) .roll__strip { transform: none; }\n  .roll.is-in .roll__strip { transition: transform 1100ms var(--ease-expo) calc(var(--i) * var(--stagger-item)); }\n}\n```\n\n```js\n(() => {\n  const els = [...document.querySelectorAll('[data-roll]')];\n  if (!els.length) return;\n  els.forEach((el) => {\n    const value = el.textContent.trim();\n    const said = Object.assign(document.createElement('span'), { className: 'sr-only', textContent: value });\n    const shown = Object.assign(document.createElement('span'), { className: 'roll__digits' });\n    shown.setAttribute('aria-hidden', 'true');\n    let i = 0;\n    for (const ch of value) {\n      if (!/\\d/.test(ch)) { shown.append(ch); continue; }\n      const col = Object.assign(document.createElement('span'), { className: 'roll__col' });\n      const strip = Object.assign(document.createElement('span'), { className: 'roll__strip' });\n      strip.style.setProperty('--d', ch);\n      strip.style.setProperty('--i', i++);\n      for (let n = 0; n < 10; n++) strip.append(Object.assign(document.createElement('span'), { textContent: n }));\n      col.append(strip);\n      shown.append(col);\n    }\n    el.classList.add('roll');\n    el.replaceChildren(said, shown);\n  });\n  if (!('IntersectionObserver' in window)) { els.forEach((el) => el.classList.add('is-in')); return; }\n  const io = new IntersectionObserver((entries) => {\n    for (const e of entries) if (e.isIntersecting) { e.target.classList.add('is-in'); io.unobserve(e.target); }\n  }, { rootMargin: '0px 0px -15% 0px' });\n  els.forEach((el) => io.observe(el));\n})();\n```\n\nStudy: 6 pages roll digit columns (stats, a year, coordinates), about 0.9-1.1 s per column on an\nexpo-out, staggered by column. Use it for three or four figures at display size, never in running text\nand never for a value that changes after load. Reduced motion: the figure is set at its value.\n\n### Accordion\n\n```css\n.acc__panel { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 320ms var(--ease-out); }\n.acc__panel > div { overflow: hidden; }\n.acc[open] .acc__panel, .acc__item.is-open .acc__panel { grid-template-rows: 1fr; }\n```\n\nAnimating `grid-template-rows` from `0fr` to `1fr` opens to the content's real height without measuring\nit in JavaScript.\n\n### Menu or dialog\n\n```css\n.menu { transform-origin: top right; transition: opacity var(--t-ui) var(--ease-out), transform var(--t-ui) var(--ease-out); }\n.menu[hidden], .menu.is-closed { opacity: 0; transform: scale(0.97) translateY(-6px); pointer-events: none; }\n```\n\nThings open from where they were triggered (`transform-origin` at the trigger). Nothing enters from\n`scale(0)`; start at 0.95–0.98. A centred dialog is the one case that scales from its centre.\n\n## 7. Signature moves\n\nThe direction sheet names one. Each of these was seen repeatedly on the studied gallery sites.\n\n| Move | What happens | Build with |\n| --- | --- | --- |\n| Masked headline | Lines rise from behind their baselines on load | Masked line reveal recipe |\n| Shutter image | Hero or showcase image opens from an edge, settling from 1.12 scale | Image shutter recipe |\n| Scaling wordmark | A giant wordmark shrinks or grows a few percent as the hero scrolls out | Scroll-linked recipe on `scale` |\n| Pinned story | A heading holds while its items scroll past | Sticky recipe |\n| Index with preview | Text rows; the hovered row shows its image | Index with preview, anchored to the row |\n| Curtain footer | The last section is revealed from under the page as you reach the end | `position: sticky; bottom: 0` footer under a main with a background and `z-index` |\n| Slow crossfade | Hero image crossfades through 3–4 photographs, 5–6s each | Stacked images, opacity keyframes, pause when the tab is hidden |\n| Edge-to-edge marquee | One line of very large type travels sideways, slowly | Duplicate the content, `translateX(-50%)` linear loop, pause on hover and under reduced motion |\n| Drag row | A horizontally scrollable row of large images with scroll snapping | `overflow-x: auto; scroll-snap-type: x mandatory`, no library |\n| Colour by chapter | Each chapter is its own full-bleed colour field, so the ground changes at section edges; a fixed header takes the ink of the chapter beneath | Section backgrounds in CSS; `base.js` sets `--header-ink` from `data-ink`. Never recolour the whole page from an observer |\n| Opening window | A type screen hands over to the big picture: a window in the middle of a held stage opens to full-bleed over about one screen | Opening window recipe |\n| Ink-fill statement | One statement fills from 45% to full ink as it rises through the screen | Ink fill recipe |\n| Sheet over a held picture | A full-bleed photograph holds for one screen; the next chapter slides up over it as an opaque sheet | A 100svh `position: sticky; top: 0` figure followed by a section with its own background and a higher `z-index`; no script |\n| Sideways gallery | A short row of pictures moves sideways while the vertical scroll holds the stage | Sideways gallery recipe |\n| Pushed line | One line of very large type is pushed sideways by the scroll, reading whole at the middle of its run | `animation-timeline: view()` on the line, `translateX` from 12% to -12%, linear; static where unsupported |\n| Rolling figures | The few figures that make the case roll up to their values once | Rolling figures recipe |\n| Carried picture | The picture clicked in a list travels into place as the next page's hero | Page to page recipe |\n\nPick by subject. A portfolio wants the index with preview; a restaurant wants the slow crossfade; a\nproduct wants the shutter on its hero object. If the move says nothing about the subject, it is\ndecoration and the page is better without it.\n\nPick by subject, as before: the opening window for a product or a place with one great photograph; the\nsheet for chapters that each own a picture; the sideways gallery for a short set of rooms, kitchens or\npieces; the pushed line for a brand whose claim is a word; rolling figures for a report, a fund or a\npractice that leads with numbers; the carried picture for a portfolio whose index and case pages are\nboth built.\n\n## 8. Reduced motion and performance\n\n- `prefers-reduced-motion: reduce` means fewer and gentler, not none: keep opacity and colour changes,\n  drop travel, scale, parallax and autoplay. All recipes above are written inside\n  `no-preference` blocks so the reduced state is simply the finished state.\n- Animate `transform`, `opacity` and `clip-path`. Animating `width`, `height`, `top`, `left`, `margin`\n  or `padding` forces layout on every frame. `grid-template-rows` for accordions is the accepted\n  exception because it is short and rare.\n- Do not drive many children from one changing CSS variable on a parent; set the transform on the\n  element that moves.\n- `will-change` only on an element that is about to animate, removed afterwards.\n- Pause loops when off screen or when the tab is hidden.\n- No scroll hijacking and no custom cursor. They cost usability, which is 30% of an Awwwards score and\n  the line most winners score lowest on. Smoothing only through `Stage.smooth()`, which stays off for\n  touch and reduced motion.\n\n## 9. What gives generated motion away\n\n- The same fade-up on every block.\n- A dozen staggered entrances in the hero.\n- Hover lift or zoom on every card and image.\n- Bounce or elastic easing on interface elements.\n- Infinite loops that mean nothing: pulsing dots, floating shapes, shimmering text, rotating badges.\n- A reveal that never fires and leaves a blank band in the page. Run `inspect.mjs` after the motion\n  pass and look at every screenshot for missing content.\n\n### Seen in the latest Sites of the Day\n\nSeen in the study, with how often, and what the house does instead.\n\n- **Preloaders and counters (60 of 99; 26 with a counter).** Half the usable pages were unreadable\n  2.5 s after load, a third at 4.5 s; the preloaders sat mostly on pages that had already loaded, and\n  25 of the 29 that loaded in under 3 s still showed nothing readable at 4.5 s. Counters stalled,\n  outlasted the load or were tweens with nothing behind them. House: no preloader. If a scene must\n  load, the HTML first screen (headline, picture, action) is there at once and the scene fades in\n  behind it when ready.\n- **Gates (10 of 99): enter, sound, age or gesture before any content.** House: none. Sound is a\n  control on the page, off by default.\n- **Scroll hijacking (16 wheel-driven scenes, 9 of them endless, plus 14 single screens where the wheel\n  does nothing).** The visitor cannot tell where they are, how much is left or how to get out, and the\n  keyboard and screen readers get nothing. Usability 6.01 against 6.50 for pages that scroll. House:\n  native scroll; any scene is \n\n<!-- [TRUNCATED AT 50KB] -->","skills/taste-skill/references/research.md":"# The study\n\nEverything numeric in this skill comes from here. Cite these figures; do not round them up or invent\nothers.\n\n## Contents\n\n1. Method and its limits\n2. Scores\n3. Where the idea comes from\n4. Headlines\n5. Type\n6. Devices: what separates strong from weak, and what does not\n7. Colour and shape\n8. Imagery and page structure\n9. What the inspector says about the gallery itself\n10. The 25 highest-scored sites and their ideas\n11. How the skill was tested\n12. The October 2026 study: 100 Sites of the Day\n13. The app-screen study\n\n## 1. Method and its limits\n\n- **Sample.** 248 sites collected on 5 October 2026: 156 from One Page Love (the latest gallery pages\n  and the category listings) and 92 Awwwards Sites of the Day (the three most recent listing pages).\n  247 loaded; 246 were re-measured with the final probe.\n- **Capture.** Headless Chrome at 1440×900 and 390×844. For each site: the first viewport, five more\n  frames while scrolling with real wheel input, the mobile first viewport, and a measurement pass in\n  the page (computed styles, text geometry, colours, fonts actually loaded).\n- **Panel.** 21 model reviewers each studied about 12 sites from the screenshots and the measurements,\n  described them (idea, hero, type, colour, imagery, layout, sections) and scored them the Awwwards\n  way: design 40%, usability 30%, creativity 20%, content 10%. These are model judgements from still\n  frames, not human jurors and not the real Awwwards scores. Batches mixed both sources so each\n  reviewer saw a spread.\n- **Usable sets.** 235 sites were usable for the panel (12 showed only a preloader, an entry gate or a\n  bot wall). 202 were measurable for typography (a page with at least 25 words and a detectable\n  headline). \"Top\" below means panel score 7.5 or higher (82 measurable sites); \"weak\" means under 6.5\n  (23 measurable sites).\n- **Limits.** One capture per site on one day. Some heroes were caught mid-animation or behind a cookie\n  notice. WebGL-heavy sites are under-described by text measurements. The eyebrow detector counts any\n  small short label directly above a large heading, so it over-counts against the panel's stricter\n  reading (60% measured against 35% observed). Motion was inferred from frames, not watched. The sample\n  is whatever the two galleries had recently featured; it is fashion as much as quality.\n\n## 2. Scores\n\n| | All 235 | One Page Love (151) | Awwwards (84) |\n| --- | --- | --- | --- |\n| Median overall | 7.2 | 7.1 | 7.5 |\n| Middle half | 6.8–7.6 | | |\n| 8.0 or higher | 25 sites (11%) | | |\n| 7.5 or higher | 90 sites (38%) | | |\n| Under 6.5 | 29 sites | | |\n\nMedian by criterion: design 8, usability 7, creativity 7, content 7. Among the top 25: design 9,\nusability 7, creativity 8, content 8. Usability is the one line that does not rise with the rest: the\nbest sites are no easier to use than the average one. Do not copy their gates, preloaders, tiny text\nor hidden navigation.\n\n## 3. Where the idea comes from\n\nThe clearest pattern in the panel's notes: high scores go with a concept taken from the subject, and\nlow scores go with its absence. The weakest entries' ideas were recorded in words like \"none beyond the\nstandard dark SaaS launch formula\", \"no visual idea beyond clarity\", \"no strong idea\". The strongest\nwere sentences only that subject could own (section 10).\n\nRecurring engines among the 7.3+ sites, each the basis of a direction in the library:\n\n- **The product demonstrates itself.** A colour picker's loupe reads the page's own background; a list\n  tool is sold with tiny working lists; a photo app's page is a wall of its own output.\n- **The page is an artefact from the subject's world.** A wedding site that is the invitation; an\n  archive as tabbed folders; a coupon with a cut line; a portfolio as a contact sheet.\n- **The name is the hero.** Wordmarks as wide as the screen, a photograph set inside the name like a\n  letter, a name split to opposite corners with the page between.\n- **One motif from the subject drives everything.** A tool's octagonal section as button, mask and\n  loader; two circles for two accounts; a café's stripes.\n- **Dressed as another category.** A money app as a streetwear drop; an industrial roaster as a design\n  object; a parcel service as a fairground.\n- **The place carries it.** One full-bleed view and a name along the bottom edge.\n- **A fixed stage.** A title or object stays put while content swaps beneath it.\n- **One section, one colour.** Flat fields as chapters.\n- **Radical understatement.** A 27px headline and tiny live demonstrations, carried through completely.\n\nHero types, by the panel's classification (top sites against weak sites): full-bleed media with type\nover it 16% / 10%; giant wordmark 14% / 0%; typographic poster 13% / 7%; text beside media 10% / 3%;\n**centred statement with media below 7% / 24%**. The centred headline over a screenshot is the weak\nsites' signature layout.\n\n## 4. Headlines\n\n| Hero headline | All | Top | Weak |\n| --- | --- | --- | --- |\n| Words, median | 5 | 5 | 5 |\n| Words, middle half | 3–9 | 2–8 | 3–8 |\n| Characters, median | 32 | | |\n| One line at 1440 | 47% | | |\n| Two lines or fewer at 1440 | 70% | 71% | 83% |\n| Two lines or fewer at 390 | 57% | | |\n| Three lines or fewer at 390 | 82% | | |\n\nAwwwards heroes are shorter (median 4 words, 76% within two lines) than One Page Love's (6 words, 66%).\nSection headings have a median of 3 words. Length does not separate strong from weak; nearly everyone\nin the gallery writes short headlines. The two-line limit in this skill is a house rule that most of\nthe gallery already meets on desktop and that takes care to meet on a phone.\n\n## 5. Type\n\n| | All | Top | Weak |\n| --- | --- | --- | --- |\n| Hero size, median | 72px (5.0vw) | 6.0vw | 4.7vw |\n| Hero size, middle half | 3.0–7.6vw | 2.5–9.7vw | 2.7–6.1vw |\n| Largest text on the page, median | 6.4vw | 8.4vw | 5.0vw |\n| Largest text, upper quarter starts at | 10.4vw | 12.5vw | 6.7vw |\n| Hero on a phone, median | 40px | | |\n| Hero tracking, median (middle half) | -0.01em (-0.03 to 0) | | |\n| Hero leading, median (middle half) | 1.0 (0.95–1.1) | | |\n| Body size, median (middle half) | 16px (14–18) | | |\n| Headline ÷ body, median | 4.3 | 4.7 | 4.0 |\n| Typefaces carrying 3%+ of text | one 31%, two 45%, three 22% | | |\n| Distinct font sizes, median | 8 | | |\n\nHero weight: regular 48%, medium 18%, semibold 6%, bold or heavier 22%, light 6%. Capitals 24%.\nCentred 39% overall, 52% on weak sites. Display classes by the panel: neo-grotesk 48%, transitional\nserif 11%, geometric sans 10%, condensed 6%, extended 6%, old-style serif 4%, custom lettering 4%.\n\nStrong sites push the extremes: their biggest type is bigger and their range is wider. Weak sites\ncluster in the middle.\n\n## 6. Devices: what separates strong from weak, and what does not\n\nMeasured in the page unless marked (panel).\n\n**More common on weak sites (the data supports avoiding them):**\n\n| Device | Top | Weak |\n| --- | --- | --- |\n| Icon-topped feature cards (panel) | 1% | 28% |\n| Rows of identical cards with a small icon (measured) | 7% | 26% |\n| Pill badges (panel) | 14% | 34% |\n| Pill-shaped label above a heading (measured) | 5% | 26% |\n| Tiny uppercase letter-spaced labels, any | 16% | 57% |\n| Tiny uppercase letter-spaced labels, three or more | 6% | 43% |\n| Gradient fills (not counting scrims) | 22% | 52% |\n| Gradient text | 2% | 13% |\n| Shadows on resting elements, any | 24% | 48% |\n| Shadows, five or more | 10% | 30% |\n| Emoji in the page | 10% | 26% |\n| Eyebrow labels (panel) | 32% | 45% |\n\n**No real difference:**\n\n| Device | Top | Weak |\n| --- | --- | --- |\n| Backdrop blur anywhere | 32% | 39% |\n| Italic-serif accent word (panel) | 4% | 7% |\n| Thin rules, any | 61% | 52% |\n\n**More common on strong sites (banned here anyway, as house style):**\n\n| Device | Top | Weak |\n| --- | --- | --- |\n| Monospace labels (panel) | 44% | 24% |\n| Monospace anywhere outside code (measured) | 45% | 26% |\n| Index numbering (panel) | 38% | 21% |\n\nMonospace captions, index numbers and ruled grids are the present fashion of award sites. They are\nexcluded from this skill by the owner's choice, not by the data: they are the devices generators copy\nfirst, and a page that cannot lean on them has to find structure in space, tone and scale.\n\n## 7. Colour and shape\n\n- Dark page ground 41%; pure white 25%; pure black 12%; a warm off-white 13%.\n- Scheme (panel): monochrome plus one accent 23%, light neutral 22%, dark neutral 14%, several flat\n  colours 13%, two-tone 12%, photographic 9%, one colour field 6%.\n- Primary buttons are neutral (black, white, grey) on 52% of sites. One site in 246 has a terracotta\n  button; none has a violet one.\n- Median number of distinct section grounds: 2 on top sites, 1 on weak sites.\n- Button shape: top sites square (0–2px) 52%, fully round 23%, small radius 19%, medium (9–16px) 6%.\n  Weak sites fully round 59%, medium 24%, square 18%.\n- Media corners are square on 73% of sites; where rounded, the median radius is 12px.\n- Buttons in the first viewport: none on 55% of top sites and 39% of weak ones.\n\n## 8. Imagery and page structure\n\n- Hero media covers at least half the first viewport on 60% of sites (top 68%, weak 48%) and nearly\n  all of it on 50% (top 56%, weak 39%). No hero media: 15%.\n- Video is present on 49% of sites and a canvas element on 49% (top 62%, weak 35%).\n- Images per page, median: 24 overall, 37 on top sites, 5 on weak ones.\n- Imagery kind (panel): mixed 32%, photography 14%, generative or WebGL 13%, product interface 12%,\n  3D render 11%, illustration 9%, video 6%, type only 3%. Median panel score is lowest for\n  illustration-led (6.9) and product-interface-led (7.1) pages and highest for video and type-only\n  (7.5).\n- Page length, median: 8.7 screens and 575 words (middle half 1.6–14.4 screens, 250–956 words). A\n  quarter of the sites are a single screen or two.\n- Navigation: a median of 3 links; fixed or sticky on 66%.\n- Density (panel): airy 46%, balanced 45%, dense 9%. Alignment: centred 33%, mixed 31%, left-anchored\n  17%, modular grid 13%, free 6%.\n- Asked to describe each site's most interesting sections, the panel picked a pricing, testimonial or\n  FAQ section only 7, 12 and 9 times across 235 sites. Where strong sites have them at all, they are\n  not where the design effort goes, and they avoid the stock form.\n\n**From the panel's written notes on the 114 sites scoring 7.3 or more** (hand tallies, approximate;\n`layout.md` turns these into practice):\n\n- Outer margins of 32px or less on about 45; 80px or more on about 8. A centred 700–1300px container\n  on about 15, several of them the pages the panel called stock.\n- Text anchored to a fixed off-centre line on about 22. Text docked in corners or at opposite ends of\n  a baseline on about 25 and 15.\n- Two or three type sizes with nothing between on about 30; no note describes a graded five-step\n  scale.\n- One thing per screen on about 20. A full background colour per section on about 20; alternating\n  light and dark on about 12.\n- Every section recomposed on about 14; one planned exception to the page's own system on about 14.\n- No conventional top navigation bar on about 45; small corner links on about 22; a single link or\n  button on about 10.\n- Endings: the name at full width about 18, the hero repeated inverted about 12, a closing scene of\n  its own about 14, no footer or a single line about 22. Link-column footers are mentioned only as\n  criticism.\n- Motion (inferred from frames): autoplaying video about 50; pinned or fixed stages about 40; text\n  reveals about 30 (blur-in 10, masked line rises 8, scroll-tied word colouring 7); horizontal strips\n  about 27; marquees about 26; media swapped behind a fixed element about 15; scroll-linked scaling\n  about 12. Rare: hover effects (4 mentions), parallax (6), accordions (5), bounce or spring motion\n  (none). About 10 strong sites show little or no motion at all.\n- How weak sites fail (54 sites under 6.8): the category's stock template about 20; centred headline,\n  pill badge, two buttons and a screenshot about 9; stock modules after a distinctive hero about 8,\n  plus about 17 in the middle band; a characterless default typeface about 13; text too small or too\n  faint about 13; never saying what the thing is about 12.\n- Faults of the best sites (90 at 7.5 or more), not to be copied: text at 9–13px about 24;\n  information hidden behind the concept about 20; the idea running out mid-page about 15; text over\n  footage with no scrim about 12; gates, preloaders and blank first paints about 12.\n\n## 9. What the inspector says about the gallery itself\n\nRunning this skill's own `inspect.mjs` rules over the 202 measurable gallery sites: the median site\nhas 4 `FAIL`s and only 4% have none. The rules that fire most: headline over two lines somewhere on\nthe page 60%, eyebrow-like label 60%, thin rules 50%, monospace 37%, shadows 32%, gradients 29%, index\nnumbering 29%.\n\nSo the house style is deliberately stricter than the gallery. It is not a description of award sites;\nit is a narrower target inside what they do: their scale, their ideas, their imagery and restraint,\nwithout the ornaments that have since become a uniform.\n\n## 10. The 25 highest-scored sites and their ideas\n\nThe panel's one-sentence reading of each. Notice that every one names something only that subject\ncould own. (Several use devices this skill bans; take the idea, not the ornament.)\n\n| Site | Source | Score | Idea |\n| --- | --- | --- | --- |\n| PP Neue Montreal | Awwwards | 8.6 | A typeface specimen dressed as a vintage city travel guide: the font named after Montreal is sold through guidebook titling, postcards and old tourist footage. |\n| Seasats | Awwwards | 8.4 | Calm, dusk-lit seascapes sell autonomous boats as serene instruments, and the navigation is a column of stacked colour swatches taken from that sea-and-sand palette. |\n| AI in Design Report 2026 | Awwwards | 8.4 | A research report laid out like a colour-blocked print annual: a video collage on top, an oversized tight grotesk title, and flat orange, lilac, sage and black blocks carrying stats, quotes and chapters. |\n| House of Honey | Awwwards | 8.4 | A block-heavy wordmark pierced by a fine script: the bold-against-delicate contrast is repeated at every scale, with giant pink script behind quiet serif statements. |\n| White Desert | Awwwards | 8.4 | One word, the destination, set a third of the screen tall over footage like a film title card; sheer scale stands in for remoteness. |\n| Applied Imagination | One Page Love | 8.3 | An essay conceived on a flight is read as a descent: an altimeter ticks from 30,000 ft to zero while you scroll down through clouds to mountains at ground level. |\n| Cursor Compile | One Page Love | 8.3 | The event name drawn as seven looping one-line curves in seven colours, more signature than logotype, on an otherwise whisper-quiet off-white page. |\n| The New Industrials | One Page Love | 8.3 | A long-read essay laid out inside a drafting grid, where colour fields shift as you read and machine parts drift through the margins and finally assemble into the publisher's initials. |\n| Wild | One Page Love | 8.3 | A studio essay in which everything decorative is drawn on one square-pixel grid: the hero heatmap, the icons, the diagrams, the lettering and the footer. |\n| Hildén & Kaira | Awwwards | 8.3 | The agency name is cast in liquid chrome across the full width, and the same chrome becomes the objects that float through the page, tying the pitch to one material. |\n| PX Push | Awwwards | 8.2 | A design subscription presented as a retro broadcast: the entire site is seen through a CRT screen, with a chrome logo token as its mascot. |\n| Illoca | Awwwards | 8.2 | Software for architects sold as a drafting table: a two-colour illustrated studio on graph paper that the scroll pushes into until the drawing fills the screen. |\n| Aspen Search | Awwwards | 8.2 | The page is a tile system with no margins: the two-word name is split across cells that alternate type, dithered image, black and one mint green. |\n| Dragonfly Redux | Awwwards | 8.2 | A crypto fund presented as a terminal artefact: every picture is rendered in characters, framed by four letters of the name pinned to the viewport corners. |\n| Monolog | Awwwards | 8.2 | A studio pitch run as an asymmetric sheet: a narrow left column carries the sales talk while a wide right column stacks a very heavy headline and the proof. |\n| The Queue | One Page Love | 8.1 | An essay on queueing where the queue is the ornament: a line of drawn figures stands along the bottom of the hero and returns between chapters in changing period dress. |\n| Paul Kalkbrenner | Awwwards | 8.1 | Swiss poster typography for a techno artist: the name as one black line with a photo set inside it like a glyph, then every chapter gets its own flat colour. |\n| Vero New York | Awwwards | 8.1 | A keepsake treated like couture: a slow close-up film opens, then a white sculpture of a dress stays pinned at centre while one sentence passes over it. |\n| Depo Luxe | Awwwards | 8.1 | A film production roster shown as a full-screen reel in which every step is one film with only a title, a director and a client, set like credits at body size. |\n| Longbow | Awwwards | 8.1 | The page is built on a visible four-column construction grid, and cars, cards and a giant condensed marquee are slotted into its cells like objects on an artboard. |\n| Mosby's Files | Awwwards | 8.0 | An archive of architects presented as a physical stack of coloured index-tab file folders that you flip through. |\n| Sarah & Matt Wedding | One Page Love | 8.0 | The site is the invitation: a letterpress-style card opens the page, and its ornaments and small typographic parts become the components for everything after it. |\n| Zara Webb | One Page Love | 8.0 | A one-woman newborn-care practice presented like a hand-made keepsake: a mascot rabbit, scalloped and flower-shaped cut-outs, candid film photographs. |\n| Noho | Awwwards | 8.0 | Furniture sold through people misusing it (wearing, balancing on, hiding behind chairs on flat colour backdrops) while the interface stays quiet. |\n| Juggle | One Page Love | 8.0 | The headline literally drowns: a flat blue field rises to half height and the lines below the waterline change colour. |\n\nFull notes on any studied site: `node scripts/draw.mjs --site <id>` (ids appear on direction sheets).\n\n## 11. How the skill was tested\n\nSix client briefs (an invoicing tool, a restaurant, a designer's portfolio, a ceramic product, a\nguesthouse, a design conference), each with no photographs. For every brief a fresh agent built the\npage three ways: with no skill (baseline), with another published design skill (atelier, three briefs)\nand with this skill. Every build was photographed by `inspect.mjs` in the same way and judged blind\nby a separate agent with the juror brief (Awwwards weights, anonymous A/B/C folders, screenshots\nonly). The skill was revised after each round from the jurors' reasons and the builders' notes.\n\n| Round | Briefs | This skill | Baseline | Atelier | Wins |\n| --- | --- | --- | --- | --- | --- |\n| 1 | 4 | 6.6 | 7.7 | 6.8 | 1 of 4 |\n| 2 | 3 | 7.1 | 8.0 | | 0 of 3 |\n| 3 | 3 | 7.5 | 7.5 | | 1 of 3 |\n| 4 (unseen briefs) | 3 | 6.9 | 7.9 | 7.5 | 0 of 3 |\n| 5 (same three) | 3 | 7.7 | 7.8 | 7.2 | 2 of 3 |\n\nUnder the inspector, the final builds measured 0 FAIL each; the baselines measured 8 to 13 FAIL each\n(eyebrows, monospace labels, 01/02/03 numbering, hairlines, gradients, shadows, three-line headlines,\ntext under 13px).\n\nWhat the jurors rewarded, in the order they named it: an idea that belongs to this client and not to\nthe category (the competitor test); one live thing on the page; full content at a readable size; a\nfirst screen with one dominant element and a real button; drawings of the subject with detail. What\nthey punished: a quiet page that read as empty, a small headline, text sliding over pictures or cut\nat the top, a page recoloured mid-section, rows cut at the right edge, a large sentence over three or\nmore lines (read as a long headline whatever its markup), navigation that took over the first screen.\nEach of these is now a rule in SKILL.md or a check in the inspector.\n\nLimits: one juror per brief per round, so single scores carry about half a point of noise; the round-5\nbriefs had been seen in round 4; jurors are models, not people.\n\n## 12. The October 2026 study: 100 Sites of the Day\n\nA second study, made for v2.1, of the latest 100 Awwwards Sites of the Day (10 July to 17 October\n2026), with a different aim from the first: where the pictures and footage sit, how pages move, and\nthe frame (margins, balance, empty space, titles). About three in four of these sites were also in\nthe first study.\n\n- **Capture.** Headless Chrome at 1440×900 and 390×844 on 18 October 2026: four frames of the first\n  4.5 seconds after load, every screen while scrolling with real wheel input (one frame at rest per\n  step; the mid-step frames were cut from the top of the document instead of the viewport, so they\n  were not used), five phone screens, and a measurement pass in the page: every picture and\n  clip with its box, ratio, fit and corners; every section's content edges and pictures; blank runs;\n  the CSS that loaded (curves, durations, keyframes, breakpoints, feature counts); the animations,\n  transitions and script-driven moves that actually ran; GSAP tweens and scroll triggers where the\n  page exposed them. Nothing a site owns (code, copy, pictures) is reproduced in the skill; only\n  measurements and descriptions in our own words.\n- **Panel.** One model reader per site studied its frames and measurements, described the idea, the\n  first screen, the frame, every section, where each picture sits, the motion and what not to copy,\n  and scored it the Awwwards way. 91 of 99 captures were usable (the rest showed a gate, a bot wall or\n  a firewall page). Scores ran 6.7 to 7.9 (median 7.45); \"top\" means 7.5 or more (36 sites), \"lowest\"\n  under 7.3 (16).\n- **What it changed.** Where pictures and footage go: `imagery.md` §12. What strong pages do with\n  motion, new tokens, recipes and the gimmicks to avoid: `motion.md` §2, §4–6 and §9–10. Empty space\n  and the frame: `layout.md` §4–5. New compositions in `library/heroes.json` and `sections.json` and\n  notes on media and motion in `library/sites.json` (`draw.mjs --site <id>`).\n- **Headline numbers.** Pictures fill a median 16% of a scrolled screen, but in whole screens: 42% of\n  screens hold none and 19% are 90% picture or more. The median page carries 7 pictures (top 8,\n  lowest 2) and 42% carry footage (half of the top sites, one of the 16 lowest). 94% of pictures have\n  square corners. Strong ease-outs are the curves that ran (expo and quint out); the median of all\n  that ran on a site is 420ms. 60 of 99 open on a loading screen, and a third of the usable pages were\n  still unreadable 4.5 seconds after load, with no gain in the design marks. About 1 text section in\n  100 leaves half the width empty; the outer margins of strong pages match to a few pixels; 82% of\n  text sections open with a heading; 15 of 97 first screens never say what the thing is, and those\n  lose usability points.\n- **Limits.** One capture per site on one day; a WebGL scene can render blank in a headless browser;\n  the scroll-linked frames are partly an artefact of smooth-scroll libraries; one reader per site, so\n  single scores carry about half a point of noise.\n\n## 13. The app-screen study\n\nFor dashboards and app screens (v2.1), a separate study of 23 real product screens chosen by the\nowner (17 products, 17 light and 6 dark, at 1440–1512px): each screen measured from its pixels by a\nreader with full-resolution crops, six cross-cutting reports (shell, data and charts, tables and\nforms, visual language, taste, styles), and a synthesis into `references/app-screens.md` and\n`library/app.json` (seven styles, five shells, screen patterns). The screenshots stay private; the\nskill carries only the measurements and the rules. Blind test rounds of app screens built with and\nwithout the skill then shaped the warnings at the top of that file.\n","skills/taste-skill/references/scenes.md":"# Scroll scenes\n\nThe big moments of a page: stretches of scroll where the page stops being a column of sections and\nbecomes a scene. A camera flies through a field of pictures, a picture grows from a window to the whole\nscreen, a word buckles under the scroll, a set of photographs orbits and lands in a grid. These are what\nvisitors remember from award sites, and what a page built from tidy sections alone never has.\n\nThe scene library is taken apart from recent Awwwards Sites of the Day (October 2026: 43 sites recorded\nframe by frame while scrolling, 261 scenes described, 30 types), rebuilt from scratch in our own code,\ntested frame by frame at desktop and phone width and under reduced motion, and reviewed against the\nscenes it came from. Nothing a site owns is in them. Until `library/scenes.json` ships the draw deals\nnone; a page that needs a scene builds one on the stage (section 8), with every rule here.\n\n## Contents\n\n1. What a scene is\n2. Putting a scene on a page\n3. Filling it\n4. Fitting it to the page\n5. The phone, reduced motion, no script\n6. Checking it\n7. Rules for scenes\n8. When no scene in the library fits\n9. The catalogue\n\n## 1. What a scene is\n\nA tall section whose stage holds still while the page scrolls past it. The stage is\n`position: sticky`; the section is (hold + 1) screens tall, so the stage is held for `hold` screens;\na GSAP timeline is scrubbed from 0 to 1 by that scroll. Nothing captures the wheel: the scrollbar always\ntells the truth, the keyboard and the trackpad work as everywhere else, and the scene ends.\n\nWhat a scene is not: a fade-up, a small parallax, a sticky footer, a marquee. Those are the quiet layer\n(`references/motion.md`). A scene changes the whole screen.\n\nThe direction sheet deals two or three (section 9 of the sheet), from different families, each placed\non the section of the argument it can carry. Build them in step 6, with that section: a scene is\ncomposition, not decoration added at the end.\n\n## 2. Putting a scene on a page\n\nCopy the shared stage and the dealt scene's files into the project (`assets/scenes/stage.css`,\n`stage.js`, `<id>.css`, `<id>.js`). Each scene file's header comment lists the markup it expects and\nits options; `assets/scenes/demo/<id>.html` is a complete working page to read beside it.\n\n```html\n<head>\n  <script>document.documentElement.classList.add('js')</script>\n  <link rel=\"stylesheet\" href=\"scenes/stage.css\">\n  <link rel=\"stylesheet\" href=\"scenes/<id>.css\">\n</head>\n<body>\n  …\n  <section class=\"scene\" data-scene=\"<id>\" data-options='{\"hold\": 3}' aria-label=\"…\">\n    <div class=\"scene-stage\">\n      <!-- the markup from the scene file's header, filled with this page's content -->\n    </div>\n  </section>\n  …\n  <script src=\"https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js\"></script>\n  <script src=\"https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/ScrollTrigger.min.js\"></script>\n  <script src=\"https://cdn.jsdelivr.net/npm/lenis@1.3.26/dist/lenis.min.js\"></script>\n  <script src=\"scenes/stage.js\"></script>\n  <script src=\"scenes/<id>.js\"></script>\n  <script>Stage.smooth(); Stage.init();</script>\n</body>\n```\n\n- Load SplitText (`gsap@3.15.0/dist/SplitText.min.js`) only when a scene file says it needs it.\n- `Stage.smooth()` adds weighted wheel scrolling (Lenis at lerp 0.12). It stays off for touch and for\n  reduced motion. Leave it out on a quiet page; the scenes work either way.\n- `Stage.init()` starts every `[data-scene]` on the page. A page with two scenes loads both files.\n- The versions are pinned. Do not change them to `@latest` or an unpinned major.\n\n## 3. Filling it\n\nA scene is only as strong as what goes in it. The scene file's header and the sheet's \"Content\" line\nsay how many pictures and words it takes; these hold for all of them:\n\n- **Pictures of one family.** Same light, same grade, same kind of subject: a field of mismatched stock\n  photographs breaks the illusion of one space faster than any timing error. Real pictures of the\n  subject's world (`assets.mjs`), the project's own, or the dealt photographs, in that order\n  (`references/imagery.md`). Size each to its largest display size, set `width` and `height`.\n- **Words that read in a breath.** A held statement is 4 to 12 words; captions are one to four words in\n  the text face, sentence case. One statement on screen at a time.\n- **The scene says something about the subject.** A fly-through of the studio's work, the route a\n  shipment really takes, the four rooms of the house, the product's change of state. A scene filled\n  with unrelated pictures is a gimmick and reads as one.\n- **Real content only.** If the scene needs eight pictures of the subject and there are three, take the\n  `--redraw scenes`, never pad it with stand-ins.\n\n## 4. Fitting it to the page\n\n- The scene files read the page's tokens: `--ground`, `--ink`, `--muted`, `--accent`,\n  `--font-display`, `--font-text` (with fallbacks). Set them on `:root` from the sheet and the scene\n  takes the page's colour and type. Check the demo against your page, not the other way round.\n- Display type in a scene uses the dealt display face and the two-line headline rule; statements stay\n  at statement size.\n- Leave a quiet section between two scenes (a text section, a list, a plain picture) so each one lands.\n  Two scenes back to back read as one long ride and the second loses.\n- A scene on the first screen must be readable at progress 0: the title, the sentence and the action are\n  there on the first frame (motion rule 1), and the scene starts moving only when the visitor scrolls.\n- Give the section a heading. If the design has no visible heading in the scene, the section still\n  carries one (`aria-label` on the section and a real heading in the finished composition).\n\n## 5. The phone, reduced motion, no script\n\n- **The phone.** Each scene has a phone plan in its file: the same scene with changed numbers, a\n  simpler version, or `phone: 'rest'`, where the phone shows the finished composition. Touch scrolling\n  is never smoothed. Look at the phone sheet as carefully as the desktop one.\n- **Reduced motion and no script.** The section is an ordinary section showing the finished\n  composition: the same content, laid out to read without motion. Nothing is hidden waiting for a\n  script. The inspector's `reduced-hidden` check and the reduced sheet of `scenes.mjs` show it.\n- **A failed CDN** falls back to the finished composition too (the stage adds `.is-rest`). The\n  inspector fails a scene that rests on desktop (`scene-not-live`), so a broken script cannot pass.\n\n## 6. Checking it\n\n```bash\nnode <skill>/scripts/scenes.mjs <page>        # every scene at 0, 10 … 100%, desktop and phone, and reduced motion\nnode <skill>/scripts/inspect.mjs <page>       # the gate; with scenes on the sheet it also films the scroll\n```\n\n`scenes.mjs` writes one contact sheet per scene and width to `.taste-skill/scenes/`. Read every one.\nAt every frame ask: is there one clear thing to look at; can the statement on screen be read; is\nanything popping, blank, cut off or crossing the words; is it as bold as it should be? The inspector's\n`desktop-film-NN.jpg` shows the whole page's scroll a third of a screen at a time: check that the\nscenes and the quiet sections between them make a rhythm, and that nothing between them is empty.\n\n## 7. Rules for scenes\n\n1. **Two or three per page,** from different families, a quiet section between them. The inspector\n   warns over four (`many-scenes`) and when scenes hold more than 60% of the page (`scene-heavy`).\n2. **Each holds one to four screens:** about one screen per beat of the story; a hold with nothing new\n   to show is cut, not padded.\n3. **Native scroll only.** No wheel capture, no locking the page, no scenes that only run on a click.\n   Smoothing only through `Stage.smooth()`.\n4. **Readable at its rest points.** The statement on screen reads whole; nothing passes over text while\n   it is being read; text on a picture has a flat scrim or a calm area under it.\n5. **Inside a scene the scene's numbers apply** (motion rule 7): a picture may grow from a window to the\n   whole screen, type may cross the stage, a camera may fly through pictures. Outside scenes, the quiet\n   limits of `references/motion.md` hold.\n6. **Transform, opacity, clip-path.** Nothing that forces layout on every frame. Pictures decoded before\n   they move.\n7. **The house rules hold inside scenes:** no monospace captions, no 01/07 counters (a plain \"3 of 7\" if\n   a count is needed), no gradients (flat scrims), no shadows or glows, no hairline decoration, no\n   decorative particles, no violet.\n8. **The finished composition is designed,** not an afterthought: it is what reduced motion, a failed\n   script and some phones see.\n\n## 8. When no scene in the library fits\n\nRedraw first (`--redraw scenes`). If the brief really needs a scene the library does not have, build it\non the same stage so it inherits the guards:\n\n```js\nScenes['my-scene'] = (root, opts = {}) => Stage.scene(root, {\n  hold: opts.hold ?? 2,          // screens the stage is held for\n  scrub: opts.scrub ?? true,     // true when Lenis runs; 0.4-0.8 without it reads as weight\n  phone: 'same',                 // or 'rest', or { hold, build } for a phone plan\n  build(tl, { q, phone }) {      // positions are fractions of the scene, 0-1\n    tl.fromTo(q('.picture'), { clipPath: 'inset(30% 30% 30% 30%)' }, { clipPath: 'inset(0% 0% 0% 0%)', duration: 0.6 }, 0)\n      .to(q('.title'), { yPercent: -40, autoAlpha: 0, duration: 0.25 }, 0.7);\n  },\n});\n```\n\nand write its CSS finished composition first, then the live layout under `.scene.is-live`. Check it\nwith `scenes.mjs` like any other.\n\n## 9. The catalogue\n\n(Generated from `library/scenes.json`; the draw deals from it. `node <skill>/scripts/draw.mjs --list\nscenes` prints it.)\n","skills/taste-skill/references/tells.md":"# Tells — the dated registry\n\nA tell is a device that makes a page read as generated. Tells are not bad design in themselves; most\nbegan as good ideas on good sites. They became tells by being produced by default, everywhere, without\na reason. That is why this registry is dated, and why it never names a replacement font, colour or\ncomponent: every published \"use this instead\" list has become the next wave of tells within months.\nReplacements here are procedures (draw from the library, derive from the subject), not products.\n\n`scripts/inspect.mjs` and `scripts/lint.mjs` detect most entries. Status: **banned** means the\ninspector fails the page; **warned** means it flags it and you need a reason.\n\n## Contents\n\n1. First wave (2023–2024)\n2. Second wave (2025)\n3. Third wave (2025–2026): the \"fix\" that became the look\n4. Gallery fashion, banned as house style\n5. Structural tells\n6. Copy tells\n7. Motion tells\n8. Why removal is not enough\n\n## 1. First wave (2023–2024)\n\n| Tell | Status | Do instead |\n| --- | --- | --- |\n| Violet / indigo gradients on hero, buttons and glows | banned | The dealt palette; flat colour |\n| Gradient-filled headline text | banned | Solid ink |\n| Glass panels: backdrop blur, translucent cards | warned (2 or more) | Opaque surfaces one tone step from the ground |\n| Glowing or gradient \"Get started\" button | banned | Flat button named for its action |\n| Soft grey drop shadow under every card | banned | Tone step, or no box |\n| Three identical feature cards, each with an icon in a rounded square | banned | The dealt section blueprint |\n| Emoji as icons or bullets | banned | Words, or a real picture |\n| Centred headline, subtitle, two buttons, screenshot below | no rule; the draw avoids it | The dealt hero |\n| The same typeface on every generated page | warned (lint: default-font) | The dealt type system |\n\n## 2. Second wave (2025)\n\n| Tell | Status | Do instead |\n| --- | --- | --- |\n| Eyebrow / kicker: tiny tracked uppercase label above every heading | banned | Fold it into the heading, or delete |\n| Pill badge above the hero headline (\"New\", \"Beta\", \"Introducing\") | banned | Say it in the supporting sentence |\n| One word of the headline in italic serif, colour or underline | warned | One face, one colour |\n| Bento grid of rounded tiles as the feature section | warned as card rows | A composed section; tiles only in the dense-tiles direction, filled, strict sizes |\n| Near-black ground with one neon accent and a glow | banned via shadow, gradient | A dealt dark palette, no glow |\n| Floating rounded pill navigation with blur | warned | A plain bar |\n| Fake dashboard hero built from grey bars and donut charts | no rule; see imagery.md §7 | A real interface fragment, or no image |\n| Decorative status dot (\"Available for work\", pulsing \"live\") | lint: bounce | Remove |\n| Fade-and-rise on every section | no rule; see motion.md | One signature move |\n\n## 3. Third wave (2025–2026): the \"fix\" that became the look\n\nThe remedy published for the first two waves was \"warm it up and make it editorial\". Models adopted\nthe remedy wholesale and it is now the most recognisable generated look of all.\n\n| Tell | Status | Do instead |\n| --- | --- | --- |\n| Yellow-cream ground + terracotta / rust / clay accent | banned together; terracotta banned alone; cream warned | The dealt palette. Warmth from a low-chroma stone, a deep ink, a photograph, or a full warm field |\n| High-contrast or soft serif display as the shortcut to \"premium\" | no rule | The dealt type system, whatever class it is |\n| Oversized italic serif headline | no rule | As dealt |\n| Broadsheet cosplay: hairline rules everywhere, zero radius, dense columns | banned via hairline | Structure from space and tone |\n| \"Field notes\", \"Quietly trusted by\", \"On our desks\": performative labels | lint: copy | Plain section names |\n\n## 4. Gallery fashion, banned as house style\n\nThese are common on award sites right now. In the study they appear *more* often on the top-scored\nsites than on the weak ones (panel observations: monospace labels 44% against 24%, index numbering 38%\nagainst 21%; measured thin rules 61% against 52%). They are banned here regardless, by the owner's\ndecision: they are the first things a generator copies from the gallery, they carry no information,\nand a page built without them has to find real structure.\n\n| Tell | Status | Do instead |\n| --- | --- | --- |\n| Monospace micro-labels, mono as a \"technical\" voice, mono captions | banned | The text face; tabular figures for data |\n| Index numbering: 01 / 02 / 03, (001), \"Step 02\", numbered section markers | banned | Order by position, scale, or the words; `<ol>` when it is truly a list |\n| Thin rules: hairline dividers, ruled grids, 1px outlined boxes and tiles | banned (boxes: 3 or more) | Space, tone steps, filled shapes, a thick bar if a bar is the idea |\n| Design-tool chrome as ornament: crosshairs, crop marks, selection handles, dashed guides, rulers | banned via hairline, dashed | Remove |\n| Agency micro-meta: local time, coordinates, weather, version stamps, \"©2026 — Scroll\", middle-dot strings | lint: copy; micro-label | Remove |\n| Tiny uppercase letter-spaced captions scattered around the viewport | banned (3 or more) | Sentence case at readable size, placed with the content it describes |\n\nTiny tracked capitals are the one item in this group the data condemns as well: 16% of top sites\nagainst 57% of weak ones.\n\n## 5. Structural tells\n\n| Tell | Status | Do instead |\n| --- | --- | --- |\n| Headline as a full sentence at display size, three or four lines | banned (over two lines) | A title of about five words; the rest goes below |\n| Stock section order: hero, logos, features, testimonial, pricing, CTA | no rule; see copy.md §1 | The order of the argument |\n| Every section the same layout family | critique.md pass 9 | Different composition per section, from the sheet |\n| Everything centred | warned over 72% | Left-anchored, one centred moment |\n| One medium border radius (12–16px) on everything | none | Square or fully round, chosen once |\n| Nine nearly equal font sizes | warned over 9 | Five sizes, far apart |\n| Invented social proof: logos, quotes, star rows, \"10,000+ teams\" | copy.md §5 | Real proof, or none |\n| Text or a CSS box where a picture belongs | critique.md cap | A real picture, or a design that needs none |\n\n## 6. Copy tells\n\nFlagged by `lint.mjs`: the genre's verbs and adjectives (unlock, supercharge, seamless, elevate,\neffortless, cutting-edge, all-in-one …); the correction (\"not just X, it's Y\"); tricolon headlines;\n\"Get started\" and \"Learn more\" as labels; more than a handful of em dashes; lorem ipsum. See\n`copy.md` §6.\n\n## 7. Motion tells\n\nIdentical fade-up on every block; a dozen staggered hero entrances; hover lift on every card; bounce\neasing; infinite loops that mean nothing; reveals that fail and leave a blank band. See `motion.md` §9.\n\n## 8. Why removal is not enough\n\nA page with every tell removed and nothing put in their place is an empty page with good manners, and\nthat is a tell too (the \"avoidance aesthetic\": anyone could guess it from the category plus the list of\nthings to avoid). The tells were filling a gap where an idea should have been. The order of work in\n`SKILL.md` exists to fill that gap first: the idea from the subject, the dealt composition, real\npictures or committed type, and only then the checks.\n","skills/taste-skill/references/type.md":"# Type\n\nTypography is most of what a visitor sees and most of what makes a page look designed or assembled.\nThe direction sheet deals you a type system (faces, weights, settings). This file is how to use it.\n\n## Contents\n\n1. What the study measured\n2. The scale: few sizes, far apart\n3. Setting display type\n4. Setting text\n5. Loading the fonts properly\n6. One family or two\n7. Details that separate set type from typed text\n8. Mistakes the inspector cannot see\n\n## 1. What the study measured\n\nFrom 202 measurable sites out of the 247 studied (Chrome, 1440×900 and 390×844):\n\n| | Median | Middle half | Note |\n| --- | --- | --- | --- |\n| Hero headline size | 72px (5.0vw) | 43–109px | Top-scored sites: 6.0vw median |\n| Largest type on the page | 6.4vw | up to 10.4vw | Top-scored sites 8.4vw, weak sites 5.0vw |\n| Hero headline on a phone | 40px | 32–59px | |\n| Hero tracking | -0.01em | -0.03 to 0 | Tighter as size grows |\n| Hero leading | 1.0 | 0.95–1.1 | |\n| Body size | 16px | 14–18px | |\n| Headline ÷ body size | 4.3 | | Top-scored sites 4.7 |\n| Typefaces in real use | 2 | 31% use one, 45% two, 22% three | |\n| Hero weight | regular 48%, medium 18%, bold or heavier 22% | | Big type does not need to be bold |\n| Hero in capitals | 24% | | |\n| Hero centred | 39% | | 52% on the weak sites |\n\nTwo things to take from it. First, size contrast is the main lever and the best sites pull it harder.\nSecond, weight is not: half of the heroes are set in a regular weight. Scale and spacing make type\nconfident; bold is one option among several.\n\n## 2. The scale: few sizes, far apart\n\nThe panel described about 30 of the 114 strongest sites as using two or three type sizes with nothing\nin between, and none as using a graded five- or six-step scale. So: one display size, one text size\nand a small size carry the page; a lead size and a heading size exist for when they are needed. Five\nis the ceiling. The common failure is nine sizes that are all near each other (16, 18, 20, 24, 28,\n32…), which reads as mush. Choose steps that are clearly different:\n\n```css\n:root {\n  --step-small: clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem);   /* 13–14px  captions, legal */\n  --step-body:  clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem);    /* 17–19px  paragraphs */\n  --step-lead:  clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem);      /* 20–26px  supporting line, large body */\n  --step-head:  clamp(2rem, 1.3rem + 3.2vw, 4rem);             /* 32–64px  section headings */\n  --step-display: clamp(3rem, 1rem + 9vw, 9rem);               /* set by the hero blueprint */\n}\n```\n\n- `--step-display` belongs to the direction. A monument wordmark is 16–24vw; a quiet instrument's\n  headline is 28px. Use the size the hero blueprint gives, as a `clamp()` so it scales with the\n  viewport but is bounded on phones and very wide screens.\n- Keep the gap: the display size should be at least four times the body size on desktop, and nothing\n  should sit between `--step-lead` and `--step-head` unless the design truly needs a sixth size.\n- Resist a \"subheading\" size for every card and label. If two sizes look almost the same, make them\n  the same.\n\n## 3. Setting display type\n\nLarge type exposes spacing that is invisible at text size. Apply all of these to anything over 40px:\n\n```css\n.display {\n  font-size: var(--step-display);\n  line-height: 0.95;              /* 0.85–1.05; tighter for capitals and condensed faces */\n  letter-spacing: -0.035em;       /* -0.02 to -0.05em; use the value on the direction sheet */\n  font-kerning: normal;\n  text-wrap: balance;\n  max-width: 14ch;                /* choose the measure so lines break where you want */\n  margin: 0;\n}\n```\n\n- **Tracking scales with size.** The larger the type, the tighter it needs to be; a value right for\n  120px will choke 32px. Set tracking per step, not once for all headings.\n- **Leading below 1.0 needs checking.** Look for collisions between descenders and the ascenders or\n  accents of the next line. Two-line headlines make this easy to verify by eye.\n- **All capitals** want slightly open tracking (0 to +0.03em) even at display size, and leading around\n  0.9.\n- **Optical alignment.** Big letters with round or diagonal left edges (O, C, A, T, W) look indented.\n  Pull the headline left by about 0.04–0.06em (`margin-left: -0.05em`) so it aligns optically with the\n  text beneath it.\n- **Viewport-wide type.** For a line that must span the screen, size it in `vw` and verify at 390 and\n  1440; set `white-space: nowrap` and let the container clip rather than wrap. Calculate the size from\n  the character count: `font-size ≈ container width ÷ (characters × k)` with k from `copy.md` §2.\n- Never add a text shadow, an outline stroke, or a gradient fill to display type.\n\n## 4. Setting text\n\n```css\nbody { font-size: var(--step-body); line-height: 1.5; font-kerning: normal; text-rendering: optimizeLegibility; }\np { max-width: 62ch; text-wrap: pretty; margin: 0; }\np + p { margin-top: 0.9em; }\n.lead { font-size: var(--step-lead); line-height: 1.35; max-width: 40ch; }\nsmall, .caption { font-size: var(--step-small); line-height: 1.45; }\n```\n\n- Measure: 45–75 characters. Wider than that and the eye loses the next line; the inspector warns\n  past about 88.\n- Leading: 1.45–1.6 for body, tighter (1.3–1.4) for the larger lead size, looser for long reading.\n- Secondary text is the same face in a softer ink (`--muted`), not a lighter weight and not smaller\n  than 13px.\n- Do not centre paragraphs longer than three lines. Do not justify.\n- Light text on a dark ground looks heavier: drop one weight step or add 0.01em tracking, and raise\n  leading slightly.\n\n## 5. Loading the fonts properly\n\nThe sheet gives a `<link>` tag. Use it exactly; do not swap in a face you prefer.\n\n```html\n<link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\n<link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin>\n<link href=\"…from the direction sheet…\" rel=\"stylesheet\">\n```\n\n```css\n:root {\n  --font-display: \"Family From Sheet\", \"Helvetica Neue\", Arial, sans-serif;\n  --font-text: \"Family From Sheet\", Georgia, serif;\n}\n```\n\n- Request only the weights you use (usually two or three in total).\n- Always give a fallback stack of the same broad kind (sans for sans, serif for serif).\n- In a framework, use its font loader with the same family and weights (`next/font/google`, or a\n  self-hosted `@font-face` with `font-display: swap`). Fontshare faces load from the\n  `api.fontshare.com` stylesheet on the sheet.\n- After building, `inspect.mjs` reports the families that actually rendered. If it warns that a face\n  did not load, the screenshots show a fallback and nothing you judge from them is real. Fix the link\n  first.\n\n## 6. One family or two\n\nA third of the studied sites use a single family for everything, and it is the safest way to look\ncoherent. When the dealt system has two faces:\n\n- Give each a job and never swap them: one sets headlines, the other sets everything else.\n- Do not introduce a third face for labels, numbers or quotes.\n- Do not mix two faces inside one headline.\n- Italic is for titles of works and real emphasis inside paragraphs, never as decoration.\n\n## 7. Details that separate set type from typed text\n\n- Curly quotes and apostrophes, real dashes, a real ellipsis (see `copy.md` §7).\n- `font-variant-numeric: tabular-nums` for prices, tables, dates in columns; `oldstyle-nums` suits\n  serif body text.\n- `text-underline-offset: 0.18em; text-decoration-thickness: 0.07em` on links, so underlines clear the\n  descenders.\n- `hyphens: none` on headings. `overflow-wrap: anywhere` only on long URLs or emails.\n- A heading belongs to the text after it: space above a heading is at least twice the space below.\n- `::selection { background: var(--accent); color: var(--accent-ink); }` and a visible\n  `:focus-visible` outline in the accent, so even the browser's own states belong to the design.\n- Do not change weight on hover; the line reflows.\n\n## 8. Mistakes the inspector cannot see\n\n- A headline that passes the two-line rule but breaks badly: one orphan word on line two, or a break\n  that splits a phrase (\"Stools for small / kitchens\"). Author the break.\n- Display type so tight that letters touch, or so loose it falls apart.\n- A confident hero followed by section headings almost as large. Keep one size dominant per screen.\n- Body text set in the display face when that face was drawn for large sizes only.\n- Everything bold. If every line is emphasised, none is.\n"},"items":[{"name":"evals.json","path":"skills/taste-skill/evals/evals.json","rawUrl":"https://raw.githubusercontent.com/Leonxlnx/taste-skill/HEAD/skills/taste-skill/evals/evals.json","title":"Evals Skill","category":"anthropic-skill","format":"json","content":"{\n  \"skill_name\": \"design-taste-frontend\",\n  \"how_to_run\": \"For each eval, give the prompt to a fresh agent that has this skill, and to a second fresh agent without it (the baseline). Render both with scripts/inspect.mjs and have a judge who does not know which is which score the screenshots with references/critique.md. Record inspector FAIL counts for both. Evals 7 to 10 are app screens: inspect them with --app (a sheet dealt by draw.mjs --app switches it on by itself) and judge them with the app-screen passes in references/critique.md.\",\n  \"evals\": [\n    {\n      \"id\": 1,\n      \"name\": \"saas-invoicing\",\n      \"prompt\": \"Build a landing page for Ledgerly, an invoicing tool for freelance designers. What it does: you write an invoice in under a minute, the client pays by card or bank transfer, and it sends polite reminders by itself when an invoice is overdue. It costs 9 euros a month flat, with a 14-day free trial and no card needed. Include pricing and a short FAQ. There is no existing brand and no screenshots; the product name is all we have. Plain static HTML, CSS and JS in one folder.\",\n      \"expected_output\": \"A static landing page with a clear idea drawn from invoicing itself, headlines of two lines or fewer at 1440/768/390, no eyebrow labels, no monospace, no index numbering, no thin rules, no gradients or shadows, a non-default palette and type system, a pricing section that is not three cards, and no invented customers or statistics.\",\n      \"files\": []\n    },\n    {\n      \"id\": 2,\n      \"name\": \"restaurant-osteria\",\n      \"prompt\": \"Make a one-page website for Osteria Nove, a 38-seat Italian restaurant in Alfama, Lisbon. Handmade pasta, a short natural wine list, dinner only, Tuesday to Saturday from 19:00. Address: Rua dos Remédios 9. Reservations by phone (+351 21 000 0009) or email (mesa@osterianove.pt). The page needs the menu (invent a believable short one: antipasti, pasta, dolci, with prices in euros), hours, address and how to book. We have no photographs yet. Static HTML/CSS/JS.\",\n      \"expected_output\": \"A one-page restaurant site with a specific idea (for example the page as the menu itself), the menu set typographically without divider lines, practical information easy to find, bundled photographs used only as atmosphere and listed for replacement, and all house rules met.\",\n      \"files\": []\n    },\n    {\n      \"id\": 3,\n      \"name\": \"portfolio-designer\",\n      \"prompt\": \"I'm Mara Lindqvist, a product designer in Stockholm with eight years in fintech and health apps. I need a portfolio homepage: six selected projects (make up plausible names, clients, years and one-line descriptions), a short about paragraph, and a way to contact me (mara@lindqvist.studio). I don't have project images ready, so design it so it still looks finished without them, or use placeholders that I can swap. Static HTML/CSS/JS.\",\n      \"expected_output\": \"A portfolio page that looks finished without project imagery (a typographic index, a name-led hero, or atmosphere photographs clearly marked for replacement), with a designed footer, a phone layout that is its own composition, and all house rules met.\",\n      \"files\": []\n    },\n    {\n      \"id\": 4,\n      \"name\": \"product-ceramics\",\n      \"prompt\": \"Launch page for Kiln, a ceramic pour-over coffee set (dripper, carafe and two cups) that is hand-glazed in small batches in Porto. It costs 84 euros and ships across the EU within a week. The glaze is mixed by hand so no two sets are identical. We have not shot product photos yet, so there are no images of the set. One page, with a way to buy (a button is enough). Static HTML/CSS/JS.\",\n      \"expected_output\": \"A product page that does not fake product photography: it either commits to type and colour, uses one shape from the object as a motif, or uses atmosphere photographs honestly, with the price and purchase action clear, and all house rules met.\",\n      \"files\": []\n    },\n    {\n      \"id\": 5,\n      \"name\": \"guesthouse-ericeira\",\n      \"prompt\": \"Website for Casa Mirante, a six-room guesthouse on the cliffs above Ericeira, Portugal. Rooms from 140 euros a night with breakfast included; ten minutes' walk to the surf at Ribeira d'Ilhas; open March to November. One page: what it is, the rooms, what's nearby, and how to book (email reservas@casamirante.pt). We have no photographs yet. Static HTML/CSS/JS.\",\n      \"expected_output\": \"A calm, photograph-led or type-led one-pager whose hero is one clear thing, with rooms and booking information easy to find, bundled coast photographs used as atmosphere and listed for replacement, and all house rules met.\",\n      \"files\": []\n    },\n    {\n      \"id\": 6,\n      \"name\": \"conference-format\",\n      \"prompt\": \"Landing page for Format, a two-day design conference in Rotterdam on 14 and 15 May 2027. Twelve speakers (invent plausible names and talk titles), 400 seats, tickets at 390 euros, venue: Maassilo. Sections: what it is, the line-up, the schedule in brief, tickets, and a short FAQ. No brand exists yet beyond the name. Static HTML/CSS/JS.\",\n      \"expected_output\": \"An event page with a strong typographic or colour idea, the line-up and schedule set as structured text without divider lines or index numbers, a ticket section that is not three cards, and all house rules met.\",\n      \"files\": []\n    },\n    {\n      \"id\": 7,\n      \"name\": \"app-budget-overview\",\n      \"prompt\": \"Build the main screen of Ledgerly, a budgeting app for couples who share money: the October overview with their accounts and balances, the spending plan (planned against spent by category), bills due in the next 14 days and recent transactions. Two people use it, Mia and Tom. Desktop first, and it must work on a phone. Static HTML/CSS/JS.\",\n      \"expected_output\": \"An app screen, not a landing page: a quiet shell (sidebar or rail), a clear screen title, numbers that add up and are right-aligned with tabular figures, one chart per question, colour spent on data and status only, no icons in tinted squares, no gradients or glows, no placeholder names, and a phone layout where the navigation folds away. inspect.mjs --app passes.\",\n      \"files\": []\n    },\n    {\n      \"id\": 8,\n      \"name\": \"app-deploy-dashboard\",\n      \"prompt\": \"Dashboard for Relay, an edge deployment platform for web teams: one project's overview with recent deployments (status, branch, commit message, author, duration, region), requests and p95 latency over the last 24 hours, the error rate, and usage against the plan's limits. Dark theme. Static HTML/CSS/JS.\",\n      \"expected_output\": \"A dense, readable dark screen on a neutral (not navy) ground: one surface step or one hairline between regions, a deployments table with honest statuses and aligned numbers, charts with few gridlines and one series each, IDs in monospace at most, no rainbow series, no glow, and app inspector checks passing.\",\n      \"files\": []\n    },\n    {\n      \"id\": 9,\n      \"name\": \"app-settings-billing\",\n      \"prompt\": \"Workspace settings for Proofline, a design-review tool: general settings, members and roles (a members table with an invite form), billing (current plan, seats, invoices) and notifications. Static HTML/CSS/JS, desktop and phone.\",\n      \"expected_output\": \"A settings screen with a label column beside its fields (or stacked fields on a phone), labels above inputs, one control height, quiet borders, honest disabled states, a members table with right-aligned figures and one status pill per row, and no decorative icons or gradients.\",\n      \"files\": []\n    },\n    {\n      \"id\": 10,\n      \"name\": \"app-support-queue\",\n      \"prompt\": \"The queue screen of Hearth, a support inbox for a six-person SaaS team: the list of conversations with assignee, priority, channel and time to the SLA, the open conversation with the customer's details beside it, plus filters and saved views. Static HTML/CSS/JS.\",\n      \"expected_output\": \"A three-region work screen (navigation, list, conversation) that stays readable at 1440 and folds to one region at a time on a phone, with status shown once per row, times in words, no tinted icon squares or emoji, and app inspector checks passing.\",\n      \"files\": []\n    }\n  ]\n}\n","frontmatter":{"skill_name":"design-taste-frontend","how_to_run":"For each eval, give the prompt to a fresh agent that has this skill, and to a second fresh agent without it (the baseline). Render both with scripts/inspect.mjs and have a judge who does not know which is which score the screenshots with references/critique.md. Record inspector FAIL counts for both. Evals 7 to 10 are app screens: inspect them with --app (a sheet dealt by draw.mjs --app switches it on by itself) and judge them with the app-screen passes in references/critique.md.","evals":[{"id":1,"name":"saas-invoicing","prompt":"Build a landing page for Ledgerly, an invoicing tool for freelance designers. What it does: you write an invoice in under a minute, the client pays by card or bank transfer, and it sends polite reminders by itself when an invoice is overdue. It costs 9 euros a month flat, with a 14-day free trial and no card needed. Include pricing and a short FAQ. There is no existing brand and no screenshots; the product name is all we have. Plain static HTML, CSS and JS in one folder.","expected_output":"A static landing page with a clear idea drawn from invoicing itself, headlines of two lines or fewer at 1440/768/390, no eyebrow labels, no monospace, no index numbering, no thin rules, no gradients or shadows, a non-default palette and type system, a pricing section that is not three cards, and no invented customers or statistics.","files":[]},{"id":2,"name":"restaurant-osteria","prompt":"Make a one-page website for Osteria Nove, a 38-seat Italian restaurant in Alfama, Lisbon. Handmade pasta, a short natural wine list, dinner only, Tuesday to Saturday from 19:00. Address: Rua dos Remédios 9. Reservations by phone (+351 21 000 0009) or email (mesa@osterianove.pt). The page needs the menu (invent a believable short one: antipasti, pasta, dolci, with prices in euros), hours, address and how to book. We have no photographs yet. Static HTML/CSS/JS.","expected_output":"A one-page restaurant site with a specific idea (for example the page as the menu itself), the menu set typographically without divider lines, practical information easy to find, bundled photographs used only as atmosphere and listed for replacement, and all house rules met.","files":[]},{"id":3,"name":"portfolio-designer","prompt":"I'm Mara Lindqvist, a product designer in Stockholm with eight years in fintech and health apps. I need a portfolio homepage: six selected projects (make up plausible names, clients, years and one-line descriptions), a short about paragraph, and a way to contact me (mara@lindqvist.studio). I don't have project images ready, so design it so it still looks finished without them, or use placeholders that I can swap. Static HTML/CSS/JS.","expected_output":"A portfolio page that looks finished without project imagery (a typographic index, a name-led hero, or atmosphere photographs clearly marked for replacement), with a designed footer, a phone layout that is its own composition, and all house rules met.","files":[]},{"id":4,"name":"product-ceramics","prompt":"Launch page for Kiln, a ceramic pour-over coffee set (dripper, carafe and two cups) that is hand-glazed in small batches in Porto. It costs 84 euros and ships across the EU within a week. The glaze is mixed by hand so no two sets are identical. We have not shot product photos yet, so there are no images of the set. One page, with a way to buy (a button is enough). Static HTML/CSS/JS.","expected_output":"A product page that does not fake product photography: it either commits to type and colour, uses one shape from the object as a motif, or uses atmosphere photographs honestly, with the price and purchase action clear, and all house rules met.","files":[]},{"id":5,"name":"guesthouse-ericeira","prompt":"Website for Casa Mirante, a six-room guesthouse on the cliffs above Ericeira, Portugal. Rooms from 140 euros a night with breakfast included; ten minutes' walk to the surf at Ribeira d'Ilhas; open March to November. One page: what it is, the rooms, what's nearby, and how to book (email reservas@casamirante.pt). We have no photographs yet. Static HTML/CSS/JS.","expected_output":"A calm, photograph-led or type-led one-pager whose hero is one clear thing, with rooms and booking information easy to find, bundled coast photographs used as atmosphere and listed for replacement, and all house rules met.","files":[]},{"id":6,"name":"conference-format","prompt":"Landing page for Format, a two-day design conference in Rotterdam on 14 and 15 May 2027. Twelve speakers (invent plausible names and talk titles), 400 seats, tickets at 390 euros, venue: Maassilo. Sections: what it is, the line-up, the schedule in brief, tickets, and a short FAQ. No brand exists yet beyond the name. Static HTML/CSS/JS.","expected_output":"An event page with a strong typographic or colour idea, the line-up and schedule set as structured text without divider lines or index numbers, a ticket section that is not three cards, and all house rules met.","files":[]},{"id":7,"name":"app-budget-overview","prompt":"Build the main screen of Ledgerly, a budgeting app for couples who share money: the October overview with their accounts and balances, the spending plan (planned against spent by category), bills due in the next 14 days and recent transactions. Two people use it, Mia and Tom. Desktop first, and it must work on a phone. Static HTML/CSS/JS.","expected_output":"An app screen, not a landing page: a quiet shell (sidebar or rail), a clear screen title, numbers that add up and are right-aligned with tabular figures, one chart per question, colour spent on data and status only, no icons in tinted squares, no gradients or glows, no placeholder names, and a phone layout where the navigation folds away. inspect.mjs --app passes.","files":[]},{"id":8,"name":"app-deploy-dashboard","prompt":"Dashboard for Relay, an edge deployment platform for web teams: one project's overview with recent deployments (status, branch, commit message, author, duration, region), requests and p95 latency over the last 24 hours, the error rate, and usage against the plan's limits. Dark theme. Static HTML/CSS/JS.","expected_output":"A dense, readable dark screen on a neutral (not navy) ground: one surface step or one hairline between regions, a deployments table with honest statuses and aligned numbers, charts with few gridlines and one series each, IDs in monospace at most, no rainbow series, no glow, and app inspector checks passing.","files":[]},{"id":9,"name":"app-settings-billing","prompt":"Workspace settings for Proofline, a design-review tool: general settings, members and roles (a members table with an invite form), billing (current plan, seats, invoices) and notifications. Static HTML/CSS/JS, desktop and phone.","expected_output":"A settings screen with a label column beside its fields (or stacked fields on a phone), labels above inputs, one control height, quiet borders, honest disabled states, a members table with right-aligned figures and one status pill per row, and no decorative icons or gradients.","files":[]},{"id":10,"name":"app-support-queue","prompt":"The queue screen of Hearth, a support inbox for a six-person SaaS team: the list of conversations with assignee, priority, channel and time to the SLA, the open conversation with the customer's details beside it, plus filters and saved views. Static HTML/CSS/JS.","expected_output":"A three-region work screen (navigation, list, conversation) that stays readable at 1440 and folds to one region at a time on a phone, with status shown once per row, times in words, no tinted icon squares or emoji, and app inspector checks passing.","files":[]}]},"isInternal":false,"tokens":1947,"sizeBytes":8198},{"name":"app.json","path":"skills/taste-skill/library/app.json","rawUrl":"https://raw.githubusercontent.com/Leonxlnx/taste-skill/HEAD/skills/taste-skill/library/app.json","title":"Library Skill","category":"anthropic-skill","format":"json","content":"{\n  \"version\": 1,\n  \"about\": \"App-screen library for tasteskill: styles (directions), shells and screen patterns, distilled from the study of 23 desktop product screens (17 light, 6 dark, 17 products) chosen by the owner. Every number is a measurement from the study or a median over it, except where a note says a value was moved for contrast or for the house palette bans. Reference products are not named; the screenshots stay private.\",\n  \"styles\": [\n    {\n      \"id\": \"achromatic-ledger\",\n      \"name\": \"Achromatic ledger\",\n      \"theme\": \"light\",\n      \"basis\": \"4 screens: a seller home, a per-agent insights page, a generated report, a settings page with usage numbers\",\n      \"suits\": [\n        \"finance\",\n        \"commerce\",\n        \"devtools\",\n        \"support\",\n        \"report\",\n        \"workspace\",\n        \"builder\"\n      ],\n      \"idea\": \"The chrome holds no colour at all; money and counts are set in ink, the one chart hue marks the screen's main data element, and the only other hue is a small signal where a figure changed.\",\n      \"colourBudget\": \"under 1% coloured pixels; the chrome is ink, the one chart hue goes on the main data element, and the only other hue is a small change signal\",\n      \"tokens\": {\n        \"ground\": \"#f8f8f8\",\n        \"surface\": \"#ffffff\",\n        \"raised\": \"#eeeeee\",\n        \"border\": \"#e6e6e6\",\n        \"rule\": \"#f0f0f0\",\n        \"control\": \"#d4d4d4\",\n        \"text\": \"#0a0a0a\",\n        \"muted\": \"#6b6b6b\",\n        \"accent\": \"#141414\",\n        \"positive\": \"#2e7d32\",\n        \"negative\": \"#c4242a\",\n        \"warning\": \"#92400e\",\n        \"chart\": [\n          \"#141414\",\n          \"#8a8a8a\",\n          \"#1d5fbf\"\n        ],\n        \"pills\": {\n          \"positive\": [\n            \"#dcfae5\",\n            \"#04250e\"\n          ],\n          \"negative\": [\n            \"#ffedea\",\n            \"#831c1e\"\n          ],\n          \"warning\": [\n            \"#fffbeb\",\n            \"#92400e\"\n          ],\n          \"neutral\": [\n            \"#eeeeee\",\n            \"#3d3d3d\"\n          ]\n        },\n        \"radius\": {\n          \"card\": 8,\n          \"control\": 6\n        },\n        \"font\": {\n          \"family\": \"Geist\",\n          \"second\": \"Geist Mono, for IDs and keys only\",\n          \"fallback\": \"Inter, system-ui, sans-serif\",\n          \"sizes\": {\n            \"title\": 24,\n            \"section\": 16,\n            \"kpi\": 30,\n            \"body\": 14,\n            \"small\": 12\n          },\n          \"weights\": [\n            400,\n            500,\n            700\n          ],\n          \"note\": \"700 is for money figures only; every other number is 400-500.\"\n        },\n        \"density\": \"sparse\",\n        \"rowHeight\": 44,\n        \"sidebarWidth\": 256,\n        \"gap\": 12,\n        \"pad\": 24,\n        \"controlHeight\": 36\n      },\n      \"shell\": \"open-plane\",\n      \"shellAlternatives\": [\n        \"icon-rail\",\n        \"no-sidebar\"\n      ],\n      \"signature\": \"No brand colour anywhere in the chrome: the one primary action is near-black (a grey pill, #e5e5e5, is the secondary), the main data element (today's series, the booked bars, the current period) takes the one chart hue, #1d5fbf, and everything else is drawn in ink with the comparison or the part after the cursor in grey, zero balances are set in grey, and the only hue on the screen is a small triangle or a short coloured number where a figure changed.\",\n      \"identity\": [\n        \"A ground from the product's world in place of #f8f8f8, one level off white and low in chroma: a stone (#f4f3f1) for a bakery or a shop, a sage (#f2f5f2) for a garden or a greenhouse, a blue-grey (#f2f4f7) for a ledger or a meter. Cards stay white; a warm tint stays under the cream check (saturation under about 15%).\",\n        \"The one chart hue (#1d5fbf, or the brand's own hue at 3:1 or more on white) on the screen's main data element: today's line, the booked bars, the current period's column, the margin that breaks. The chrome stays ink and the hue stays under 1% of the screen.\",\n        \"Every figure in Geist Mono, as the style's decision, so money and counts read as a ledger's columns while the text stays Geist. Lint and the inspector flag mono; give the reason in the report.\"\n      ],\n      \"avoid\": [\n        \"a brand-coloured primary button\",\n        \"tinted cards or tinted KPI tiles\",\n        \"a coloured chart where one series in ink says it\",\n        \"bold on anything but money\",\n        \"a chart with no y-scale (the study's one example of this look hid magnitude behind hover and was flagged)\",\n        \"a grey pill as the only button for the screen's main job: in testing an Approve repeated in grey on every row left the screen without a primary\"\n      ],\n      \"notes\": \"The studied screens of this kind used 11-12px card radii, which §9.4 counts among the rare middle values; the library sets the tight pair (8 and 6) so the style lands on the bimodal rule. After testing, the chart hue moved from an unused third series colour onto the main data element: a screen whose only hue was a delta read as a kit.\"\n    },\n    {\n      \"id\": \"framed-sheet\",\n      \"name\": \"Framed sheet\",\n      \"theme\": \"light\",\n      \"basis\": \"6 screens: a developer platform overview, an analytics overview, an events analytics tab, a list detail, a reports dashboard, a flow builder\",\n      \"suits\": [\n        \"analytics\",\n        \"devtools\",\n        \"builder\",\n        \"smb-admin\",\n        \"support\",\n        \"commerce\",\n        \"report\"\n      ],\n      \"idea\": \"The app chrome is one tinted L-shaped frame; the work sits on a white sheet with a hairline edge and soft corners, so depth comes from a single tone step and no shadow.\",\n      \"colourBudget\": \"under 3%; the brand shrinks to the logo and a 2px tab underline, the data carries the chroma\",\n      \"tokens\": {\n        \"ground\": \"#f9fbfc\",\n        \"surface\": \"#ffffff\",\n        \"raised\": \"#f4f6f8\",\n        \"active\": \"#ebedee\",\n        \"border\": \"#e8eaec\",\n        \"rule\": \"#f0f1f2\",\n        \"control\": \"#cdced1\",\n        \"text\": \"#131416\",\n        \"muted\": \"#5d5f60\",\n        \"accent\": \"#1b6c80\",\n        \"positive\": \"#1e7b4f\",\n        \"negative\": \"#c4242a\",\n        \"warning\": \"#92400e\",\n        \"chart\": [\n          \"#1b6c80\",\n          \"#2f70bb\",\n          \"#a86f0c\"\n        ],\n        \"pills\": {\n          \"positive\": [\n            \"#dcfae5\",\n            \"#04250e\"\n          ],\n          \"negative\": [\n            \"#ffedea\",\n            \"#831c1e\"\n          ],\n          \"warning\": [\n            \"#fffbeb\",\n            \"#92400e\"\n          ],\n          \"neutral\": [\n            \"#ebedee\",\n            \"#353736\"\n          ]\n        },\n        \"radius\": {\n          \"card\": 8,\n          \"control\": 6,\n          \"sheet\": 16\n        },\n        \"sheetInset\": 8,\n        \"font\": {\n          \"family\": \"IBM Plex Sans\",\n          \"second\": \"IBM Plex Mono, for IDs and keys only\",\n          \"fallback\": \"Inter, system-ui, sans-serif\",\n          \"sizes\": {\n            \"title\": 22,\n            \"section\": 16,\n            \"kpi\": 28,\n            \"body\": 14,\n            \"small\": 12\n          },\n          \"weights\": [\n            400,\n            500,\n            600\n          ],\n          \"note\": \"KPI values at 400; the semibold goes on the label and the active tab.\"\n        },\n        \"density\": \"medium\",\n        \"rowHeight\": 48,\n        \"sidebarWidth\": 228,\n        \"gap\": 24,\n        \"pad\": 24,\n        \"controlHeight\": 32\n      },\n      \"shell\": \"framed-sheet\",\n      \"shellAlternatives\": [],\n      \"signature\": \"One tinted frame holds the sidebar and the 48px top bar with no rule between them; the page is a white sheet inset 8px from the window's right and bottom edges, with a 1px edge, 16px corners and no shadow. The active tab is a 2px underline in ink or the accent; everything else in the chrome is grey.\",\n      \"identity\": [\n        \"The frame tinted from the product's colour in place of #f9fbfc: one low-chroma step of its hue (a green-grey for a climate or farm tool, a blue-grey for an observability tool, a stone for a print shop). The sheet stays white.\",\n        \"The brand's own hue from the brief as --chart-1 in place of the dealt teal, on the main series and the one selected state, at 3:1 or more on white, never violet or indigo.\",\n        \"IBM Plex Mono for IDs, keys and the figures in tables (one job): its figures have their own drawing, and a developer reads them as the product's.\"\n      ],\n      \"avoid\": [\n        \"a border between the sidebar and the top bar\",\n        \"a shadow under the sheet\",\n        \"cards whose border is heavier than the sheet's (#cdcfcf on cards read as heavy in the study)\",\n        \"a fourth nesting level: frame, sheet and card are enough\",\n        \"different gutters for the KPI row and the chart row (20 against 24 was flagged)\"\n      ],\n      \"notes\": \"The study's second data hue in this style was an orange (#e88e46) that falls inside the house terracotta range; the third chart colour here is an amber moved out of that range and darkened to 3:1 on white.\"\n    },\n    {\n      \"id\": \"accent-ladder\",\n      \"name\": \"Accent ladder\",\n      \"theme\": \"light\",\n      \"basis\": \"3 screens: a newsletter home, a network analytics overview, a cap-table company home\",\n      \"suits\": [\n        \"creator\",\n        \"smb-admin\",\n        \"community\",\n        \"analytics\"\n      ],\n      \"idea\": \"One brand hue at full strength only on small marks, and its pale tints doing all the area work: the active nav row, a plan card, badges and progress tracks.\",\n      \"colourBudget\": \"3-10%, nearly all of it as pale tints of the one hue\",\n      \"tokens\": {\n        \"ground\": \"#f9fafb\",\n        \"surface\": \"#ffffff\",\n        \"raised\": \"#f3f4f6\",\n        \"border\": \"#e5e7eb\",\n        \"rule\": \"#f2f2f2\",\n        \"control\": \"#d1d5db\",\n        \"text\": \"#111827\",\n        \"muted\": \"#5f6672\",\n        \"accent\": \"#b8336a\",\n        \"accentSoft\": \"#fdf2f7\",\n        \"accentTrack\": \"#f8dbe8\",\n        \"accentInk\": \"#6b1d3e\",\n        \"positive\": \"#247b50\",\n        \"negative\": \"#c4242a\",\n        \"warning\": \"#92400e\",\n        \"chart\": [\n          \"#b8336a\",\n          \"#6b7280\",\n          \"#d4618f\"\n        ],\n        \"pills\": {\n          \"positive\": [\n            \"#dcfce7\",\n            \"#14532d\"\n          ],\n          \"negative\": [\n            \"#ffedea\",\n            \"#831c1e\"\n          ],\n          \"warning\": [\n            \"#fffbeb\",\n            \"#92400e\"\n          ],\n          \"neutral\": [\n            \"#f3f4f6\",\n            \"#374151\"\n          ],\n          \"accent\": [\n            \"#fdf2f7\",\n            \"#6b1d3e\"\n          ]\n        },\n        \"radius\": {\n          \"card\": 8,\n          \"control\": 6\n        },\n        \"font\": {\n          \"family\": \"DM Sans\",\n          \"second\": null,\n          \"fallback\": \"Inter, system-ui, sans-serif\",\n          \"sizes\": {\n            \"title\": 32,\n            \"section\": 18,\n            \"kpi\": 24,\n            \"body\": 14,\n            \"small\": 12\n          },\n          \"weights\": [\n            400,\n            500,\n            600,\n            700\n          ],\n          \"note\": \"700 for the page title only.\"\n        },\n        \"density\": \"sparse\",\n        \"rowHeight\": 45,\n        \"sidebarWidth\": 230,\n        \"gap\": 24,\n        \"pad\": 24,\n        \"controlHeight\": 32\n      },\n      \"shell\": \"open-plane\",\n      \"shellAlternatives\": [\n        \"ruled-t-frame\"\n      ],\n      \"signature\": \"The full hue goes only on small marks: the one filled-button style, the data series and the active nav icon. Its 50-200 tints carry every area: the active nav row (tint fill with the dark ink of the hue), the plan or trial card, badges and progress tracks. The primary action may instead be near-black, as on the study's newsletter home.\",\n      \"identity\": [\n        \"The ladder built from the brand's own hue (its logo, the brief's object) in place of the dealt raspberry: the full hue on small marks, its pale tints on areas, never violet or indigo.\",\n        \"The product's objects in the lead block: the newsletter's latest issue as its cover, the shop's products as 40px thumbnails, the course's lessons with their own art.\",\n        \"A ground one level toward the hue's palest tint (#fbf7f8 for the raspberry) in place of #f9fafb, so the page and the tints read as one family.\"\n      ],\n      \"avoid\": [\n        \"the full hue on large areas\",\n        \"a second accent family (four families on one screen was flagged in the study)\",\n        \"a gradient on the trial chip or upgrade button\",\n        \"a left accent bar on the active nav row on top of the tint (seen once in 23 screens)\",\n        \"violet or indigo\"\n      ],\n      \"notes\": \"All three studied screens of this kind used violet, purple or pink as the one hue. The move does not depend on the hue, so the house's violet and indigo ban holds and the library deals a raspberry instead.\"\n    },\n    {\n      \"id\": \"editorial-greeting\",\n      \"name\": \"Editorial greeting\",\n      \"theme\": \"light\",\n      \"basis\": \"2 screens: a team workspace home and a personal insights home\",\n      \"suits\": [\n        \"workspace\",\n        \"creator\"\n      ],\n      \"idea\": \"A personal or team home that opens with a typeset greeting in a centred column; every number below it is set at regular weight on tonal panels.\",\n      \"colourBudget\": \"under 2% for the accent; tonal panels carry the structure\",\n      \"tokens\": {\n        \"ground\": \"#ffffff\",\n        \"surface\": \"#f9f9f9\",\n        \"raised\": \"#ffffff\",\n        \"border\": \"#eaeaea\",\n        \"rule\": \"#f3f3f3\",\n        \"control\": \"#d9d9d6\",\n        \"text\": \"#1f201d\",\n        \"muted\": \"#636361\",\n        \"accent\": \"#1b6e66\",\n        \"positive\": \"#2e7d32\",\n        \"negative\": \"#b42318\",\n        \"warning\": \"#92400e\",\n        \"chart\": [\n          \"#1f201d\",\n          \"#1b6e66\",\n          \"#8c8c88\"\n        ],\n        \"pills\": {\n          \"positive\": [\n            \"#dcfae5\",\n            \"#04250e\"\n          ],\n          \"negative\": [\n            \"#fdecea\",\n            \"#7a1d14\"\n          ],\n          \"warning\": [\n            \"#fffbeb\",\n            \"#92400e\"\n          ],\n          \"neutral\": [\n            \"#f3f3f3\",\n            \"#3d3d3a\"\n          ]\n        },\n        \"radius\": {\n          \"card\": 22,\n          \"control\": 999\n        },\n        \"font\": {\n          \"family\": \"Instrument Sans\",\n          \"second\": \"Instrument Serif, for the greeting only\",\n          \"fallback\": \"Inter, system-ui, sans-serif\",\n          \"sizes\": {\n            \"title\": 48,\n            \"section\": 14,\n            \"kpi\": 32,\n            \"body\": 14,\n            \"small\": 12\n          },\n          \"weights\": [\n            400,\n            500,\n            600\n          ],\n          \"note\": \"The 48px title is the serif greeting; set in the sans it is 24/400. Every figure is 400.\"\n        },\n        \"density\": \"sparse\",\n        \"rowHeight\": 63,\n        \"sidebarWidth\": 224,\n        \"gap\": 16,\n        \"pad\": 20,\n        \"controlHeight\": 38\n      },\n      \"shell\": \"open-plane\",\n      \"shellAlternatives\": [\n        \"framed-sheet\"\n      ],\n      \"signature\": \"The greeting is the h1, in a centred 1100px column on a real 12-column grid (77px columns, 16px gutters), with spans that change by row but share column lines (3/3/3/3, then 9/3, then 6/6, so every internal edge meets one above it). Every figure below is set at regular weight on tonal panels, one layer each: a panel one step off white holds its title and its content directly; a white inner card is used once, for the main chart.\",\n      \"identity\": [\n        \"The greeting names this team or household and today's one fact, set from the data (\\\"Morning, Okoro house. The car is ready by 06:10.\\\"), never \\\"Welcome back\\\".\",\n        \"Each person's stable hue as a pale tint on their avatar and their own lane or column (a couple and their joint account as three lanes): identity, not data, so it stays out of the chart legends.\",\n        \"A surface from the product's world in place of #f9f9f9, one level toward its material (a sage for a garden, a stone for a kitchen, a blue-grey for a studio), with the page white kept.\"\n      ],\n      \"avoid\": [\n        \"an emoji in the greeting\",\n        \"a tracked uppercase date above the greeting (put the date after it or in the grey line below)\",\n        \"a 624-864px column on a desktop screen (both were flagged as wasted width)\",\n        \"a tray around every card (a grey panel with a white card 6px inside it, on every block, read as a bento template in testing)\",\n        \"red as the accent: in testing red marked a record week of upgrades and read as an alarm; red is for the failing fact only\"\n      ],\n      \"notes\": \"One studied screen set its greeting in a serif at 48/700 and its counts in a mono; the other set the greeting at 24/400 in the sans. The red is the second screen's chart red moved two degrees of hue out of the house terracotta range. After testing, the studied red accent was replaced by a deep teal: red on good news read as an alarm.\"\n    },\n    {\n      \"id\": \"pastel-consumer\",\n      \"name\": \"Pastel consumer\",\n      \"theme\": \"light\",\n      \"basis\": \"2 screens: a wallet home and a personal finance home\",\n      \"suits\": [\n        \"wallet\",\n        \"finance\"\n      ],\n      \"idea\": \"Categories are coded by pale tints whose ink is the dark of the same hue, all under one large radius, and each headline sum sits inside the card that explains it.\",\n      \"colourBudget\": \"5-8%, as pale tiles and data marks\",\n      \"tokens\": {\n        \"ground\": \"#f3f5f7\",\n        \"surface\": \"#ffffff\",\n        \"raised\": \"#f2f8fd\",\n        \"border\": \"#e6e6e6\",\n        \"rule\": \"#f4f4f4\",\n        \"control\": \"#d6d9dd\",\n        \"text\": \"#1b1d1f\",\n        \"muted\": \"#5c6064\",\n        \"accent\": \"#1d5fd6\",\n        \"accentSoft\": \"#dcf1ff\",\n        \"accentInk\": \"#0a3a80\",\n        \"positive\": \"#2f7a45\",\n        \"negative\": \"#c41c29\",\n        \"warning\": \"#92400e\",\n        \"chart\": [\n          \"#1d5fd6\",\n          \"#b45309\",\n          \"#2a8798\"\n        ],\n        \"pills\": {\n          \"positive\": [\n            \"#dcfae5\",\n            \"#04250e\"\n          ],\n          \"negative\": [\n            \"#ffedea\",\n            \"#831c1e\"\n          ],\n          \"warning\": [\n            \"#fffbeb\",\n            \"#92400e\"\n          ],\n          \"neutral\": [\n            \"#eef1f4\",\n            \"#3a3d40\"\n          ],\n          \"accent\": [\n            \"#dcf1ff\",\n            \"#0a3a80\"\n          ]\n        },\n        \"radius\": {\n          \"card\": 20,\n          \"control\": 10\n        },\n        \"font\": {\n          \"family\": \"Manrope\",\n          \"second\": null,\n          \"fallback\": \"Inter, system-ui, sans-serif\",\n          \"sizes\": {\n            \"title\": 28,\n            \"section\": 20,\n            \"kpi\": 32,\n            \"body\": 16,\n            \"small\": 14\n          },\n          \"weights\": [\n            400,\n            500,\n            600\n          ],\n          \"note\": \"Money at 24-32px; card titles regular; semibold for net worth, bill amounts and actions.\"\n        },\n        \"density\": \"medium\",\n        \"rowHeight\": 72,\n        \"sidebarWidth\": 240,\n        \"gap\": 24,\n        \"pad\": 24,\n        \"controlHeight\": 40\n      },\n      \"shell\": \"open-plane\",\n      \"shellAlternatives\": [\n        \"icon-rail\"\n      ],\n      \"signature\": \"Pale category tiles with the dark of their own hue as ink (#dcf1ff with #0a3a80), one large radius (20px on cards, stepping down to 10, 8 and 5 inside), and quiet money polarity: income green with a plus sign, spending in ink, no red on ordinary outgoings. Tints go on small tiles, avatars and chips; a panel that holds a list stays white. When the product has people (two partners, a family), each gets one hue, at least 60 degrees from the next.\",\n      \"identity\": [\n        \"The tile hues from the account's own colours (the card's colour, each pot's colour in the app) in place of the dealt cobalt, each tile pale with the dark of its own hue as ink.\",\n        \"The money's own objects: the card art at its real ratio, merchant marks at 24px in the rows, the goal's picture on its pot.\",\n        \"Manrope's figures carry the balance: 30-36px at 600 with tabular figures and the pence in a smaller grey, so the number itself is the face.\"\n      ],\n      \"avoid\": [\n        \"a gradient balance card\",\n        \"two data palettes on one page (flagged in the study)\",\n        \"red on every outgoing amount\",\n        \"a 624px phone-width column on a desktop screen (flagged as a stretched phone screen)\",\n        \"a KPI strip on top: the sums belong in their cards\",\n        \"whole panels tinted per person or category beside white cards (two surface languages on one screen)\"\n      ],\n      \"notes\": \"The two studied screens used a pure #0000ff and an indigo #4723f5 as their brand colour, and pastels such as #7cbecf that fall under 3:1 on white. The library uses a cobalt that reads as blue rather than indigo, and data colours darkened to at least 3:1 on the card.\"\n    },\n    {\n      \"id\": \"true-black-flat\",\n      \"name\": \"True-black flat\",\n      \"theme\": \"dark\",\n      \"basis\": \"5 screens: an events back office, an event analytics tab, a community overview, an artist studio home, an artist insights page\",\n      \"suits\": [\n        \"community\",\n        \"creator\",\n        \"markets\"\n      ],\n      \"idea\": \"Night mode on true black: sidebar, top bar and page share one ground, elevation is a lightness step alone, and colour is confined to data marks.\",\n      \"colourBudget\": \"at or under 3%; the accent never touches buttons, tabs or nav\",\n      \"tokens\": {\n        \"ground\": \"#000000\",\n        \"surface\": \"#111111\",\n        \"raised\": \"#2a2a2a\",\n        \"border\": \"#1a1a1a\",\n        \"rule\": \"#161616\",\n        \"control\": \"#444444\",\n        \"text\": \"#ffffff\",\n        \"muted\": \"#b4b4b4\",\n        \"faint\": \"#949494\",\n        \"accent\": \"#c6f24e\",\n        \"positive\": \"#c6f24e\",\n        \"negative\": \"#e5484d\",\n        \"warning\": \"#e5a93b\",\n        \"chart\": [\n          \"#c6f24e\",\n          \"#e6e6e6\",\n          \"#6b6b6b\"\n        ],\n        \"pills\": {\n          \"positive\": [\n            \"#222a10\",\n            \"#c6f24e\"\n          ],\n          \"negative\": [\n            \"#2c1a20\",\n            \"#e5566f\"\n          ],\n          \"warning\": [\n            \"#2b2414\",\n            \"#e5a93b\"\n          ],\n          \"neutral\": [\n            \"#222222\",\n            \"#ffffff\"\n          ]\n        },\n        \"radius\": {\n          \"card\": 20,\n          \"control\": 999\n        },\n        \"font\": {\n          \"family\": \"Inter\",\n          \"second\": null,\n          \"fallback\": \"system-ui, sans-serif\",\n          \"sizes\": {\n            \"title\": 20,\n            \"section\": 16,\n            \"kpi\": 24,\n            \"body\": 14,\n            \"small\": 12\n          },\n          \"weights\": [\n            400,\n            500,\n            600\n          ],\n          \"note\": \"Nothing above 600; inactive nav labels #bbb, active #fff.\"\n        },\n        \"density\": \"medium\",\n        \"rowHeight\": 80,\n        \"sidebarWidth\": 210,\n        \"gap\": 14,\n        \"pad\": 22,\n        \"controlHeight\": 36\n      },\n      \"shell\": \"ruled-t-frame\",\n      \"shellAlternatives\": [\n        \"no-sidebar\"\n      ],\n      \"signature\": \"Elevation by lightness alone (#000 ground, #111 card, #2a2a2a nested panel) with no borders or shadows on cards; the active nav item is marked only by its label going from #bbb to #fff; the primary control is made primary by inversion, a white 36px pill with black text.\",\n      \"identity\": [\n        \"The one data hue from the product's world in place of the dealt lime: a solar amber (#f2b33d) for an energy home, a sky blue (#4cb3f0) for water or weather, a lime only for sport. It is still the only hue on data and never touches buttons, tabs or nav. A green or yellow-green hue is also --positive; an amber that sits beside --warning leaves the warning to its pill pair.\",\n        \"A ground with the product's temperature: the studied #000 for media and events, a warm near-black (#0e0d0c) for a home, a cool one (#0c0d0f) for a monitor, with cards one lightness step above it (#181716, #15171a). Never navy or slate.\",\n        \"A signature element from the product's world as the lead: the energy home's power flow (sun, house, battery and grid with their live kW), an event's doors against capacity, an artist's release with its cover.\"\n      ],\n      \"avoid\": [\n        \"a navy or slate dark theme\",\n        \"glow, neon borders or shadows\",\n        \"a hue per chart (five hues across four charts was flagged)\",\n        \"the accent on buttons, tabs or nav\",\n        \"a 64px top bar left empty across most of its width (flagged twice)\"\n      ],\n      \"notes\": \"The studied screens of this kind used a violet-magenta (#dd6cff) and an orange (#ff5500) as their one data hue. The library deals a lime, which keeps the move and stays clear of the violet ban; because the lime is a yellow-green, it is also the positive colour (a second, mint green beside it read as two greens). The greys are #b4b4b4 for secondary text and #949494 for meta, 32 levels apart rather than the 20 of the measured #aaa and #969696, which read as one grey; #949494 still holds 4.5:1 on the #2a2a2a nested panel.\"\n    },\n    {\n      \"id\": \"data-terminal\",\n      \"name\": \"Data terminal\",\n      \"theme\": \"dark\",\n      \"basis\": \"1 screen: a stock research view. Keep it narrow.\",\n      \"suits\": [\n        \"markets\",\n        \"devtools\"\n      ],\n      \"idea\": \"A research or monitoring screen read in long sessions: cards darker than the ground, tabular digits that stack, signs instead of colour, and every selection marked by the same 1px accent line.\",\n      \"colourBudget\": \"under 3%; the accent is never more than a 1px line\",\n      \"tokens\": {\n        \"ground\": \"#171719\",\n        \"surface\": \"#131217\",\n        \"raised\": \"#212023\",\n        \"border\": \"#222224\",\n        \"rule\": \"#1b1a1f\",\n        \"control\": \"#3a3a3e\",\n        \"text\": \"#ffffff\",\n        \"muted\": \"#8a8c92\",\n        \"accent\": \"#4a8ad6\",\n        \"positive\": \"#44a282\",\n        \"negative\": \"#e5566f\",\n        \"warning\": \"#d9a441\",\n        \"chart\": [\n          \"#f2f2f3\",\n          \"#e5566f\",\n          \"#4a8ad6\"\n        ],\n        \"pills\": {\n          \"positive\": [\n            \"#1b2828\",\n            \"#5fc39c\"\n          ],\n          \"negative\": [\n            \"#2c1a20\",\n            \"#e5566f\"\n          ],\n          \"warning\": [\n            \"#2a2416\",\n            \"#d9a441\"\n          ],\n          \"neutral\": [\n            \"#212023\",\n            \"#bdbdc0\"\n          ]\n        },\n        \"shadow\": \"0 12px 28px rgba(0,0,0,.2)\",\n        \"radius\": {\n          \"card\": 6,\n          \"control\": 999\n        },\n        \"font\": {\n          \"family\": \"Public Sans\",\n          \"second\": null,\n          \"fallback\": \"Inter, system-ui, sans-serif\",\n          \"sizes\": {\n            \"title\": 26,\n            \"section\": 20,\n            \"kpi\": 20,\n            \"body\": 13,\n            \"small\": 12\n          },\n          \"weights\": [\n            400,\n            500,\n            600,\n            700\n          ],\n          \"note\": \"Section titles 20/400 in the muted grey; card titles 16/600; tabular figures everywhere.\"\n        },\n        \"density\": \"dense\",\n        \"rowHeight\": 42,\n        \"sidebarWidth\": 50,\n        \"gap\": 24,\n        \"pad\": 32,\n        \"controlHeight\": 34\n      },\n      \"shell\": \"icon-rail\",\n      \"shellAlternatives\": [],\n      \"signature\": \"Every selection (tab, toggle, range, nav item) is a 1px accent line exactly as wide as its label, placed on the nearest existing edge; numbers stay white or grey and carry their sign in the text ('+$24,000,000').\",\n      \"identity\": [\n        \"Every figure in a monospace as the style's decision (IBM Plex Mono or JetBrains Mono for each price, count and time, digits that stack), with the text in Public Sans. Lint and the inspector flag mono; give the reason in the report.\",\n        \"The one accent line from the product's world in place of the dealt blue (the exchange's or the team's hue): still the only selection mark, never violet or indigo.\",\n        \"A signature of the market or the system as the lead: an order book's depth as two mirrored bar lists, an incident as a minute-by-minute strip, a region map with the list beside it.\"\n      ],\n      \"avoid\": [\n        \"filled pill tabs or a coloured segmented control\",\n        \"a chart with no scale and no dates (the studied screen had none and was flagged)\",\n        \"tertiary text under 4.5:1 (#4c4c4f read at about 2:1 in the study)\",\n        \"lighter cards with borders and a glow\",\n        \"green and red on every number; the one column whose job is \\\"what moved today\\\" and a negative headline figure may carry the polarity colours\"\n      ],\n      \"notes\": \"The studied screen's muted grey #82848a and red #d4405d were lifted to #8a8c92 and #e5566f so text passes 4.5:1 on the card. Its card list rows sit on a 28px pitch and its table rows on 42px.\"\n    }\n  ],\n  \"shells\": [\n    {\n      \"id\": \"open-plane\",\n      \"name\": \"Open plane\",\n      \"basis\": \"5 of 23 screens\",\n      \"suits\": [\n        \"finance\",\n        \"wallet\",\n        \"workspace\",\n        \"creator\",\n        \"analytics\"\n      ],\n      \"numbers\": {\n        \"sidebarWidth\": \"230-256 (230, 240, 256 in the study; 280 and 292 with a built-in icon rail)\",\n        \"separation\": \"none, or one 1px hairline; the sidebar sits on the page ground or within 1-2% of it\",\n        \"navPitch\": 34,\n        \"navRowHeight\": 32,\n        \"navIcon\": \"16px outline, about 1.5px stroke\",\n        \"navLabel\": \"14px, 400, grey or ink\",\n        \"activeItem\": \"neutral grey pill, radius 6-12, inset 8-12px from the sidebar edges (#e9e9e9-#ededed)\",\n        \"topBar\": \"none\",\n        \"canvas\": \"fluid with a 24-64px gutter, or a centred 1100px column\"\n      },\n      \"blueprint\": \"The labelled sidebar sits on the page ground with nothing or one hairline between it and the canvas; there is no top bar, and the page header and cards sit straight on the ground about 32-36px from the top. Workspace or account switcher at the top of the sidebar, primary nav on a 34px pitch, groups under 12-13px sentence-case grey labels with 22-56px of air above, utilities and the user row pushed to the bottom. Cards are white on the off-white ground (or the sidebar is white with a 1px border on a #f9fafb canvas). The canvas is fluid with one gutter value, or a centred column for personal homes.\",\n      \"phone\": \"The sidebar folds into a 48px top bar holding the screen's name, a menu button that opens a full-screen sheet with the nav and the switcher, and at most one action. Content takes the full width with 16px margins.\"\n    },\n    {\n      \"id\": \"framed-sheet\",\n      \"name\": \"Tinted frame, white sheet\",\n      \"basis\": \"8 of 23 screens, in three variants\",\n      \"suits\": [\n        \"analytics\",\n        \"devtools\",\n        \"builder\",\n        \"smb-admin\",\n        \"support\"\n      ],\n      \"numbers\": {\n        \"chrome\": \"#f6f6f6-#f9fbfc (a warm #f7f6f2 once)\",\n        \"sheetInset\": \"8px from the window's right and bottom edges (12 and 16 once each)\",\n        \"sheetRadius\": \"10-16, median 16\",\n        \"sheetEdge\": \"1px #eaeaea-#ededed, no shadow\",\n        \"sidebarWidth\": \"220-263 (228 on two screens)\",\n        \"topBar\": \"48px on the chrome ground with no rule; search 548x32 centred on the window with a shortcut hint\",\n        \"contentPadding\": 24,\n        \"floatingVariant\": \"both panels inset 12px with a 12px gutter, radius 10\"\n      },\n      \"blueprint\": \"Sidebar and top bar share one tinted ground with no rule between them, forming an L; the page lives on a white sheet. Variant one: the sheet butts against the sidebar and the top bar and is inset 8px from the right and bottom edges, 16px radius, 1px edge. Variant two: a flush L-frame with no inset, the frame marked by one rule. Variant three: sidebar and content are two floating panels inset 12px from every edge with a 12px gutter. The top bar, when present, is 48px and holds a centred search, the account button and a help or AI icon. Inside the sheet the content has 24px padding and starts with the breadcrumb or title row.\",\n      \"phone\": \"The frame disappears: the sheet becomes the screen, with a 48px top bar (menu button, title, one action) on the chrome tint. The search moves into the menu sheet or behind an icon.\"\n    },\n    {\n      \"id\": \"ruled-t-frame\",\n      \"name\": \"Ruled T-frame\",\n      \"basis\": \"4 of 23 screens (3 dark, 1 light)\",\n      \"suits\": [\n        \"community\",\n        \"creator\",\n        \"smb-admin\"\n      ],\n      \"numbers\": {\n        \"sidebarWidth\": \"210-240\",\n        \"topBar\": \"64px with a 1px bottom rule\",\n        \"rules\": \"1px; #1a1a1a on #000, #f2f2f2 on white\",\n        \"navPitch\": \"34 (dark) or 40 (light)\",\n        \"switcher\": \"at the top bar's right end, behind a full-height 1px divider\",\n        \"contentGutter\": \"29px from the sidebar rule and the window edge\"\n      },\n      \"blueprint\": \"A 210-240px sidebar and a 64px top bar share one ground, divided only by 1px rules. The workspace or community switcher sits at the right end of the top bar behind a full-height divider; the sidebar holds the wordmark and the nav on a 34px pitch with sentence-case group labels. On dark, the active item is its label going from #bbb to #fff. The top bar must carry something real (search, the back link and object name, the switcher): two studied screens left about 1070px of it blank and were flagged.\",\n      \"phone\": \"The top bar stays at 48-56px with the switcher reduced to its mark; the sidebar becomes a full-screen menu sheet or a bottom bar of four or five destinations.\"\n    },\n    {\n      \"id\": \"icon-rail\",\n      \"name\": \"Icon rail\",\n      \"basis\": \"3 of 23 screens\",\n      \"suits\": [\n        \"markets\",\n        \"devtools\",\n        \"finance\",\n        \"wallet\"\n      ],\n      \"numbers\": {\n        \"railWidth\": \"50-60, median 55\",\n        \"icon\": \"15-18px outline\",\n        \"pitch\": \"34-49\",\n        \"active\": \"icon colour alone, or a full-bleed 50px band at a 2% tint, or a 1px accent bar on the rail's border\",\n        \"groups\": \"short 20px hairlines, no labels\",\n        \"utilities\": \"pushed to the bottom after a gap of about 200px\"\n      },\n      \"blueprint\": \"An unlabelled rail of 50-60px carries the brand mark at the top and 15-18px outline icons on a 34-49px pitch; groups are split by 20px hairlines, utilities sit at the bottom. The rail sits on the page ground with a 1px edge, or is white with a faint 4px shadow on a grey ground. It saves about 180px of width against a labelled sidebar, so it suits products with few destinations and screens that need the width. Icons need tooltips and an accessible name.\",\n      \"phone\": \"The rail becomes a bottom bar with the same four or five icons, each with a short label under it.\"\n    },\n    {\n      \"id\": \"no-sidebar\",\n      \"name\": \"No sidebar\",\n      \"basis\": \"3 of 23 screens\",\n      \"suits\": [\n        \"report\",\n        \"creator\",\n        \"community\"\n      ],\n      \"numbers\": {\n        \"topBar\": \"46-48px on the page ground, no border\",\n        \"column\": \"centred, 1088-1208px\",\n        \"gutters\": \"152-212px at a 1512px window\",\n        \"logo\": \"on the column's left edge\",\n        \"links\": \"14-15px semibold grey\"\n      },\n      \"blueprint\": \"A 46-48px top bar on the page ground over a centred 1088-1208px column; the logo sits exactly on the column's left edge and the bar's right cluster ends near its right edge, so header and content share one column. Three to five text links, a 36px search, the account. Use it for generated reports, viewers and products with few destinations; with a sticky bar on the same ground, give it a 1px rule when content scrolls under it (the studied bar without one sliced content off).\",\n      \"phone\": \"The bar keeps the logo, a search icon and a menu button; the links move into the menu sheet. The column becomes the full width with 16px margins.\"\n    }\n  ],\n  \"patterns\": [\n    {\n      \"id\": \"kpi-strip-chart-rail\",\n      \"name\": \"KPI strip, main chart and a side rail\",\n      \"screen\": \"overview\",\n      \"kinds\": [\n        \"creator\",\n        \"smb-admin\",\n        \"community\",\n        \"analytics\"\n      ],\n      \"basis\": \"a newsletter home; a community overview\",\n      \"blueprint\": \"Title row: a 24px noun or the product's name at 600-700, an optional 14-16px grey line under it, and the one primary action on the right, bottom-aligned with that line. 16-24px below, the scope row: section tabs and the date range in one row of 32-36px controls, or a 48px segmented track with the range select inside its right end. Then a grid of 1fr and a fixed 384px rail with a 24px gap. Main column: one KPI container split by 1px dividers into 3-5 equal cells (14px grey label, 24px value at 400-600, a 12px caption naming the baseline and window), then the main chart card, which is the largest thing on the screen, then the next card, all 16px apart. Rail: 16px headings outside their cards, 8px above each and 16px after the previous card; a recent-items list of 3-5 rows on a 45px pitch with 1px rules, closed by a 30px outlined 'View all' button instead of pagination. The rail starts level with the first card, not with the title.\",\n      \"phone\": \"The rail moves below the main column; the KPI container becomes a 2-column grid; tabs scroll inside their own row.\"\n    },\n    {\n      \"id\": \"kpi-tabs-chart\",\n      \"name\": \"KPIs as the chart's tabs\",\n      \"screen\": \"overview\",\n      \"kinds\": [\n        \"finance\",\n        \"commerce\"\n      ],\n      \"basis\": \"a seller home\",\n      \"blueprint\": \"One card per subject, 8-16px apart: the main chart card runs full width, and any card holding a table of five columns or fewer, or a short list, pairs with its neighbour in two columns, the page header indented by the card padding so the title, the card titles, the numbers and the plot share one left edge. Balances that do not change during the day go first, in one container split by 1px dividers into equal columns; a zero balance is grey and its caption becomes the next step. In the main card, 2-4 KPIs sit in a row and act as the chart's series tabs: the selected one carries a 2px rule and an ink label, the others keep a grey label and their value in ink at a lighter weight (a grey value reads as disabled); when the tabs are the per-entity breakdown the brief asks for (takings by shop), nothing is greyed and the rule alone marks the selection. Choosing one swaps the series. Under them, one line chart as wide as the card's content (about 1136x220 in the study): 3-4 solid 1px gridlines, 4-6 round y ticks at 12px, a 2-3px line in ink with straight segments and no fill, an 8px hover dot with a 1px dashed guide and the line after the cursor in pale grey. Close with a 2-3 row comparison table on a 36px pitch, value and change columns right-aligned under a 14px grey header such as 'vs prior Monday'.\",\n      \"phone\": \"KPI tabs become a 2-up grid above the chart, with the selected cell marked by a fill (never an underline floating inside the grid) or a row of tabs that scrolls sideways; the chart is full width, 160-200px tall, with 4 x labels; the comparison table keeps its two right-aligned columns.\"\n    },\n    {\n      \"id\": \"chart-pairs\",\n      \"name\": \"Per-period and running-total pairs\",\n      \"screen\": \"analytics\",\n      \"kinds\": [\n        \"community\",\n        \"smb-admin\",\n        \"analytics\"\n      ],\n      \"basis\": \"a network analytics overview\",\n      \"blueprint\": \"Title at 24-32px with one sentence under it saying what the filters do, then one filter row of 36-38px controls (one filled or near-black, the rest borderless or text, a reset link last) and 16-24px to the KPIs. KPI row: 3 equal cards in the content column (3 x 372 + 2 x 17 = 1152 in the study) or one divided container; a 16px label over the value with the change written as a phrase on the value's baseline ('+8 in the last 90 days'), grey when it is zero. Then one row per metric: the per-period column chart on the left and its cumulative line on the right, at equal width (2 x 568 + 16 = 1152) and with the same x ticks; square bars, a 2px straight line, integer ticks from zero, no legend because each chart has one series. One gap value horizontally and vertically.\",\n      \"phone\": \"Pairs stack, the cumulative chart directly under its per-period chart; KPI cards become a single column of label-value rows.\"\n    },\n    {\n      \"id\": \"insights-share-tables\",\n      \"name\": \"Insights with share tables\",\n      \"screen\": \"analytics\",\n      \"kinds\": [\n        \"analytics\",\n        \"devtools\",\n        \"builder\"\n      ],\n      \"basis\": \"a per-agent insights page\",\n      \"blueprint\": \"No cards: sections are carried by whitespace and a 16/500 heading with one 14px grey sentence under it saying what the section shows. A row of up to 6 KPIs on a fixed pitch (12px grey label over a 30px tabular value, no boxes, no dividers), then one full-width time chart (about 218px plot, 5 hairline gridlines, 11-12px grey ticks, a dot legend under the title, a 'Compare to previous period' text button on the right). Then a 2 x 2 grid of small tables with a 24px gutter whose rows align across the two columns. Each table: a header of 12px grey labels with no fill and no rule, 44px rows with 2px gaps whose rounded fill (#f5f7f9, radius 8) is the data bar, its width the row's share divided by the largest share; Share in 12px grey and Count in 14px ink, both right-aligned. An empty table keeps its header and shows one dashed 1px box about 38px tall with one sentence ('No Slack channel usage in this range.').\",\n      \"phone\": \"KPIs become a 2 x 3 grid; the chart is full width; the share tables stack in one column and keep their row bars.\"\n    },\n    {\n      \"id\": \"table-filter-bar\",\n      \"name\": \"Table with tabs and a filter bar\",\n      \"screen\": \"list\",\n      \"kinds\": [\n        \"community\",\n        \"devtools\",\n        \"commerce\",\n        \"support\",\n        \"smb-admin\"\n      ],\n      \"basis\": \"an events back office, a tracks studio, a sessions overview\",\n      \"blueprint\": \"Title row: an 18-24px title on the left, at most an outlined secondary and the one primary (36px) on the right. Underline tabs for the list's states on a full-width 1px rule with a 2px indicator as wide as the label; 22-32px below, the toolbar: a search of about 252-316 x 32-36 on the left, the count ('7 events') and the sort on the right. The table sits on the panel or page ground with no card around it: a header of 12-13px grey sentence-case labels with no fill and no rule, rows on a 48-56px pitch for one line or 72-92px with a thumbnail (media height plus 24-32px), 1px rules 3-7% darker than the ground or no rules at all, the identity column given the most width, numbers right-aligned in tabular figures with the unit muted ('5 /10'), one status mark per row and one kebab at the far right. Drop a column that is empty in every row (a blank co-host column left a 300px dead band). On an overview, cap the rows and link to the full list; on the full list, state the total and load more at the end.\",\n      \"phone\": \"Rows become two-line items: identity and the key number on line 1, the secondary fields in 13px grey on line 2, the kebab at the right. Tabs scroll in their own row; the search becomes a full-width field.\"\n    },\n    {\n      \"id\": \"count-cards-filter\",\n      \"name\": \"Count cards that filter\",\n      \"screen\": \"list\",\n      \"kinds\": [\n        \"community\",\n        \"commerce\",\n        \"support\"\n      ],\n      \"basis\": \"an events back office\",\n      \"blueprint\": \"Above a list, 3-5 equal count cards (61px tall, 12px padding, a 13px grey label over a 16/600 value, 8px gap) are the type filter: the selected card gets a 1.5px accent border and a pale accent fill, and the list below shows that type only. Zero counts print as '0' in the same style; no deltas, no icons. This is one place where a row of identical small cards is right: the cards are peers and each one does work.\",\n      \"phone\": \"The count cards become a horizontally scrolling row of chips with the count inside each, or a select above the list.\"\n    },\n    {\n      \"id\": \"settings-two-column\",\n      \"name\": \"Settings in two columns\",\n      \"screen\": \"settings\",\n      \"kinds\": [\n        \"devtools\",\n        \"smb-admin\",\n        \"support\",\n        \"workspace\",\n        \"commerce\",\n        \"analytics\",\n        \"finance\",\n        \"wallet\",\n        \"creator\",\n        \"community\",\n        \"builder\",\n        \"markets\",\n        \"report\"\n      ],\n      \"basis\": \"one settings page; stacking from a narrow rail card. The basis is thin.\",\n      \"blueprint\": \"A centred column of about 1152px. Each section is one row: a label column of about 450px (16/500 title, 14px grey description; the title's cap top 6-8px below the panel top, level with the panel's first line) beside a panel of about 700px with a #fafafa fill, 16px radius, 16px padding, no border and no shadow. Sections are split by a full-width 1px rule with 32px above and below. Inside a panel: field labels 14/500 above 40px white inputs (1px #e8e8e8, radius 10), 8px from label to field, 16px between fields, 24px from the description to the first label, 16px to the Save button; switch rows with a 14/500 title, a 20px status badge 8px after it, a 14px grey description and a 28x16 toggle 16px from the right edge, centred on the title line. A plan-gated feature shows a 48px tinted strip with a 32px button directly above its panel, and the panel stays readable. When a panel runs much taller than its label, put the section's help or a summary of the current values in the label column rather than 250px of nothing.\",\n      \"phone\": \"Each section stacks: title and description, then the panel at full width. Inside, label, 8-10px, field, 16-26px to the next pair; toggles stay on the right of their title.\"\n    },\n    {\n      \"id\": \"settings-with-usage\",\n      \"name\": \"Settings with usage on top\",\n      \"screen\": \"settings\",\n      \"kinds\": [\n        \"devtools\",\n        \"smb-admin\",\n        \"support\"\n      ],\n      \"basis\": \"one settings page\",\n      \"blueprint\": \"Use this only when usage is the question of the view (a plan, billing or quota view), and show only numbers no section below repeats, at a size below the h1. When a settings screen also reports usage, put 3-4 usage numbers in one row on top (a 14px grey label, a 30px regular value, a 12px change pinned to the card bottom with its window in words, a grey dash where there is no comparison) and link out to the analytics screen ('View more') instead of drawing a chart. Below, the two-column settings rows. One dark primary per screen. Keep upsell to one surface: the studied settings page carried three nags (a top banner, a setup button and a gated strip) and was flagged for it.\",\n      \"phone\": \"The usage row becomes a 2-column grid of label-value pairs; settings rows stack.\"\n    },\n    {\n      \"id\": \"wallet-balance-actions-assets\",\n      \"name\": \"Balance, actions and assets\",\n      \"screen\": \"wallet\",\n      \"kinds\": [\n        \"wallet\",\n        \"finance\"\n      ],\n      \"basis\": \"a wallet home\",\n      \"blueprint\": \"One column whose every element snaps to its two edges. A balance card (1px border, 16px radius, about 134px tall) holding one 32px figure and one line under it in which only the change is coloured ('-$0.09 in the last 30 days'); the title says what the figure is, so it needs no label. 32px below, 4 equal action tiles in a pale tint with dark same-hue icon and 12-14px label (4 x 144 + 3 x 16 = 624 in the study; scale the column and keep the arithmetic). 32-40px below, text tabs for the asset kinds on a 1px rule with a 2px ink indicator as wide as the word, a network or account select on the right of the same row. Then the asset table: 72px rows (48px round icon plus 24px), no dividers, two-line cells pairing a 16px value with a 14px grey unit amount, numeric columns right-aligned to shared edges, change as a small solid triangle and a coloured percentage, zero change grey, a missing share a grey em dash. On a desktop do not leave the column at phone width: the study's 624px column was flagged as a stretched phone screen; widen it to 864-1100 or give it a second column.\",\n      \"phone\": \"This pattern is phone-first: the same column at full width with 16px margins, the 4 tiles in one row, the table as two-line rows with the value right-aligned.\"\n    },\n    {\n      \"id\": \"finance-home-pinned-rail\",\n      \"name\": \"Finance home with a pinned accounts column\",\n      \"screen\": \"overview\",\n      \"kinds\": [\n        \"finance\",\n        \"wallet\"\n      ],\n      \"basis\": \"a personal finance home\",\n      \"blueprint\": \"No page header and no KPI strip: cards start 36px from the top and each headline sum sits in the card that explains it. On the left, a 306px accounts card pinned at the viewport height minus the 36px margins opens with net worth (16/600 label left, value right) and holds the account tree with no dividers: groups 16px ink, categories 14px ink, leaves 14px grey indented 8px, values right-aligned, a 30px pitch and about 45px between groups; an empty group is a bordered box with an '+ Add account' link instead of $0.00. On the right, a 2-column grid with 24px gaps of cards that answer this month's questions, each with its own period caption: the plan (spanning both columns; a ring with an empty hole, a dot legend, the available figure beside it with a per-day line), recent spending as 61px two-line rows (payee over category, amount over date, right-aligned) and upcoming bills. Income is green with a plus sign; spending stays in ink.\",\n      \"phone\": \"Net worth becomes the first card; the account tree collapses to its groups with totals; the month cards stack.\"\n    },\n    {\n      \"id\": \"builder-canvas\",\n      \"name\": \"Builder canvas\",\n      \"screen\": \"builder\",\n      \"kinds\": [\n        \"builder\"\n      ],\n      \"basis\": \"a flow builder in analytics mode\",\n      \"blueprint\": \"No global navigation: a 44px top bar on the window ground with no rule (an exit arrow, the object's name at 16/600 with a status pill, and on the right 16px icon buttons on a 40px pitch, a secondary and a near-black primary, split by 1px dividers). Below, two panels on the ground with 8px outer margins and a 12px gap, both wi\n\n<!-- [TRUNCATED AT 50KB] -->","isInternal":false,"tokens":13188,"sizeBytes":50031},{"name":"directions.json","path":"skills/taste-skill/library/directions.json","rawUrl":"https://raw.githubusercontent.com/Leonxlnx/taste-skill/HEAD/skills/taste-skill/library/directions.json","title":"Library Skill","category":"anthropic-skill","format":"json","content":"[\n {\n  \"id\": \"name-as-monument\",\n  \"name\": \"The name as a monument\",\n  \"sectors\": [\n   \"agency\",\n   \"studio-portfolio\",\n   \"personal-portfolio\",\n   \"hospitality\",\n   \"restaurant\",\n   \"music\",\n   \"culture\",\n   \"fashion\",\n   \"event\",\n   \"architecture\",\n   \"real-estate\",\n   \"physical-product\",\n   \"consumer-app\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"bold\",\n   \"editorial\",\n   \"luxury\"\n  ],\n  \"needs\": [],\n  \"idea\": \"The name is the headline. Set it so large that it becomes architecture: as wide as the viewport, cropped by an edge, or stacked to fill the screen. Nothing else on the first screen competes; the description of what this is drops to a single small sentence. The idea comes from treating the name's letters as material. Ask what the subject can do to its own name: a photograph of the work sits inside a counter or replaces a letter, the name repeats down the page like a reel, the letters are split to opposite corners and the page happens between them. In the study this was the single most common device among sites scoring 7.5 or more.\",\n  \"composition\": \"First screen: the wordmark spans 88–100% of the viewport width (font-size 16–24vw, set with a clamp so it never wraps), anchored either to the bottom edge with its descenders nearly touching it, or dead centre with everything else pushed to the corners. One line of supporting text at 16–20px sits in a corner on a shared margin; navigation is three or four words in the opposite corner. After the hero the page is deliberately small and calm: a narrow text column or a simple two-column grid, so the contrast with the monument holds. The name returns once more at full width as the footer, in the inverse colours. Margins are tight (20–32px) so the type reaches the edges. Two type sizes do nearly all the work: the monument and a small text size, with one mid size for section headings.\",\n  \"typography\": \"One family. The display cut must survive enormous sizes: tight tracking (-0.04 to -0.07em), leading 0.8–0.9, optical kerning on. Section headings are modest (28–40px) on purpose.\",\n  \"typeClasses\": [\n   \"grotesk-tight\",\n   \"condensed-heavy\",\n   \"extended-heavy\",\n   \"heavy-black\",\n   \"serif-display\"\n  ],\n  \"colour\": \"Two values carry the page (ground and ink). The accent, if used at all, appears on one thing only: the single action or the inset image frame. The footer inverts ground and ink.\",\n  \"paletteTags\": [\n   \"light-neutral\",\n   \"dark-neutral\",\n   \"two-tone\",\n   \"mono-accent\"\n  ],\n  \"imagery\": \"Few images, used as inserts in the typography rather than as illustrations beside it: one photograph inside or behind the name (a 4:5 or 1:1 frame replacing a letter, or tucked between two words), then a short run of large full-width or half-width photographs further down. Square corners. No collage of small thumbnails.\",\n  \"sectionTags\": [\n   \"type-led\",\n   \"quiet\",\n   \"poster\"\n  ],\n  \"motion\": \"scaling-wordmark\",\n  \"richness\": \"Scale. The size of the name against the smallness of everything else is the entire visual event, so protect both ends: do not shrink the name to make room, and do not let body text creep above 20px.\",\n  \"pitfalls\": \"A long name set small is just a logo. If the name has more than about 12 characters, stack it on two lines or crop it with the viewport edge; never drop below 12vw. Do not add a second big headline under the name. Do not decorate the letters.\",\n  \"seenIn\": [\n   \"aww-nothin\",\n   \"opl-kereliott\",\n   \"aww-paul-kalkbrenner\",\n   \"opl-nia-creative\",\n   \"aww-house-of-honey-1\",\n   \"aww-produx-design\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"sentence-as-layout\",\n  \"name\": \"The sentence is the layout\",\n  \"sectors\": [\n   \"agency\",\n   \"saas\",\n   \"ai-product\",\n   \"dev-tool\",\n   \"nonprofit\",\n   \"culture\",\n   \"education\",\n   \"physical-product\",\n   \"consumer-app\",\n   \"finance\",\n   \"health\",\n   \"event\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"bold\",\n   \"editorial\"\n  ],\n  \"needs\": [],\n  \"idea\": \"One short sentence, set at poster scale, is the composition. The trick that makes it an idea rather than a big headline: something from the subject sits inside the sentence where a word would be. A strip of photograph fills the gap between two words; a small live fragment of the product replaces the noun; the object the sentence names is pictured at the size of a letter. Write the sentence first, find the word that can be shown instead of said, and put the showing in its place. The reader completes the sentence with their eyes.\",\n  \"composition\": \"The sentence is four to seven words and runs as one or two full-width lines at 9–13vw. Inline with the type, on the baseline, sits one media slot: a rounded-rectangle or square frame exactly one line-height tall and two to three ems wide, holding a photograph or a looping crop. Above and below the sentence the screen is empty except for a small navigation line and one supporting sentence set small, both on the same left margin. Later sections repeat the grammar at smaller scale: each is a short statement on the left six columns with its proof (image, figure, list) on the right, so the page reads as a series of sentences with evidence. Generous vertical space (160px or more) between sections.\",\n  \"typography\": \"Display weight with real presence (medium to bold), tracking -0.03 to -0.05em, leading 0.95–1.0 so two lines sit close. The inline frame aligns to cap height and baseline exactly; set it with em units so it scales with the type.\",\n  \"typeClasses\": [\n   \"grotesk-tight\",\n   \"serif-display\",\n   \"condensed-heavy\",\n   \"serif-light-large\"\n  ],\n  \"colour\": \"A calm ground with ink at full contrast. The only colour comes from the photograph inside the sentence; if the palette has an accent, use it once, on the action.\",\n  \"paletteTags\": [\n   \"two-tone\",\n   \"light-neutral\",\n   \"single-field\",\n   \"mono-accent\"\n  ],\n  \"imagery\": \"One strong, simple photograph that reads at small size (a face, an object, a texture, a horizon), cropped to a wide strip inside the sentence. The same image may open to full width in the next section, so the small slot feels like a window onto something larger.\",\n  \"sectionTags\": [\n   \"type-led\",\n   \"poster\",\n   \"quiet\"\n  ],\n  \"motion\": \"masked-headline\",\n  \"richness\": \"The collision of big type and one live image inside it. Because there is only one image on the first screen, choose it with care and give it perfect alignment to the letters.\",\n  \"pitfalls\": \"The sentence must be short enough for two lines on a phone, where the inline frame drops to its own line between the two halves. Do not style one word differently to fake the device. Do not use more than one slot per sentence.\",\n  \"seenIn\": [\n   \"aww-colonia-zacamil\",\n   \"aww-bleibtgleich26\",\n   \"opl-spatial\",\n   \"aww-coffeetech-r\",\n   \"opl-midnight-2\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"pinned-poster\",\n  \"name\": \"The pinned poster\",\n  \"sectors\": [\n   \"culture\",\n   \"music\",\n   \"event\",\n   \"fashion\",\n   \"personal-portfolio\",\n   \"studio-portfolio\",\n   \"physical-product\",\n   \"ecommerce\",\n   \"hospitality\",\n   \"consumer-app\"\n  ],\n  \"tones\": [\n   \"bold\",\n   \"editorial\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Something stays put while everything else changes. A title holds its place across the viewport and the images beneath it swap; the name is split to two opposite corners and the page passes between the halves; a single frame stays centred while its contents change. Every scroll step is a new cover of the same magazine. The idea suits subjects that are a series (a book of portraits, a line-up, a collection, a set of projects): the fixed element says what the series is, the changing element shows its members.\",\n  \"composition\": \"A sticky layer holds the fixed element for the height of two to three viewports: usually the title at 10–14vw across the middle or top of the screen, or two words pinned to the top-left and bottom-right corners. Under it, a stack of full-height panels scrolls by, each a single large photograph (portrait 4:5, centred, 40–50% of the viewport wide) with one line of caption at the same small size everywhere. The title sits above the images in the stacking order and uses `mix-blend-mode: difference` or a solid colour that reads on every panel. When the pinned run ends, the page releases into ordinary flowing sections with a narrow measure. Build with `position: sticky`; never hijack the scroll.\",\n  \"typography\": \"The pinned title is the only large type on the page. Captions and body share one small size (15–17px). Tight tracking and solid weight so the title reads over photographs.\",\n  \"typeClasses\": [\n   \"grotesk-tight\",\n   \"condensed-heavy\",\n   \"heavy-black\",\n   \"extended-heavy\"\n  ],\n  \"colour\": \"One strong title colour against a pale or dark ground. Each panel may take its own flat ground colour sampled from its photograph.\",\n  \"paletteTags\": [\n   \"two-tone\",\n   \"photographic-neutral\",\n   \"single-field\"\n  ],\n  \"imagery\": \"A series of photographs with the same crop ratio and the same framing (all portraits, all objects, all rooms), so that swapping them reads as one image changing. Five to eight in the pinned run.\",\n  \"sectionTags\": [\n   \"photo-led\",\n   \"poster\",\n   \"type-led\"\n  ],\n  \"motion\": \"pinned-story\",\n  \"richness\": \"Repetition with change. The fixed title makes each new photograph feel like an event, so the photographs must be good and consistent.\",\n  \"pitfalls\": \"If the title is not legible over every panel, the idea fails: test each one. Keep the pinned run under six viewports or it feels like a trap. On a phone the title shrinks to 16–18vw and stays pinned at the top; panels become full-width. A pin longer than three screens, or one where the screens under it are nearly empty, read in blind tests as a stuck page. Every screen under the pin needs its own content, and nothing may pass over the pinned words.\",\n  \"seenIn\": [\n   \"opl-city-of-angels\",\n   \"aww-normal-is-boring\",\n   \"aww-glitch-grit\",\n   \"aww-revelatio-studio\"\n  ],\n  \"allow\": [],\n  \"needsPictures\": true\n },\n {\n  \"id\": \"colour-chapters\",\n  \"name\": \"Colour chapters\",\n  \"sectors\": [\n   \"agency\",\n   \"music\",\n   \"event\",\n   \"education\",\n   \"nonprofit\",\n   \"saas\",\n   \"consumer-app\",\n   \"culture\",\n   \"physical-product\",\n   \"health\",\n   \"finance\",\n   \"ai-product\"\n  ],\n  \"tones\": [\n   \"bold\",\n   \"playful\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Every section is a chapter with its own flat colour, floor to ceiling. The page reads like a set of posters hung in a row, held together by one typeface and one grid. The colours are not decoration: they come from the subject (the brand's packaging, the artist's record sleeves, the product's own colour ways, the categories of the content) and each chapter's colour means that chapter. Decide the sequence like a designer orders a book: a strong opener, a quiet second, a surprise in the middle, a dark or very light closer.\",\n  \"composition\": \"Sections are full-bleed fields, each at least 90svh tall, butted directly against each other with no gap and no divider. Inside every field the same 12-column grid and the same margins apply, and each field holds one thing: a huge heading (8–12vw) with a small paragraph, or one photograph with a caption, or one list. Text colour is chosen per field for strong contrast (ink or paper, never grey). Headings start on the same left edge in every chapter, so the eye feels the system as colours change. The navigation and the footer take the colours of the first and last chapter.\",\n  \"typography\": \"One typeface in two weights. Headings very large and tight; body 18–20px. Because colour is loud, the type stays plain: no italics, no second face.\",\n  \"typeClasses\": [\n   \"grotesk-tight\",\n   \"heavy-black\",\n   \"geometric\",\n   \"rounded-friendly\"\n  ],\n  \"colour\": \"Four to six flat fields used at full strength, one per section, each with its assigned text colour. No tints, no gradients between them: the hard edge where two fields meet is the look.\",\n  \"paletteTags\": [\n   \"flat-loud\",\n   \"pastel-fields\"\n  ],\n  \"imagery\": \"Sparing. One photograph or object per chapter at most, either cut out and sitting directly on the colour, or a plain rectangle with generous colour around it. Photographs should be simple enough not to fight the field.\",\n  \"sectionTags\": [\n   \"colour-field\",\n   \"type-led\",\n   \"poster\"\n  ],\n  \"motion\": \"colour-on-scroll\",\n  \"richness\": \"Colour at scale. A whole screen of one saturated colour is rich on its own, so a chapter needs few elements; it still needs its content at full size, because a coloured screen with one small line on it reads as empty.\",\n  \"pitfalls\": \"Check contrast on every field with the palette's assigned ink. Do not put cards on the fields. Do not use more than six colours. Two neighbouring fields should differ clearly in lightness as well as hue.\",\n  \"seenIn\": [\n   \"aww-warm-fuzzy\",\n   \"aww-paul-kalkbrenner\",\n   \"opl-anidachi\",\n   \"aww-aardvark-book-club\",\n   \"aww-ai-in-design-report-2026\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"place-carries-it\",\n  \"name\": \"The place carries it\",\n  \"sectors\": [\n   \"hospitality\",\n   \"restaurant\",\n   \"real-estate\",\n   \"architecture\",\n   \"event\",\n   \"health\",\n   \"culture\",\n   \"nonprofit\"\n  ],\n  \"tones\": [\n   \"quiet\",\n   \"luxury\",\n   \"warm\"\n  ],\n  \"needs\": [],\n  \"idea\": \"For a place, the photograph is the argument. One full-bleed image of where you would be standing fills the first screen, and the design steps back: the name sits along the bottom edge like a film title, or small in a corner, and nothing else interrupts the view. The page that follows keeps that restraint: few words, large pictures, long pauses. The designer's work here is editing: choosing the one frame that makes someone want to be there, and then not covering it.\",\n  \"composition\": \"First screen: a single photograph at 100vw by 100svh, focal point kept clear of text. The name is set either very large (14–20vw) hugging the bottom edge with 16–24px of margin, or small (20–28px) top-left with a one-line description bottom-left. Navigation is two to four words in the top corners in the same small size. If text sits on the image, a soft neutral scrim under the text area only. Below, sections alternate between a short centred or left-set paragraph in a narrow column (max 52ch) with wide empty margins, and photographs shown large: one full-bleed, then a pair at different sizes, then one portrait offset to the right. Practical information (hours, address, rates, booking) is gathered once near the end in a plain two-column block.\",\n  \"typography\": \"A face with some grace for the name; small, calm, well-spaced text everywhere else. Sentence case. Body 17–19px with leading around 1.55.\",\n  \"typeClasses\": [\n   \"serif-display\",\n   \"serif-light-large\",\n   \"condensed-heavy\",\n   \"grotesk-light\"\n  ],\n  \"colour\": \"Neutral paper or deep neutral ground chosen to flatter the photographs; text ink drawn from the darkest tone in the imagery. Colour lives in the pictures.\",\n  \"paletteTags\": [\n   \"photographic-neutral\",\n   \"dark-neutral\",\n   \"earth\"\n  ],\n  \"imagery\": \"The dealt set is the palette. Choose four to six photographs with the same light. The hero image must have a calm area for the name. Full-bleed or large with square corners; never thumbnails, never a carousel of ten.\",\n  \"photoTreatment\": \"Leave photographs ungraded. If text overlays one, darken only the area behind the text with a neutral scrim.\",\n  \"sectionTags\": [\n   \"photo-led\",\n   \"quiet\"\n  ],\n  \"motion\": \"slow-crossfade\",\n  \"richness\": \"The photographs, at full size, uninterrupted. Empty paper around short text makes the next image land harder.\",\n  \"pitfalls\": \"A weak hero photograph cannot be fixed by typography; pick again. Do not stack a headline, a paragraph and two buttons on the image. Do not use a booking bar that covers the bottom of the view; one small action is enough.\",\n  \"seenIn\": [\n   \"aww-white-desert\",\n   \"opl-eagles-nest\",\n   \"aww-tengile-malamala-collection\",\n   \"aww-izanami\",\n   \"aww-seasats\"\n  ],\n  \"allow\": [],\n  \"needsPictures\": true\n },\n {\n  \"id\": \"page-is-the-object\",\n  \"name\": \"The page is the object\",\n  \"sectors\": [\n   \"restaurant\",\n   \"event\",\n   \"hospitality\",\n   \"culture\",\n   \"music\",\n   \"physical-product\",\n   \"ecommerce\",\n   \"nonprofit\",\n   \"education\",\n   \"personal-portfolio\",\n   \"consumer-app\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"warm\",\n   \"playful\",\n   \"editorial\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Find the printed or physical artefact that already exists in the subject's world and build the page as that thing. A wedding site is the invitation card. A restaurant is its menu. A conference is the ticket; a record is its sleeve; a shop is the receipt or the swing tag; an archive is a stack of tabbed folders; a course is the syllabus sheet. The artefact supplies everything a template would otherwise invent: its proportions, its typographic manners, its way of grouping information. Visitors recognise the object instantly, which is why these pages feel specific.\",\n  \"composition\": \"The first screen shows the artefact as a single filled panel (paper colour on a contrasting ground) centred or offset, with believable proportions: a card at 5:7, a ticket at about 2.2:1 with a notch cut by `clip-path`, a menu as a tall sheet. All primary content lives on it, set the way that object is set: centred and symmetrical for an invitation, in tidy aligned columns for a menu or ticket. The ground behind is a flat colour or one full-bleed photograph. As the page continues, each section is another piece of the same stationery: a second card, a tear-off stub, a folded panel, always filled shapes with real edges (straight, notched, scalloped, perforated by a dotted `border` of round dots at 4px or more), never outlined boxes. The footer is the back of the object.\",\n  \"typography\": \"Take the manners of the artefact: a bookish serif with small caps avoided, or a blunt condensed face for tickets and posters. Sizes stay within what print would use relative to the panel; the name is large on the panel, details are small and exact.\",\n  \"typeClasses\": [\n   \"serif-text\",\n   \"serif-display\",\n   \"slab\",\n   \"condensed-heavy\",\n   \"grotesk-tight\"\n  ],\n  \"colour\": \"Paper and ink plus the ground the paper sits on. Two or three flat colours in total, like a two-colour print job.\",\n  \"paletteTags\": [\n   \"two-tone\",\n   \"earth\",\n   \"light-neutral\"\n  ],\n  \"imagery\": \"Optional. One photograph behind the object, or small photographs placed on it like tipped-in plates. The object itself is the image.\",\n  \"sectionTags\": [\n   \"object-led\",\n   \"type-led\",\n   \"colour-field\"\n  ],\n  \"motion\": \"curtain-footer\",\n  \"richness\": \"Recognition. The shaped edges, the print-like alignment and the limited inks make a familiar object out of plain HTML.\",\n  \"pitfalls\": \"Choose an artefact that truly belongs to the subject, or it becomes costume. Shape the edges with fills and `clip-path`; an outlined rectangle with a thin border is not an object. Keep text sizes readable on a phone, where the object becomes full width with its shaped edge kept at top and bottom.\",\n  \"seenIn\": [\n   \"opl-sarah-matt-wedding\",\n   \"aww-mosbys-files\",\n   \"opl-the-deep-end\",\n   \"opl-weeksync\",\n   \"opl-le-petit-bleu\",\n   \"opl-archiv\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"one-motif\",\n  \"name\": \"One motif\",\n  \"sectors\": [\n   \"saas\",\n   \"finance\",\n   \"consumer-app\",\n   \"ai-product\",\n   \"dev-tool\",\n   \"health\",\n   \"physical-product\",\n   \"restaurant\",\n   \"education\",\n   \"nonprofit\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"playful\",\n   \"technical\",\n   \"warm\",\n   \"bold\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Take one shape from the subject and let it run the whole system. A drilling tool's octagonal cross-section becomes the buttons, the image masks and the loader. A two-account money app becomes two circles that recur as icon, inline dot and section colour. A café's striped awning becomes every band on the page. Look at the product, the logo, the object or the word in the headline and find the simplest geometry in it (a circle, an arc, a chamfer, a stripe, a notch, a ring). Then use only that shape, at three or four very different scales, everywhere a designer would normally reach for a generic rounded rectangle.\",\n  \"composition\": \"Hero: the motif appears once at enormous scale as a flat filled shape, cropped by the viewport (a circle 120vh across entering from the right, a chamfered block filling the lower half), with a short headline at 6–8vw and one supporting sentence set on the remaining ground, left-aligned on a shared margin. Through the page the motif returns as: the mask for every photograph (via `clip-path` or `border-radius` made from the same geometry), the shape of the primary button, the bullet beside list items at text size, and one full-width band that separates the two halves of the page. Sections use simple two-column or single-column layouts so the shape is the only thing with character.\",\n  \"typography\": \"A clean geometric or grotesk face that echoes the shape (round bowls for circles, squared terminals for chamfers). Medium weight; headings 6–8vw in the hero and 3–4vw after.\",\n  \"typeClasses\": [\n   \"geometric\",\n   \"grotesk-tight\",\n   \"rounded-friendly\"\n  ],\n  \"colour\": \"The motif carries the accent colour at large scale, flat. Everything else is ground and ink. A second motif colour is allowed only if the subject has a real pair (two accounts, two modes).\",\n  \"paletteTags\": [\n   \"mono-accent\",\n   \"two-tone\",\n   \"pastel-fields\"\n  ],\n  \"imagery\": \"Photographs appear inside the motif's shape. If there is product interface to show, it sits on a flat colour stage shaped by the motif. Draw the shape with CSS or a simple inline SVG path; do not draw illustrations.\",\n  \"sectionTags\": [\n   \"colour-field\",\n   \"object-led\",\n   \"type-led\"\n  ],\n  \"motion\": \"shutter-image\",\n  \"richness\": \"One shape at many sizes. The giant cropped shape gives the hero mass and colour without a single image.\",\n  \"pitfalls\": \"One motif means one. A circle here, a hexagon there and a blob behind is the generated look this replaces. The motif must come from the subject and you must be able to say from where in one clause.\",\n  \"seenIn\": [\n   \"aww-sstr-friction-reduction\",\n   \"opl-tara\",\n   \"opl-boaxt\",\n   \"opl-midnight-2\",\n   \"opl-superlocal-2026\",\n   \"opl-billow\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"product-performs\",\n  \"name\": \"The product performs\",\n  \"sectors\": [\n   \"saas\",\n   \"dev-tool\",\n   \"ai-product\",\n   \"consumer-app\",\n   \"finance\"\n  ],\n  \"tones\": [\n   \"technical\",\n   \"quiet\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Software is most convincing when it is doing its job in front of you. Instead of describing features, put small, true, working fragments of the product on the page: the actual control, with real content, responding to the pointer. A colour picker's loupe reads the page's own background and prints its value. A list tool lets you tick an item right there. A type-scale plugin sets the page's own headings. Find the one interaction that is the product and make the hero that interaction; then show each further capability as another fragment at real size. No dashboard collage, no browser frame, no screenshots shrunk until unreadable.\",\n  \"composition\": \"Hero: a short plain headline (4–6vw, left-aligned, upper-left third) and one sentence; the rest of the first screen is the main fragment at actual interface size, sitting directly on the page or on one flat stage colour, large enough to read every label. The fragment is built in HTML and works. Below, capabilities are a single-column sequence, each a row of two parts on a 5/7 split: a two-line statement on one side and the relevant fragment on the other, with the fragments varying in size and shape so the column never becomes a zigzag of equal blocks. Fragments are cropped pieces of interface (a menu, a row, a control, a panel edge), not whole windows. One section pins a fragment while three short statements change it.\",\n  \"typography\": \"The marketing type matches the product's interface type so the fragments and the page feel like one thing. Headline modest; interface text at its true size (13–15px) inside fragments.\",\n  \"typeClasses\": [\n   \"grotesk-tight\",\n   \"grotesk-light\",\n   \"geometric\"\n  ],\n  \"colour\": \"Neutral ground. The product's own interface colours provide the colour. At most one flat stage colour behind fragments.\",\n  \"paletteTags\": [\n   \"light-neutral\",\n   \"dark-neutral\",\n   \"mono-accent\"\n  ],\n  \"imagery\": \"The interface fragments are the main imagery: build them carefully with real labels, real numbers and sensible states (one hovered, one selected). Around them, two or three real pictures of the customer's world (found with scripts/assets.mjs), never stock of people at laptops.\",\n  \"sectionTags\": [\n   \"ui-led\",\n   \"quiet\"\n  ],\n  \"motion\": \"pinned-story\",\n  \"richness\": \"Fidelity. A fragment with believable content and a real hover state is more interesting than any illustration. Spend the effort there.\",\n  \"pitfalls\": \"A fake interface made of grey bars and circles is the worst outcome; if you cannot build a believable fragment, change direction. Mark each fragment's root element with the attribute data-ui: inside it the product's own conventions apply (1px control borders, small radii, a shadow on its open menu) and the inspector leaves them alone; outside it the house rules hold as usual. data-ui is for cropped fragments only, never for a page wrapper. Do not put the fragment in a browser or laptop frame.\",\n  \"seenIn\": [\n   \"opl-dabbit\",\n   \"opl-rows\",\n   \"opl-typewave\",\n   \"opl-shelf\",\n   \"opl-uni\",\n   \"opl-kontu\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"quiet-instrument\",\n  \"name\": \"The quiet instrument\",\n  \"sectors\": [\n   \"saas\",\n   \"dev-tool\",\n   \"ai-product\",\n   \"personal-portfolio\",\n   \"consumer-app\",\n   \"finance\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"quiet\",\n   \"technical\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Radical understatement. Where every competitor shouts, this page almost whispers: a headline barely larger than body text, a narrow column, small exact demonstrations, and a great deal of untouched space. The restraint is the claim. It says the thing is simple, finished and sure of itself. This only works when it is carried through completely; one loud element breaks it. In the study, a tool for simple lists sold itself with a 27px headline and 12–14px copy and was one of the most confident pages in the set.\",\n  \"composition\": \"A single column 440–560px wide, placed left of centre (starting at about 22% of the viewport width) or dead centre, running the whole page. The headline is the one large thing on the first screen: two lines at display size (5–7vw), medium weight, starting on the column's left edge and allowed to run wider than the column. The supporting paragraph follows at body size (17–19px) in the full ink. One small primary button and one text link. Below, each point is a short paragraph followed by a compact demonstration or image no wider than the column. Sections are separated only by space (96–140px). Nothing spans the full width until the footer, which is a single quiet line. The first screen is mostly empty and that emptiness is composed: the column's top edge sits at about 30% of the viewport height.\",\n  \"typography\": \"One family, two weights. A display size for the headline (5–7vw), one heading size for section titles (about 32–40px), body at 17–19px, a small size for captions (14–15px). Leading 1.5 for text. Letter-spacing near zero. The typeface must be handsome at small sizes.\",\n  \"typeClasses\": [\n   \"grotesk-light\",\n   \"serif-text\",\n   \"geometric\"\n  ],\n  \"colour\": \"Paper and two inks (full and soft). One accent used on exactly one element per screen.\",\n  \"paletteTags\": [\n   \"light-neutral\",\n   \"mono-accent\"\n  ],\n  \"imagery\": \"Precise rather than loud: cropped interface details at true size, and real photographs of the customer's world held to the column width, each doing one job. One short looping clip can sit at column width too. Never a large stock hero image.\",\n  \"sectionTags\": [\n   \"quiet\",\n   \"ui-led\",\n   \"type-led\"\n  ],\n  \"motion\": \"stillness\",\n  \"richness\": \"Precision. With so little on the page, alignment, spacing and the exact size relationships are the design. Every element shares the column's left edge.\",\n  \"pitfalls\": \"This is the one direction where a small headline is right; the inspector will not object, but do not mix it with a large display line. Emptiness must look decided: keep the column edges exact and the vertical rhythm even. Not suitable when the subject needs emotion or photography to sell. Quiet is not thin: the column must still deliver every piece of content the brief asks for, in full, at 16px or more in the full ink. In blind tests the quiet version lost every time it was quiet everywhere: a small headline beside an empty panel read as unfinished. Quiet means few things, not small things: the headline and the demonstration are large, and every screen holds content.\",\n  \"seenIn\": [\n   \"opl-rows\",\n   \"opl-compile\",\n   \"opl-plastic\",\n   \"opl-bueno-fyi\",\n   \"aww-gil-huybrecht\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"hero-object\",\n  \"name\": \"The object, large\",\n  \"sectors\": [\n   \"physical-product\",\n   \"ecommerce\",\n   \"consumer-app\",\n   \"fashion\",\n   \"finance\",\n   \"health\",\n   \"restaurant\",\n   \"music\"\n  ],\n  \"tones\": [\n   \"bold\",\n   \"luxury\",\n   \"quiet\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"idea\": \"Show the thing, bigger than seems reasonable. One photographed object fills the first screen, scaled until the viewport crops it, with the text small and tucked beside or behind it. The crop is the idea: a record whose edge leaves the top-right corner, a bottle whose shoulder runs off the bottom, a chair seen so close you read its grain. Being that close reads as confidence in the object. Everything else on the page serves it: details as tight close-ups, facts as short lines, one way to buy.\",\n  \"composition\": \"First screen: the object occupies 55–75% of the viewport and breaks at least one edge. It sits on a flat field (ground colour or one bold colour), never in a box. The headline is short and either very large and partly hidden behind the object (10–13vw, the object overlapping two or three letters) or small (28–36px) in the opposite corner with a one-line description. No navigation bar beyond a wordmark and one action. Following sections: a row of three or four close-up details at different crop ratios (not equal tiles), a single wide photograph of the object in use, a plain list of facts set large (materials, size, price) aligned to one edge, then the purchase action. The object returns once at the end from a different angle.\",\n  \"typography\": \"Either very large and structural or very small and precise; pick one for the headline and hold it. Facts are set in the text face at 22–28px, not in a table.\",\n  \"typeClasses\": [\n   \"grotesk-light\",\n   \"grotesk-tight\",\n   \"extended-heavy\",\n   \"serif-light-large\"\n  ],\n  \"colour\": \"A flat field chosen to make the object's own colour sing (its complement, or a tone darker than its shadow side). One field for the whole page, or a second for the facts section.\",\n  \"paletteTags\": [\n   \"single-field\",\n   \"light-neutral\",\n   \"pastel-fields\",\n   \"dark-neutral\"\n  ],\n  \"imagery\": \"Use the product's own photographs if they exist. Otherwise use a still-life from the dealt set as a stand-in and say so. Prefer images with a plain background; use `mix-blend-mode: multiply` on light fields so a white studio background disappears into the page colour.\",\n  \"photoTreatment\": \"Scale the main image well past its container (`width: 120–160%`) and let `overflow: hidden` on the section do the cropping.\",\n  \"sectionTags\": [\n   \"object-led\",\n   \"photo-led\",\n   \"colour-field\"\n  ],\n  \"motion\": \"shutter-image\",\n  \"richness\": \"The object's surface at close range, and the tension of the crop.\",\n  \"pitfalls\": \"A small centred product shot with space all round is a catalogue thumbnail, not this direction. If the image has a busy background it cannot sit on a field; crop tighter or change image. Keep text off the object's focal area.\",\n  \"seenIn\": [\n   \"opl-when-you-wish-upon-a-starboy\",\n   \"opl-plastic\",\n   \"opl-archiv\",\n   \"aww-moto-finance\",\n   \"aww-the-watch\",\n   \"opl-aevion\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"specimen-catalogue\",\n  \"name\": \"The specimen catalogue\",\n  \"sectors\": [\n   \"ecommerce\",\n   \"physical-product\",\n   \"restaurant\",\n   \"fashion\",\n   \"culture\",\n   \"education\",\n   \"health\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"playful\",\n   \"warm\",\n   \"editorial\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"idea\": \"Present what is on offer the way a field guide presents birds: each item alone on a flat colour, same scale, same angle, named plainly. A bakery's pastries become specimens and the specimens become the menu. A furniture maker's chairs each get their own colour tile. The format flatters ordinary objects because it treats each as worth looking at, and it replaces both the feature grid and the product-card grid with something that has a point of view.\",\n  \"composition\": \"Hero: a left-aligned statement of what this is (5–7vw, upper-left) beside or above a tight cluster of four to seven specimen tiles of different sizes arranged as a loose mosaic that runs off the right edge. Each tile is a flat colour square or 4:5 rectangle with one photograph centred on it, no border, 8–12px gaps. The main section is the catalogue itself: a grid of tiles in which each item has its name and one fact set beneath the tile in the text face, aligned left to the tile edge. Tile colours rotate through three or four fields from the palette. One tile in every six or seven is double size. Supporting sections (about, how to order) are plain text on the ground colour, kept short.\",\n  \"typography\": \"Friendly and plain. Item names at 18–22px in medium weight, facts beneath in the soft ink. One big statement in the hero; no other display type.\",\n  \"typeClasses\": [\n   \"grotesk-tight\",\n   \"serif-text\",\n   \"slab\",\n   \"rounded-friendly\"\n  ],\n  \"colour\": \"The tiles are the colour: three or four flat fields from the palette, repeated in a steady rotation. Ground stays neutral.\",\n  \"paletteTags\": [\n   \"pastel-fields\",\n   \"flat-loud\",\n   \"light-neutral\"\n  ],\n  \"imagery\": \"Photographs of single items on plain backgrounds, all cropped to sit at the same apparent size within their tile. On light tiles, `mix-blend-mode: multiply` removes white studio backgrounds. If the subject's own item photographs are missing, use the dealt set and say so.\",\n  \"sectionTags\": [\n   \"object-led\",\n   \"colour-field\",\n   \"photo-led\"\n  ],\n  \"motion\": \"drag-row\",\n  \"richness\": \"Rhythm of colour tiles and the pleasure of comparing like with like.\",\n  \"pitfalls\": \"It needs at least six items that can be shown as objects; with three it is a feature row. Keep labels outside the tiles. No shadows under the objects, no hover lift.\",\n  \"seenIn\": [\n   \"aww-noho\",\n   \"opl-madie\",\n   \"opl-humanoid-index\",\n   \"opl-smallbits\",\n   \"aww-butter\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"borrowed-category\",\n  \"name\": \"Dressed as something else\",\n  \"sectors\": [\n   \"finance\",\n   \"saas\",\n   \"consumer-app\",\n   \"physical-product\",\n   \"health\",\n   \"dev-tool\",\n   \"ai-product\",\n   \"education\",\n   \"nonprofit\",\n   \"real-estate\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"bold\",\n   \"playful\",\n   \"luxury\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Art-direct the subject as if it belonged to a different, more vivid category. A money app is sold like a streetwear drop. An industrial roaster is presented like a design object. Drilling hardware gets the calm of a watch brand. A parcel-locker service becomes a fairground of stickers. Choose the borrowed category by asking what feeling the audience is missing from this kind of product (swagger, calm, glamour, play) and which category owns that feeling. Then take its manners completely: its type, its pacing, its way of photographing things. The contrast between dull subject and vivid dress is what people remember.\",\n  \"composition\": \"Depends on the borrowed category, so decide it explicitly and write it in your notes. Fashion drop: one shouted condensed headline across the full width, a single cropped image under it, then product facts as a blunt list. Watch or perfume: a centred object on a dark field, a small serif name, very few words, long vertical pauses. Poster or zine: flat colour blocks, heavy type, tilted cut-out images. Museum: one item per screen on a plinth-like band of colour with a short label beside it. Whichever you choose, the page structure stays simple (four to six sections) and every section uses the borrowed manners, including pricing and the footer.\",\n  \"typography\": \"The borrowed category's type, fully committed: condensed and loud, or refined and small. No halfway.\",\n  \"typeClasses\": [\n   \"condensed-heavy\",\n   \"serif-display\",\n   \"extended-heavy\",\n   \"heavy-black\"\n  ],\n  \"colour\": \"The borrowed category's palette, which will be unlike the subject's sector norm. That mismatch is intended.\",\n  \"paletteTags\": [\n   \"flat-loud\",\n   \"two-tone\",\n   \"dark-neutral\",\n   \"single-field\"\n  ],\n  \"imagery\": \"Photograph the subject the way the borrowed category would be photographed. With the dealt set, choose images for attitude, not literal relevance, and crop them hard.\",\n  \"sectionTags\": [\n   \"poster\",\n   \"type-led\",\n   \"photo-led\",\n   \"colour-field\"\n  ],\n  \"motion\": \"edge-marquee\",\n  \"richness\": \"Attitude. The page has a recognisable voice from another world, applied to a subject nobody expected it for.\",\n  \"pitfalls\": \"Name the borrowed category in one word before you start, or the result is merely loud. The content must still be clear: what it is, what it costs, how to get it. Avoid borrowing from 'tech startup', which is the default you are escaping.\",\n  \"seenIn\": [\n   \"opl-uglycash\",\n   \"aww-coffeetech-r\",\n   \"aww-sstr-friction-reduction\",\n   \"opl-locker-land\",\n   \"aww-moto-finance\",\n   \"aww-vero-new-york\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"contact-sheet\",\n  \"name\": \"The contact sheet\",\n  \"sectors\": [\n   \"personal-portfolio\",\n   \"studio-portfolio\",\n   \"agency\",\n   \"fashion\",\n   \"culture\",\n   \"architecture\",\n   \"music\",\n   \"ecommerce\"\n  ],\n  \"tones\": [\n   \"quiet\",\n   \"technical\",\n   \"editorial\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Show everything at once, small, in order. The work is laid out like a photographer's contact sheet or an archive drawer: dozens of small frames in strict rows, with all text set at one small size. Nothing is featured, which is the point: the volume and consistency of the body of work is the statement, and the visitor does the choosing. It suits people and studios whose strength is range and output.\",\n  \"composition\": \"The name, or one sentence about the work, sits at display size (6–9vw) across the top of the first screen, and the sheet begins directly under it, still inside the first screen. The first screen opens with three or four short blocks of small text across the top on a 12-column grid (who, what, where to reach them), all at 14–16px, and immediately below, the sheet begins: rows of thumbnails at a fixed height (90–140px) with their natural widths, 6–10px gaps, each project forming a run of four to eight frames preceded by its title in the same small text. The sheet fills the whole page width edge to edge with 16–20px margins. Hovering a run dims the others and shows that project's one-line description in a fixed position. A single enlarged frame may interrupt the sheet once per screen at four times the size.\",\n  \"typography\": \"One face. The name at display size on the first screen; everything else at one text size and one small size; hierarchy below the name comes from position and from a single brighter ink for titles.\",\n  \"typeClasses\": [\n   \"grotesk-light\",\n   \"grotesk-tight\"\n  ],\n  \"colour\": \"Black or white ground, so the thumbnails are the only colour.\",\n  \"paletteTags\": [\n   \"dark-neutral\",\n   \"light-neutral\"\n  ],\n  \"imagery\": \"Many images: at least 24 frames to make a sheet. They can be project photographs from the dealt set cropped to mixed ratios, or page captures of the work. Square corners, no captions on the frames.\",\n  \"sectionTags\": [\n   \"dense\",\n   \"photo-led\",\n   \"quiet\"\n  ],\n  \"motion\": \"index-preview\",\n  \"richness\": \"Density and order. The mass of small images forms a texture; the strict rows keep it calm.\",\n  \"pitfalls\": \"With fewer than about 20 images it looks unfinished; choose another direction. Do not add a big headline above the sheet. On a phone the frames become two per row at a fixed height and each run scrolls sideways. Rows that run past the right edge read as clipped in screenshots and to most visitors: wrap the frames onto the next line, or end each row inside the grid.\",\n  \"seenIn\": [\n   \"aww-gil-huybrecht\",\n   \"opl-smallbits\",\n   \"opl-gunes-atakan-peksen\",\n   \"opl-proooof\",\n   \"aww-oimachi\"\n  ],\n  \"allow\": [],\n  \"needsPictures\": true\n },\n {\n  \"id\": \"editorial-report\",\n  \"name\": \"The printed annual\",\n  \"sectors\": [\n   \"culture\",\n   \"nonprofit\",\n   \"education\",\n   \"finance\",\n   \"saas\",\n   \"ai-product\",\n   \"health\",\n   \"agency\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"editorial\",\n   \"bold\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Lay the page out like a well-designed printed report or magazine feature: a masthead image, a tight oversized title, text held to a strict column line, and colour used in solid blocks the way a two-colour print job would. It gives weight and authority to subjects that are really about content: findings, a manifesto, a programme, a serious product. The reader should feel that someone edited this.\",\n  \"composition\": \"A fixed vertical axis at about 42% of the viewport width organises everything: headings begin on it, body columns hang from it, and the 0–42% zone holds small side notes, figures or stays empty. Masthead: a wide image band (photographic mosaic or a single crop) across the top 45% of the first screen; below it the title at 7–9vw starting on the axis, with a two-sentence standfirst at 20–24px. Sections alternate between text pages (title on the axis, body in one or two columns of 34–40ch to its right) and full-bleed colour pages carrying one large figure, quotation or image mosaic. Mosaics are gutterless: photographs and flat colour tiles butted together in a 4- or 6-cell grid. Page numbers, running heads and other print furniture are left out.\",\n  \"typography\": \"A tight heavy grotesk or a sharp serif for titles; an excellent text face for reading at 18–20px with leading near 1.5. Headings in sentence case, tracked tight.\",\n  \"typeClasses\": [\n   \"grotesk-tight\",\n   \"serif-display\",\n   \"serif-text\"\n  ],\n  \"colour\": \"Paper, ink and two or three solid block colours. A colour page is a whole section in one flat colour.\",\n  \"paletteTags\": [\n   \"flat-loud\",\n   \"two-tone\",\n   \"mono-accent\"\n  ],\n  \"imagery\": \"Photographs used as blocks in mosaics alongside flat colour tiles; mixed subjects are fine if cropped tight and converted to one treatment.\",\n  \"photoTreatment\": \"Give all photographs in a mosaic one treatment: greyscale via `filter: grayscale(1) contrast(1.05)`, or all full colour. Do not mix.\",\n  \"sectionTags\": [\n   \"type-led\",\n   \"colour-field\",\n   \"dense\",\n   \"poster\"\n  ],\n  \"motion\": \"masked-headline\",\n  \"richness\": \"The column line, the mosaics and whole pages of colour give structure and variety without ornaments.\",\n  \"pitfalls\": \"The axis must be exact and reused everywhere or it reads as random indentation. Keep paragraphs to a real reading measure. On a phone the axis collapses to the left margin and side notes move inline above their paragraph.\",\n  \"seenIn\": [\n   \"aww-ai-in-design-report-2026\",\n   \"opl-applied-imagination\",\n   \"opl-the-queue\",\n   \"opl-artem-taradash\",\n   \"opl-belgrade-architecture\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"loud-flat-poster\",\n  \"name\": \"Loud and flat\",\n  \"sectors\": [\n   \"agency\",\n   \"consumer-app\",\n   \"music\",\n   \"event\",\n   \"education\",\n   \"nonprofit\",\n   \"physical-product\",\n   \"saas\",\n   \"culture\"\n  ],\n  \"tones\": [\n   \"bold\",\n   \"playful\"\n  ],\n  \"needs\": [],\n  \"idea\": \"A page with the directness of a street poster: flat saturated colour, the heaviest type you can find, short blunt statements, and photographs cut out and stuck on. It is for subjects with a voice. Write the page as things a person would actually say out loud, and let the design say them at full volume. The craft is in the control beneath the noise: a strict grid, two or three colours, and exact alignment keep it from becoming a mess.\",\n  \"composition\": \"Hero: a statement of three to six words in ultra-heavy type at 11–15vw, filling the width, lines stacked tight (leading 0.85), flush left with 20–28px margins, on a flat saturated ground. One cut-out or hard-cropped photograph overlaps the type from the right or bottom, tilted 3–6 degrees. A single chunky button in the contrasting flat colour. Sections are solid panels in alternating palette colours: one is a row of short statements each on its own panel of unequal width; one is a single photograph bleeding off two edges with a caption block set over a solid colour bar; one is a large plain list. Panels meet edge to edge. Corners are square or use one large radius (28–40px) consistently.\",\n  \"typography\": \"The heaviest weight available, set tight, mostly lowercase or mostly uppercase (choose one). Body text is a plain grotesk at 18–20px.\",\n  \"typeClasses\": [\n   \"heavy-black\",\n   \"condensed-heavy\",\n   \"extended-heavy\",\n   \"rounded-friendly\"\n  ],\n  \"colour\": \"Three or four flat colours at full strength including black or white. Each panel is one colour; text on it is one other.\",\n  \"paletteTags\": [\n   \"flat-loud\"\n  ],\n  \"imagery\": \"Photographs with attitude, cropped hard or cut to a simple shape with `clip-path` (circle, arch, blunt polygon), slightly rotated, overlapping the type. Two or three on the page.\",\n  \"sectionTags\": [\n   \"poster\",\n   \"colour-field\",\n   \"type-led\"\n  ],\n  \"motion\": \"edge-marquee\",\n  \"richness\": \"Colour mass, type mass, and overlap.\",\n  \"pitfalls\": \"Headlines still obey the two-line rule: at 13vw that means very few words, which is correct for this voice. No outlines, no offset shadows, no sticker confetti. Rotation is for two or three images only, never for text blocks.\",\n  \"seenIn\": [\n   \"aww-warm-fuzzy\",\n   \"aww-aardvark-book-club\",\n   \"opl-uglycash\",\n   \"opl-depo-budget-app\",\n   \"aww-trevor-noah\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"split-stage\",\n  \"name\": \"The split stage\",\n  \"sectors\": [\n   \"restaurant\",\n   \"hospitality\",\n   \"personal-portfolio\",\n   \"physical-product\",\n   \"fashion\",\n   \"real-estate\",\n   \"health\",\n   \"culture\",\n   \"ecommerce\",\n   \"saas\",\n   \"consumer-app\"\n  ],\n  \"tones\": [\n   \"warm\",\n   \"quiet\",\n   \"editorial\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Half the screen never moves. One side is a fixed photograph (or object, or product view) that stays in place for the whole visit; the other side is a calm scrolling column with everything you need to read. The fixed half keeps the feeling present while the reader gets on with the facts, like sitting in the room while reading the menu. As sections pass, the fixed image may quietly change to the one that matches.\",\n  \"composition\": \"Desktop: a two-column page, 50/50 or 45/55. One column is `position: sticky; top: 0; height: 100svh` and holds a single photograph filling it edge to edge, or the object centred on a flat field. The other column scrolls and holds all content in a single narrow measure (max 46ch) with comfortable padding (48–72px): name and one-line description first, then sections separated by generous space, then contact and footer. Headings in the scrolling column are modest (32–44px). The column grounds differ: photograph on one side, flat paper colour on the other, meeting at a clean vertical edge. On a phone the fixed half becomes a 60svh image at the top that stays sticky behind the first section, then releases.\",\n  \"typography\": \"A text-first setting: a readable serif or a calm sans at 17–19px, with one display size for the name. Left-aligned throughout.\",\n  \"typeClasses\": [\n   \"serif-text\",\n   \"serif-display\",\n   \"grotesk-light\",\n   \"slab\"\n  ],\n  \"colour\": \"The paper colour of the reading column is chosen against the photograph: a tone taken from its shadows or its lightest area. One ink, optionally one accent ink for links and the action.\",\n  \"paletteTags\": [\n   \"two-tone\",\n   \"earth\",\n   \"light-neutral\",\n   \"photographic-neutral\"\n  ],\n  \"imagery\": \"One excellent portrait-orientation photograph for the fixed half, plus three or four more that crossfade in as their sections arrive. Small inline photographs in the reading column are optional and should be few.\",\n  \"sectionTags\": [\n   \"quiet\",\n   \"photo-led\",\n   \"type-led\"\n  ],\n  \"motion\": \"slow-crossfade\",\n  \"richness\": \"A full-height photograph always in view, against a quiet, well-set column of text.\",\n  \"pitfalls\": \"The reading column must be genuinely well typeset, since it is half the page. Do not put cards or grids in it. Check that the fixed image crops well at short viewport heights. In blind tests the commonest complaint was monotony: several screens of the same split with only the text changing. Change what the reading half holds from section to section (a list, a large figure, a table, a full-colour panel, a drawing) and let at least one section break the split and run full width.\",\n  \"seenIn\": [\n   \"opl-le-petit-bleu\",\n   \"opl-rafael-derolez-2026\",\n   \"opl-flowjam-2\",\n   \"opl-devonshire\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"dense-tiles\",\n  \"name\": \"The well-kept board\",\n  \"sectors\": [\n   \"agency\",\n   \"studio-portfolio\",\n   \"saas\",\n   \"dev-tool\",\n   \"ai-product\",\n   \"culture\",\n   \"music\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"technical\",\n   \"bold\"\n  ],\n  \"needs\": [],\n  \"idea\": \"The whole page is a board of tiles fitted edge to edge with narrow gaps, like a tidy desk seen from above. Each tile is one thing: the name, a statement, a photograph, a number, a link, a short list. There is no hero and no sequence of bands; the page is one continuous composition that the eye roams. It suits subjects with many small true things to show (a studio with work, writing, clients and news; a product with several distinct capabilities) and it replaces the gen\n\n<!-- [TRUNCATED AT 50KB] -->","isInternal":false,"tokens":12547,"sizeBytes":50147},{"name":"heroes.json","path":"skills/taste-skill/library/heroes.json","rawUrl":"https://raw.githubusercontent.com/Leonxlnx/taste-skill/HEAD/skills/taste-skill/library/heroes.json","title":"Library Skill","category":"anthropic-skill","format":"json","content":"[\n {\n  \"id\": \"name-under-photograph\",\n  \"name\": \"Name under a photograph\",\n  \"archetype\": \"giant-wordmark\",\n  \"directions\": [\n   \"name-as-monument\",\n   \"place-carries-it\",\n   \"dark-room\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A full-bleed photograph fills the top 58% of the 1440×900 viewport, touching the top, left and right edges, `object-fit: cover`, with its focal point in the upper two-thirds. The lower 42% is a flat ground colour that butts against the photograph with no gap. The name runs across this band on one line, spanning all 12 columns between 24px margins, at clamp(120px, 19vw, 300px), tracking -0.05em, line-height 0.85, its baseline 28px above the bottom edge so descenders nearly touch it. Fit the size to the length of the name so it never wraps. In the strip of ground between photograph and name, 24px under the photograph's edge, sits one row at 17px: the supporting sentence on columns 1–5 at the left margin, and the single action as a small solid rectangular button flush to the right margin. Navigation is four text links at 15px laid over the photograph's top-right corner, 24px in, with a neutral scrim behind that row only if the image is light there. No logo is repeated: the name is the logo. Nothing else is on the screen.\",\n  \"mobile\": \"The photograph takes the top 50svh at full width, re-cropped around its focal point. The name sits under it at 23vw on one line; a name longer than seven characters breaks onto two lines at 21vw, line-height 0.85, and fills the band down to a 16px bottom margin. The supporting sentence at 16px and the action button stack above the name on the left margin. The links collapse to one 'Menu' word over the photograph, top-right.\",\n  \"headline\": \"The name itself on one line, up to about 12 characters at 19vw (drop towards 13vw for longer names), and at most two lines on a phone.\",\n  \"motion\": \"scaling-wordmark\",\n  \"seenIn\": [\n   \"aww-house-of-honey-1\",\n   \"opl-kereliott\",\n   \"aww-lxl-creative\"\n  ]\n },\n {\n  \"id\": \"stacked-name-two-inks\",\n  \"name\": \"Stacked name, two inks\",\n  \"archetype\": \"type-poster\",\n  \"directions\": [\n   \"name-as-monument\",\n   \"colour-chapters\",\n   \"type-only-statement\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One saturated flat field covers the whole 1440×900 viewport and there is no image. The name is broken into two lines and set flush left from a 40px margin at clamp(110px, 15vw, 230px), heavy weight, tracking -0.04em, line-height 0.82 so the lines almost touch. The block starts 14% down and fills the top 58% of the screen; the longer line reaches at least column 11. Line one is set in the light ink and line two in the dark ink, so the break reads as a change of voice: split a two-word name between the lines, or break one long name with a hyphen at a syllable. The top edge carries only small text at 15px, 24px in: a monogram top-left, and two or three text links plus the single action as an underlined link top-right. The supporting sentence, 18px in the light ink and max 30ch, is right-aligned in the bottom-right corner on columns 9–12, its last line 40px above the bottom edge. The bottom-left corner stays empty. The next section begins as a different flat field exactly at the fold.\",\n  \"mobile\": \"The field fills 100svh. The name keeps its two lines and two inks at 21vw, flush left at a 16px margin, starting 18% down; a long name hyphenates rather than dropping below 18vw. The supporting sentence moves to the bottom-left at 16px across the full width, with the action as an underlined link beneath it, 24px above the bottom edge. The top-right links reduce to one word.\",\n  \"headline\": \"The name on exactly two lines, one per ink, each line up to about 8 characters at 15vw on desktop and 21vw on a phone.\",\n  \"motion\": \"masked-headline\",\n  \"seenIn\": [\n   \"opl-marina-rachello\",\n   \"opl-anidachi\"\n  ]\n },\n {\n  \"id\": \"photograph-for-a-letter\",\n  \"name\": \"Photograph for a letter\",\n  \"archetype\": \"giant-wordmark\",\n  \"directions\": [\n   \"name-as-monument\",\n   \"sentence-as-layout\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A flat white or pale ground, about 85% empty. The name sits on one line at the exact vertical centre, bold, at clamp(96px, 10.5vw, 168px), tracking -0.04em, spanning 78–88% of the width with equal side margins. One photograph is set into the line as if it were a glyph. Either it fills the word space between first and last name (a landscape frame one x-height tall and about 1.6em wide, resting on the baseline), or it replaces one round letter of a short name (a square frame exactly one cap-height tall). Build the line as an inline-flex row with `align-items: baseline` and size the frame in em so it scales with the type; square corners, `object-fit: cover`. Navigation is small and pushed to the edges: a 15px wordmark or monogram top-left at a 24px margin and up to five text links at 14px spread evenly across the right half of the top edge. Along the bottom edge, on the same margin: one supporting sentence at 16px starting at column 6, and the single action as an underlined text link flush right.\",\n  \"mobile\": \"The name stacks on two centred lines at 19vw with line-height 0.9. The photograph leaves the line and becomes a 3:2 frame at full width minus 16px margins between the two lines, so the screen reads word, picture, word. A single short name keeps the square frame inline at cap height instead. The supporting sentence and action sit under the block at 16px; the links collapse to one word top-right.\",\n  \"headline\": \"The name on one line with a photograph in its word space or in place of one letter, up to about 16 characters at 10.5vw, splitting into two lines on a phone.\",\n  \"motion\": \"shutter-image\",\n  \"seenIn\": [\n   \"aww-paul-kalkbrenner\",\n   \"opl-nia-creative\"\n  ]\n },\n {\n  \"id\": \"name-split-to-corners\",\n  \"name\": \"Name split to corners\",\n  \"archetype\": \"pinned-stage\",\n  \"directions\": [\n   \"pinned-poster\",\n   \"name-as-monument\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"The name is cut into two halves that stay pinned to opposite corners while the page passes between them. A layer with `position: sticky; top: 0; height: 100svh` and `pointer-events: none` holds both: the first word top-left, 28px from the top and left edges; the second word bottom-right, 28px from the bottom and right edges. Both are set at clamp(72px, 9vw, 140px), line-height 0.85, in white with `mix-blend-mode: difference` so they read on every panel beneath. On the first screen the stage between them is a paper-white panel on columns 1–9 and one full-height photograph on columns 10–12 touching the top, right and bottom edges. The supporting sentence, 20px and max 34ch, starts at column 3 at 44% of the height; the single action is a text link with an arrow directly under it. Three text links are stacked at 15px along the right edge of the white panel at mid-height. The rest of the panel is empty. Later panels, full-height photographs and text panels of different widths, scroll under the pinned halves for three to five viewports; then the layer releases into ordinary sections.\",\n  \"mobile\": \"Both halves stay pinned: the first word top-left and the second bottom-right, each at 15vw with 16px margins. Between them every panel is a full-width photograph 56svh tall followed by its sentence at 17px. On the first screen the photograph crosses the middle band with the supporting sentence and the action link beneath it. The stacked links collapse to one word at the top-right corner.\",\n  \"headline\": \"The name in two halves (two words, or one word cut at a syllable), each up to about 9 characters at 9vw, one per corner, with no other headline.\",\n  \"motion\": \"pinned-story\",\n  \"seenIn\": [\n   \"aww-normal-is-boring\",\n   \"aww-the-state-of-the-gallery\",\n   \"aww-milledollars\"\n  ]\n },\n {\n  \"id\": \"pinned-title-over-portraits\",\n  \"name\": \"Pinned title over portraits\",\n  \"archetype\": \"pinned-stage\",\n  \"directions\": [\n   \"pinned-poster\",\n   \"name-as-monument\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A pale flat ground. The title runs on one line of extra-bold uppercase at clamp(90px, 10vw, 160px), centred, spanning about 82% of the width, its cap line 120px from the top. It lives in a sticky layer (`position: sticky; top: 0; height: 100svh`) stacked above the images and set in one saturated ink that reads on both ground and photograph. Beneath it a single portrait photograph, 2:3, sits centred on columns 5–8 (about 37% of the width) and runs from 90px below the top edge down to the bottom edge, so the title crosses its upper quarter and the middle letters sit on the image. The wordmark sits top-left at 24px in 15px bold; one 'Menu' word sits top-right. Bottom-left on columns 1–3: the supporting sentence as a narrow column at 16px bold, max 26ch, its last line 32px above the bottom edge. Bottom-right: the single action as a solid rectangular button. As the page scrolls, further portraits of identical ratio and position replace the first, five to eight in all, each bringing its own flat ground colour sampled from the photograph, before the layer releases.\",\n  \"mobile\": \"The title stays pinned at the top at 17vw on one line, or two lines at 15vw if longer than ten characters. Each portrait becomes full width minus 16px margins at 2:3 and starts behind the lower half of the title. The supporting sentence follows the first portrait at 16px. The action button is fixed to the bottom-right corner, 16px in. The wordmark shrinks to a monogram top-left.\",\n  \"headline\": \"The title of the series, or the name: one uppercase line of up to about 14 characters at 10vw, two short lines on a phone.\",\n  \"motion\": \"pinned-story\",\n  \"seenIn\": [\n   \"opl-city-of-angels\",\n   \"aww-glitch-grit\"\n  ]\n },\n {\n  \"id\": \"sentence-with-photo-strip\",\n  \"name\": \"Sentence with a photo strip\",\n  \"archetype\": \"inline-media-sentence\",\n  \"directions\": [\n   \"sentence-as-layout\",\n   \"place-carries-it\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A warm flat ground with no navigation bar. One sentence of four or five words runs as a single line of condensed capitals at clamp(120px, 13vw, 200px), sitting on the vertical centre and reaching edge to edge inside 28px margins. Where one word of the sentence would be, a strip of photograph takes its place: a frame exactly one cap-height tall (set in em) and 45–50% of the viewport wide, ratio near 5:1, corners radiused 14px, `object-fit: cover`. Build the line as a flex row with `align-items: baseline` and give the strip `flex: 1` so words and picture always fill the width. The photograph shows the thing the sentence names: a wide view of the place, taken from above or along a horizon, so it survives the letterbox crop. The top third of the screen is empty apart from a 15px wordmark top-left and two text links top-right. About 150px under the sentence the single action sits centred as a small solid button. One supporting sentence at 22px, max 44ch, is centred 48px above the bottom edge.\",\n  \"mobile\": \"The sentence breaks into two lines at 21vw with the strip between them: the first words, then the photograph as a 2:1 frame at full width minus 16px margins with the same 14px corners, then the remaining words. The block is centred vertically. The action button sits 32px under the last line and the supporting sentence under that at 16px. The top links collapse to one word.\",\n  \"headline\": \"A sentence of four or five short words, about 14 characters of type in total, whose missing word is the photograph.\",\n  \"motion\": \"shutter-image\",\n  \"seenIn\": [\n   \"aww-colonia-zacamil\"\n  ]\n },\n {\n  \"id\": \"sentence-split-by-frame\",\n  \"name\": \"Sentence split by a frame\",\n  \"archetype\": \"inline-media-sentence\",\n  \"directions\": [\n   \"sentence-as-layout\",\n   \"pinned-poster\",\n   \"product-performs\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A white or pale ground. One short sentence is broken in two and pushed to the edges: the first half flush to the 32px left margin, the second half flush to the right margin, both on the vertical centre line at clamp(40px, 3.6vw, 60px), medium weight. Between them, dead centre on columns 5–8, sits one media frame: 35% of the viewport wide, 16:9, corners 4px, holding a photograph or a working fragment of the product. The frame belongs to a vertical reel: the bottom 60px of the previous frame shows at the top edge of the viewport and the top 60px of the next at the bottom edge, same width, 24px gaps, so the centre column reads as a strip passing through the sentence. The stage is sticky; the reel advances three or four steps while the two halves of the sentence hold their place. Wordmark top-left; three text links and the single action as a small solid button top-right, all at 15px. Bottom-left on columns 1–4: one supporting sentence at 18px, its last line 32px above the bottom edge. The other corners stay empty.\",\n  \"mobile\": \"The halves stack: the first half of the sentence at 9vw flush left under the wordmark, then the frame at full width minus 16px margins and 4:3, then the second half flush right at 9vw. The neighbouring frames show as 28px slivers above and below. The supporting sentence and the action button follow at 16px. The links collapse to one word.\",\n  \"headline\": \"One sentence of four to six words split into two halves of up to about 14 characters each; the frame between them shows what it is about.\",\n  \"motion\": \"pinned-story\",\n  \"seenIn\": [\n   \"aww-made-with-gsap-1\",\n   \"aww-artem-shcherbakov\"\n  ]\n },\n {\n  \"id\": \"headline-across-two-fields\",\n  \"name\": \"Headline across two fields\",\n  \"archetype\": \"colour-field\",\n  \"directions\": [\n   \"colour-chapters\",\n   \"sentence-as-layout\",\n   \"type-only-statement\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"The viewport is two flat fields meeting at exactly half height: paper above, one saturated colour below, with a hard edge and nothing drawn on it. A two-line headline in black-weight capitals at clamp(96px, 9.5vw, 150px), line-height 0.86, is centred across the seam and spans about 70% of the width, so line one stands on the upper field and line two is cut through its upper third by the seam. The type changes ink where it crosses: above the seam it takes the accent ink, below it a deep ink two steps darker than the lower field, as if submerged. Build it as two stacked copies of the same headline, one per ink, the first clipped with `clip-path: inset(0 0 50% 0)` and the second with `inset(50% 0 0 0)`. Wordmark top-left at 28px; up to four text links and the single action, a solid rectangular button, top-right. One supporting sentence at 20px in the paper colour is centred on the lower field, 56px above the bottom edge. The lower field continues for 30svh past the fold before the next colour begins.\",\n  \"mobile\": \"The same two fields with the seam at 46svh. The headline stays on two lines at 15vw, centred, still cut by the seam and still changing ink. Wordmark top-left and the action button top-right; the links drop into one menu word beside it. The supporting sentence sits on the lower field at 16px, centred, max 28ch, with 40px beneath it.\",\n  \"headline\": \"A statement of two to four words on two lines, up to about 10 characters per line, whose meaning the rising field acts out.\",\n  \"motion\": \"colour-on-scroll\",\n  \"seenIn\": [\n   \"opl-juggle\"\n  ]\n },\n {\n  \"id\": \"swatch-column-beside-view\",\n  \"name\": \"Swatch column beside the view\",\n  \"archetype\": \"split\",\n  \"directions\": [\n   \"colour-chapters\",\n   \"place-carries-it\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A 10px frame of paper colour surrounds the screen. Columns 1–10 are one photograph panel, full height inside the frame, corners radiused 12px, `object-fit: cover`: a wide, calm view with a low horizon and a great deal of sky. The headline is centred in the panel's upper third on two lines of light-weight serif at clamp(72px, 8.6vw, 132px), white, with a neutral scrim behind that band only if the sky is pale. The wordmark sits top-left inside the panel, 28px in. The single action, a white rectangular button, sits bottom-centre, 36px above the panel's lower edge; one supporting sentence at 18px sits bottom-left on columns 1–4, level with it. Columns 11–12 are both the navigation and a preview of the page: a full-height stack of five flat colour blocks of equal height, butted together with no gaps, each holding one text link at 16px in its top-left corner with 20px padding. The five colours are sampled from the photograph, ordered light to dark, and each is the ground colour of the section its link scrolls to. There is no other navigation.\",\n  \"mobile\": \"The photograph panel takes the top 64svh inside an 8px frame, with the headline at 12vw on two lines in its upper third and the action button at its bottom-centre. The swatch column becomes five full-width bars, each 52px tall with its link at 15px, stacked directly under the panel; the first three show above the fold. The supporting sentence moves into the first section.\",\n  \"headline\": \"A two-line statement of three to five words, up to about 14 characters per line at 8.6vw, set over the sky.\",\n  \"motion\": \"colour-on-scroll\",\n  \"seenIn\": [\n   \"aww-seasats\"\n  ]\n },\n {\n  \"id\": \"film-title-on-bottom-edge\",\n  \"name\": \"Film title, bottom edge\",\n  \"archetype\": \"bottom-anchored-type\",\n  \"directions\": [\n   \"place-carries-it\",\n   \"name-as-monument\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One photograph fills the viewport at 100vw by 100svh, `object-fit: cover`, with its subject in the upper two-thirds and a calmer, darker zone along the bottom. The name is one condensed uppercase word, or a short name in a high-contrast serif, set at clamp(150px, 17.5vw, 290px) and sized to span the full width between 32px margins. It is centred and anchored so its baseline sits 34px above the bottom edge, covering roughly the lowest quarter of the frame. A soft neutral dark scrim lies under that bottom band only, about 40% of the height; the rest of the image is untouched. Directly above the name's left end, on the same margin, sits the supporting sentence at 16px on two short lines. Directly above its right end, right-aligned, sits the single action as a small paper-coloured rectangular button. The top edge carries a small emblem or wordmark at the left margin and up to five text links at 15px grouped at the right, all in white. The central half of the screen belongs to the view.\",\n  \"mobile\": \"The photograph is re-cropped to portrait with `object-position` on its subject and fills 100svh. The name stays on the bottom edge at 22vw on one line, or two lines at 20vw beyond eight characters, 20px above the edge. The supporting sentence sits above the name's left end at 15px. The action button moves to the top-right corner and the links collapse to a menu word beside the emblem.\",\n  \"headline\": \"The name of the place: one word of up to about 12 characters at 17.5vw, or two words stacked on a phone.\",\n  \"motion\": \"slow-crossfade\",\n  \"seenIn\": [\n   \"aww-white-desert\",\n   \"opl-eagles-nest\"\n  ]\n },\n {\n  \"id\": \"small-name-open-sky\",\n  \"name\": \"Small name, open sky\",\n  \"archetype\": \"fullbleed-media\",\n  \"directions\": [\n   \"place-carries-it\",\n   \"uneven-photographs\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A single photograph fills the viewport edge to edge with no frame: choose one whose upper 45% is sky, wall or water with nothing in it and whose subject sits low and off-centre. All type is white and stays out of that empty zone. Top-left at a 24px margin, the name is stacked on two or three lines at 14px, like a letterhead. Top-right, three or four text links run in one line at 14px separated by commas, the current one marked by a 2px underline. Bottom-left, 32px from the left and bottom edges, the name repeats as the only larger type: two tight lines at clamp(44px, 4.2vw, 64px), line-height 1.0, regular weight, on columns 1–5. On the same baseline at the bottom-right margin sits the single action as an underlined text link with an arrow, and above it one supporting sentence at 15px, right-aligned, max 32ch. If a lower corner is too bright for white type, darken that corner alone with a neutral scrim. The page below opens on plain paper with one narrow paragraph and wide empty margins.\",\n  \"mobile\": \"The photograph is cropped to portrait around its subject and fills 100svh, its upper half still empty. The small stacked name stays top-left at 13px and the links collapse to one word top-right. The larger name sits bottom-left at 9.5vw on two lines, 20px in. The supporting sentence and the underlined action stack beneath it at 15px, left-aligned, 24px above the bottom edge.\",\n  \"headline\": \"The name set small on two lines of up to about 16 characters each at 4.2vw; the photograph does the work of a headline.\",\n  \"motion\": \"slow-crossfade\",\n  \"seenIn\": [\n   \"aww-kononenko-architectural-bureau\",\n   \"aww-julien-calot\",\n   \"aww-depo-luxe\"\n  ]\n },\n {\n  \"id\": \"invitation-card-cropped\",\n  \"name\": \"Invitation card, cropped\",\n  \"archetype\": \"artefact\",\n  \"directions\": [\n   \"page-is-the-object\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A flat field of one soft colour fills the viewport. Centred on it is a single portrait card in paper colour, 5:7, on columns 4–9, its top edge 190px down and its lower third cut off by the bottom of the viewport, so the page visibly continues as the rest of the card. The card is a filled shape with scalloped inner corners, made with `clip-path` or with four corner circles in the field colour, and no outline. Inside, with 56px padding, everything is centred and symmetrical like letterpress stationery. The two names, or the title, are set in a large italic serif at clamp(56px, 5.6vw, 88px) on two lines, staggered so line one sits left of centre and line two right. Between and beneath them, date, time and place appear as short lines at 15px in sentence case, separated by space and by one solid 10px diamond. The top row sits on the field above the card at 28px margins: a small monogram top-left, three text links centred, and the single action, a solid rectangular button in the ink colour, top-right.\",\n  \"mobile\": \"The card becomes full width minus 12px margins, starts 96px down and is still cropped by the bottom edge, with its scalloped top corners kept. The names stay on two lines at 12vw, centred without the stagger, and the details follow at 15px. The monogram sits top-left and the action button top-right on the field; the three links move onto the card's lower part, below the fold.\",\n  \"headline\": \"The two names or the title on two lines, up to about 12 characters per line, set as they would be printed on the card.\",\n  \"motion\": \"curtain-footer\",\n  \"seenIn\": [\n   \"opl-sarah-matt-wedding\"\n  ]\n },\n {\n  \"id\": \"card-over-dim-room\",\n  \"name\": \"Card over a dim room\",\n  \"archetype\": \"artefact\",\n  \"directions\": [\n   \"page-is-the-object\",\n   \"pinned-poster\",\n   \"dark-room\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A full-bleed, low-key photograph of the room fills the viewport, darkened with `filter: brightness(0.7)` so it reads as atmosphere. Centred over it is one square-cornered panel in a flat warm tone taken from the photograph: columns 4–10, about 55% of the width and 62% of the height, a filled programme card with 32px padding. Along its top edge the three words of the title are spread to the left, centre and right in bold condensed capitals at clamp(28px, 2.5vw, 38px); that line is the headline. Under it sit two left-aligned blocks in the same face and size, line-height 1.0: the facts (date, time, place) as three short lines, then one supporting sentence held to 30ch. Along the card's bottom edge: a credit at left in 14px, the single action as a solid rectangular button in the centre, one text link at right. There is no navigation outside the card. The card is `position: sticky`: as the page scrolls it shrinks with `transform: scale` toward the bottom-left corner and stays there as a ticket-sized stub while photographs of differing sizes pass on a flat ground.\",\n  \"mobile\": \"The photograph fills 100svh and the card sits centred at full width minus 16px margins, 70svh tall. The title words stack as a two-line heading at 9vw at the card's top-left. The facts and the supporting sentence follow at 5.2vw in the condensed face. The action button spans the card's bottom edge. On scroll the card shrinks to a 120px stub pinned bottom-left.\",\n  \"headline\": \"The event or venue name, three words at most and up to about 8 characters each, spread across the card's top edge; two lines on a phone.\",\n  \"motion\": \"pinned-story\",\n  \"seenIn\": [\n   \"opl-the-deep-end\"\n  ]\n },\n {\n  \"id\": \"tabbed-folder-stack\",\n  \"name\": \"Tabbed folder stack\",\n  \"archetype\": \"artefact\",\n  \"directions\": [\n   \"page-is-the-object\",\n   \"one-motif\",\n   \"colour-chapters\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A dark flat ground. A slim top row at 24px holds the wordmark dead centre and one text link far right at 15px. The headline is one centred line of heavy condensed capitals at clamp(96px, 10vw, 160px), spanning about 70% of the width, its cap line 110px from the top. Under it one supporting sentence in a serif at 20px, centred, max 46ch. From 51% of the height down the screen is a stack of five file folders: flat colour bands 86% of the viewport wide, centred, each offset 64px below the one behind so only a strip of the back four shows. Every folder has one trapezoid tab rising 40px from its top edge, cut with `clip-path: polygon()`, at its own horizontal position and in its own colour, holding one section name at 18px. The front folder is open and runs off the bottom edge; it carries the single action as a solid button at its top-left with 32px padding. Each folder links to its section and lends that section its ground colour. The tab shape returns as the button's top corners.\",\n  \"mobile\": \"The headline sits 96px down at 17vw on one line, or two at 15vw, centred, with the supporting sentence at 16px beneath. The folder stack starts at 48svh at full width: bands offset 52px, tabs 32px tall with names at 15px, staggered left, centre and right. The front folder runs off the bottom with the action button at full width inside it.\",\n  \"headline\": \"The name or a two-word statement on one line of up to about 12 characters at 10vw; two lines allowed on a phone.\",\n  \"motion\": \"index-preview\",\n  \"seenIn\": [\n   \"aww-mosbys-files\",\n   \"opl-medium-rare\"\n  ]\n },\n {\n  \"id\": \"striped-card-beside-room\",\n  \"name\": \"Striped card beside the room\",\n  \"archetype\": \"split\",\n  \"directions\": [\n   \"one-motif\",\n   \"page-is-the-object\",\n   \"split-stage\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"The viewport is split 50/50 with a 12px gap and 12px outer margins. The right half is one full-height photograph of the room, corners radiused 16px, `position: sticky` so it stays in view while the left half scrolls. The left half is a printed card: a flat paper-colour panel with the same 16px radius, and the subject's stripe (from its awning, label or ribbon) as the only ornament. Across the card's top runs a band 56px tall made of alternating bars of the single ink colour and paper, each bar 28px wide, built as a flex row of filled blocks. The same stripe returns as an 8px band above the footer and inside the button on hover. Under the band, centred: the wordmark about 300px wide, then a two-line headline in a light serif at clamp(40px, 3.6vw, 56px) in the ink colour, one supporting sentence at 17px held to 36ch, and the single action as a solid rectangular button. Three text links sit in one centred row at 15px, 28px above the card's bottom edge. One ink on paper; the photograph supplies every other colour.\",\n  \"mobile\": \"The photograph comes first at full width inside 12px margins, 48svh tall, with the 16px radius. The card follows and overlaps the photograph's bottom edge by 24px using a negative margin. Its striped band is 40px tall; below it the wordmark at 56% width, the headline at 8vw on two lines, the sentence and the button, all centred. The links wrap into the card's foot.\",\n  \"headline\": \"A warm two-line welcome of three to six words, up to about 18 characters per line at 3.6vw.\",\n  \"motion\": \"slow-crossfade\",\n  \"seenIn\": [\n   \"opl-le-petit-bleu\",\n   \"opl-zara-webb\"\n  ]\n },\n {\n  \"id\": \"giant-cropped-shape\",\n  \"name\": \"Giant cropped shape\",\n  \"archetype\": \"colour-field\",\n  \"directions\": [\n   \"one-motif\",\n   \"colour-chapters\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A plain ground with one flat shape at enormous scale. The shape is the simplest geometry found in the subject (a circle, a ring segment, a chamfered block, an arch), drawn in CSS or as a single inline SVG path and filled with the accent colour. It is about 120vh across and enters from the right, centred near 78% of the width and 55% of the height, so the top, right and bottom edges of the viewport crop it and its left boundary reaches column 7. If the subject has a true pair (two accounts, two modes), a second shape in a second flat colour overlaps the first by a quarter with `mix-blend-mode: multiply`. The headline sits on the bare ground on columns 1–6, vertically centred, flush left at 8% from the left edge: two lines at clamp(64px, 6.4vw, 100px), heavy weight, tracking -0.03em. Beneath it comes one supporting sentence at 19px, then the single action as a solid button cut to the same shape. A bold wordmark sits top-left at 32px; up to three text links sit top-right in the ground colour.\",\n  \"mobile\": \"The shape moves to the bottom: 130vw across, centred horizontally, its top at 56svh, cropped by the left, right and bottom edges. The headline sits above it at 11.5vw on two lines at a 16px margin, starting 15% down, with the sentence at 16px and the motif-shaped button beneath. Wordmark top-left; the links collapse to one word top-right.\",\n  \"headline\": \"Two lines of two or three words each, up to about 12 characters per line at 6.4vw.\",\n  \"motion\": \"shutter-image\",\n  \"seenIn\": [\n   \"opl-tara\",\n   \"opl-superlocal-2026\",\n   \"aww-sstr-friction-reduction\"\n  ]\n },\n {\n  \"id\": \"fragment-on-shaped-stage\",\n  \"name\": \"Fragment on a shaped stage\",\n  \"archetype\": \"split\",\n  \"directions\": [\n   \"product-performs\",\n   \"one-motif\",\n   \"colour-chapters\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A neutral ground. The headline occupies the upper-left third: two lines at clamp(52px, 5.2vw, 80px), medium weight, flush left on columns 1–6 at a 40px margin, starting 150px down. One supporting sentence at 18px, max 40ch, follows, then the single action as a small rectangular button. The rest of the screen belongs to one flat stage in a saturated colour: it spans columns 5–12, begins 42% down, and bleeds off the right and bottom edges. Its top-left corner is cut with the product's own shape using `clip-path` (a notch, a chamfer or a tab two columns wide), the only decoration on the page. On the stage, 56px in from its left and top edges, sits the main fragment of the interface at true size with labels at 13–15px, built in HTML and working: one panel or control about 620px wide, cropped by the bottom edge, never a whole window and never inside a browser or laptop frame. Mark its root with data-ui. Navigation is a plain row at 28px from the top: wordmark left and four text links right at 15px. Nothing overlaps the headline.\",\n  \"mobile\": \"The headline sits under the wordmark at 10vw on two lines, followed by the sentence at 16px and the button. The stage comes next at full width, bleeding off both sides and the bottom, its corner cut kept at 72px wide. The fragment sits 16px inside it at true size; if it is wider than the screen the right edge crops it rather than scaling it down.\",\n  \"headline\": \"A plain statement of what the product does in three to six words, two lines of up to about 16 characters each at 5.2vw.\",\n  \"motion\": \"shutter-image\",\n  \"seenIn\": [\n   \"opl-typewave\",\n   \"opl-vessa\",\n   \"opl-uni\"\n  ]\n },\n {\n  \"id\": \"control-reads-the-page\",\n  \"name\": \"Control that reads the page\",\n  \"archetype\": \"split\",\n  \"directions\": [\n   \"product-performs\",\n   \"quiet-instrument\",\n   \"dark-room\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A near-black or deep neutral ground split into two halves by tone alone: the right half is one step lighter than the left, and they meet at a clean vertical edge at 50%. Left half: a small logo mark top-left at a 40px margin, then two-thirds of empty ground, then everything else anchored bottom-left, 40px from the edges: a one-line headline at clamp(26px, 2.1vw, 32px) in medium weight, one supporting sentence at 17px in the softer ink held to 44ch, and the single action as a light rectangular button. Right half: one fragment of the product, centred, about 450px square, built in HTML and working. It is the product's defining control (a loupe, a picker, a dial, a field) and it acts on the page itself: it reads the real background colour, the real headline size or the pointer position and prints that value in its own readout at 13px. Mark its root with data-ui so the product's own radii and borders apply inside it. There is no navigation bar; one text link sits top-right at 15px.\",\n  \"mobile\": \"The halves stack as two tones. The fragment comes first: 78vw square, centred in the lighter block, which is 58svh tall, still live and reading the page under the visitor's finger. The darker block below holds the headline at 6.4vw on up to two lines, the sentence at 16px and the button, left-aligned at 20px. The logo mark sits top-left over the first block.\",\n  \"headline\": \"One plain line at 26–32px naming what the tool is, up to about 32 characters, wrapping to two lines on a phone.\",\n  \"motion\": \"masked-headline\",\n  \"seenIn\": [\n   \"opl-dabbit\"\n  ]\n },\n {\n  \"id\": \"controls-on-the-sentence\",\n  \"name\": \"Controls on the sentence\",\n  \"archetype\": \"type-poster\",\n  \"directions\": [\n   \"product-performs\",\n   \"sentence-as-layout\",\n   \"type-only-statement\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A dark flat ground with no logo bar: a 14px wordmark top-left and the single action as an underlined text link top-right, both 28px in. The headline is a two-line sentence, centred, at clamp(96px, 9vw, 150px), line-height 1.0, occupying the middle 64% of the width and sitting slightly above the midline. It is set in a variable font and it is the demonstration. Three small control chips from the product sit on top of the sentence, each about 300 by 80px with the product's true radius, a text label and a numeric readout: one above the first line near its left end, one overlapping the start of the second line, and a two-state switch at the lower right. They are tilted 2 to 4 degrees and filled solid, one step lighter than the ground. Each one works: dragging the first changes the headline's weight through `font-variation-settings`, the second changes its letter-spacing, the third toggles uppercase. Mark each chip's root with data-ui. One supporting sentence at 17px, max 40ch, is centred 72px under the headline. The bottom third of the screen stays empty.\",\n  \"mobile\": \"The sentence stays on two lines at 13.5vw, centred at 38% of the height. The three chips shrink to 200 by 60px and move off the letters: one above the sentence and two side by side beneath it, untilted and still live. The supporting sentence follows at 16px. The wordmark stays top-left and the action link top-right.\",\n  \"headline\": \"A two-line sentence of three to five words, up to about 11 characters per line at 9vw, that still reads when its weight and spacing change.\",\n  \"motion\": \"masked-headline\",\n  \"seenIn\": [\n   \"opl-dialkit\"\n  ]\n },\n {\n  \"id\": \"column-on-one-line\",\n  \"name\": \"Column on one line\",\n  \"archetype\": \"quiet-column\",\n  \"directions\": [\n   \"quiet-instrument\",\n   \"product-performs\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A warm off-white page that is more than 80% empty. Everything hangs on one vertical alignment 27% in from the left edge, the start of column 4; nothing is centred and nothing sits to its left. A small logo mark sits on that alignment 56px from the top. About 220px lower the column begins, only 380px wide: a two-line headline at 27px in medium weight, line-height 1.25; one supporting sentence at 15px in the softer ink, line-height 1.5; then, 28px below, the single action as a near-black rectangular button with 4px corners and one text link with an arrow beside it. A sign-in text link sits alone in the top-right corner at 14px; there is no navigation bar. At the bottom edge the first demonstration peeks in on the same alignment: a flat panel one step darker than the page, 368px wide, its top 90px visible, holding two real rows of the product's interface at true size with a visible pointer. Mark the panel's root with data-ui. The right half of the screen is blank on purpose, and nothing spans the full width until the footer.\",\n  \"mobile\": \"The alignment becomes the 24px left margin. The logo mark sits 32px from the top and the column starts at 30% of the height: headline at 24px on two lines, the sentence at 15px, then button and text link side by side. The demonstration panel spans the width between the margins and shows its top 120px above the fold. The sign-in link stays top-right.\",\n  \"headline\": \"A dry two-line statement at 27px, up to about 30 characters per line; it never grows larger at any width.\",\n  \"motion\": \"slow-crossfade\",\n  \"seenIn\": [\n   \"opl-rows\",\n   \"opl-lovably\"\n  ]\n },\n {\n  \"id\": \"single-object-on-plinth\",\n  \"name\": \"Single object on a plinth\",\n  \"archetype\": \"object-centre\",\n  \"directions\": [\n   \"quiet-instrument\",\n   \"hero-object\",\n   \"specimen-catalogue\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"blueprint\": \"An off-white screen that is about 80% empty and does not need to scroll. One photographed object stands dead centre: a studio shot on a plain background, shown 440px tall (about half the viewport height) whatever its width, with `mix-blend-mode: multiply` so its backdrop disappears into the page. It rests on a plinth, a rounded square 520px across filled one step lighter than the page and centred behind it, with no border. The wordmark sits top-left at a 56px margin in a heavy serif or grotesk, about 400px wide (28% of the viewport) and 80px tall; it is the only large type. Opposite it, top-right on the same margin and aligned to the wordmark's top, sits the one supporting sentence at 15px, right-aligned, max 36ch. Centred 40px under the plinth is the single action: a compact email field or button 240px wide with 8px corners. Further objects replace the first in the same position by crossfade, each scaled to the same visual mass. There is no navigation. Nothing else touches the edges, and the object never grows beyond half the viewport height.\",\n  \"mobile\": \"The wordmark sits top-left at 44vw wide with 20px margins and the supporting sentence drops beneath it at 14px. The plinth is 78vw square, centred at 54% of the height, with the object 44svh tall on it. The action sits 32px under the plinth, 40px in from each side. The screen stays mostly empty and the objects swap in place.\",\n  \"headline\": \"None beyond the name: the wordmark top-left, up to about 10 characters, is the only large type and the object is the statement.\",\n  \"motion\": \"slow-crossfade\",\n  \"seenIn\": [\n   \"opl-archiv\",\n   \"opl-humanoid-index\"\n  ]\n },\n {\n  \"id\": \"object-crops-three-edges\",\n  \"name\": \"Object cropped by three edges\",\n  \"archetype\": \"object-centre\",\n  \"directions\": [\n   \"hero-object\",\n   \"loud-flat-poster\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"blueprint\": \"A flat off-white or single bold colour field with no navigation bar: only a small wordmark top-right at 24px and the single action fixed bottom-right as a solid rectangular button. The left 60% of the screen is one object photographed on a plain background and scaled far past its container. Set the image to about 150% of the hero's height, rotate it 10 to 20 degrees and position it so the top, left and bottom edges of the viewport all crop it and only its right-hand third is fully inside; use `overflow: hidden` on the section and `mix-blend-mode: multiply` if the field is light. The headline fills the right half: two stacked lines of very bold lowercase at clamp(120px, 13vw, 210px), right-aligned 16px from the right edge, tracking -0.05em, line-height 0.86, vertically centred. It sits behind the object in the stacking order, so the object's right-hand contour tucks over the first one or two letters of each line. One supporting sentence at 18px, max 28ch, is right-aligned under the headline on columns 9–12. Nothing else is on the screen: no second image, no list.\",\n  \"mobile\": \"The object moves to the top: the image is 150vw wide, rotated, cropped by the top, left and right edges, and occupies the upper 52svh. The headline sits below it at 19vw on two lines, right-aligned at a 12px margin, its first line overlapped by the object's lower contour. The supporting sentence follows at 16px, right-aligned. The action button stays fixed bottom-right.\",\n  \"headline\": \"Two lines of one or two short words each, up to about 8 characters per line at 13vw, partly tucked behind the object.\",\n  \"motion\": \"shutter-image\",\n  \"seenIn\": [\n   \"opl-when-you-wish-upon-a-starboy\"\n  ]\n },\n {\n  \"id\": \"object-splits-the-headline\",\n  \"name\": \"Object splits the headline\",\n  \"archetype\": \"object-centre\",\n  \"directions\": [\n   \"hero-object\",\n   \"sentence-as-layout\",\n   \"dark-room\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"blueprint\": \"One deep, flat ground colour. The object, a low-key studio photograph whose background matches the ground, stands at dead centre, scaled to 66% of the viewport height and tilted about 8 degrees, with its base cropped by the bottom edge. The headline is split around it: line one is centred across the object's upper fifth and line two across its lower fifth, both at clamp(64px, 5.8vw, 92px), regular weight, spanning columns 2–11, so the object fills the gap where a paragraph would normally sit. The type lies above the object in the stacking order in the light ink, so every letter stays readable where it crosses. At the object's mid-height two small text blocks at 14px face each other: the supporting sentence far left on columns 1–2, and two short facts (size, price) far right on columns 11–12, right-aligned, each 32px from its edge. Wordmark top-left; three text links top-centre; the single action top-right as a small light rectangular tab, the only light solid on the screen. The lower corners stay dark and empty.\",\n  \"mobile\": \"The object is 54svh tall, centred, its base cropped by the bottom edge. Line one of the headline crosses its top at 11vw and line two its lower third at 11vw, both centred inside 16px margins. The side text blocks merge into one 15px sentence under the navigation. Wordmark top-left and the action tab top-right; the links collapse to one word.\",\n  \"headline\": \"A two-line statement of four to six words, up to about 16 characters per line at 5.8vw, with the object standing between the lines.\",\n  \"motion\": \"slow-crossfade\",\n  \"seenIn\": [\n   \"aww-zeroz-brand-site\",\n   \"aww-moto-finance\"\n  ]\n },\n {\n  \"id\": \"object-on-the-seam\",\n  \"name\": \"Object on the seam\",\n  \"archetype\": \"object-centre\",\n  \"directions\": [\n   \"hero-object\",\n   \"quiet-instrument\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"blueprint\": \"A white or very pale page organised by one change of tone. A square-cornered panel one step darker than the page (a flat pale blue-grey or warm grey) fills the top 44% of the viewport inside 12px margins; the page colour runs below it. The object, photographed on a plain background and blended with `mix-blend-mode: multiply`, straddles the seam between the two tones: it is about 62% of the viewport wide, starts at column 6 and runs off the right edge, with its upper half over the panel and its lower half over the page. Type is small and exact. The headline is two lines at 24px in medium weight, far left on columns 1–3 at a 32px margin, its first baseline resting exactly on the seam; the second line is set in the softer ink. One supporting sentence at 15px, max 34ch, sits 120px lower on the same margin with the single action as a small rectangular button under it. A plain top row inside the panel at 14px: wordmark left, three text links centred, one text link right.\",\n  \"mobile\": \"The tonal panel takes the top 46svh. The object is 120vw wide, centred on the seam and cropped by the right edge. The headline sits just under the seam at 22px on two lines at a 20px margin, with the sentence at 15px beneath and then the button. The wordmark sits top-left inside the panel; the links collapse to one word top-right.\",\n  \"headline\": \"Two short sentences at 24px, one per line and up to about 28 characters each, the second in the softer ink.\",\n  \"motion\": \"shutter-image\",\n  \"seenIn\": [\n   \"opl-aevion\"\n  ]\n },\n {\n  \"id\": \"statement-beside-specimen-mosaic\",\n  \"name\": \"Statement beside specimen mosaic\",\n  \"archetype\": \"mosaic\",\n  \"directions\": [\n   \"specimen-catalogue\",\n   \"split-stage\",\n   \"uneven-photographs\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"blueprint\": \"The viewport is split 50/50 by tone alone: the left half is the page ground, the right half a field one step darker, meeting at a clean vertical edge with no line. Left half: the wordmark at 22px sits top-left on a 32px margin; under it the statement at clamp(44px, 4.4vw, 68px), bold, tracking -0.04em, leading 1.0, top-left aligned and filling the upper 40% of the half. The lower part of this side stays empty except for one supporting sentence at 18px pinned bottom-left and the single action as a solid rectangle beside it. Right half: a loose mosaic of seven specimen tiles on a 4-column, 3-row grid with 14px gaps. Each tile is a flat palette colour at 3:4 holding one cut-out item, centred, object-fit: contain, mix-blend-mode: multiply. Five cells are left empty so the tiles stagger; one tile spans two columns and two rows; the rightmost column is cropped by the viewport edge. Two text links sit top-right over the darker field. The right half may be position: sticky while the left scrolls.\",\n  \"mobile\": \"The split becomes a stack. The statement comes first at 10.5vw on two lines inside 20px margins, the supporting sentence under it at 16px, then the action. Below, the darker field runs full width and the mosaic becomes two columns of tiles, the right column started 48px lower than the left; five tiles show and the last row is cropped by the bottom of the screen. Navigation is the wordmark and one link.\",\n  \"headline\": \"A 3-5 word statement of what is on offer, at most 28 characters so it holds two lines at 10.5vw on a phone.\",\n  \"motion\": \"shutter-image\",\n  \"seenIn\": [\n   \"aww-noho\"\n  ]\n },\n {\n  \"id\": \"specimen-wall-docked-panel\",\n  \"name\": \"Specimen wall, docked panel\",\n  \"archetype\": \"tiles\",\n  \"directions\": [\n   \"specimen-catalogue\",\n   \"dense-tiles\",\n   \"contact-sheet\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"blueprint\": \"There is no header and no display headline: the whole viewport is a wall of specimens. Square tiles of about 112px (7.8vw) with 8px gaps fill the screen edge to edge in eight rows; alternate rows shift half a tile sideways so the wall reads as brickwork, and tiles at every edge are cropped by the viewport (overflow: hidden on the section). Each tile is a flat fill, rotating through three palette colours, holding one cut-out item at 60% of the tile, centred, with mix-blend-mode: multiply on light fills. A solid panel in the ink colour, 800px wide (columns 4-9) and about 170px tall with square corners, is docked at the bottom centre, 24px above the bottom edge, covering the tiles behind it. Inside, on 28px padding: the sentence that says what this is at 24px semibold on the left across two lines, the single action as a filled rectangle in the paper colour on the right, and beneath them a row holding the wordmark and four text links at 15px. Nothing else overlays the wall.\",\n  \"mobile\": \"Tiles become 22vw squares with 6px gaps, four and a half per row, still offset as brickwork and cropped at both sides. The panel turns into a full-width block fixed to the bottom of the first screen, about a third of its height: the sentence at 6vw on two lines, the action full width beneath it, the wordmark and links in one wrapped row at 14px. The wall fills everything above.\",\n  \"headline\": \"No display line: one plain sentence of up to 56 characters inside the panel names what the items are.\",\n  \"motion\": \"index-preview\",\n  \"seenIn\": [\n   \"opl-smallbits\",\n   \"opl-beige-force\"\n  ]\n },\n {\n  \"id\": \"single-specimen-name-list\",\n  \"name\": \"Single specimen with name list\",\n  \"archetype\": \"object-centre\",\n  \"directions\": [\n   \"specimen-catalogue\",\n   \"borrowed-category\",\n   \"hero-object\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"blueprint\": \"Borrowed from a museum plinth. A calm light ground with roughly 70% left empty. The wordmark is set large for a logo, about 28% of the viewport wide (clamp(64px, 6vw, 92px), heavy serif or grotesk), top-left on a 56px margin; one sentence of description at 15px sits top-right on the same margin, its first line aligned to the top of the wordmark. Dead centre stands one specimen: a flat tile in a palette colour, 400px wide and 460px tall (columns 5-8) with a 16px radius, holding a single cut-out item at about 80% of the tile height, object-fit: contain. Left of the tile, in columns 2-4, a vertical list of item names is right-aligned towards it: the selected name in full ink at 20px, the names above and below stepping down in size and opacity (18, 16, 14px; 60, 35, 15%). Choosing a name swaps the item and the tile colour. Below the tile, centred: the item's one-line fact at 14px, then the single action, a filled rectangle 240px wide. Three text links sit bottom-left at 14px.\",\n  \"mobile\": \"The wordmark sits top-left at 11vw with the description sentence beneath it at 15px. The tile takes the full width inside 20px margins at 4:5, starting at 30% of the height. The name list becomes one horizontal row under the tile that scrolls sideways with scroll-snap, the selected name centred in full ink at 18px. The action sits full width at the bottom of the screen; the links move to the footer.\",\n  \"headline\": \"The name itself as an oversized wordma\n\n<!-- [TRUNCATED AT 50KB] -->","isInternal":false,"tokens":13107,"sizeBytes":50084},{"name":"motions.json","path":"skills/taste-skill/library/motions.json","rawUrl":"https://raw.githubusercontent.com/Leonxlnx/taste-skill/HEAD/skills/taste-skill/library/motions.json","title":"Library Skill","category":"anthropic-skill","format":"json","content":"[\n {\n  \"id\": \"masked-headline\",\n  \"name\": \"Masked headline\",\n  \"description\": \"On load, each line of the headline rises from behind its own baseline, about 900ms with a strong ease-out, the second line 110ms after the first; the supporting sentence and the action then fade up together. Nothing else on the page performs. Because headlines are two lines at most, you author the line breaks and wrap each line yourself. Recipe: 'Masked line reveal' in references/motion.md.\"\n },\n {\n  \"id\": \"shutter-image\",\n  \"name\": \"Shutter image\",\n  \"description\": \"The one hero or showcase image opens from an edge with a clip-path over about 1.1 seconds while the picture inside settles from 1.12 scale to rest. Use it once, on the image that matters most; later images simply are there. Recipe: 'Image shutter' in references/motion.md.\"\n },\n {\n  \"id\": \"scaling-wordmark\",\n  \"name\": \"Scaling wordmark\",\n  \"description\": \"The giant name responds to the scroll: as the first screen leaves, the wordmark scales down a few percent (or grows from 0.94 to 1 as the footer arrives) on a scroll-linked timeline, so the monument feels heavy. Travel stays under 8%. Static fallback where scroll timelines are unsupported. Recipe: 'Scroll-linked progress' in references/motion.md, animating `scale`.\"\n },\n {\n  \"id\": \"pinned-story\",\n  \"name\": \"Pinned story\",\n  \"description\": \"One element holds its place with `position: sticky` (a title, a frame, a product fragment) while the items that belong to it scroll past or swap inside it. The page's ordinary scrolling does the work; nothing is hijacked. Hold it for about one screen per step and three screens at most, two held stages per page at most, with a line of text on every held screen. Recipe: 'Pinned story' in references/motion.md.\"\n },\n {\n  \"id\": \"index-preview\",\n  \"name\": \"Index with preview\",\n  \"description\": \"Rows of text are the navigation through the work; pointing at a row brings up its image in one fixed frame and dims the other rows. On touch screens each row shows its image inline instead. Fast and exact (about 240ms crossfade), no lag behind the pointer. Recipe: 'Index with preview, anchored to the row' in references/motion.md.\"\n },\n {\n  \"id\": \"curtain-footer\",\n  \"name\": \"Curtain footer\",\n  \"description\": \"The page content slides up like a sheet to uncover the footer waiting beneath it, so the last screen is revealed rather than scrolled to. Build with a sticky footer at the bottom and a main element with its own background and a higher stacking order. No JavaScript.\"\n },\n {\n  \"id\": \"slow-crossfade\",\n  \"name\": \"Slow crossfade\",\n  \"description\": \"The principal photograph quietly changes: three or four images of the same framing crossfade over about 1.6 seconds, holding five to six seconds each, or the fixed image changes when its matching section arrives. It should feel like light shifting in a room. Pause when the tab is hidden; under reduced motion show only the first image.\"\n },\n {\n  \"id\": \"edge-marquee\",\n  \"name\": \"Edge-to-edge marquee\",\n  \"description\": \"One line of very large type travels sideways across the full width at a slow constant speed, as a band between two sections or as the closing statement. Linear timing, duplicated content for a seamless loop, paused on hover and under reduced motion. One marquee per page, carrying real words (the name, the claim), never a list of buzzwords.\"\n },\n {\n  \"id\": \"drag-row\",\n  \"name\": \"Drag row\",\n  \"description\": \"A row of large items wider than the screen that the visitor pulls sideways: native horizontal scrolling with scroll snapping, the first item aligned to the page margin and the last allowed to run off the edge so the row visibly continues. No carousel library, no arrows, no dots.\"\n },\n {\n  \"id\": \"colour-on-scroll\",\n  \"name\": \"Colour by chapter\",\n  \"description\": \"Each chapter is its own full-bleed field of one palette colour, so the ground changes exactly at section edges as you scroll, never as a global recolouring of the screen. The only movement: the fixed header (or the one pinned element) takes the ink of the chapter beneath it, switching with a 300ms colour transition as each edge passes under it. Do not drive the page background from an observer: in blind tests a page recoloured mid-section, with a paragraph sitting on two colours, read as broken twice.\"\n },\n {\n  \"id\": \"stillness\",\n  \"name\": \"Stillness\",\n  \"description\": \"No showpiece. The page is simply there, instantly, and the discipline is the statement. Motion is limited to exact feedback: a 140ms press on the button, a 180ms colour change on links, focus rings that appear without delay. Do not add a load animation or scroll reveals to this direction.\"\n },\n {\n  \"id\": \"opening-window\",\n  \"name\": \"Opening window\",\n  \"description\": \"A type screen hands over to the one great photograph: the picture first shows as a window about 45% of the width in the middle of a held stage and opens to full-bleed over about one screen of scroll, while the image inside settles from 1.15 scale. Scroll-linked and linear, so the reader sets the pace; it is fully open after three quarters of the hold and rests a moment before the page moves on. Use it once, for the picture that carries the subject. Where scroll timelines are unsupported, or under reduced motion, the picture is simply a full-bleed screen. Recipe: 'Opening window' in references/motion.md.\"\n },\n {\n  \"id\": \"ink-fill\",\n  \"name\": \"Ink-fill statement\",\n  \"description\": \"One statement of three to five lines at 32px or more starts at 45% ink and fills to full ink line by line as it rises from three quarters of the way down the screen to just past half way, so the reading pace follows the scroll. Every word is readable before it fills; the fill only sets the rhythm. Once per page, never on body copy, never on a headline the visitor needs at once. Full ink without scroll timelines or under reduced motion. Recipe: 'Ink fill' in references/motion.md.\"\n },\n {\n  \"id\": \"sheet-over\",\n  \"name\": \"Sheet over a held picture\",\n  \"description\": \"A full-bleed photograph holds its place for one screen and the next chapter, an opaque sheet in the page ground carrying its heading at the top edge, slides up over it like a page being turned. The chapter change is read, not just seen, and nothing is hijacked: the photograph is a 100svh figure with position: sticky; top: 0, followed by a section with its own background and a higher stacking order. Hold for one screen at most, use it at one or two chapter changes, and give each held photograph a caption so the held screen carries a line of text.\"\n },\n {\n  \"id\": \"sideways-gallery\",\n  \"name\": \"Sideways gallery\",\n  \"description\": \"A short set of pictures (eight or fewer: rooms, kitchens, pieces) moves sideways while the vertical scroll holds the stage, one pixel of scroll for one pixel of travel, and the hold ends the moment the last picture reaches the margin. Only on wide screens with motion allowed and only when the row is under three screens long; phones, reduced motion and longer rows get the native drag row with snapping. Focusing a link scrolls its picture into view, and the only copy of a call to action never sits inside the moving row. Recipe: 'Sideways gallery' in references/motion.md.\"\n },\n {\n  \"id\": \"pushed-line\",\n  \"name\": \"Pushed line\",\n  \"description\": \"One line of very large type, the name or the claim, is pushed sideways by the scroll rather than by a clock: it travels from 12% right to 12% left of its place while it crosses the screen, linear and locked to the scrollbar, and reads whole at the middle of its run. One per page, never across running text, and the words must never be cropped at the moment the line sits in the middle of the screen. Build with animation-timeline: view() on the line and a translateX keyframe; static where scroll timelines are unsupported and under reduced motion.\"\n },\n {\n  \"id\": \"rolling-figures\",\n  \"name\": \"Rolling figures\",\n  \"description\": \"For a page whose case is a handful of numbers (a report, a fund, a practice with a founding year): three or four figures at display size roll each digit up to its value once as they come into view, about 1.1 seconds on a strong ease-out, the columns 70ms apart. Tabular figures, the real number kept in the text for screen readers and search, never in running text and never for a value that changes after load. Set at its value under reduced motion. Recipe: 'Rolling figures' in references/motion.md.\"\n },\n {\n  \"id\": \"carried-picture\",\n  \"name\": \"Carried picture\",\n  \"description\": \"Between the index and a case page, the picture the visitor clicked travels into place as the new page's hero while the old page fades out in 200ms and the new one rises in, all within 480ms, using the browser's own cross-document view transitions with no library and no full-screen curtain. Give the card picture and the hero the same view-transition-name; each name appears once per page. Browsers without view transitions simply navigate; reduced motion turns it off. Recipe: 'Page to page' in references/motion.md.\"\n }\n]\n","isInternal":false,"tokens":2110,"sizeBytes":9033},{"name":"palettes.json","path":"skills/taste-skill/library/palettes.json","rawUrl":"https://raw.githubusercontent.com/Leonxlnx/taste-skill/HEAD/skills/taste-skill/library/palettes.json","title":"Library Skill","category":"anthropic-skill","format":"json","content":"[\n {\n  \"id\": \"white-link-blue\",\n  \"name\": \"Sheet and biro\",\n  \"tags\": [\n   \"light-neutral\",\n   \"mono-accent\"\n  ],\n  \"bg\": \"#ffffff\",\n  \"surface\": \"#f4f4f4\",\n  \"ink\": \"#111111\",\n  \"muted\": \"#6b6b6b\",\n  \"accent\": \"#1a4be0\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#111111\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"White holds the whole page with black type, one grey for secondary lines and a pale grey step for tiles and inputs; the footer may invert to black. Blue is the colour of text links and the one button, and nothing else is tinted.\",\n  \"seenIn\": [\n   \"opl-shawn-golden\",\n   \"opl-lovably\",\n   \"aww-bleibtgleich26\"\n  ]\n },\n {\n  \"id\": \"cool-white-slate\",\n  \"name\": \"Frost and slate\",\n  \"tags\": [\n   \"light-neutral\"\n  ],\n  \"bg\": \"#f7f9fa\",\n  \"surface\": \"#ecf0f2\",\n  \"ink\": \"#1f3038\",\n  \"muted\": \"#5d6b72\",\n  \"accent\": \"#0d7480\",\n  \"accentInk\": \"#ffffff\",\n  \"note\": \"Cool white and one paler blue-grey step hold everything, with type in dark slate instead of black. Teal appears once per screen at most, as the primary button or one small detail beside the product photograph.\",\n  \"seenIn\": [\n   \"opl-aevion\",\n   \"aww-cominvi\"\n  ]\n },\n {\n  \"id\": \"rose-grey-green\",\n  \"name\": \"Rose grey, green\",\n  \"tags\": [\n   \"light-neutral\"\n  ],\n  \"bg\": \"#ebe5e3\",\n  \"surface\": \"#e1dad7\",\n  \"ink\": \"#2b2622\",\n  \"muted\": \"#6a615d\",\n  \"accent\": \"#0f7d45\",\n  \"accentInk\": \"#ffffff\",\n  \"note\": \"A single rosy grey covers the page from top to bottom with brown-black text and grey secondary lines; images are kept greyscale. Green appears only on the current-page link and on one button in the footer.\",\n  \"seenIn\": [\n   \"opl-the-queue\"\n  ]\n },\n {\n  \"id\": \"paper-grey-brass\",\n  \"name\": \"Newsprint and brass\",\n  \"tags\": [\n   \"light-neutral\"\n  ],\n  \"bg\": \"#e8e8e3\",\n  \"surface\": \"#dcdcd6\",\n  \"ink\": \"#181715\",\n  \"muted\": \"#63625c\",\n  \"accent\": \"#bfb21a\",\n  \"accentInk\": \"#181715\",\n  \"fields\": [\n   {\n    \"bg\": \"#181715\",\n    \"ink\": \"#e8e8e3\"\n   }\n  ],\n  \"note\": \"Warm paper grey with near-black type holds the upper page, then whole sections flip to near-black with paper-grey type; no section is tinted. Brass yellow marks one small detail per screen, such as the button or a single word.\",\n  \"seenIn\": [\n   \"aww-monolog\"\n  ]\n },\n {\n  \"id\": \"stone-blueprint\",\n  \"name\": \"Stone and blueprint\",\n  \"tags\": [\n   \"light-neutral\"\n  ],\n  \"bg\": \"#dfdedb\",\n  \"surface\": \"#d3d2ce\",\n  \"ink\": \"#26251e\",\n  \"muted\": \"#5f5d55\",\n  \"accent\": \"#2456d6\",\n  \"accentInk\": \"#ffffff\",\n  \"note\": \"Stone paper carries the whole page with near-black and grey text. One image at a time is printed in the accent blue as its only ink, and the same blue fills the single button.\",\n  \"seenIn\": [\n   \"opl-compile\"\n  ]\n },\n {\n  \"id\": \"white-navy-tab\",\n  \"name\": \"Navy on white\",\n  \"tags\": [\n   \"light-neutral\",\n   \"photographic-neutral\"\n  ],\n  \"bg\": \"#ffffff\",\n  \"surface\": \"#f4f4f2\",\n  \"ink\": \"#1f2b4d\",\n  \"muted\": \"#6a7186\",\n  \"accent\": \"#f7941d\",\n  \"accentInk\": \"#1f2b4d\",\n  \"fields\": [\n   {\n    \"bg\": \"#05070a\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#e3e1dc\",\n    \"ink\": \"#1f2b4d\"\n   }\n  ],\n  \"note\": \"Pure white pages with navy type sit between full-bleed photographs, opening on near-black and closing on a warm grey footer. Tangerine is one small tab or button, never larger than a thumbnail.\",\n  \"seenIn\": [\n   \"aww-white-desert\",\n   \"aww-realevate\"\n  ]\n },\n {\n  \"id\": \"three-stones\",\n  \"name\": \"Three stones\",\n  \"tags\": [\n   \"light-neutral\",\n   \"photographic-neutral\"\n  ],\n  \"bg\": \"#eeecea\",\n  \"surface\": \"#e4e1dd\",\n  \"ink\": \"#333231\",\n  \"muted\": \"#6b6763\",\n  \"accent\": \"#5c6b54\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#cdc3b6\",\n    \"ink\": \"#333231\"\n   }\n  ],\n  \"note\": \"Three close stone tones share the interface: the lightest for the page, the middle one for panels, the darkest for a single band, all with charcoal type. Saturated colour is left to the photographs and their backdrops; the grey-green fills the button only.\",\n  \"seenIn\": [\n   \"aww-noho\",\n   \"aww-vero-new-york\"\n  ]\n },\n {\n  \"id\": \"putty-black-teal\",\n  \"name\": \"Putty and black\",\n  \"tags\": [\n   \"light-neutral\",\n   \"photographic-neutral\"\n  ],\n  \"bg\": \"#dedad3\",\n  \"surface\": \"#d3cec6\",\n  \"ink\": \"#0a0a0a\",\n  \"muted\": \"#5c5852\",\n  \"accent\": \"#256f82\",\n  \"accentInk\": \"#ffffff\",\n  \"note\": \"Warm putty covers the page and pure black handles all type and the main shapes. The only tint in the interface is teal, used for the one button or a single marker placed near the photographs.\",\n  \"seenIn\": [\n   \"aww-colonia-zacamil\",\n   \"opl-archiv\"\n  ]\n },\n {\n  \"id\": \"moss-sand\",\n  \"name\": \"Sand and moss\",\n  \"tags\": [\n   \"light-neutral\",\n   \"earth\"\n  ],\n  \"bg\": \"#ddd6c6\",\n  \"surface\": \"#d2cab8\",\n  \"ink\": \"#2a2a26\",\n  \"muted\": \"#59574e\",\n  \"accent\": \"#4f6238\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#3f5a2a\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"Sand grey holds the page with charcoal type, and one deep leaf-green band may close it. Moss green is reserved for buttons; brighter greens and blues arrive only through photographs.\",\n  \"seenIn\": [\n   \"opl-vestris\",\n   \"aww-izanami\"\n  ]\n },\n {\n  \"id\": \"green-mat-chocolate\",\n  \"name\": \"Bone, green, chocolate\",\n  \"tags\": [\n   \"light-neutral\",\n   \"earth\"\n  ],\n  \"bg\": \"#e5e1d8\",\n  \"surface\": \"#dad5ca\",\n  \"ink\": \"#2a1d17\",\n  \"muted\": \"#6b5b51\",\n  \"accent\": \"#456f3a\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#456f3a\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"Bone ground with chocolate-brown text takes most of the page. The green is spent on one large flat block, about a third of a screen, and on the button; all other colour comes from photographs.\",\n  \"seenIn\": [\n   \"opl-davesocozy\",\n   \"opl-mat\"\n  ]\n },\n {\n  \"id\": \"lunar-grey-bronze\",\n  \"name\": \"Lunar and bronze\",\n  \"tags\": [\n   \"dark-neutral\"\n  ],\n  \"bg\": \"#111111\",\n  \"surface\": \"#1c1c1c\",\n  \"ink\": \"#f2f2f2\",\n  \"muted\": \"#8f8f8f\",\n  \"accent\": \"#a08672\",\n  \"accentInk\": \"#111111\",\n  \"note\": \"Soft black holds the page with panels one step lighter, white text and grey secondary lines, so photographs supply all the colour. Muted bronze goes on small markers and the one button only.\",\n  \"seenIn\": [\n   \"aww-21-hrs-on-the-moon\",\n   \"opl-dialkit\",\n   \"opl-lorenzo-bocchi-photography\"\n  ]\n },\n {\n  \"id\": \"blue-black-cornflower\",\n  \"name\": \"Night and cornflower\",\n  \"tags\": [\n   \"dark-neutral\"\n  ],\n  \"bg\": \"#0a0d14\",\n  \"surface\": \"#131824\",\n  \"ink\": \"#e9edf3\",\n  \"muted\": \"#8891a1\",\n  \"accent\": \"#5a9bfc\",\n  \"accentInk\": \"#0a0d14\",\n  \"note\": \"Blue-black ground and slate panels with silver-white text fill the page; no section changes colour. Cornflower blue marks the buttons and at most one word in a heading.\",\n  \"seenIn\": [\n   \"opl-viewport-2\",\n   \"aww-moto-finance\",\n   \"opl-rafael-derolez-2026\"\n  ]\n },\n {\n  \"id\": \"green-black-bone\",\n  \"name\": \"Green-black and bone\",\n  \"tags\": [\n   \"dark-neutral\",\n   \"earth\"\n  ],\n  \"bg\": \"#161c1a\",\n  \"surface\": \"#1f2725\",\n  \"ink\": \"#e3e2da\",\n  \"muted\": \"#8e948d\",\n  \"accent\": \"#9fc7b8\",\n  \"accentInk\": \"#161c1a\",\n  \"note\": \"Bone type on green-black from top to bottom, with panels and drawn details barely lighter than the ground so photographs supply the colour. Pale jade is for the booking or contact button alone.\",\n  \"seenIn\": [\n   \"opl-kereliott\",\n   \"aww-lama-lama-2\"\n  ]\n },\n {\n  \"id\": \"black-crimson\",\n  \"name\": \"Black and crimson\",\n  \"tags\": [\n   \"dark-neutral\",\n   \"mono-accent\"\n  ],\n  \"bg\": \"#0a0a0a\",\n  \"surface\": \"#151515\",\n  \"ink\": \"#efefef\",\n  \"muted\": \"#8c8c8c\",\n  \"accent\": \"#b11226\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#efefef\",\n    \"ink\": \"#0a0a0a\"\n   }\n  ],\n  \"note\": \"Black with off-white text and mid-grey texture takes nearly the whole page, and the last sections may invert to off-white with black type. Deep crimson is scattered sparingly: a few characters in a heading, a slider fill, the one button.\",\n  \"seenIn\": [\n   \"opl-textmode-overlay\"\n  ]\n },\n {\n  \"id\": \"forest-pale-lime\",\n  \"name\": \"Forest and lime\",\n  \"tags\": [\n   \"dark-neutral\",\n   \"earth\"\n  ],\n  \"bg\": \"#0f1f10\",\n  \"surface\": \"#162a17\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#9aa39a\",\n  \"accent\": \"#c6f19d\",\n  \"accentInk\": \"#0f1f10\",\n  \"fields\": [\n   {\n    \"bg\": \"#000000\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#ffffff\",\n    \"ink\": \"#0f1f10\"\n   }\n  ],\n  \"note\": \"Forest green, black and white sections alternate, with forest green holding the most; photographs stay in moss greens and stone browns. Pale lime sits on small squares only, such as arrow buttons and the closing wordmark.\",\n  \"seenIn\": [\n   \"aww-alethia\"\n  ]\n },\n {\n  \"id\": \"charcoal-room-sage\",\n  \"name\": \"Charcoal and sage\",\n  \"tags\": [\n   \"dark-neutral\",\n   \"photographic-neutral\"\n  ],\n  \"bg\": \"#1c1c1c\",\n  \"surface\": \"#262626\",\n  \"ink\": \"#f1f1ef\",\n  \"muted\": \"#9a9b96\",\n  \"accent\": \"#8fa68e\",\n  \"accentInk\": \"#1c1c1c\",\n  \"fields\": [\n   {\n    \"bg\": \"#c8c5ba\",\n    \"ink\": \"#1c1c1c\"\n   }\n  ],\n  \"note\": \"Charcoal holds the page with off-white text, and one section may flip to a pale concrete tone with dark text. Colour comes from the photographs; grey sage is used for the single button and the active state of a control.\",\n  \"seenIn\": [\n   \"opl-transport\",\n   \"opl-amanda-guo-design\"\n  ]\n },\n {\n  \"id\": \"warm-black-gold\",\n  \"name\": \"Warm black, gold\",\n  \"tags\": [\n   \"dark-neutral\",\n   \"photographic-neutral\"\n  ],\n  \"bg\": \"#0c0a08\",\n  \"surface\": \"#181512\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#8f8a84\",\n  \"accent\": \"#c9a45a\",\n  \"accentInk\": \"#0c0a08\",\n  \"note\": \"Warm near-black fills the page and photographs sit bright against it, with pure white small type; panels warm to a brown-black. Gold is for one text link or small button per screen, never a field.\",\n  \"seenIn\": [\n   \"aww-cipher\",\n   \"opl-hebbia\"\n  ]\n },\n {\n  \"id\": \"graphite-safety-orange\",\n  \"name\": \"Graphite and orange\",\n  \"tags\": [\n   \"mono-accent\",\n   \"dark-neutral\"\n  ],\n  \"bg\": \"#18191b\",\n  \"surface\": \"#222427\",\n  \"ink\": \"#eff0f1\",\n  \"muted\": \"#9c9ea3\",\n  \"accent\": \"#ff4a1f\",\n  \"accentInk\": \"#18191b\",\n  \"fields\": [\n   {\n    \"bg\": \"#eff0f1\",\n    \"ink\": \"#18191b\"\n   }\n  ],\n  \"note\": \"Graphite and cool light-grey sections alternate, graphite taking about two thirds, and photographs are desaturated so nothing competes. Safety orange marks the buttons, one thick solid bar across the top of the page and the highlighted item in a list or chart.\",\n  \"seenIn\": [\n   \"aww-sstr-friction-reduction\",\n   \"aww-boc-studio\",\n   \"aww-dragonfly-redux\"\n  ]\n },\n {\n  \"id\": \"soot-pale-lime\",\n  \"name\": \"Soot and lime\",\n  \"tags\": [\n   \"mono-accent\",\n   \"dark-neutral\"\n  ],\n  \"bg\": \"#0f0f0f\",\n  \"surface\": \"#1a1a1a\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#8f8f8f\",\n  \"accent\": \"#dafa9c\",\n  \"accentInk\": \"#0f0f0f\",\n  \"fields\": [\n   {\n    \"bg\": \"#ffffff\",\n    \"ink\": \"#0f0f0f\"\n   },\n   {\n    \"bg\": \"#dafa9c\",\n    \"ink\": \"#0f0f0f\"\n   }\n  ],\n  \"note\": \"A soot-black opening and close bracket white middle sections, all in black, white and grey. Pale lime is the single action colour: every button, and at most one headline set in it on the dark ground.\",\n  \"seenIn\": [\n   \"opl-builders-table\",\n   \"aww-made-with-gsap-1\",\n   \"aww-hilden-kaira\"\n  ]\n },\n {\n  \"id\": \"plum-black-pink\",\n  \"name\": \"Plum-black and pink\",\n  \"tags\": [\n   \"mono-accent\",\n   \"dark-neutral\"\n  ],\n  \"bg\": \"#0d060b\",\n  \"surface\": \"#1b0e17\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#9a8f97\",\n  \"accent\": \"#ff488b\",\n  \"accentInk\": \"#0d060b\",\n  \"fields\": [\n   {\n    \"bg\": \"#470c35\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#ffffff\",\n    \"ink\": \"#101421\"\n   }\n  ],\n  \"note\": \"Near-black and plum at the top and bottom bracket a white middle with navy-black text. Hot pink is reserved for primary buttons, bars in charts and map markers; it never fills a section.\",\n  \"seenIn\": [\n   \"aww-cerebrium\"\n  ]\n },\n {\n  \"id\": \"white-signal-red\",\n  \"name\": \"Signal red, white\",\n  \"tags\": [\n   \"mono-accent\"\n  ],\n  \"bg\": \"#ffffff\",\n  \"surface\": \"#f2f2f2\",\n  \"ink\": \"#0a0a0a\",\n  \"muted\": \"#6b6b6b\",\n  \"accent\": \"#d92b21\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#000000\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"White ground, black text and paper grey for filled panels, with one full black band allowed. Signal red is the only colour in the interface: one word in a headline, a few solid blocks, or the button.\",\n  \"seenIn\": [\n   \"opl-rsquad\",\n   \"aww-serotoninn\",\n   \"opl-estacion-venenta\"\n  ]\n },\n {\n  \"id\": \"white-mint-tiles\",\n  \"name\": \"Greys and mint\",\n  \"tags\": [\n   \"mono-accent\"\n  ],\n  \"bg\": \"#ffffff\",\n  \"surface\": \"#f3f3f3\",\n  \"ink\": \"#232323\",\n  \"muted\": \"#6e6e6e\",\n  \"accent\": \"#a1ffcb\",\n  \"accentInk\": \"#232323\",\n  \"fields\": [\n   {\n    \"bg\": \"#a1ffcb\",\n    \"ink\": \"#232323\"\n   },\n   {\n    \"bg\": \"#232323\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"White, near-black and two greys fill a board of flat tiles. Mint floods a few whole tiles (one statement, one figure, the closing call to action) and appears nowhere else.\",\n  \"seenIn\": [\n   \"aww-aspen-search\"\n  ]\n },\n {\n  \"id\": \"cool-grey-cobalt\",\n  \"name\": \"Cool grey, cobalt\",\n  \"tags\": [\n   \"mono-accent\"\n  ],\n  \"bg\": \"#eef0f3\",\n  \"surface\": \"#e2e5ea\",\n  \"ink\": \"#0b0c0e\",\n  \"muted\": \"#5d6470\",\n  \"accent\": \"#1f2de6\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#1f2de6\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"Cool pale grey holds the page with near-black type and nothing else tinted. Cobalt starts as the button and one highlighted sentence, takes one whole section as a flat field with white text, then returns as a single button block.\",\n  \"seenIn\": [\n   \"opl-vessa\",\n   \"opl-specia1ne\",\n   \"opl-brikkenco\"\n  ]\n },\n {\n  \"id\": \"offwhite-bottle-yellow\",\n  \"name\": \"Bottle ink, yellow\",\n  \"tags\": [\n   \"mono-accent\"\n  ],\n  \"bg\": \"#f7f7f7\",\n  \"surface\": \"#ebebeb\",\n  \"ink\": \"#0d2a1c\",\n  \"muted\": \"#5f6b64\",\n  \"accent\": \"#f6e016\",\n  \"accentInk\": \"#0d2a1c\",\n  \"fields\": [\n   {\n    \"bg\": \"#f6e016\",\n    \"ink\": \"#0d2a1c\"\n   }\n  ],\n  \"note\": \"Off-white ground with all type in a near-black bottle green instead of black. Yellow is the only saturated note: the button or one small object on most screens, and one later section that turns fully yellow.\",\n  \"seenIn\": [\n   \"aww-leo-parpeix-portfolio-2026\",\n   \"opl-wild-as\"\n  ]\n },\n {\n  \"id\": \"teal-on-paper\",\n  \"name\": \"Teal on paper\",\n  \"tags\": [\n   \"two-tone\"\n  ],\n  \"bg\": \"#f7f9f8\",\n  \"surface\": \"#ebf0ee\",\n  \"ink\": \"#06525c\",\n  \"muted\": \"#2f737d\",\n  \"accent\": \"#06525c\",\n  \"accentInk\": \"#f7f9f8\",\n  \"fields\": [\n   {\n    \"bg\": \"#06525c\",\n    \"ink\": \"#f7f9f8\"\n   }\n  ],\n  \"note\": \"Cool white paper and a single teal used for every word, shape and button, with no black anywhere. The accent is that same teal filled solid, for the button and for one inverted band with paper-coloured type.\",\n  \"seenIn\": [\n   \"opl-le-petit-bleu\"\n  ]\n },\n {\n  \"id\": \"navy-pink\",\n  \"name\": \"Navy and pink\",\n  \"tags\": [\n   \"two-tone\",\n   \"single-field\"\n  ],\n  \"bg\": \"#1a2039\",\n  \"surface\": \"#212846\",\n  \"ink\": \"#f9a3c0\",\n  \"muted\": \"#b9879c\",\n  \"accent\": \"#f9a3c0\",\n  \"accentInk\": \"#1a2039\",\n  \"note\": \"One navy field runs the entire page. Pink does everything else, from the name and headings to body text, and fills one solid button.\",\n  \"seenIn\": [\n   \"aww-trevor-noah\"\n  ]\n },\n {\n  \"id\": \"blush-aubergine\",\n  \"name\": \"Blush and aubergine\",\n  \"tags\": [\n   \"two-tone\"\n  ],\n  \"bg\": \"#edccbe\",\n  \"surface\": \"#e8c2b2\",\n  \"ink\": \"#351a2b\",\n  \"muted\": \"#6c4857\",\n  \"accent\": \"#351a2b\",\n  \"accentInk\": \"#edccbe\",\n  \"fields\": [\n   {\n    \"bg\": \"#351a2b\",\n    \"ink\": \"#edccbe\"\n   }\n  ],\n  \"note\": \"Blush pink and dark aubergine alternate as full fields and serve as each other's text colour, in roughly equal shares. There is no third colour: the button is a solid block of whichever of the two is not the ground.\",\n  \"seenIn\": [\n   \"aww-house-of-honey-1\",\n   \"opl-sarah-matt-wedding\"\n  ]\n },\n {\n  \"id\": \"cobalt-on-sand\",\n  \"name\": \"Cobalt on sand\",\n  \"tags\": [\n   \"two-tone\"\n  ],\n  \"bg\": \"#e6dbc7\",\n  \"surface\": \"#ddd0b9\",\n  \"ink\": \"#062b8a\",\n  \"muted\": \"#3a5aa8\",\n  \"accent\": \"#062b8a\",\n  \"accentInk\": \"#e6dbc7\",\n  \"note\": \"Sand paper and one cobalt do everything: text, drawings and solid shapes are all the same blue. The button is a cobalt block with sand-coloured type, and no black or second hue is used.\",\n  \"seenIn\": [\n   \"aww-illoca\"\n  ]\n },\n {\n  \"id\": \"oxblood-grey\",\n  \"name\": \"Oxblood and grey\",\n  \"tags\": [\n   \"two-tone\"\n  ],\n  \"bg\": \"#e2e2e2\",\n  \"surface\": \"#d6d6d6\",\n  \"ink\": \"#7d0c14\",\n  \"muted\": \"#7a4a4e\",\n  \"accent\": \"#7d0c14\",\n  \"accentInk\": \"#e2e2e2\",\n  \"fields\": [\n   {\n    \"bg\": \"#7d0c14\",\n    \"ink\": \"#e2e2e2\"\n   }\n  ],\n  \"note\": \"Deep red text on grey paper holds most of the page, then pale grey text on a solid red field takes one long section and the footer. Photographs are desaturated so nothing breaks the pair, and the button is a solid red block.\",\n  \"seenIn\": [\n   \"opl-belgrade-architecture\"\n  ]\n },\n {\n  \"id\": \"olive-on-bone\",\n  \"name\": \"Olive on bone\",\n  \"tags\": [\n   \"two-tone\",\n   \"earth\"\n  ],\n  \"bg\": \"#ecebe7\",\n  \"surface\": \"#e1dfd9\",\n  \"ink\": \"#38450f\",\n  \"muted\": \"#5d683a\",\n  \"accent\": \"#38450f\",\n  \"accentInk\": \"#ecebe7\",\n  \"fields\": [\n   {\n    \"bg\": \"#38450f\",\n    \"ink\": \"#ecebe7\"\n   }\n  ],\n  \"note\": \"A bone page with every word, large or small, in one olive green; the footer inverts to a solid olive field with bone text. Photography supplies all other colour, and the button is the same olive, filled.\",\n  \"seenIn\": [\n   \"aww-tengile-malamala-collection\"\n  ]\n },\n {\n  \"id\": \"burgundy-bubblegum\",\n  \"name\": \"Burgundy and bubblegum\",\n  \"tags\": [\n   \"two-tone\"\n  ],\n  \"bg\": \"#3d0012\",\n  \"surface\": \"#4d0519\",\n  \"ink\": \"#ff99d3\",\n  \"muted\": \"#c77aa0\",\n  \"accent\": \"#ff99d3\",\n  \"accentInk\": \"#3d0012\",\n  \"note\": \"Deep burgundy is the ground for the whole page and bubblegum pink sets every word on it. The button and the active state of a control are solid pink with burgundy type; product photographs supply any other colour.\",\n  \"seenIn\": [\n   \"opl-madie\"\n  ]\n },\n {\n  \"id\": \"bottle-green-gold\",\n  \"name\": \"Bottle green, gold\",\n  \"tags\": [\n   \"two-tone\",\n   \"earth\"\n  ],\n  \"bg\": \"#133621\",\n  \"surface\": \"#1a4429\",\n  \"ink\": \"#f4d96c\",\n  \"muted\": \"#b3a55e\",\n  \"accent\": \"#f4d96c\",\n  \"accentInk\": \"#133621\",\n  \"note\": \"Bottle green covers the page and warm gold sets all the type, with panels one step lighter than the ground. The button is solid gold with green text, and photographs are kept dark and warm so the pair is not disturbed.\",\n  \"seenIn\": [\n   \"aww-lacoste-ace-breaker\"\n  ]\n },\n {\n  \"id\": \"cobalt-field\",\n  \"name\": \"Cobalt field\",\n  \"tags\": [\n   \"single-field\"\n  ],\n  \"bg\": \"#0034eb\",\n  \"surface\": \"#002fd6\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#c5d0ff\",\n  \"accent\": \"#e9e34a\",\n  \"accentInk\": \"#111111\",\n  \"note\": \"One electric cobalt fills everything, with white and pale-blue type; photographs are tinted into blue monotone or kept as small thumbnails. A single yellow dot or button is the only other colour on the page.\",\n  \"seenIn\": [\n   \"opl-george-wood\",\n   \"aww-studio-k95-3\"\n  ]\n },\n {\n  \"id\": \"mustard-field\",\n  \"name\": \"Mustard and black\",\n  \"tags\": [\n   \"single-field\"\n  ],\n  \"bg\": \"#e1ac10\",\n  \"surface\": \"#cd9d0f\",\n  \"ink\": \"#0b0b0b\",\n  \"muted\": \"#4d3d0a\",\n  \"accent\": \"#24338f\",\n  \"accentInk\": \"#ffffff\",\n  \"note\": \"One warm mustard field for the whole page with black ink only. Royal blue is the single interruption, kept to a sliver along one edge or one small button.\",\n  \"seenIn\": [\n   \"opl-beige-force\"\n  ]\n },\n {\n  \"id\": \"carmine-field\",\n  \"name\": \"Carmine field\",\n  \"tags\": [\n   \"single-field\"\n  ],\n  \"bg\": \"#9c1220\",\n  \"surface\": \"#8a101c\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#f0b9bd\",\n  \"accent\": \"#ffd9dc\",\n  \"accentInk\": \"#9c1220\",\n  \"fields\": [\n   {\n    \"bg\": \"#2a2a2a\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"A deep red field bookends or fills the page, with white type and pale pink secondary lines; work shown in between sits on flat charcoal so it keeps its own colours. The button is a pale pink block with red type.\",\n  \"seenIn\": [\n   \"opl-marina-rachello\",\n   \"opl-belgrade-architecture\"\n  ]\n },\n {\n  \"id\": \"pink-field-lime\",\n  \"name\": \"Bubblegum and lime\",\n  \"tags\": [\n   \"single-field\"\n  ],\n  \"bg\": \"#ff87ab\",\n  \"surface\": \"#ff739d\",\n  \"ink\": \"#0a0a0a\",\n  \"muted\": \"#6b1f3a\",\n  \"accent\": \"#def915\",\n  \"accentInk\": \"#0a0a0a\",\n  \"fields\": [\n   {\n    \"bg\": \"#0a0a0a\",\n    \"ink\": \"#ff87ab\"\n   }\n  ],\n  \"note\": \"A flat bubblegum pink field with black type from top to bottom. Fluorescent lime is the action colour only: the menu button, one highlighter swipe behind a word and the main button.\",\n  \"seenIn\": [\n   \"opl-nodeck\",\n   \"aww-decathlon-yestalgia\"\n  ]\n },\n {\n  \"id\": \"sky-field-navy\",\n  \"name\": \"Sky and navy\",\n  \"tags\": [\n   \"single-field\"\n  ],\n  \"bg\": \"#6bb4ee\",\n  \"surface\": \"#7dbdf0\",\n  \"ink\": \"#0e1822\",\n  \"muted\": \"#1b3d5c\",\n  \"accent\": \"#ff5a1f\",\n  \"accentInk\": \"#0e1822\",\n  \"fields\": [\n   {\n    \"bg\": \"#ffffff\",\n    \"ink\": \"#0e1822\"\n   },\n   {\n    \"bg\": \"#0e1822\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"Sky blue sits behind everything, white cards lie on top of it, and navy handles all text and the footer. Orange is for buttons and one highlighted word, so orange against blue is the single clash on the page.\",\n  \"seenIn\": [\n   \"opl-ohhmydesign\",\n   \"opl-anidachi\"\n  ]\n },\n {\n  \"id\": \"orange-field-black\",\n  \"name\": \"Orange and black\",\n  \"tags\": [\n   \"single-field\",\n   \"two-tone\"\n  ],\n  \"bg\": \"#ff7a1f\",\n  \"surface\": \"#ff8633\",\n  \"ink\": \"#050f16\",\n  \"muted\": \"#5a2306\",\n  \"accent\": \"#050f16\",\n  \"accentInk\": \"#ff7a1f\",\n  \"fields\": [\n   {\n    \"bg\": \"#ffffff\",\n    \"ink\": \"#050f16\"\n   }\n  ],\n  \"note\": \"Hot orange is the page: one flat field with blue-black type, flipping at a hard horizontal seam to a white section when the content needs a rest. The button is a solid block of the same blue-black with orange text, and every other colour comes from the objects shown.\",\n  \"seenIn\": [\n   \"opl-postaway\",\n   \"opl-the-new-industrials\"\n  ]\n },\n {\n  \"id\": \"tobacco-olive\",\n  \"name\": \"Tobacco and olive\",\n  \"tags\": [\n   \"single-field\",\n   \"earth\"\n  ],\n  \"bg\": \"#472913\",\n  \"surface\": \"#55321a\",\n  \"ink\": \"#e4e0cf\",\n  \"muted\": \"#b39f84\",\n  \"accent\": \"#525e1b\",\n  \"accentInk\": \"#e4e0cf\",\n  \"fields\": [\n   {\n    \"bg\": \"#c79a3e\",\n    \"ink\": \"#2b170a\"\n   },\n   {\n    \"bg\": \"#525e1b\",\n    \"ink\": \"#e4e0cf\"\n   }\n  ],\n  \"note\": \"Tobacco brown fills the page with bone type, and photographs stay in browns and ochre. One olive block holds the main text or the button, and a single ochre band may break the brown once.\",\n  \"seenIn\": [\n   \"aww-the-tuscan-journey-begins\"\n  ]\n },\n {\n  \"id\": \"poster-chapters\",\n  \"name\": \"Poster chapters\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#e6e0d2\",\n  \"surface\": \"#dcd5c5\",\n  \"ink\": \"#1a1a1a\",\n  \"muted\": \"#5f5b52\",\n  \"accent\": \"#18bc42\",\n  \"accentInk\": \"#1a1a1a\",\n  \"fields\": [\n   {\n    \"bg\": \"#ed4b44\",\n    \"ink\": \"#0f0f0f\"\n   },\n   {\n    \"bg\": \"#1a1a1a\",\n    \"ink\": \"#e6e0d2\"\n   },\n   {\n    \"bg\": \"#18bc42\",\n    \"ink\": \"#1a1a1a\"\n   },\n   {\n    \"bg\": \"#f2c21a\",\n    \"ink\": \"#1a1a1a\"\n   },\n   {\n    \"bg\": \"#e6e0d2\",\n    \"ink\": \"#1a1a1a\"\n   }\n  ],\n  \"note\": \"Each chapter takes one flat field in turn (coral red, near-black, bone, green, yellow) with black or bone type and no tints between them. Green doubles as the accent for the one button when the ground is bone or black.\",\n  \"seenIn\": [\n   \"aww-pp-neue-montreal\"\n  ]\n },\n {\n  \"id\": \"blue-red-black\",\n  \"name\": \"Blue, red, black\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#ffffff\",\n  \"surface\": \"#f3f3f3\",\n  \"ink\": \"#0a0a0a\",\n  \"muted\": \"#6b6b6b\",\n  \"accent\": \"#2436ff\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#2436ff\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#ff3b1f\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#0a0a0a\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#050a5c\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"Three flat poster colours each own whole sections: electric blue, red-orange and black, with white for the areas that show the product. No tints sit between them, and blue is the button colour on white.\",\n  \"seenIn\": [\n   \"opl-juggle\"\n  ]\n },\n {\n  \"id\": \"charcoal-primaries\",\n  \"name\": \"Charcoal and primaries\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#191919\",\n  \"surface\": \"#242424\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#9a9a9a\",\n  \"accent\": \"#0c7866\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#d71e1e\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#1e4bd7\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#0c7866\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#ffe927\",\n    \"ink\": \"#111111\"\n   }\n  ],\n  \"note\": \"A charcoal ground holds flat poster primaries assigned to whole panels: red, blue, teal green and yellow, each placed against a different one. Type is white, or black on yellow; teal green is the button colour on charcoal.\",\n  \"seenIn\": [\n   \"aww-mosbys-files\"\n  ]\n },\n {\n  \"id\": \"ultramarine-yellow\",\n  \"name\": \"Ultramarine and yellow\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#1423b8\",\n  \"surface\": \"#1220a6\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#b4bcf0\",\n  \"accent\": \"#1fc27a\",\n  \"accentInk\": \"#0a0a0a\",\n  \"fields\": [\n   {\n    \"bg\": \"#1423b8\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#000000\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#f7dd47\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#e9479f\",\n    \"ink\": \"#000000\"\n   }\n  ],\n  \"note\": \"Each section is one flat field in sequence: ultramarine, black, yellow, then ultramarine again, with white type on blue and black, and black type on yellow. Green is the only small accent and never grows larger than a button.\",\n  \"seenIn\": [\n   \"aww-warm-fuzzy\",\n   \"aww-px-push\"\n  ]\n },\n {\n  \"id\": \"candy-chapters\",\n  \"name\": \"Candy chapters\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#ffd249\",\n  \"surface\": \"#f5c63c\",\n  \"ink\": \"#0a0a0a\",\n  \"muted\": \"#5e4a0a\",\n  \"accent\": \"#f53fd6\",\n  \"accentInk\": \"#0a0a0a\",\n  \"fields\": [\n   {\n    \"bg\": \"#ffd249\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#ffffff\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#ffc4ef\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#a4f6f8\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#f9a21f\",\n    \"ink\": \"#0a0a0a\"\n   }\n  ],\n  \"note\": \"Each section owns one flat candy colour: yellow first, then white, pink, cyan and orange, with all type in black. Magenta is kept for buttons alone.\",\n  \"seenIn\": [\n   \"aww-aardvark-book-club\"\n  ]\n },\n {\n  \"id\": \"orange-sky-lime\",\n  \"name\": \"Orange, sky, lime\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#ff8126\",\n  \"surface\": \"#ff8d3a\",\n  \"ink\": \"#111111\",\n  \"muted\": \"#5c2a05\",\n  \"accent\": \"#de194b\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#ff8126\",\n    \"ink\": \"#111111\"\n   },\n   {\n    \"bg\": \"#4db3ff\",\n    \"ink\": \"#111111\"\n   },\n   {\n    \"bg\": \"#c5f53d\",\n    \"ink\": \"#111111\"\n   },\n   {\n    \"bg\": \"#161615\",\n    \"ink\": \"#f2f2f2\"\n   }\n  ],\n  \"note\": \"The page ground changes as you read: orange first, then sky blue, then acid lime at the end, with one near-black band between; type stays black on all three colours. Crimson is one small button per field.\",\n  \"seenIn\": [\n   \"opl-the-new-industrials\",\n   \"opl-anidachi\"\n  ]\n },\n {\n  \"id\": \"post-red-mustard\",\n  \"name\": \"Post red, mustard\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#e2dccf\",\n  \"surface\": \"#d7d0c1\",\n  \"ink\": \"#2a1110\",\n  \"muted\": \"#6b524c\",\n  \"accent\": \"#4a6f84\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#dc1928\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#952625\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#e0a912\",\n    \"ink\": \"#2a1110\"\n   },\n   {\n    \"bg\": \"#4a6f84\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#e2dccf\",\n    \"ink\": \"#2a1110\"\n   }\n  ],\n  \"note\": \"Post red and bone alternate as full section fields, with red holding the opening and the close. Mustard, slate blue and maroon are kept for whole card frames, and slate blue also fills the one button.\",\n  \"seenIn\": [\n   \"opl-locker-land\"\n  ]\n },\n {\n  \"id\": \"mint-orange-grey\",\n  \"name\": \"Grey, mint, orange\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#ffffff\",\n  \"surface\": \"#f5f5f5\",\n  \"ink\": \"#000000\",\n  \"muted\": \"#666666\",\n  \"accent\": \"#a7ff9c\",\n  \"accentInk\": \"#000000\",\n  \"fields\": [\n   {\n    \"bg\": \"#c5c5c5\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#a7ff9c\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#ff6831\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#000000\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"Black on white to start, then whole sections flood with flat mid-grey, acid mint and orange in turn. Photographs inside a flooded section are shown in black-and-white, and mint is also the button colour on white and black.\",\n  \"seenIn\": [\n   \"aww-paul-kalkbrenner\"\n  ]\n },\n {\n  \"id\": \"report-blocks\",\n  \"name\": \"Report blocks\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#ffffff\",\n  \"surface\": \"#f6f6f6\",\n  \"ink\": \"#000000\",\n  \"muted\": \"#5f5f5f\",\n  \"accent\": \"#fe7141\",\n  \"accentInk\": \"#000000\",\n  \"fields\": [\n   {\n    \"bg\": \"#fe7141\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#d1ddd3\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#f0ff1c\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#000000\",\n    \"ink\": \"#f4f4f4\"\n   }\n  ],\n  \"note\": \"A white base with flat blocks of orange, sage, acid yellow and black assigned to whole modules: figure tiles, quote panels and chapter bands. Text is black on every colour and off-white on black, and orange is also the button colour.\",\n  \"seenIn\": [\n   \"aww-ai-in-design-report-2026\"\n  ]\n },\n {\n  \"id\": \"card-pastels\",\n  \"name\": \"Card pastels\",\n  \"tags\": [\n   \"pastel-fields\"\n  ],\n  \"bg\": \"#f7f7f5\",\n  \"surface\": \"#ebebe8\",\n  \"ink\": \"#000000\",\n  \"muted\": \"#666662\",\n  \"accent\": \"#d0106f\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#97aaf6\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#bbf697\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#fed878\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#6ef8fb\",\n    \"ink\": \"#000000\"\n   }\n  ],\n  \"note\": \"Neutral paper ground and black type, with each card or tile given its own flat pastel (periwinkle, lime, amber or cyan), never two alike side by side. Magenta is reserved for the logo, the email address and text links.\",\n  \"seenIn\": [\n   \"opl-medium-rare\"\n  ]\n },\n {\n  \"id\": \"mint-pink-accounts\",\n  \"name\": \"Mint and pink\",\n  \"tags\": [\n   \"pastel-fields\"\n  ],\n  \"bg\": \"#f8f8f8\",\n  \"surface\": \"#eeeeee\",\n  \"ink\": \"#0a0a0a\",\n  \"muted\": \"#6a6a6a\",\n  \"accent\": \"#1f6b3a\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#c3edce\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#f8c7c9\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#ffffff\",\n    \"ink\": \"#0a0a0a\"\n   }\n  ],\n  \"note\": \"Near-white base with black type; mint and pink are the only two colours and each stands for one side of the product. They first appear as small circles, then as full-screen section fields, and deep green is used only for the button.\",\n  \"seenIn\": [\n   \"opl-tara\"\n  ]\n },\n {\n  \"id\": \"swap-pastels\",\n  \"name\": \"Swapping pastels\",\n  \"tags\": [\n   \"pastel-fields\"\n  ],\n  \"bg\": \"#c3cbe5\",\n  \"surface\": \"#d0d6eb\",\n  \"ink\": \"#141414\",\n  \"muted\": \"#4a5068\",\n  \"accent\": \"#0f5257\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#c3cbe5\",\n    \"ink\": \"#141414\"\n   },\n   {\n    \"bg\": \"#efd3da\",\n    \"ink\": \"#141414\"\n   },\n   {\n    \"bg\": \"#e6dccd\",\n    \"ink\": \"#141414\"\n   },\n   {\n    \"bg\": \"#cfd3cb\",\n    \"ink\": \"#141414\"\n   },\n   {\n    \"bg\": \"#f9cdbd\",\n    \"ink\": \"#141414\"\n   }\n  ],\n  \"note\": \"One flat pastel is the whole background and it swaps per project or chapter: periwinkle, pink, sand, sage, peach. Type and one solid box stay near-black on all five, and dark teal is only for the button.\",\n  \"seenIn\": [\n   \"opl-belen-jones\"\n  ]\n },\n {\n  \"id\": \"blush-sage-slate\",\n  \"name\": \"Blush, sage, slate\",\n  \"tags\": [\n   \"pastel-fields\",\n   \"earth\"\n  ],\n  \"bg\": \"#a6b3bc\",\n  \"surface\": \"#b2bdc5\",\n  \"ink\": \"#1c1c1c\",\n  \"muted\": \"#38424a\",\n  \"accent\": \"#2c3620\",\n  \"accentInk\": \"#e3e2da\",\n  \"fields\": [\n   {\n    \"bg\": \"#a6b3bc\",\n    \"ink\": \"#1c1c1c\"\n   },\n   {\n    \"bg\": \"#b7c8be\",\n    \"ink\": \"#1c1c1c\"\n   },\n   {\n    \"bg\": \"#d6c4b8\",\n    \"ink\": \"#1c1c1c\"\n   },\n   {\n    \"bg\": \"#2c3620\",\n    \"ink\": \"#e3e2da\"\n   }\n  ],\n  \"note\": \"Slate blue-grey, sage and blush share the page as soft flat blocks, one per chapter or menu tile, with dark type; one deep olive block anchors the close with pale type. Olive is also the button colour, and photographs of sea and sky do the rest.\",\n  \"seenIn\": [\n   \"aww-seasats\",\n   \"opl-nia-creative\"\n  ]\n },\n {\n  \"id\": \"candy-on-black\",\n  \"name\": \"Candy on black\",\n  \"tags\": [\n   \"pastel-fields\"\n  ],\n  \"bg\": \"#000000\",\n  \"surface\": \"#0d0d0d\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#999999\",\n  \"accent\": \"#93f1f7\",\n  \"accentInk\": \"#000000\",\n  \"fields\": [\n   {\n    \"bg\": \"#9ae187\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#93f1f7\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#f3ea7a\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#fbb65c\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#b9c8ff\",\n    \"ink\": \"#000000\"\n   }\n  ],\n  \"note\": \"Black ground and dark photographs take nearly all of the surface. The only flat colour is a solid block behind each title, which takes a new candy pastel per project (mint, cyan, lemon, orange, cornflower); cyan is the default for the button.\",\n  \"seenIn\": [\n   \"aww-glitch-grit\"\n  ]\n },\n {\n  \"id\": \"sky-sand\",\n  \"name\": \"Sky and sand\",\n  \"tags\": [\n   \"pastel-fields\"\n  ],\n  \"bg\": \"#cbe4f2\",\n  \"surface\": \"#bcdcee\",\n  \"ink\": \"#0a0a0a\",\n  \"muted\": \"#44606e\",\n  \"accent\": \"#b0298f\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#cbe4f2\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#f1e3b5\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#ffc013\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#0a0a0a\",\n    \"ink\": \"#f2f2f2\"\n   }\n  ],\n  \"note\": \"Sky blue and sand yellow are the constant ground, each holding whole sections, with black text throughout. Saturated colour arrives only as small solid objects, and magenta is kept for the contact card and its button.\",\n  \"seenIn\": [\n   \"opl-applied-imagination\"\n  ]\n },\n {\n  \"id\": \"studio-grey\",\n  \"name\": \"Studio grey\",\n  \"tags\": [\n   \"photographic-neutral\"\n  ],\n  \"bg\": \"#a8a8aa\",\n  \"surface\": \"#b4b4b6\",\n  \"ink\": \"#0e0e0e\",\n  \"muted\": \"#3a3a3c\",\n  \"accent\": \"#1f5c49\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#1b1b1c\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"One mid grey serves as both page and studio backdrop, so the photographed object seems to stand on the page itself; type is black and one black band comes late. Colour comes only from the product, and racing green is for the single button.\",\n  \"seenIn\": [\n   \"aww-longbow\",\n   \"aww-l-i-s-a\"\n  ]\n },\n {\n  \"id\": \"walnut-tan\",\n  \"name\": \"Walnut and tan\",\n  \"tags\": [\n   \"photographic-neutral\",\n   \"earth\"\n  ],\n  \"bg\": \"#2b2216\",\n  \"surface\": \"#382d1e\",\n  \"ink\": \"#e4e2da\",\n  \"muted\": \"#a39a8b\",\n  \"accent\": \"#bda38b\",\n  \"accentInk\": \"#2b2216\",\n  \"fields\": [\n   {\n    \"bg\": \"#bda38b\",\n    \"ink\": \"#1c150d\"\n   }\n  ],\n  \"note\": \"Dark walnut holds the opening and the close with bone type, and the middle of the page may turn to flat tan around honey-lit photographs. There is no bright accent: tan is the fill for the one button on walnut.\",\n  \"seenIn\": [\n   \"opl-the-deep-end\"\n  ]\n }\n]","isInternal":false,"tokens":12140,"sizeBytes":34753},{"name":"photos.json","path":"skills/taste-skill/library/photos.json","rawUrl":"https://raw.githubusercontent.com/Leonxlnx/taste-skill/HEAD/skills/taste-skill/library/photos.json","title":"Library Skill","category":"anthropic-skill","format":"json","content":"{\n \"source\": \"Lorem Picsum (https://picsum.photos): photographs from Unsplash, used under the Unsplash licence\",\n \"url\": \"https://picsum.photos/id/{id}/{width}/{height}\",\n \"sets\": {\n  \"fog-and-quiet\": {\n   \"title\": \"Fog and quiet\",\n   \"note\": \"misty, muted, minimal landscapes and empty horizons; calm areas for text\",\n   \"sectors\": [\n    \"hospitality\",\n    \"health\",\n    \"fashion\",\n    \"agency\",\n    \"studio-portfolio\",\n    \"personal-portfolio\",\n    \"saas\",\n    \"ai-product\",\n    \"finance\",\n    \"architecture\",\n    \"real-estate\",\n    \"other\",\n    \"nonprofit\",\n    \"culture\"\n   ],\n   \"keywords\": [\n    \"fog\",\n    \"mist\",\n    \"quiet\",\n    \"calm\",\n    \"minimal\",\n    \"silence\",\n    \"retreat\",\n    \"wellness\",\n    \"spa\",\n    \"meditation\",\n    \"slow\"\n   ],\n   \"primary\": [\n    \"health\"\n   ],\n   \"photos\": [\n    {\n     \"id\": 70,\n     \"alt\": \"Road lined with tall trees fading into thick fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"centre\",\n     \"quality\": 5,\n     \"ratio\": 1.51,\n     \"by\": \"Dorothy Lin\",\n     \"page\": \"https://unsplash.com/photos/OokBLPrkCNk\"\n    },\n    {\n     \"id\": 172,\n     \"alt\": \"Stone jetty stretching into still water and dense grey fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"warm grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.51,\n     \"by\": \"Aleksi Tappura\",\n     \"page\": \"https://unsplash.com/photos/TQeX8khR54I\"\n    },\n    {\n     \"id\": 194,\n     \"alt\": \"Wooden deck and a single rock disappearing into thick fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"cool grey\",\n      \"weathered brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.51,\n     \"by\": \"Aleksi Tappura\",\n     \"page\": \"https://unsplash.com/photos/hVOv8me9ue8\"\n    },\n    {\n     \"id\": 228,\n     \"alt\": \"Single round hay bale in a field under dense fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey green\",\n      \"golden tan\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.33,\n     \"by\": \"Michal Kubicek\",\n     \"page\": \"https://unsplash.com/photos/0AbVUUorULU\"\n    },\n    {\n     \"id\": 255,\n     \"alt\": \"Gravel path leading to a cluster of bare trees on a hill\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"olive green\",\n      \"pale grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Jon Ottosson\",\n     \"page\": \"https://unsplash.com/photos/Xg1e5bR_bL4\"\n    },\n    {\n     \"id\": 266,\n     \"alt\": \"Three ships on a distant horizon across a calm blue sea\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"pale blue\",\n      \"deep blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"all\",\n     \"quality\": 5,\n     \"ratio\": 1.78,\n     \"by\": \"John Maravelakis\",\n     \"page\": \"https://unsplash.com/photos/Vosp2wlY3Bs\"\n    },\n    {\n     \"id\": 269,\n     \"alt\": \"Gulls perched on a concrete wall beside a pale still sea\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"pale blue\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Jill Heyer\",\n     \"page\": \"https://unsplash.com/photos/bbV7QzDUJus\"\n    },\n    {\n     \"id\": 279,\n     \"alt\": \"Still misty water fading into a soft pink-grey sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"dusty pink\",\n      \"slate grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"all\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Taylor Leopold\",\n     \"page\": \"https://unsplash.com/photos/OHS0yA7OkrQ\"\n    },\n    {\n     \"id\": 302,\n     \"alt\": \"Lone marker post standing in still water wrapped in fog\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"all\",\n     \"quality\": 5,\n     \"ratio\": 1.6,\n     \"by\": \"Billy Lam\",\n     \"page\": \"https://unsplash.com/photos/O3rmGgNYLKo\"\n    },\n    {\n     \"id\": 353,\n     \"alt\": \"Low cloud drifting over dark green forested hills\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"deep green\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.78,\n     \"by\": \"Forrest Cavale\",\n     \"page\": \"https://unsplash.com/photos/qfmd9bu7IgA\"\n    },\n    {\n     \"id\": 465,\n     \"alt\": \"Dark rocky peak emerging from thick white cloud\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"charcoal\",\n      \"pale grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 5,\n     \"ratio\": 1.51,\n     \"by\": \"Paula Vermeulen\",\n     \"page\": \"https://unsplash.com/photos/_f2m3mEkaaU\"\n    },\n    {\n     \"id\": 510,\n     \"alt\": \"Small red-roofed church below a mountain under a blank white sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"olive brown\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.33,\n     \"by\": \"Jeff Sheldon\",\n     \"page\": \"https://unsplash.com/photos/4IPe3tnBKK0\"\n    },\n    {\n     \"id\": 544,\n     \"alt\": \"Layered hill ridges fading into warm beige mist\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"beige\",\n      \"warm brown\",\n      \"cream\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Francesco Gallarotti\",\n     \"page\": \"https://unsplash.com/photos/-HkuuUSY1pE\"\n    },\n    {\n     \"id\": 552,\n     \"alt\": \"Tiny sailboat on a calm sea with distant hills, black and white\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"white\",\n      \"black\"\n     ],\n     \"mono\": true,\n     \"calm\": \"all\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Hugo Kerr\",\n     \"page\": \"https://unsplash.com/photos/Ke96snCJ1m0\"\n    },\n    {\n     \"id\": 594,\n     \"alt\": \"Small boathouse at the end of a jetty on dark water at night\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"black\",\n      \"deep purple\",\n      \"warm white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Aurélien bellanger\",\n     \"page\": \"https://unsplash.com/photos/uoSEDUu8F-I\"\n    },\n    {\n     \"id\": 634,\n     \"alt\": \"Pine forest dissolving into fog beneath a pale pink sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"dark green\",\n      \"pale pink\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Jay Mantri\",\n     \"page\": \"https://unsplash.com/photos/TFyi0QOx08c\"\n    },\n    {\n     \"id\": 813,\n     \"alt\": \"Still blue lake with a faint distant shoreline in haze\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"slate blue\",\n      \"powder blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"all\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Roger Burkhard\",\n     \"page\": \"https://unsplash.com/photos/rlX9J28Pd9g\"\n    },\n    {\n     \"id\": 842,\n     \"alt\": \"Wooden steps with railings descending into pale pink fog\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"blush pink\",\n      \"pale grey\",\n      \"slate\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 0.75,\n     \"by\": \"Joe Beck\",\n     \"page\": \"https://unsplash.com/photos/NbUokuw0BQI\"\n    },\n    {\n     \"id\": 922,\n     \"alt\": \"Dark treeline dissolving upward into pale fog, black and white\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"charcoal\",\n      \"grey\",\n      \"white\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.8,\n     \"by\": \"Patrick Hendry\",\n     \"page\": \"https://unsplash.com/photos/37ZuGYD3JOk\"\n    },\n    {\n     \"id\": 926,\n     \"alt\": \"Lone figure standing on a hilltop in thick beige fog\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"warm beige\",\n      \"olive grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.78,\n     \"by\": \"Harman Abiwardani\",\n     \"page\": \"https://unsplash.com/photos/mU_aX6JBYmg\"\n    },\n    {\n     \"id\": 941,\n     \"alt\": \"Small island on a pale, glassy sea beneath soft clouds\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale blue\",\n      \"soft white\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Ivan Slade\",\n     \"page\": \"https://unsplash.com/photos/RdyMe8KQAV0\"\n    },\n    {\n     \"id\": 989,\n     \"alt\": \"Low cloud covering a forested lakeshore under a pale sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"dark teal\",\n      \"soft blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Paul Jarvis\",\n     \"page\": \"https://unsplash.com/photos/eBDdgbM5dSo\"\n    },\n    {\n     \"id\": 994,\n     \"alt\": \"Silky long-exposure sea beneath a blue and orange sunset sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"soft blue\",\n      \"peach\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"all\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Jonathan Bean\",\n     \"page\": \"https://unsplash.com/photos/ywnnwzcdR5o\"\n    },\n    {\n     \"id\": 11,\n     \"alt\": \"Misty river winding through a grassy valley between forested slopes\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"pale green\",\n      \"grey green\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Paul Jarvis\",\n     \"page\": \"https://unsplash.com/photos/Cm7oKel-X2Q\"\n    },\n    {\n     \"id\": 93,\n     \"alt\": \"Marshland with scattered pine trees under a soft pastel sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"moss green\",\n      \"pale blue\",\n      \"soft pink\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Caroline Sada\",\n     \"page\": \"https://unsplash.com/photos/r1XwWjI4PyE\"\n    },\n    {\n     \"id\": 130,\n     \"alt\": \"Single seagull gliding over a grey sea beneath pale clouds\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"white\"\n     ],\n     \"mono\": true,\n     \"calm\": \"all\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Ryan Jacques\",\n     \"page\": \"https://unsplash.com/photos/ywiAen4L4qA\"\n    },\n    {\n     \"id\": 131,\n     \"alt\": \"Tiny figure on a pier under a vast pale yellow sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale yellow\",\n      \"sand beige\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.48,\n     \"by\": \"Charlie Foster\",\n     \"page\": \"https://unsplash.com/photos/yPaskTQiNjA\"\n    },\n    {\n     \"id\": 135,\n     \"alt\": \"Dark choppy sea fading into dense blue-grey fog\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"indigo\",\n      \"slate blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.33,\n     \"by\": \"Yuriy Khimanin\",\n     \"page\": \"https://unsplash.com/photos/o4H20aIIAt8\"\n    },\n    {\n     \"id\": 213,\n     \"alt\": \"Soft orange sunset sky above a calm misty sea\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"peach orange\",\n      \"slate blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"all\",\n     \"quality\": 4,\n     \"ratio\": 1.51,\n     \"by\": \"Kelly Sikkema\",\n     \"page\": \"https://unsplash.com/photos/X7dy114KWs4\"\n    },\n    {\n     \"id\": 227,\n     \"alt\": \"Railway tracks curving into a misty forest of bare trees\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"dark teal\",\n      \"grey green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"centre\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Andrea Boldizsar\",\n     \"page\": \"https://unsplash.com/photos/1iP1dozVO8I\"\n    },\n    {\n     \"id\": 264,\n     \"alt\": \"Wooden post standing among stones beside still misty water\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"warm beige\",\n      \"grey\",\n      \"tan\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Jon Phillips\",\n     \"page\": \"https://unsplash.com/photos/XsPM2CBTTpI\"\n    },\n    {\n     \"id\": 282,\n     \"alt\": \"Wooden railing overlooking a pine forest covered by low fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"muted brown\",\n      \"dark green\",\n      \"warm grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Taylor Leopold\",\n     \"page\": \"https://unsplash.com/photos/9dw0xLlxw1s\"\n    },\n    {\n     \"id\": 291,\n     \"alt\": \"Two figures standing in a misty blue field at dusk\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"deep blue\",\n      \"muted rust\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Caleb George\",\n     \"page\": \"https://unsplash.com/photos/zdjOYZeJj3w\"\n    },\n    {\n     \"id\": 300,\n     \"alt\": \"Hay bales scattered across a pale field under white sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"light grey\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Pavel Voinov\",\n     \"page\": \"https://unsplash.com/photos/2f_CnEeZsVg\"\n    },\n    {\n     \"id\": 313,\n     \"alt\": \"Distant clump of trees in a foggy field at dusk\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"dusty mauve\",\n      \"slate blue\",\n      \"dark olive\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Sonja Langford\",\n     \"page\": \"https://unsplash.com/photos/4xYgBTYC2-Q\"\n    },\n    {\n     \"id\": 385,\n     \"alt\": \"Calm sea stretching to a thin glowing horizon at dusk\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"slate blue\",\n      \"teal\",\n      \"soft orange\"\n     ],\n     \"mono\": false,\n     \"calm\": \"all\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Griffin Keller\",\n     \"page\": \"https://unsplash.com/photos/7oS_26cb1Wo\"\n    },\n    {\n     \"id\": 406,\n     \"alt\": \"Low clouds drifting across steep forested mountain slopes\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"white\",\n      \"dark green\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.51,\n     \"by\": \"Roland Batke-Mutschler\",\n     \"page\": \"https://unsplash.com/photos/SmhN4FejPFs\"\n    },\n    {\n     \"id\": 443,\n     \"alt\": \"Mist and cloud hanging over dark pine-covered mountains\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"dark green\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Tim Mossholder\",\n     \"page\": \"https://unsplash.com/photos/p3kpqGBRPok\"\n    },\n    {\n     \"id\": 457,\n     \"alt\": \"Faint ships on a pale foggy sea with almost no horizon\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"pale grey\"\n     ],\n     \"mono\": true,\n     \"calm\": \"all\",\n     \"quality\": 4,\n     \"ratio\": 1.77,\n     \"by\": \"Volkan Olmez\",\n     \"page\": \"https://unsplash.com/photos/ccPpd02Spe0\"\n    },\n    {\n     \"id\": 467,\n     \"alt\": \"Dark sea fading into white fog in black and white\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"white\",\n      \"grey\",\n      \"charcoal\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Taylor Leopold\",\n     \"page\": \"https://unsplash.com/photos/COE-CIGj8VA\"\n    },\n    {\n     \"id\": 472,\n     \"alt\": \"Small wooded island wrapped in fog on a dark lake\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"dark green\",\n      \"grey\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Dustin Scarpitti\",\n     \"page\": \"https://unsplash.com/photos/gR_zHJqbtzo\"\n    },\n    {\n     \"id\": 481,\n     \"alt\": \"Still lake at dusk with mist and dark conifers along the shore\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"teal grey\",\n      \"slate\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Dustin Scarpitti\",\n     \"page\": \"https://unsplash.com/photos/RdF3apSExR0\"\n    },\n    {\n     \"id\": 722,\n     \"alt\": \"Tree silhouettes in thick golden fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"ochre\",\n      \"olive brown\",\n      \"pale gold\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 0.67,\n     \"by\": \"Sebastian Kostrubala\",\n     \"page\": \"https://unsplash.com/photos/4yDg-dDX9uM\"\n    },\n    {\n     \"id\": 727,\n     \"alt\": \"Sandy mound with dark shrubs beneath a blank foggy sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"ochre\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.33,\n     \"by\": \"Devan Freeman\",\n     \"page\": \"https://unsplash.com/photos/HrUbyeQvL_w\"\n    },\n    {\n     \"id\": 731,\n     \"alt\": \"Grassy rocky mountain ridge emerging from thick grey mist\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"mist grey\",\n      \"olive green\",\n      \"dark brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.33,\n     \"by\": \"Rob Bye\",\n     \"page\": \"https://unsplash.com/photos/61XW8CMNX6A\"\n    },\n    {\n     \"id\": 807,\n     \"alt\": \"Lone tree on a grassy slope disappearing into thick fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"moss green\",\n      \"mist grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.78,\n     \"by\": \"Tiago Aguiar\",\n     \"page\": \"https://unsplash.com/photos/FtVQIQ9rDFI\"\n    },\n    {\n     \"id\": 886,\n     \"alt\": \"Flat grassy field vanishing into pale yellow fog\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"straw yellow\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.33,\n     \"by\": \"Glen Carrie\",\n     \"page\": \"https://unsplash.com/photos/p62O--o1x-U\"\n    },\n    {\n     \"id\": 925,\n     \"alt\": \"Conifer trees fading into dense grey fog on a hillside\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"mist grey\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"right\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Patrick Fore\",\n     \"page\": \"https://unsplash.com/photos/vpAKO21abME\"\n    },\n    {\n     \"id\": 965,\n     \"alt\": \"Long bridge disappearing into thick grey fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"mist grey\",\n      \"slate\",\n      \"pale green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Liane Metzler\",\n     \"page\": \"https://unsplash.com/photos/c5uShPcKLAE\"\n    },\n    {\n     \"id\": 966,\n     \"alt\": \"Forested mountainside sloping diagonally beneath white fog\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"olive green\",\n      \"brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Alberto Restifo\",\n     \"page\": \"https://unsplash.com/photos/kKrfPaKgE1c\"\n    },\n    {\n     \"id\": 991,\n     \"alt\": \"Hazy sun above layered dark hills in sepia tones\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"sepia\",\n      \"dark brown\",\n      \"pale gold\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Fritz Bielmeier\",\n     \"page\": \"https://unsplash.com/photos/ooJi3CJQRa8\"\n    },\n    {\n     \"id\": 1028,\n     \"alt\": \"Bare dead trees standing in dry ground under sepia haze\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"sepia\",\n      \"tan\",\n      \"dark brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Dikaseva\",\n     \"page\": \"https://unsplash.com/photos/zvf7cZ0PC20\"\n    }\n   ]\n  },\n  \"coast\": {\n   \"title\": \"Coast\",\n   \"note\": \"sea, shoreline, cliffs, piers and beaches\",\n   \"sectors\": [\n    \"hospitality\",\n    \"health\",\n    \"real-estate\",\n    \"restaurant\",\n    \"event\",\n    \"fashion\",\n    \"other\"\n   ],\n   \"keywords\": [\n    \"coast\",\n    \"sea\",\n    \"ocean\",\n    \"beach\",\n    \"surf\",\n    \"island\",\n    \"harbour\",\n    \"harbor\",\n    \"seaside\",\n    \"sail\",\n    \"boat\",\n    \"fish\",\n    \"marine\",\n    \"cliff\",\n    \"guesthouse\",\n    \"shore\",\n    \"bay\",\n    \"atlantic\",\n    \"lookout\"\n   ],\n   \"primary\": [\n    \"hospitality\"\n   ],\n   \"photos\": [\n    {\n     \"id\": 77,\n     \"alt\": \"Wooden jetty leading to a small pavilion over calm sea\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"warm tan\",\n      \"pale teal\",\n      \"soft grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.48,\n     \"by\": \"May Pamintuan\",\n     \"page\": \"https://unsplash.com/photos/j9nfqTi5T5o\"\n    },\n    {\n     \"id\": 626,\n     \"alt\": \"Red and white lighthouse in turquoise sea below a chalk cliff\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"turquoise\",\n      \"white\",\n      \"grass green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Nick Diamantidis\",\n     \"page\": \"https://unsplash.com/photos/jkPKQWK1sKU\"\n    },\n    {\n     \"id\": 640,\n     \"alt\": \"Aerial view of turquoise surf breaking onto golden sand\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"sand\",\n      \"turquoise\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Sarah Bürvenich\",\n     \"page\": \"https://unsplash.com/photos/vigsqYux_-8\"\n    },\n    {\n     \"id\": 641,\n     \"alt\": \"Empty lifeguard chair on a beach at pastel dusk\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"peach\",\n      \"slate blue\",\n      \"dusty teal\"\n     ],\n     \"mono\": false,\n     \"calm\": \"right\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Fré Sonneveld\",\n     \"page\": \"https://unsplash.com/photos/2qLT_Rq-2tk\"\n    },\n    {\n     \"id\": 853,\n     \"alt\": \"Lone rock in a calm blue sea beneath a pastel sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"sea blue\",\n      \"peach\",\n      \"pale pink\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.51,\n     \"by\": \"Stephen Radford\",\n     \"page\": \"https://unsplash.com/photos/674bDNKmnIk\"\n    },\n    {\n     \"id\": 1049,\n     \"alt\": \"Rock island reflected on a wet beach under a pale sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"soft white\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.25,\n     \"by\": \"Rosan Harmens\",\n     \"page\": \"https://unsplash.com/photos/Sd8O2SgKDJA\"\n    },\n    {\n     \"id\": 1052,\n     \"alt\": \"Black sea stacks off a dark beach with white surf under a pale sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"black\",\n      \"white\",\n      \"pale grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Annie Spratt\",\n     \"page\": \"https://unsplash.com/photos/x8R2oSWZRSE\"\n    },\n    {\n     \"id\": 12,\n     \"alt\": \"Dark rocks on a sandy beach with calm sea and islands\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"sand beige\",\n      \"dark brown\",\n      \"pale grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Paul Jarvis\",\n     \"page\": \"https://unsplash.com/photos/I_9ILwtsl_k\"\n    },\n    {\n     \"id\": 14,\n     \"alt\": \"Rocky shoreline meeting a calm pale sea under hazy sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"pale blue\",\n      \"warm brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Paul Jarvis\",\n     \"page\": \"https://unsplash.com/photos/IQ1kOQTJrOQ\"\n    },\n    {\n     \"id\": 16,\n     \"alt\": \"Blue sea and distant islands seen over a rocky driftwood shore\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"sky blue\",\n      \"deep blue\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Paul Jarvis\",\n     \"page\": \"https://unsplash.com/photos/gkT4FfgHO5o\"\n    },\n    {\n     \"id\": 27,\n     \"alt\": \"Person standing on a rocky shore watching misty waves at sunset\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"warm orange\",\n      \"brown\",\n      \"pale gold\"\n     ],\n     \"mono\": false,\n     \"calm\": \"right\",\n     \"quality\": 4,\n     \"ratio\": 1.78,\n     \"by\": \"Yoni Kaplan-Nadel\",\n     \"page\": \"https://unsplash.com/photos/iJnZwLBOB1I\"\n    },\n    {\n     \"id\": 47,\n     \"alt\": \"Long wooden pier over misty surf in black and white\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"light grey\",\n      \"charcoal\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Christopher Sardegna\",\n     \"page\": \"https://unsplash.com/photos/uDUiRS8YroY\"\n    },\n    {\n     \"id\": 68,\n     \"alt\": \"Curving pier with a railing, lamp post and weather vane\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"light grey\",\n      \"charcoal\"\n     ],\n     \"mono\": true,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Cristian Moscoso\",\n     \"page\": \"https://unsplash.com/photos/2SfRAWkinpU\"\n    },\n    {\n     \"id\": 108,\n     \"alt\": \"Palm trees silhouetted against a bright washed-out sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"soft pink\",\n      \"dark brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Florian Klauer\",\n     \"page\": \"https://unsplash.com/photos/t1mqA3V3-7g\"\n    },\n    {\n     \"id\": 144,\n     \"alt\": \"Pavilion at the end of a pier over waves, monochrome\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"black\",\n      \"white\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.78,\n     \"by\": \"Mouly Kumar\",\n     \"page\": \"https://unsplash.com/photos/TuOiIpkIea8\"\n    },\n    {\n     \"id\": 154,\n     \"alt\": \"Hazy beach at dusk with distant walkers and soft surf\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"dusty pink\",\n      \"muted purple\",\n      \"pale blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Christopher Sardegna\",\n     \"page\": \"https://unsplash.com/photos/x_jTtMOOMd4\"\n    },\n    {\n     \"id\": 162,\n     \"alt\": \"Aerial view of a coastline with turquoise sea and patchwork fields\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"turquoise\",\n      \"sand brown\",\n      \"deep blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Dillon McIntosh\",\n     \"page\": \"https://unsplash.com/photos/SlGVAKyP20U\"\n    },\n    {\n     \"id\": 179,\n     \"alt\": \"Waves breaking around dark rocks on a misty shoreline\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"slate grey\",\n      \"white\",\n      \"warm brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Angelina Odemchuk\",\n     \"page\": \"https://unsplash.com/photos/lp0IFw6YqZg\"\n    },\n    {\n     \"id\": 215,\n     \"alt\": \"Wide empty sandy beach with palm trees and blue sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale sand\",\n      \"sky blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 4,\n     \"ratio\": 1.33,\n     \"by\": \"Paula Borowska\",\n     \"page\": \"https://unsplash.com/photos/04paG2PxKGs\"\n    },\n    {\n     \"id\": 218,\n     \"alt\": \"Calm turquoise bay between two limestone cliffs under storm clouds\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"turquoise\",\n      \"slate grey\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"centre\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Monika Majkowska\",\n     \"page\": \"https://unsplash.com/photos/Nq8LdWC7HnM\"\n    },\n    {\n     \"id\": 268,\n     \"alt\": \"White lifeguard chair standing in dune grass under overcast sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"straw yellow\",\n      \"green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.52,\n     \"by\": \"davide ragusa\",\n     \"page\": \"https://unsplash.com/photos/vc3ZOCf5BN8\"\n    },\n    {\n     \"id\": 317,\n     \"alt\": \"Long wooden pier with railings reaching toward a pastel horizon\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"weathered brown\",\n      \"pale peach\",\n      \"soft blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.78,\n     \"by\": \"Paula Borowska\",\n     \"page\": \"https://unsplash.com/photos/cKYgt4K0g5w\"\n    },\n    {\n     \"id\": 323,\n     \"alt\": \"Steep green headlands dropping into a deep blue bay\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"deep blue\",\n      \"olive green\",\n      \"tan\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Paweł Wojciechowski\",\n     \"page\": \"https://unsplash.com/photos/QYAojSRu82c\"\n    },\n    {\n     \"id\": 347,\n     \"alt\": \"Dune grass bending in wind beneath a wide white sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"straw gold\",\n      \"grey blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Alex Talmon\",\n     \"page\": \"https://unsplash.com/photos/umq-jgTjr28\"\n    },\n    {\n     \"id\": 356,\n     \"alt\": \"Lone surfer walking along a misty beach in black and white\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"charcoal\",\n      \"silver grey\",\n      \"white\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.33,\n     \"by\": \"Daniel Ruswick\",\n     \"page\": \"https://unsplash.com/photos/fqtOAqbbnJg\"\n    },\n    {\n     \"id\": 372,\n     \"alt\": \"Lifeguard tower on an empty sandy beach under a hazy sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale blue\",\n      \"sand\",\n      \"soft grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Gabriel Santiago\",\n     \"page\": \"https://unsplash.com/photos/KWkMiUIxcD0\"\n    },\n    {\n     \"id\": 374,\n     \"alt\": \"Coastline with green headlands, a curving beach and turquoise sea\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"turquoise\",\n      \"deep green\",\n      \"sky blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Ma. Alejandra\",\n     \"page\": \"https://unsplash.com/photos/TDahcrcPhhA\"\n    },\n    {\n     \"id\": 404,\n     \"alt\": \"Waves breaking in white foam around a rugged brown rock\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey blue\",\n      \"white\",\n      \"rust brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Cole Patrick\",\n     \"page\": \"https://unsplash.com/photos/H28ODcp4EUk\"\n    },\n    {\n     \"id\": 440,\n     \"alt\": \"Rugged coastal headlands in soft backlit haze at sunset\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"pale gold\",\n      \"warm brown\",\n      \"cream\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Artur Pokusin\",\n     \"page\": \"https://unsplash.com/photos/0nv-h04oPhM\"\n    },\n    {\n     \"id\": 483,\n     \"alt\": \"Dark sea cliffs and rocks with white surf breaking below\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"charcoal\",\n      \"teal\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.78,\n     \"by\": \"Paulo Simões Mendes\",\n     \"page\": \"https://unsplash.com/photos/hrcRtexM7M0\"\n    },\n    {\n     \"id\": 485,\n     \"alt\": \"White chalk cliffs above a curved beach in sea mist\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"turquoise\",\n      \"sand\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.51,\n     \"by\": \"David Marcu\",\n     \"page\": \"https://unsplash.com/photos/DNXWtB33WWE\"\n    },\n    {\n     \"id\": 574,\n     \"alt\": \"Grassy cliff and black sand beach with sea stacks offshore\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"green\",\n      \"charcoal\",\n      \"pale blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"right\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Julien Lavallée\",\n     \"page\": \"https://unsplash.com/photos/lVtlz3JRV6o\"\n    },\n    {\n     \"id\": 606,\n     \"alt\": \"Wooden boardwalk winding through grassy dunes toward the sea\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"sage green\",\n      \"sand\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Aleksandra Boguslawska\",\n     \"page\": \"https://unsplash.com/photos/MS7KD9Ti7FQ\"\n    },\n    {\n     \"id\": 614,\n     \"alt\": \"Aerial view of white surf washing over a dark rocky shore\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"charcoal\",\n      \"white\",\n      \"dark brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Josefa Holland-Merten\",\n     \"page\": \"https://unsplash.com/photos/GnP5Kfg5ebU\"\n    },\n    {\n     \"id\": 732,\n     \"alt\": \"Dark rocky shoreline beside a calm sea under a pale cloudy sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale blue\",\n      \"soft grey\",\n      \"charcoal\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Dominik Schröder\",\n     \"page\": \"https://unsplash.com/photos/ivieBAESVWM\"\n    },\n    {\n     \"id\": 851,\n     \"alt\": \"Aerial view of turquoise sea meeting a curved reddish coastline\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"turquoise\",\n      \"teal\",\n      \"rust brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.66,\n     \"by\": \"Tiago Aguiar\",\n     \"page\": \"https://unsplash.com/photos/uXzNVOZT5no\"\n    },\n    {\n     \"id\": 969,\n     \"alt\": \"Wet rocky shore with sea stacks under a bright sky, black and white\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"black\",\n      \"grey\",\n      \"silver\"\n     ],\n     \"mono\": true,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Lee Miller\",\n     \"page\": \"https://unsplash.com/photos/_rsGm7nob3w\"\n    },\n    {\n     \"id\": 997,\n     \"alt\": \"Aerial view of a forested headland beside deep blue sea\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"deep blue\",\n      \"forest green\",\n      \"yellow green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 0.68,\n     \"by\": \"Mickey O'neil\",\n     \"page\": \"https://unsplash.com/photos/GSzD6vGIWKM\"\n    },\n    {\n     \"id\": 1055,\n     \"alt\": \"Wide wet sand flat with a distant shoreline under a pale sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"warm brown\",\n      \"sand\",\n      \"off-white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Neil Thomas\",\n     \"page\": \"https://unsplash.com/photos/12rzbJhQ89E\"\n    }\n   ]\n  },\n  \"mountain\": {\n   \"title\": \"Mountain\",\n   \"note\": \"peaks, alpine valleys, snow and rock\",\n   \"sectors\": [\n    \"hospitality\",\n    \"health\",\n    \"event\",\n    \"physical-product\",\n    \"nonprofit\",\n    \"other\",\n    \"education\"\n   ],\n   \"keywords\": [\n    \"mountain\",\n    \"alpine\",\n    \"peak\",\n    \"summit\",\n    \"hike\",\n    \"hiking\",\n    \"climb\",\n    \"outdoor\",\n    \"lodge\",\n    \"chalet\",\n    \"trail\",\n    \"expedition\"\n   ],\n   \"photos\": [\n    {\n     \"id\": 235,\n     \"alt\": \"Snow-covered peak rising above dark forested slopes and a lake\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"slate blue\",\n      \"white\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Paul E. Harrer\",\n     \"page\": \"https://unsplash.com/photos/TI-B-TNYJMU\"\n    },\n    {\n     \"id\": 260,\n     \"alt\": \"Snowy mountain peak framed by dark pine trees in mist\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"pale grey\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"centre\",\n     \"quality\": 5,\n     \"ratio\": 0.67,\n     \"by\": \"Sylwia Bartyzel\",\n     \"page\": \"https://unsplash.com/photos/OdAqbedkfiA\"\n    },\n    {\n     \"id\": 830,\n     \"alt\": \"Layered blue mountain ridges receding into haze\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"cobalt blue\",\n      \"pale blue\",\n      \"navy\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Luca Zanon\",\n     \"page\": \"https://unsplash.com/photos/X0OoHrPvgXE\"\n    },\n    {\n     \"id\": 906,\n     \"alt\": \"Sunlit snowy pyramid peak against a clear blue sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"sky blue\",\n      \"white\",\n      \"dark slate\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.33,\n     \"by\": \"Andras Toth\",\n     \"page\": \"https://unsplash.com/photos/E9CrQou9K0Y\"\n    },\n    {\n     \"id\": 931,\n     \"alt\": \"Layered mountain slopes fading into blue haze\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"steel blue\",\n      \"pale blue\",\n      \"dark teal\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.51,\n     \"by\": \"Paul Earle\",\n     \"page\": \"https://unsplash.com/photos/xJ2tjuUHD9M\"\n    },\n    {\n     \"id\": 1018,\n     \"alt\": \"Green cliffs and a winding road under low mist\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"moss green\",\n      \"mist grey\",\n      \"dark brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.33,\n     \"by\": \"Andrew Ridley\",\n     \"page\": \"https://unsplash.com/photos/Kt5hRENuotI\"\n    },\n    {\n     \"id\": 29,\n     \"alt\": \"Rocky ridges and snow-covered peaks in a high mountain range\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"slate grey\",\n      \"white\",\n      \"blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Go Wild\",\n     \"page\": \"https://unsplash.com/photos/V0yAek6BgGk\"\n    },\n    {\n     \"id\": 66,\n     \"alt\": \"Lone mountain peak beyond open grassland under heavy grey cloud\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"olive green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.33,\n     \"by\": \"Nicholas Swanson\",\n     \"page\": \"https://unsplash.com/photos/agnhLQWqr1Q\"\n    },\n    {\n     \"id\": 121,\n     \"alt\": \"Hazy mountain gorge with steep slopes in black and white\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"black\",\n      \"white\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Radio Pink\",\n     \"page\": \"https://unsplash.com/photos/p-bkdO43shE\"\n    },\n    {\n     \"id\": 166,\n     \"alt\": \"Moody valley with a river, dark hills and a foreground boulder\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"charcoal\",\n      \"grey\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.78,\n     \"by\": \"Romain Briaux\",\n     \"page\": \"https://unsplash.com/photos/yD3PXDV7Sjc\"\n    },\n    {\n     \"id\": 296,\n     \"alt\": \"Snow-capped mountain range beneath a deep blue sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"deep blue\",\n      \"white\",\n      \"dark brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Greg Shield\",\n     \"page\": \"https://unsplash.com/photos/Du30R57aCyM\"\n    },\n    {\n     \"id\": 327,\n     \"alt\": \"Snow-covered mountain range under a clear teal sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"teal\",\n      \"white\",\n      \"rust brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Ryan Schroeder\",\n     \"page\": \"https://unsplash.com/photos/Gg7uKdHFb_c\"\n    },\n    {\n     \"id\": 368,\n     \"alt\": \"Sheer granite cliffs above a hazy valley in warm evening light\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"peach\",\n      \"warm grey\",\n      \"slate\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Tyssul Patel\",\n     \"page\": \"https://unsplash.com/photos/o-zOatT4kQw\"\n    },\n    {\n     \"id\": 377,\n     \"alt\": \"Snow-capped mountain range under a dark blue evening sky\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"navy\",\n      \"slate blue\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Martin Staněk\",\n     \"page\": \"https://unsplash.com/photos/8WClaa1CmZ0\"\n    },\n    {\n     \"id\": 393,\n     \"alt\": \"Green mountain streaked with snow rising above a dark gravel plain\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"moss green\",\n      \"charcoal\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Alex Talmon\",\n     \"page\": \"https://unsplash.com/photos/UFskvng2OMU\"\n    },\n    {\n     \"id\": 426,\n     \"alt\": \"Layered blue mountains and a hazy valley under streaked clouds\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"slate blue\",\n      \"teal\",\n      \"pale grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Ales Krivec\",\n     \"page\": \"https://unsplash.com/photos/01ZeHnK3F_4\"\n    },\n    {\n     \"id\": 450,\n     \"alt\": \"Turquoise lake in a forested valley between snow-dusted mountains\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"turquoise\",\n      \"slate grey\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.51,\n     \"by\": \"Tanvi Malik\",\n     \"page\": \"https://unsplash.com/photos/OeC1wIsKNpk\"\n    },\n    {\n     \"id\": 523,\n     \"alt\": \"Volcanic crater rising from a hazy plain beneath a teal sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"teal\",\n      \"tan\",\n      \"brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 2.21,\n     \"by\": \"Harman Abiwardani\",\n     \"page\": \"https://unsplash.com/photos/WLUHO9A_xik\"\n    },\n    {\n     \"id\": 538,\n     \"alt\": \"Bird soaring above snowy mountain ridges in black and white\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"white\",\n      \"black\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.51,\n     \"by\": \"Julia Revitt\",\n     \"page\": \"https://unsplash.com/photos/yypv2Tu-mxU\"\n    },\n    {\n     \"id\": 565,\n     \"alt\": \"Snowy peak veiled in cloud with birds crossing a white sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"pale grey\",\n      \"dark brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"René Reichelt\",\n     \"page\": \"https://unsplash.com/photos/HzaT5l4Fzqc\"\n    },\n    {\n     \"id\": 591,\n     \"alt\": \"Jagged rock pinnacle rising through swirling white cloud\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"grey\",\n      \"tan\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 0.75,\n     \"by\": \"Billy Onjea\",\n     \"page\": \"https://unsplash.com/photos/_qGq1Z2Bk6c\"\n    },\n    {\n     \"id\": 684,\n     \"alt\": \"Jagged snow-covered peaks under a dark blue sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"navy\",\n      \"white\",\n      \"slate blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.78,\n     \"by\": \"Lee Roylland\",\n     \"page\": \"https://unsplash.com/photos/dfZbts6B4yw\"\n    },\n    {\n     \"id\": 735,\n     \"alt\": \"Steep dark cliffs with fog drifting through the gap between them\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"charcoal\",\n      \"mist grey\",\n      \"deep green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"centre\",\n     \"quality\": 4,\n     \"ratio\": 0.62,\n     \"by\": \"wyman H\",\n     \"page\": \"https://unsplash.com/photos/ZQeRH1XD4Tc\"\n    },\n    {\n     \"id\": 809,\n     \"alt\": \"Rocky mountain peak breaking through thick white clouds\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"slate grey\",\n      \"blue grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Namphuong Van\",\n     \"page\": \"https://unsplash.com/photos/sP4UZnpSiN4\"\n    },\n    {\n     \"id\": 814,\n     \"alt\": \"Jagged rocky peaks under a soft pink and violet dusk sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"dusty violet\",\n      \"soft pink\",\n      \"slate grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.53,\n     \"by\": \"Ales Krivec\",\n     \"page\": \"https://unsplash.com/photos/duoMdMm3aY0\"\n    },\n    {\n     \"id\": 827,\n     \"alt\": \"Conical mountain silhouette above a still lake under a starry dusk sky\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"indigo\",\n      \"dusky violet\",\n      \"navy\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 0.67,\n     \"by\": \"kazuend\",\n     \"page\": \"https://unsplash.com/photos/2KXEb_8G5vo\"\n    },\n    {\n     \"id\": 866,\n     \"alt\": \"Snowy mountain peak behind a snow slope under pink-tinted clouds\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"dusky blue\",\n      \"soft pink\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Samuel Zeller\",\n     \"page\": \"https://unsplash.com/photos/9RqA6tnT0gA\"\n    },\n    {\n     \"id\": 873,\n     \"alt\": \"Turquoise lake between steep rocky mountains with distant snow\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"teal\",\n      \"slate grey\",\n      \"pale cream\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 0.67,\n     \"by\": \"Daniel Roe\",\n     \"page\": \"https://unsplash.com/photos/lpjb_UMOyx8\"\n    },\n    {\n     \"id\": 918,\n     \"alt\": \"Rocky peak wrapped in sunlit cloud above a forested valley\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"warm gold\",\n      \"dark green\",\n      \"grey brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.51,\n     \"by\": \"David Marcu\",\n     \"page\": \"https://unsplash.com/photos/CaQ_KITtnVY\"\n    },\n    {\n     \"id\": 929,\n     \"alt\": \"Green cliff face rising out of dense white mist\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"moss green\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Tiago Muraro\",\n     \"page\": \"https://unsplash.com/photos/1kEHpwZdmtc\"\n    }\n   ]\n  },\n  \"forest\": {\n   \"title\": \"Forest\",\n   \"note\": \"woodland, paths between trees, moss and filtered light\",\n   \"sectors\": [\n    \"hospitality\",\n    \"health\",\n    \"nonprofit\",\n    \"education\",\n    \"physical-product\",\n    \"other\"\n   ],\n   \"keywords\": [\n    \"forest\",\n    \"wood\",\n    \"tree\",\n    \"cabin\",\n    \"nature\",\n    \"green\",\n    \"organic\",\n    \"sustainable\",\n    \"timber\",\n    \"garden\"\n   ],\n   \"photos\": [\n    {\n     \"id\": 229,\n     \"alt\": \"Path through tall pine trees fading into blue-grey fog\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"blue grey\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Orlova Maria\",\n     \"page\": \"https://unsplash.com/photos/7FLh300YONc\"\n    },\n    {\n     \"id\": 10,\n     \"alt\": \"Dense evergreen forest with a blue lake and distant hills beyond\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"deep green\",\n      \"teal blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Paul Jarvis\",\n     \"page\": \"https://unsplash.com/photos/6J--NXulQCs\"\n    },\n    {\n     \"id\": 190,\n     \"alt\": \"Path winding between rows of tall pine trunks\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"dark brown\",\n      \"moss green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"James Forbes\",\n     \"page\": \"https://unsplash.com/photos/jrzvClypPq8\"\n    },\n    {\n     \"id\": 216,\n     \"alt\": \"Narrow dirt trail through mossy green woodland\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"moss green\",\n      \"brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Paul Jarvis\",\n     \"page\": \"https://unsplash.com/photos/9702xTENR-M\"\n    },\n    {\n     \"id\": 243,\n     \"alt\": \"Autumn larch forest on a foggy hillside with a footpath\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"rust brown\",\n      \"pale grey\",\n      \"olive green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Orlova Maria\",\n     \"page\": \"https://unsplash.com/photos/DYW1s0AfLwo\"\n    },\n    {\n     \"id\": 423,\n     \"alt\": \"Snow-laden fir trees fading into pale winter fog\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"pale blue\",\n      \"grey green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"centre\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Gabriel Santiago\",\n     \"page\": \"https://unsplash.com/photos/pTgTMVxQE_k\"\n    },\n    {\n     \"id\": 476,\n     \"alt\": \"Sunlight bursting between tall redwood trunks in a shaded forest\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"dark brown\",\n      \"deep green\",\n      \"gold\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Mr. Marco\",\n     \"page\": \"https://unsplash.com/photos/QP1dUyQ8WsI\"\n    },\n    {\n     \"id\": 498,\n     \"alt\": \"Upward view of towering redwood trunks converging toward the canopy\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"green\",\n      \"reddish brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Kim Daniel\",\n     \"page\": \"https://unsplash.com/photos/JsqAqevX6lg\"\n    },\n    {\n     \"id\": 559,\n     \"alt\": \"Snow-covered lane lined with bare frosted trees\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"grey brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 4,\n     \"ratio\": 1.51,\n     \"by\": \"Ali Inay\",\n     \"page\": \"https://unsplash.com/photos/yNaGxHqjOuw\"\n    },\n    {\n     \"id\": 600,\n     \"alt\": \"Sunbeams streaming through tall conifers in a dark forest\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"dark green\",\n      \"pale gold\",\n      \"black\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Dustin Scarpitti\",\n     \"page\": \"https://unsplash.com/photos/eWBseWsTEpA\"\n    },\n    {\n     \"id\": 704,\n     \"alt\": \"Upward view of tall bamboo stems converging in a green canopy\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"dark green\",\n      \"green\",\n      \"black\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Ståle Grut\",\n     \"page\": \"https://unsplash.com/photos/NUgw97CVdAk\"\n    },\n    {\n     \"id\": 730,\n     \"alt\": \"Snow-dusted conifer forest fading into pale winter fog\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"frost white\",\n      \"pale grey\",\n      \"slate green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Ryan Pohanic\",\n     \"page\": \"https://unsplash.com/photos/W3V2tQAZxPA\"\n    },\n    {\n     \"id\": 805,\n     \"alt\": \"Band of dark conifer forest between a meadow and a blank white sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"white\",\n      \"dark green\",\n      \"olive brown\"\n     ],\n     \"mono\": false,\n     \"calm\"\n\n<!-- [TRUNCATED AT 50KB] -->","isInternal":false,"tokens":16442,"sizeBytes":50040},{"name":"sections.json","path":"skills/taste-skill/library/sections.json","rawUrl":"https://raw.githubusercontent.com/Leonxlnx/taste-skill/HEAD/skills/taste-skill/library/sections.json","title":"Library Skill","category":"anthropic-skill","format":"json","content":"[\n {\n  \"id\": \"features-capabilities-at-poster-scale\",\n  \"role\": \"features\",\n  \"name\": \"Capabilities at poster scale\",\n  \"shape\": \"list\",\n  \"tags\": [\n   \"type-led\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"type-only-statement\",\n   \"hero-object\",\n   \"loud-flat-poster\",\n   \"borrowed-category\",\n   \"colour-chapters\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"No images. The heading, two to four words, is the first line of the list itself, set at the same size as the items but in the soft ink, so no separate title sits above. Five to eight capability names follow, one per line, at clamp(40px, 5.2vw, 84px), medium to heavy weight, leading 1.0, tight tracking, flush left on the page margin across columns 1–8 of 12. Each name's one-sentence description is set at 16–18px in columns 9–12, its first baseline aligned with the name's baseline (CSS grid, align-items: first baseline). Rows are separated by 0.35em of space and nothing else. On hover one row keeps full ink while the others fall to 35% opacity. Leave 18–22vh of empty ground above and below; nothing else shares the section.\",\n  \"mobile\": \"Names drop to 11vw and stay one per line; a name that will not fit breaks onto a second line with a hanging indent. Each description sits directly under its name at 16px, indented one margin width, with 28px before the next name. The soft-ink heading line stays as the first row. All rows at full ink.\",\n  \"seenIn\": [\n   \"aww-cominvi\",\n   \"aww-cerebrium\",\n   \"opl-specia1ne\"\n  ]\n },\n {\n  \"id\": \"features-pinned-heading-passing-rows\",\n  \"role\": \"features\",\n  \"name\": \"Pinned heading, passing rows\",\n  \"shape\": \"pinned\",\n  \"tags\": [\n   \"colour-field\",\n   \"type-led\"\n  ],\n  \"directions\": [\n   \"pinned-poster\",\n   \"loud-flat-poster\",\n   \"colour-chapters\",\n   \"split-stage\",\n   \"editorial-report\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One flat saturated field, full-bleed, as tall as its content. Columns 1–5: the heading, two or three words, at clamp(56px, 6.6vw, 104px) in the heaviest weight, position: sticky; top: 32px, so it holds while the right side travels. Columns 7–12: four to six capability blocks stacked with 120px between them. Each block is a title at 28px bold, then a two-part row: a portrait photograph at 3:4, 180–220px wide with square corners, and beside it, top-aligned, a plain list of four to six short lines at 18px with 14px between lines. Photographs alternate between the left and the right of their list, so the column does not read as a ladder. One ink colour, chosen for contrast on the field. The heading releases when the bottom of the last block reaches it.\",\n  \"mobile\": \"The heading becomes a sticky bar at the top of the section: one line at 9vw on the field colour with 12px padding, holding while blocks pass under it. Each block stacks its title, a full-width 4:3 photograph, then the list at 17px. 72px between blocks.\",\n  \"seenIn\": [\n   \"opl-protip-marketing\",\n   \"aww-cerebrium\",\n   \"aww-sharplink\"\n  ]\n },\n {\n  \"id\": \"features-one-scene-stepping-statements\",\n  \"role\": \"features\",\n  \"name\": \"One scene, stepping statements\",\n  \"shape\": \"full-bleed\",\n  \"tags\": [\n   \"photo-led\"\n  ],\n  \"directions\": [\n   \"place-carries-it\",\n   \"pinned-poster\",\n   \"dark-room\",\n   \"hero-object\",\n   \"uneven-photographs\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A wrapper 350–450vh tall holds a sticky full-bleed photograph (100vw by 100svh) with a calm, symmetrical subject and a clear upper third; a neutral dark scrim covers only that upper third. At top centre, five or six short statements of two to five words are stacked at 18–20px with 10px between them; the first of them is the section's heading. One statement is at full white and the rest at 45% opacity; the active line steps down the stack as the reader scrolls (IntersectionObserver on invisible 70vh markers). For each statement, two small photographs with square corners, 160–240px wide and of different ratios, fade in left and right of the centre line at different heights, then leave when the next pair arrives. No other text. A low-key image on a deep ground works equally well.\",\n  \"mobile\": \"The photograph stays sticky at 100svh, cropped to its centre. The statement stack moves to the bottom third over a scrim, at 17px, left-aligned on the margin. Each statement brings one small photograph only, 44vw wide, placed in the top-right corner with a 16px margin.\",\n  \"seenIn\": [\n   \"aww-seasats\",\n   \"opl-eagles-nest\"\n  ]\n },\n {\n  \"id\": \"features-stacking-colour-sheets\",\n  \"role\": \"features\",\n  \"name\": \"Stacking colour sheets\",\n  \"shape\": \"stack\",\n  \"tags\": [\n   \"colour-field\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"colour-chapters\",\n   \"page-is-the-object\",\n   \"pinned-poster\",\n   \"loud-flat-poster\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Three to five capabilities, each a full-width flat colour sheet about 86svh tall with only its top corners rounded at 28px. Every sheet is position: sticky, with top offsets rising by 72px from one sheet to the next, so each new sheet slides up over the last and leaves the previous sheet's title band showing, like tabbed folders in a drawer. Inside a sheet: the capability name top-left at clamp(28px, 3vw, 44px), sitting within that 72px band; a paragraph of up to 40ch at 18px bottom-left; and in columns 7–12 one photograph filling the sheet from below the band to the bottom edge, square corners, no inset. Sheet colours follow the palette in a fixed order, with ink chosen per sheet. The heading, two to four words at clamp(40px, 5vw, 80px), sits on the ground above the stack with 48px beneath and scrolls away normally.\",\n  \"mobile\": \"Sheets stay sticky but the offset shrinks to 52px and the name drops to 22px so it fits the visible band. Inside each sheet the photograph comes first at 4:3 and full width, then the paragraph at 17px with 20px padding. Sheets are as tall as their content, 70svh at least.\",\n  \"seenIn\": [\n   \"aww-hilden-kaira\",\n   \"opl-nia-creative\",\n   \"opl-april-leihuanani-evangelista\",\n   \"aww-mosbys-files\"\n  ]\n },\n {\n  \"id\": \"features-mosaic-of-unlike-tiles\",\n  \"role\": \"features\",\n  \"name\": \"Mosaic of unlike tiles\",\n  \"shape\": \"mosaic\",\n  \"tags\": [\n   \"dense\",\n   \"colour-field\"\n  ],\n  \"directions\": [\n   \"dense-tiles\",\n   \"editorial-report\",\n   \"colour-chapters\",\n   \"specimen-catalogue\",\n   \"loud-flat-poster\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A 12-column grid with 8px gaps and rows of 96px, filled with no empty cells and no outlines. Six to eight filled tiles in four sizes only: 6×5, 6×3, 3×3 and 3×2 (columns × rows). The rule that keeps it from being a card grid: no two neighbouring tiles hold the same kind of thing. One tile is the heading alone, two to four words at 4vw, top-left. One is a photograph covering its tile. One is a single figure at 6vw with a caption. One is a short list of four lines at 20px. The others are a single sentence each at 28–32px. Text sits top-left with 24px padding; tiles holding one sentence leave their lower half empty. Tile fills: the ground one tone darker, two palette colours, and photographs. One corner radius everywhere, either 0 or 8px.\",\n  \"mobile\": \"Two columns with 6px gaps. The heading tile and the photograph tile span both columns; sentence tiles span both at their natural height; the figure and list tiles sit side by side as a pair of squares. Order: heading, photograph, pair, sentence, sentence.\",\n  \"seenIn\": [\n   \"opl-sand-studio\",\n   \"opl-builders-table\",\n   \"aww-cominvi\",\n   \"opl-uglycash\"\n  ]\n },\n {\n  \"id\": \"features-statement-cell-dark-rows\",\n  \"role\": \"features\",\n  \"name\": \"Statement cell, dark rows\",\n  \"shape\": \"split\",\n  \"tags\": [\n   \"type-led\",\n   \"dense\"\n  ],\n  \"directions\": [\n   \"dense-tiles\",\n   \"editorial-report\",\n   \"type-only-statement\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Two halves butted together, each 50vw wide and at least 90svh tall, with no gap. Left half, in a pale tone: the heading in three short lines at clamp(36px, 4.2vw, 68px), its middle line pushed flush right while the first and third stay flush left (text-align set per line), so the block zigzags inside the cell. A two-sentence paragraph of 30ch sits at the bottom-left and the single action at the bottom-right on the same baseline. Right half, in the darkest tone: four or five rows of equal height filling it, told apart by alternating two near-black tones, not by lines. Each row is a three-part grid: a title at 28px (5 parts), a short paragraph at 16px (4 parts) and a plain list of three terms at 15px (3 parts), all top-aligned with 28px padding. No images anywhere in the section.\",\n  \"mobile\": \"The halves stack. The light cell comes first at 70svh with the zigzag heading at 10vw and the paragraph at its foot. The dark rows follow at full width; each row stacks its title and paragraph, and its three terms run inline as one sentence separated by commas. Rows keep the alternating tones.\",\n  \"seenIn\": [\n   \"aww-aspen-search\"\n  ]\n },\n {\n  \"id\": \"features-staggered-fragment-cells\",\n  \"role\": \"features\",\n  \"name\": \"Staggered fragment cells\",\n  \"shape\": \"grid\",\n  \"tags\": [\n   \"ui-led\",\n   \"dense\"\n  ],\n  \"directions\": [\n   \"product-performs\",\n   \"dense-tiles\",\n   \"quiet-instrument\"\n  ],\n  \"needs\": [\n   \"product-ui\"\n  ],\n  \"blueprint\": \"A three-column grid of six filled cells with 8px gaps, each cell 420–460px tall and filled one tone off the ground, no outlines. Every cell has two parts: a text part (a title at 17px medium and three lines at 15px in the soft ink, 24px padding) and a real fragment of the interface at true size (a control, a menu, a table slice, a swatch strip) docked flush against the opposite edge of the cell and cropped by it. The stagger is the idea: across the first row cells run text-top, fragment-top, text-top; the second row runs the reverse, so fragments form a checkerboard. Fragments differ in shape and size on purpose. The heading, two to four words at 32–40px, sits left-aligned above the grid with 56px beneath it and no supporting line.\",\n  \"mobile\": \"One column of cells at their natural height with 6px gaps. Every cell runs text first, fragment second, but fragments alternate between docking to the left edge and the right edge, and they are allowed to run off the side of the cell at true size instead of shrinking.\",\n  \"seenIn\": [\n   \"opl-dabbit\",\n   \"opl-woblo\"\n  ]\n },\n {\n  \"id\": \"features-small-proof-beside-text\",\n  \"role\": \"features\",\n  \"name\": \"Small proof beside text\",\n  \"shape\": \"list\",\n  \"tags\": [\n   \"quiet\",\n   \"ui-led\"\n  ],\n  \"directions\": [\n   \"quiet-instrument\",\n   \"product-performs\",\n   \"split-stage\",\n   \"name-as-monument\",\n   \"contact-sheet\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One narrow module repeated four to six times down the page, never alternating sides. Each module is 640px wide at most and starts on the page's text margin (at about 22% of the viewport on an understated page). Left part: a flat panel 360px wide and 120 to 200px tall, one tone off the ground, radius 8px, holding one small exact demonstration: a cropped interface fragment at true size, or a tightly cropped photograph covering the panel. Right part, 20px away and top-aligned: a heading of one or two lines at 18px medium and two short paragraphs at 15px in the soft ink, in a column 250px wide. Panel heights vary with their content; text always hangs from the panel's top edge. 96–120px of empty ground between modules. The section heading is 24–28px, on the same left edge, 64px above the first module. In a column under 600px the text moves beneath its panel.\",\n  \"mobile\": \"Each module stacks: the panel at full width and natural height, then heading and paragraphs 16px below on the same left edge, at 17px and 15px. 64px between modules. Panels keep their true-size contents and crop from the right instead of scaling down.\",\n  \"seenIn\": [\n   \"opl-rows\"\n  ]\n },\n {\n  \"id\": \"features-comparison-set-as-text\",\n  \"role\": \"features\",\n  \"name\": \"Comparison set as text\",\n  \"shape\": \"table\",\n  \"tags\": [\n   \"type-led\",\n   \"quiet\"\n  ],\n  \"directions\": [\n   \"type-only-statement\",\n   \"editorial-report\",\n   \"product-performs\",\n   \"quiet-instrument\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A comparison table with no lines and no tick marks. A CSS grid: capability names in columns 1–5 of 12 at 22–24px medium, then three answer columns of equal width (plans, methods, or this against the usual way). Every cell answers in words at 17px: 'Yes, unlimited', 'Up to five', 'Not yet', never a symbol. Seven to ten rows, each 64–72px tall, with every other row on a ground one tone darker so the eye tracks across; rows touch. The column that matters is one filled block in the accent or ink colour running the full height of the table behind its cells and rising 24px above the first row, with its text reversed. Column names sit in the top row at 17px bold. The heading, two to four words at 40–48px, hangs top-left above column 1 with 48px beneath.\",\n  \"mobile\": \"The table turns on its side: one block per capability. The name at 20px bold, then three lines beneath, each giving a column name and its answer at 16px; the featured column's line is set on the filled colour at full width. Blocks alternate the two ground tones.\",\n  \"seenIn\": [\n   \"aww-pp-neue-montreal\"\n  ]\n },\n {\n  \"id\": \"features-one-size-name-columns\",\n  \"role\": \"features\",\n  \"name\": \"One-size name columns\",\n  \"shape\": \"index\",\n  \"tags\": [\n   \"quiet\",\n   \"type-led\",\n   \"dense\"\n  ],\n  \"directions\": [\n   \"contact-sheet\",\n   \"quiet-instrument\",\n   \"name-as-monument\",\n   \"dark-room\",\n   \"uneven-photographs\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Pure text at one size. Three columns start on columns 1, 4 and 7 of the 12-column grid, leaving columns 10–12 empty on purpose. Each column opens with a group name in full ink and continues with a tight stack of six to ten capability names in the soft ink, all at 16–17px, regular weight, line-height 1.25, no bullets and no symbols; one blank line separates group name from stack. Hovering a name brings it to full ink and shows a one-line description in a fixed spot: the top of the empty columns 10–12, at the same size. The heading is no larger than 28px; two or three words, alone on column 1, 96px above the columns. Give the section 20vh of empty ground above and below, so the smallness reads as decided. Works on light or deep grounds.\",\n  \"mobile\": \"Columns stack with 40px between groups; text rises to 18px with line-height 1.4 for touch. Group names stay in full ink. Hover descriptions are dropped; each group ends instead with one sentence in the soft ink that sums it up. The heading is 24px, 48px above.\",\n  \"seenIn\": [\n   \"aww-revelatio-studio\",\n   \"aww-pp-neue-montreal\",\n   \"aww-lama-lama-2\"\n  ]\n },\n {\n  \"id\": \"features-specimens-on-colour-tiles\",\n  \"role\": \"features\",\n  \"name\": \"Specimens on colour tiles\",\n  \"shape\": \"grid\",\n  \"tags\": [\n   \"object-led\",\n   \"colour-field\"\n  ],\n  \"directions\": [\n   \"specimen-catalogue\",\n   \"hero-object\",\n   \"one-motif\",\n   \"colour-chapters\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Each capability is represented by one object photographed alone and shown on a flat colour tile. Columns 1–3 hold the heading (two to four words at 40–52px), top-aligned, with a 30ch sentence beneath and nothing else down the rest of that column. Columns 4–12 hold a grid of five or six tiles in two rows with 10px gaps: tiles are 4:5 except one, which is double width at 8:5 and placed second in the first row. Tile colours rotate through three palette fields. Each photograph is centred at about 70% of its tile's height; on light tiles use mix-blend-mode: multiply so a white studio background disappears. Under each tile, outside it and aligned to its left edge: the capability name at 20px medium and one fact at 16px in the soft ink. No text on the tiles and no hover lift.\",\n  \"mobile\": \"The heading and its sentence sit on top at full width. Tiles become a two-column grid with 8px gaps; the double tile spans both columns at 8:5 and comes first. Names shrink to 17px and facts to 15px, still under each tile.\",\n  \"seenIn\": [\n   \"aww-noho\",\n   \"aww-coffeetech-r\",\n   \"opl-when-you-wish-upon-a-starboy\"\n  ]\n },\n {\n  \"id\": \"features-statements-on-colour-fields\",\n  \"role\": \"features\",\n  \"name\": \"Statements on colour fields\",\n  \"shape\": \"statement\",\n  \"tags\": [\n   \"colour-field\",\n   \"poster\",\n   \"type-led\"\n  ],\n  \"directions\": [\n   \"colour-chapters\",\n   \"loud-flat-poster\",\n   \"type-only-statement\",\n   \"sentence-as-layout\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Three or four full-bleed flat colour fields, each 72–80svh tall, butted together with no gap. Each field holds one benefit and is almost empty. The benefit is a phrase of two to four words at clamp(56px, 9vw, 150px), heavy, leading 0.9, on two lines at most, hugging the bottom-left corner with 28px margins. Its explanation is three lines at 17–18px, 30ch wide, placed near the top at column 8, so the eye travels the diagonal from small text to big phrase. On alternate fields the arrangement mirrors: phrase bottom-right and right-aligned, paragraph top-left at column 2. Text on each field is ink or paper, whichever contrasts more. There is no separate section heading: the first field's phrase is the heading. Nothing else appears on the fields: no images, shapes or buttons.\",\n  \"mobile\": \"Fields are 64svh tall. The paragraph sits top-left at 16px across 80% of the width; the phrase sits bottom-left at 13vw on two lines. Mirroring is dropped; alternate fields right-align the paragraph only, keeping the phrase on the left margin.\",\n  \"seenIn\": [\n   \"opl-anidachi\",\n   \"aww-px-push\"\n  ]\n },\n {\n  \"id\": \"features-rows-with-margin-photographs\",\n  \"role\": \"features\",\n  \"name\": \"Rows with margin photographs\",\n  \"shape\": \"list\",\n  \"tags\": [\n   \"type-led\",\n   \"photo-led\"\n  ],\n  \"directions\": [\n   \"editorial-report\",\n   \"uneven-photographs\",\n   \"place-carries-it\",\n   \"sentence-as-layout\",\n   \"colour-chapters\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Everything hangs from one vertical axis at column 5, about 35% of the width. First the heading: a statement of up to five words at clamp(40px, 5vw, 80px) starting on the axis, vertically centred in an otherwise empty 70svh of ground. Then four or five benefit rows, each starting on the same axis: a title at clamp(28px, 3vw, 48px) and under it a paragraph of 34ch at 17px. Columns 1–4 stay empty. At the right margin each row carries one photograph, top-aligned with its title and deliberately unequal: 240px wide at 4:5 in one row, 320px at 3:2 in the next, 180px square after that. Rows are separated by 96–120px of space, not lines. On a saturated field, set all type in one pale ink and leave the photographs ungraded.\",\n  \"mobile\": \"The axis collapses to the left margin. The statement sits at 9vw in 50svh of empty ground. Each row stacks its title at 26px, the paragraph, then its photograph at alternating widths: 100%, 70% flush right, 55% flush left. 64px between rows.\",\n  \"seenIn\": [\n   \"aww-px-push\"\n  ]\n },\n {\n  \"id\": \"features-paragraph-with-picture-words\",\n  \"role\": \"features\",\n  \"name\": \"Paragraph with picture words\",\n  \"shape\": \"statement\",\n  \"tags\": [\n   \"type-led\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"sentence-as-layout\",\n   \"one-motif\",\n   \"product-performs\",\n   \"editorial-report\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One paragraph does the work of a feature grid. Three or four sentences, 35–50 words in total, set at clamp(30px, 3.6vw, 60px), leading 1.18, medium weight, across columns 1–11, left-aligned. Each sentence names one capability, and directly after that capability's key noun sits an inline slot: an inline-block frame 1em tall and 1.9em wide, radius 0.18em, dropped 0.12em below the baseline, holding a tight photograph crop (object-fit: cover) or a real interface control at readable size. Four slots at most, never two on one line. The nouns keep the weight and colour of the rest; the slots are the only emphasis. Mark it up as a paragraph and give the section a visually hidden heading of two or three words; nothing visible sits above. 72px lower, starting at column 7, one supporting sentence at 18px and the action.\",\n  \"mobile\": \"The paragraph drops to 7vw with leading 1.22 and fills the width. Slots stay inline at 1em tall but narrow to 1.5em wide. If a slot lands alone at the start of a line, let it; do not shrink the type. The supporting sentence and the action follow at full width.\",\n  \"seenIn\": [\n   \"aww-monolog\",\n   \"opl-uncle-rudy\",\n   \"aww-cominvi\",\n   \"opl-midnight-2\"\n  ]\n },\n {\n  \"id\": \"features-capabilities-as-a-menu\",\n  \"role\": \"features\",\n  \"name\": \"Capabilities as a menu\",\n  \"shape\": \"table\",\n  \"tags\": [\n   \"object-led\",\n   \"type-led\"\n  ],\n  \"directions\": [\n   \"page-is-the-object\",\n   \"split-stage\",\n   \"borrowed-category\",\n   \"type-only-statement\",\n   \"quiet-instrument\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"The capabilities are set as a printed menu or price list. One paper-coloured sheet, 520–600px wide and taller than it is wide, sits on a contrasting flat ground, centred or starting at column 2; its top and bottom edges are cut into shallow scallops or a zigzag with clip-path, its sides straight. On it, centred at the top, the heading: two or three words at 44–56px, then 40px of space. Below, items in two or three groups; each group opens with its name at 20px bold. Each item is a row: the name at 19px on the left, a short value on the right (a price, a time, a quantity, 'included'), and between them a leader of round 4px dots (border-bottom: 4px dotted, sitting on the baseline). A description at 15px in the soft ink sits under the name, at most 34ch. 18px between items, 44px between groups.\",\n  \"mobile\": \"The sheet fills the width minus 12px margins and keeps its cut top and bottom edges. Names stay left and values right on one line with the dot leader between; descriptions wrap beneath at 15px. Group names drop to 18px. Padding inside the sheet is 20px.\",\n  \"seenIn\": [\n   \"opl-the-content-architecture\",\n   \"aww-pensatori-irrazionali\"\n  ]\n },\n {\n  \"id\": \"features-shape-marked-small-points\",\n  \"role\": \"features\",\n  \"name\": \"Shape-marked small points\",\n  \"shape\": \"split\",\n  \"tags\": [\n   \"object-led\",\n   \"quiet\"\n  ],\n  \"directions\": [\n   \"one-motif\",\n   \"hero-object\",\n   \"product-performs\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"For the many minor points that do not deserve a row each. Columns 1–5: one photograph inside a single large shape taken from the subject's own geometry (a circle, an arch, a chamfered block), made with clip-path or border-radius, about 78svh tall and pushed 12% past the section's left edge so the viewport crops it. Columns 7–12: the heading, two to four words at 40–48px, then 56px lower a grid of eight to twelve points in three columns with 40px column gaps and 44px row gaps, no cells and no fills. Each point is a title at 17px medium preceded by the same shape drawn at cap height (0.7em, flat fill, inline SVG or a styled span), then two lines at 15px in the soft ink. The small shapes take a different palette colour per column, which is the only colour on the right side.\",\n  \"mobile\": \"The shaped photograph comes first, 82vw wide, cropped by the left edge and no taller than 60svh. The heading follows at 30px. Points become one column with 28px between them; the small shape hangs in the margin to the left of each title, so titles and text share one edge.\",\n  \"seenIn\": [\n   \"opl-dabbit\",\n   \"aww-sstr-friction-reduction\"\n  ]\n },\n {\n  \"id\": \"showcase-two-giant-words-compared\",\n  \"role\": \"showcase\",\n  \"name\": \"Two giant words compared\",\n  \"shape\": \"statement\",\n  \"tags\": [\n   \"type-led\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"type-only-statement\",\n   \"editorial-report\",\n   \"loud-flat-poster\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"No photographs: the thing shown is a pair of words, characters or figures that make the point by comparison (before and after, input and output, ours and the usual). At the top of the section, on one row: the heading, two to four words at 28–36px, at the left margin, and a paragraph of up to 60 words at 17px starting at column 7. Then 12vh of space. Below, two specimens side by side, one starting on column 1 and one on column 7, each set at clamp(180px, 34vw, 520px) with leading 0.8, so each fills about half the viewport's width. The section has a fixed height and overflow: hidden, so its bottom edge cuts both specimens at roughly 60% of their height. One short caption at 16px sits above the top-left of each specimen, naming it. Both specimens share one ink; the difference is in the letterforms or values, not in colour.\",\n  \"mobile\": \"Heading first, then the paragraph, at full width. The two specimens stack, each at 62vw type size in its own 38svh box with overflow hidden so the lower part is cut. Captions sit above each box at 15px. The second box takes the inverse colours of the first.\",\n  \"seenIn\": [\n   \"aww-pp-neue-montreal\"\n  ]\n },\n {\n  \"id\": \"showcase-two-objects-two-fields\",\n  \"role\": \"showcase\",\n  \"name\": \"Two objects, two fields\",\n  \"shape\": \"split\",\n  \"tags\": [\n   \"object-led\",\n   \"colour-field\"\n  ],\n  \"directions\": [\n   \"specimen-catalogue\",\n   \"hero-object\",\n   \"colour-chapters\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Two panels side by side, each 50vw wide and 92svh tall, in two different flat tones from the palette, meeting on a clean vertical edge with no gap. Each panel is dominated by one cut-out object photograph scaled to 130–150% of the panel's width and positioned so the panel's top edge crops it: the reader sees the lower two-thirds of the object, very close. On light panels use mix-blend-mode: multiply to lose a white studio background. Along the bottom of each panel, 28px in from the edges, one row: the name at 20px medium and a price or fact at 17px on the left; on the right, two small rectangular actions, one filled with ink and one with paper. Nothing sits in the middle of a panel. The heading, two to four words at 32–40px, is set at the top-left of the first panel only, in the empty corner beside the object.\",\n  \"mobile\": \"Panels stack, each 78svh tall, the object scaled to 150% of the width and cut by the top and right edges. The bottom row becomes two lines: name and fact, then the two actions side by side at full width. The heading sits top-left on the first panel at 26px.\",\n  \"seenIn\": [\n   \"aww-noho\"\n  ]\n },\n {\n  \"id\": \"showcase-object-in-front-of-type\",\n  \"role\": \"showcase\",\n  \"name\": \"Object in front of type\",\n  \"shape\": \"statement\",\n  \"tags\": [\n   \"object-led\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"hero-object\",\n   \"borrowed-category\",\n   \"loud-flat-poster\",\n   \"sentence-as-layout\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Type and object share one space instead of sitting side by side. Three or four lines of display type, one or two words each, are stacked flush left at clamp(72px, 9vw, 150px) with leading 0.88, starting on the left margin and allowed to leave the right edge (white-space: nowrap; overflow: hidden on the section). The lines step through tones of one ink: one at 45%, one at full strength, the rest at 18%. The object photograph, a cut-out or a studio shot blended with multiply, is absolutely positioned over the upper right of the stack at 40–46vw wide, rotated no more than 6 degrees and above the type in the stacking order, so it hides parts of three or four letters. Under the stack, in columns 8–12, a two-paragraph block at 20px gives the facts. The full-strength line is the heading; nothing sits above it.\",\n  \"mobile\": \"Type drops to 15vw and still runs off the right edge. The object sits at 78vw wide, overlapping the last two lines from below instead of from the right, and is cropped by the right edge. The facts block follows at full width and 17px.\",\n  \"seenIn\": [\n   \"aww-the-watch\",\n   \"opl-aevion\",\n   \"aww-coffeetech-r\"\n  ]\n },\n {\n  \"id\": \"showcase-band-of-unequal-panels\",\n  \"role\": \"showcase\",\n  \"name\": \"Band of unequal panels\",\n  \"shape\": \"strip\",\n  \"tags\": [\n   \"photo-led\"\n  ],\n  \"directions\": [\n   \"place-carries-it\",\n   \"uneven-photographs\",\n   \"name-as-monument\",\n   \"editorial-report\",\n   \"dark-room\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A modest heading, then one wide band of pictures. The heading, two to four words at 36–44px, starts at column 3, left of centre, with 64px beneath it. The band spans the full viewport width edge to edge and is 68svh tall: four photographs standing side by side with no gaps and deliberately unequal widths, a flex row with flex-grow values of 5, 2, 3 and 2. Each panel is cropped with object-fit: cover to a tall slice, so the band reads as one folded view. The first panel carries a two-line title at 28px in paper colour at its top-left, 24px in, over a neutral scrim that covers only that corner. Hovering a panel raises its flex-grow to 6 over 500ms while the others give way; without hover the widths simply stay. One caption line at 16px sits under the band at the left margin.\",\n  \"mobile\": \"The heading sits on the margin at 28px. The band becomes a two-by-two block with no gaps, 84svh tall in total: the first row split 64/36 and the second 36/64, so the slices stay unequal. The title stays on the first panel. No hover behaviour.\",\n  \"seenIn\": [\n   \"aww-white-desert\",\n   \"aww-tengile-malamala-collection\"\n  ]\n },\n {\n  \"id\": \"showcase-close-up-with-column-card\",\n  \"role\": \"showcase\",\n  \"name\": \"Close-up with column card\",\n  \"shape\": \"full-bleed\",\n  \"tags\": [\n   \"photo-led\",\n   \"object-led\"\n  ],\n  \"directions\": [\n   \"hero-object\",\n   \"place-carries-it\",\n   \"dark-room\",\n   \"borrowed-category\",\n   \"pinned-poster\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A full-bleed close-up photograph, 100vw by 100svh, with nothing over most of it. A four-column grid lies on top. One solid card in the ink colour, exactly one grid column wide (about 22vw) and 52svh tall, sits in the second column, vertically centred. Inside it, centred: the item's name at 30–36px, a variant line at 17px, the price or key fact at 17px, a small 3:2 photograph of the whole object (the card shows the whole, the background shows the detail), and at the foot a square-cornered action filling the card's width. The card is opaque, radius 0–6px, with no blur. When the section presents two or three items, each gets its own full-bleed frame and its card moves one column to the right each time, so position carries the sequence. The first card's name is the section heading.\",\n  \"mobile\": \"The photograph fills 100svh, cropped to its most detailed area. The card becomes a full-width block docked to the bottom, 46svh tall, left-aligned inside with 20px padding; the small whole-object photograph sits to the right of the name at 96px wide.\",\n  \"seenIn\": [\n   \"aww-longbow\"\n  ]\n },\n {\n  \"id\": \"showcase-live-demo-with-controls\",\n  \"role\": \"showcase\",\n  \"name\": \"Live demo with controls\",\n  \"shape\": \"split\",\n  \"tags\": [\n   \"ui-led\",\n   \"quiet\"\n  ],\n  \"directions\": [\n   \"product-performs\",\n   \"quiet-instrument\",\n   \"dense-tiles\"\n  ],\n  \"needs\": [\n   \"product-ui\"\n  ],\n  \"blueprint\": \"One filled panel, 680–760px wide and about 640px tall, radius 12px, in a tone clearly darker or lighter than the ground, placed on the text column's left edge or centred, with at least 15vh of empty ground above and below. The panel is split 62/38 into two flat areas that differ by one tone. Left area: the product doing its job on real content at true size. Right area: a narrow column of working controls, six to nine stacked rows 44px tall, each with a name at 14px on the left and a slider, toggle or value on the right; changing one changes the demonstration at once. A text link sits in the panel's bottom-left corner. The heading, two to four words at 24–32px, sits above the panel on its left edge with one sentence at 16px; under the panel, one line of start instruction.\",\n  \"mobile\": \"The panel fills the width. The demonstration takes the top at 4:3; the controls follow beneath as full-width rows 52px tall, only the four most telling ones, with a text link that reveals the rest. Heading and sentence sit above at 24px and 16px.\",\n  \"seenIn\": [\n   \"opl-dialkit\",\n   \"opl-textmode-overlay\"\n  ]\n },\n {\n  \"id\": \"showcase-one-frame-three-distances\",\n  \"role\": \"showcase\",\n  \"name\": \"One frame, three distances\",\n  \"shape\": \"pinned\",\n  \"tags\": [\n   \"photo-led\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"pinned-poster\",\n   \"hero-object\",\n   \"dark-room\",\n   \"sentence-as-layout\",\n   \"place-carries-it\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A wrapper 300vh tall holds a sticky stage of 100svh. On the stage one frame is centred: 30vw wide at 4:5, square corners, overflow hidden. Inside it the same photograph is shown at three distances as the reader scrolls: the whole subject, then scaled to 180% toward one detail, then to 320% on a second detail (transform: scale with a transform-origin per stage, 700ms ease, switched by IntersectionObserver on three invisible markers). The sentence is delivered in halves: its first two or three words sit above the frame at clamp(56px, 8vw, 130px), centred; the last words arrive below the frame at the second stage, overlapping the frame's bottom edge by 0.3em. At the third stage one caption of 28ch at 17px appears to the right of the frame, top-aligned. The two halves together are the heading and stay within two lines.\",\n  \"mobile\": \"The frame grows to 70vw at 4:5 and stays sticky at centre. The first half of the sentence sits above it at 13vw, the second half below it at the same size. The third-stage caption appears under the sentence at 16px, centred.\",\n  \"seenIn\": [\n   \"aww-vero-new-york\",\n   \"aww-illoca\",\n   \"opl-screentune\"\n  ]\n },\n {\n  \"id\": \"showcase-one-image-across-tiles\",\n  \"role\": \"showcase\",\n  \"name\": \"One image across tiles\",\n  \"shape\": \"mosaic\",\n  \"tags\": [\n   \"photo-led\",\n   \"dense\"\n  ],\n  \"directions\": [\n   \"dense-tiles\",\n   \"contact-sheet\",\n   \"editorial-report\",\n   \"colour-chapters\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One photograph is cut across a board of tiles. A grid of six columns and four rows with 8px gaps spans the full width between 12px margins; every tile is square (aspect-ratio: 1). Each tile shows its own piece of the same image: set the photograph as every tile's background at background-size: 600% 400% and step background-position by column and row, so the picture reads whole through the gaps. Five of the twenty-four tiles are swapped for flat colour tiles from the palette, never two adjacent: one holds the heading (two to four words at 2.6vw, top-left, 16px padding), three hold one fact each at 18px, one holds the action. On hover a tile's piece scales to 108% inside its own clip. Choose a photograph with one clear subject, so the board is legible at a glance.\",\n  \"mobile\": \"Three columns by six rows with 6px gaps, the photograph re-cut at background-size 300% 600% from a portrait crop. Four colour tiles only; the heading tile spans two columns in the top row with the heading at 6vw. Facts drop to 15px.\",\n  \"seenIn\": [\n   \"aww-produx-design\",\n   \"aww-ai-in-design-report-2026\"\n  ]\n },\n {\n  \"id\": \"showcase-frame-run-one-lifted\",\n  \"role\": \"showcase\",\n  \"name\": \"Frame run, one lifted\",\n  \"shape\": \"strip\",\n  \"tags\": [\n   \"photo-led\",\n   \"quiet\"\n  ],\n  \"directions\": [\n   \"contact-sheet\",\n   \"uneven-photographs\",\n   \"specimen-catalogue\",\n   \"quiet-instrument\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Columns 1–3 are a nearly empty column: the heading (two to four words at 24–28px) at the top, a link under it, and one or two short notes at 15px much further down, each level with the frame it describes. Columns 4–12 hold a run of six to eight frames of the same subject at one fixed height of 30vh, with natural widths and 6px gaps: the whole view, a tight crop of the same thing, a detail, the reverse side. The run is allowed to leave the right edge. One frame is lifted out of the row: shown at 2.2 times the row height with its bottom aligned to the row's bottom (flex row, align-items: end), so it stands above the others. Under each frame, at 15px: a name on the left and a single fact on the right. Square corners, no captions on the images.\",\n  \"mobile\": \"The heading and link sit on top. The lifted frame comes first at full width. The rest of the run scrolls sideways beneath it at a fixed height of 34vw with 4px gaps and scroll-snap, bleeding off the right edge. Notes are listed under the run at 15px.\",\n  \"seenIn\": [\n   \"aww-serotoninn\",\n   \"aww-butter\",\n   \"aww-no-art\"\n  ]\n },\n {\n  \"id\": \"showcase-output-slips-along-the-edge\",\n  \"role\": \"showcase\",\n  \"name\": \"Output slips along the edge\",\n  \"shape\": \"full-bleed\",\n  \"tags\": [\n   \"photo-led\",\n   \"object-led\"\n  ],\n  \"directions\": [\n   \"page-is-the-object\",\n   \"borrowed-category\",\n   \"place-carries-it\",\n   \"loud-flat-poster\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"For subjects whose result is a piece of text or paper: a receipt, a note, a ticket, a written line. A full-bleed photograph, 100vw by 96svh, sets the scene. In the upper centre, left-aligned in a column starting at 18% of the width, two short paragraphs in paper colour at 28–32px, the first opening with the heading's two to four words; a neutral scrim sits behind that column only. Along the bottom, six paper-coloured slips stand side by side across the full width with 12px gaps, each a filled rectangle of a different height (between 26 and 44svh), their lower ends cut off by the section's bottom edge. Two or three of the slips, not all, are tilted by 1–2 degrees. Each slip carries a sample of real output in the text face at 15px: a bold first line, a divider made of typed characters, then four to eight lines.\",\n  \"mobile\": \"The photograph is 100svh. The paragraphs sit in the top third at 22px. Only three slips show, each 30vw wide, standing along the bottom at different heights, and the row scrolls sideways to reveal the rest. Slip text stays at 14px; do not scale it down.\",\n  \"seenIn\": [\n   \"opl-poetry-camera\"\n  ]\n },\n {\n  \"id\": \"showcase-object-on-a-disc\",\n  \"role\": \"showcase\",\n  \"name\": \"Object on a disc\",\n  \"shape\": \"index\",\n  \"tags\": [\n   \"object-led\",\n   \"colour-field\"\n  ],\n  \"directions\": [\n   \"one-motif\",\n   \"specimen-catalogue\",\n   \"hero-object\",\n   \"colour-chapters\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One section about a viewport tall on a plain ground. A flat filled disc 64vh across, in one palette colour, sits with its centre at 58% of the width; swap the disc for the subject's own shape if it has one. A cut-out object photograph stands in front of it, centred on it, about 78% of the disc's height and breaking the disc's outline at the top. Bottom-left, starting on the margin and ending level with the disc's lower edge: a vertical list of four to six item names at clamp(28px, 2.9vw, 44px), leading 1.15. The selected name is in full ink and the rest at 25%; choosing a name swaps the object (300ms crossfade) and the disc's colour. The heading, two to four words at the same size as the names but in the soft ink, is the first line of that list. One fact about the selected item sits at the disc's right edge at 17px.\",\n  \"mobile\": \"The disc comes first, 86vw across and centred, with the object in front. The names follow as a single sideways-scrolling line at 26px with 24px gaps, the selected one in full ink. The fact sits under the names at 16px.\",\n  \"seenIn\": [\n   \"aww-cominvi\",\n   \"opl-tara\"\n  ]\n },\n {\n  \"id\": \"showcase-square-plate-spare-text\",\n  \"role\": \"showcase\",\n  \"name\": \"Square plate, spare text\",\n  \"shape\": \"split\",\n  \"tags\": [\n   \"colour-field\",\n   \"photo-led\"\n  ],\n  \"directions\": [\n   \"split-stage\",\n   \"page-is-the-object\",\n   \"colour-chapters\",\n   \"editorial-report\",\n   \"one-motif\",\n   \"name-as-monument\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One flat field split 50/50, at least 88svh tall. Left half: a single square photograph filling the half's width minus 40px margins, vertically centred, square corners. A large simple shape may be laid over it to turn the photograph into the object it stands for: a ring 86% of its width with a 6px stroke and a small solid dot at the centre makes a record; a notch cut by clip-path makes a ticket stub. Right half, a flex column with space-between: at the top a row of three plain text tabs at 18px (editions, years, variants), the active one in full ink and the others at 40%; in the middle the title, two to four words at 32–40px bold, with a 34ch description 48px below; along the bottom two filled rectangular cells side by side, each half the column wide and 72px tall, acting as the two actions, one in ink and one a tone off the field.\",\n  \"mobile\": \"The square photograph comes first at full width with 16px margins. The tabs sit under it as one row at 17px. Then the title at 28px, the description, and the two action cells stacked, each full width and 60px tall.\",\n  \"seenIn\": [\n   \"aww-paul-kalkbrenner\"\n  ]\n },\n {\n  \"id\": \"how-it-works-lines-that-step-across\",\n  \"role\": \"how-it-works\",\n  \"name\": \"Lines that step across\",\n  \"shape\": \"statement\",\n  \"tags\": [\n   \"type-led\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"type-only-statement\",\n   \"sentence-as-layout\",\n   \"loud-flat-poster\",\n   \"editorial-report\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"The sequence is written, not counted. Four lines of display type, one stage per line, each a complete short clause that begins with its order word: 'First you send it.' 'Then we take it apart.' 'You choose one.' 'It ships on Friday.' Set at clamp(36px, 4.6vw, 76px), leading 1.0, one line each. The first line starts on column 1 and each following line starts two columns further right (grid-column-start 1, 3, 5, 7), so the block descends as a staircase and the eye follows the diagonal. Under each line, on that line's own left edge and 12px below, a sentence of up to 34ch at 17px in the soft ink. 56px between stages. The last line may take the accent colour as the single emphasis. The first line serves as the heading; there is no title above. Leave the columns to the left of the final stage empty.\",\n  \"mobile\": \"Lines drop to 8.4vw and may wrap onto a second line. The staircase becomes a smaller indent of 6vw per stage, so the fourth line starts 18vw in. Each sentence sits under its line at 16px on the same indent. 40px between stages.\",\n  \"seenIn\": [\n   \"opl-rendez-vous-franceclat\"\n  ]\n },\n {\n  \"id\": \"how-it-works-photographs-down-a-diagonal\",\n  \"role\": \"how-it-works\",\n  \"name\": \"Photographs down a diagonal\",\n  \"shape\": \"stack\",\n  \"tags\": [\n   \"photo-led\",\n   \"quiet\"\n  ],\n  \"directions\": [\n   \"uneven-photographs\",\n   \"place-carries-it\",\n   \"dark-room\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Three stages, three photographs of different sizes placed along a falling diagonal on the 12-column grid. Stage one: a 3:4 portrait in columns 1–4. Stage two: a 1:1 square in columns 6–8, its top edge 220px lower than the first photograph's top. Stage three: a 16:10 landscape in columns 8–12, starting 180px below the bottom of the second. Each stage's text sits in the gap the stagger leaves: a paragraph of up to 36ch at 17px, top-aligned with its photograph and placed in the columns to its right (to its left for the third). Each paragraph opens with a bold run-in phrase that carries the order: 'On the first day', 'A week later', 'By the end'. Square corners; no arrows or connecting marks. The heading, two to four words at clamp(36px, 4vw, 64px) in a light weight, sits alone in columns 7–12 at the very top, level with the first photograph's top edge.\",\n  \"mobile\": \"The diagonal becomes alternating widths: the first photograph at 100%, the second at 62% flush right, the third at 78% flush left. Each paragraph follows its photograph on that photograph's left edge at 16px. 56px between stages. The heading sits above at 30px.\",\n  \"seenIn\": [\n   \"opl-fynza\",\n   \"opl-the-queue\"\n  ]\n },\n {\n  \"id\": \"how-it-works-drag-row-of-moments\",\n  \"role\": \"how-it-works\",\n  \"name\": \"Drag row of moments\",\n  \"shape\": \"carousel\",\n  \"tags\": [\n   \"photo-led\"\n  ],\n  \"directions\": [\n   \"contact-sheet\",\n   \"place-carries-it\",\n   \"uneven-photographs\",\n   \"page-is-the-object\",\n   \"dark-room\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A story told left to right. Top row: the heading, two to four words at 28–36px, at the left margin; at the right margin two solid square buttons, 48px each, for back and forward. Directly beneath, a solid bar 6px tall spans the full width in a soft tone, with a full-ink segment showing how far the row has been scrolled. Then the row itself: six to nine columns, each 280px wide with 32px gaps, in a horizontally scrolling flex container with scroll-snap that bleeds off both viewport edges. Every column reads top to bottom: a one-line caption at 18px bold that carries the order in words ('We met', 'Two winters on', 'The move'), three lines at 15px in the soft ink, then 80–140px of empty space that varies per column, then a 4:5 portrait photograph. Because the spaces vary, the photographs' top edges rise and fall along the row.\",\n  \"mobile\": \"Columns are 72vw wide with 16px gaps, so the next one always shows at the right edge. The buttons are dropped; the 6px progress bar stays under the heading. The empty space inside columns shrinks to 32–64px but still varies from column to column.\",\n  \"seenIn\": [\n   \"opl-sarah-matt-wedding\",\n   \"aww-no-art\"\n  ]\n },\n {\n  \"id\": \"how-it-works-pinned-fragment-changing-state\",\n  \"role\": \"how-it-works\",\n  \"name\": \"Pinned fragment, changing state\",\n  \"shape\": \"pinned\",\n  \"tags\": [\n   \"ui-led\",\n   \"quiet\"\n  ],\n  \"directions\": [\n   \"product-performs\",\n   \"quiet-instrument\",\n   \"split-stage\",\n   \"pinned-poster\"\n  ],\n  \"needs\": [\n   \"product-ui\"\n  ],\n  \"blueprint\": \"Two columns. Right, columns 7–12: a stage that is position: sticky; top: 14vh, holding one fragment of the real interface at true size on a single flat stage colour, about 520px square. Left, columns 1–5: three statements, each in its own block 80vh tall, so one is in view at a time. A statement is a two-line sentence at 28–32px that begins with its order word ('Paste a link.', 'Then pick the parts you want.', 'Share it when it looks right.') plus one supporting line at 16px. The statement nearest the viewport's centre is in full ink; the others sit at 30%. As each statement becomes active the fragment changes to the matching state: an empty field, a filled list with two rows selected, a finished result with its confirmation. Build the states in HTML and switch a class; do not swap screenshots. The heading, two to four words at 24–28px, sits above the first statement.\",\n  \"mobile\": \"The stage is sticky at the top, 46svh tall, the fragment fitted by cropping to its active region, not by shrinking its text. Statements scroll beneath it in blocks 60svh tall at 22px. The stage releases after the third statement.\",\n  \"seenIn\": [\n   \"opl-juggle\",\n   \"aww-cerebrium\",\n   \"opl-vessa\"\n  ]\n },\n {\n  \"id\": \"how-it-works-itinerary-on-a-slip\",\n  \"role\": \"how-it-works\",\n  \"name\": \"Itinerary on a slip\",\n  \"shape\": \"table\",\n  \"tags\": [\n   \"object-led\",\n   \"type-led\"\n  ],\n  \"directions\": [\n   \"page-is-the-object\",\n   \"type-only-statement\",\n   \"split-stage\",\n   \"quiet-instrument\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"The process is printed as an itinerary or receipt. One paper-coloured slip 420–480px wide stands on a contrasting flat ground at columns 7–11; its bottom edge is a zigzag cut with clip-path and its top edge is straight. The heading, two to four words at clamp(40px, 4.4vw, 68px), sits in columns 1–5 with a 30ch paragraph, top-aligned with the slip. On the slip, in the text face at 16px with tabular figures: stages grouped under time headings that carry the order ('Monday', 'Midweek', 'Friday'), each heading in bold with 28px above it. Under a heading, two to four rows; each row has what happens on the left, a duration or time on the right, and a leader of round 4px dots between. The final row is inverted, paper-coloured text on a full-width ink bar 44px tall, and states the result: what the reader holds at the end and the total time.\",\n  \"mobile\": \"The heading and paragraph come first. The slip follows at full width minus 16px margins, keeping its zigzag bottom edge. Rows keep left text, dots and right value on one line; long descriptions wrap under the left text. The inverted final row stays full width.\",\n  \"seenIn\": [\n   \"opl-the-content-architecture\",\n   \"opl-lennys-newsletter-product-pass\"\n  ]\n },\n {\n  \"id\": \"how-it-works-accordion-of-tinted-panels\",\n  \"role\": \"how-it-works\",\n  \"name\": \"Accordion of tinted panels\",\n  \"shape\": \"strip\",\n  \"tags\": [\n   \"colour-field\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"colour-chapters\",\n   \"one-motif\",\n   \"loud-flat-poster\",\n   \"dense-tiles\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A two-column introduction, then one horizontal accordion. Introduction: the heading, two to four words at clamp(36px, 4vw, 60px), in columns 1–5; one paragraph at 18px in columns 7–11. 64px below, a flex row across columns 1–12, 520px tall, of four to six panels with no gaps. The open stage is a panel taking about 58% of the width; the rest are vertical slivers sharing what remains. Order is carried by colour: the first stage is the darkest tone of one hue and each later stage is a lighter flat tint of it, so the row reads dark to light from left to right. A sliver shows only its stage name, rotated 90 degrees and reading upward, at 20px bold, anchored to its bottom-left. The open panel shows the name at 40px top-left, a 36ch paragraph at 18px bottom-left and, optionally, one photograph in its right half. Clicking a sliver opens it (flex-basis transition, 450ms).\",\n  \"mobile\": \"The accordion turns vertical: stages stack at full width as bars 64px tall in the same dark-to-light order, names set horizontally at 18px. The open stage expands to its content height with the paragraph at 17px. The first stage is open by default.\",\n  \"seenIn\": [\n   \"aww-white-desert\"\n  ]\n },\n {\n  \"id\": \"how-it-works-tiles-that-grow\",\n  \"role\": \"how-it-\n\n<!-- [TRUNCATED AT 50KB] -->","isInternal":false,"tokens":13651,"sizeBytes":50175},{"name":"sites.json","path":"skills/taste-skill/library/sites.json","rawUrl":"https://raw.githubusercontent.com/Leonxlnx/taste-skill/HEAD/skills/taste-skill/library/sites.json","title":"Library Skill","category":"anthropic-skill","format":"json","content":"[\n {\n  \"id\": \"aww-pp-neue-montreal\",\n  \"name\": \"PP Neue Montreal\",\n  \"url\": \"https://neuemontreal.com/\",\n  \"source\": \"Awwwards Site of the Day\",\n  \"kind\": \"other\",\n  \"score\": 8.6,\n  \"idea\": \"A typeface specimen dressed as a vintage city travel guide: the font named after Montreal is sold through guidebook titling, postcards and old tourist footage.\",\n  \"mood\": [\n   \"bold\",\n   \"playful\",\n   \"retro-modernist\",\n   \"typographic\",\n   \"confident\"\n  ],\n  \"archetype\": \"giant-wordmark\",\n  \"hero\": \"Grainy coral-red field. Top row: a monogram in a pale pill at left, a pale-grey pill nav with seven links centred, a black pill button at right. Below at the left margin, a two-line white bold title at about 4.5vw; opposite it, a ring of repeated monograms set around a circle like a stamp. Three full-width black hairlines cut the field into bands: a two-line intro sentence at ~1.6vw sits in the second, and the typeface name fills the third in black bold at ~17vw, two lines, tight leading, 60% of the width. A 4:3 clip of 1960s street footage is inset bottom-right, 29% wide, bottom-aligned with the name.\",\n  \"type\": \"PP Neue Montreal only: Bold for display with -0.01em tracking and leading near 0.9, Text Regular 16px for body and lists. Sizes leap from 16px to 144px headings to a ~240px name; one section enlarges a single lowercase letter to viewport height.\",\n  \"colour\": \"#ed4b44 #1a1a1a #f0e7d4 #18bc42 #b5b5b5 #f2c21a — Each chapter takes a flat field (coral red, near-black, cream, green) with black or cream type; one headline colours every word differently. Warm, print-poster feel with visible grain.\",\n  \"imagery\": \"Archive 1960s city footage, saturated vintage postcards, a handwritten postcard back, and rotated specimen posters and stamp sheets scattered around a headline. All square-cornered and inset, never full-bleed.\",\n  \"layout\": \"24px side margins and full-width hairlines marking bands. Content is left-anchored in three or four columns split by vertical hairlines; chapters alternate between tabular lists, a scattered collage, a centred statement and a giant glyph comparison. A pill nav stays pinned.\",\n  \"sections\": [\n   {\n    \"role\": \"intro\",\n    \"description\": \"Near-black screen split by a vertical hairline at about 75% width. Left: a three-line small heading at the top margin, then a five-line bold oblique headline at ~6vw in which each line is indented further right like a staircase and each word takes its own colour (green, cream, grey, yellow, blue, orange). Right narrow column: two stacked postcards, one saturated photo card and one cream handwritten card with a stamp. A tiny section label sits bottom-left.\"\n   },\n   {\n    \"role\": \"other\",\n    \"description\": \"A dark band of pure tabular type. A body paragraph occupies column one; weight names stack as tight single-line lists in two further columns divided by vertical hairlines. Below, a small label over a full-width rule introduces a two-column timeline: years stacked at the left margin, release notes stacked from the centre line behind a short vertical rule. One text size, leading near 1.0, no decoration at all.\"\n   },\n   {\n    \"role\": \"gallery\",\n    \"description\": \"Dark full-viewport stage with a three-line cream headline at ~4vw placed dead centre. Around it eight or nine specimen artefacts (a stamp sheet, a green poster with a blue numeral, a grey flag chart, a rainbow ticket grid, concentric colour squares) are each rotated 10 to 30 degrees and arranged on a loose ring, several cropped by the viewport edge, as if tossed on a table.\"\n   },\n   {\n    \"role\": \"showcase\",\n    \"description\": \"Cream field. A caption row at the top: a two-line label at the left margin and a five-line paragraph starting at about 55% width. Then a full-width rule carrying a tiny label at each end naming the two cuts. Below it, two black lowercase letters, each roughly half the viewport wide and cropped by the bottom edge, one from each cut, so the reader compares shapes at poster scale.\"\n   }\n  ],\n  \"steal\": [\n   \"Give a product page a borrowed genre (here a tourist guidebook) and let that genre dictate titles, imagery and chapter names.\",\n   \"Cut a flat colour hero into bands with full-width hairlines and set the name at ~17vw in the bottom band beside a small inset film clip.\",\n   \"Scatter rotated print artefacts on a loose ring around a centred headline and let several crop off the viewport.\"\n  ],\n  \"media\": \"The hero is a red printed cover with paper grain; the real media is small, a 418x316 looping 1960s street clip at the bottom right (about 10% of the viewport) beside a wordmark filling about 60% of the width. Later: a postcard pair in the right half of a split, rotated ephemera orbiting a centred statement, full-bleed photo panels that slide up over the previous chapter, a spine accordion, and a full-bleed vintage photograph overscanned 72px each side; square corners, one video.\",\n  \"motion\": \"Black, then a turning seal of logo letters, then the cover by 4.5s; four hero groups rise 25px and fade over 400ms cubic-bezier(0.44,0,0.56,1) at 200ms steps, settling at about 5.5s though the page loaded in 2.5s. Lenis drives a chain of sticky full-screen chapters: ephemera fly off as a photo panel slides up, a headline steps through weights of the variable cut on scroll, and a single glyph rotates and zooms for about 5 screens; about 390 appear fades run over 400ms on a spring-shaped linear() curve, with no reduced-motion rule.\"\n },\n {\n  \"id\": \"aww-seasats\",\n  \"name\": \"Seasats\",\n  \"url\": \"https://www.seasats.com/\",\n  \"source\": \"Awwwards Site of the Day\",\n  \"kind\": \"physical-product\",\n  \"score\": 8.4,\n  \"idea\": \"Calm, dusk-lit seascapes sell autonomous boats as serene instruments, and the navigation is a column of stacked colour swatches taken from that sea-and-sand palette.\",\n  \"mood\": [\n   \"serene\",\n   \"cinematic\",\n   \"engineered\",\n   \"assured\"\n  ],\n  \"archetype\": \"fullbleed-media-overlay\",\n  \"hero\": \"A 10px white frame surrounds everything. The left 84% is one rounded media panel: a dusk scene of a low, solar-decked vessel centred on mirror-flat water, with two larger hulls cropped by the panel's left and right edges. The headline is centred in the panel's upper third, two lines of white light-weight flared serif at 124px (8.6vw). A wordmark in custom wide techno lettering sits top-left; a white rounded button with mono caps and a dark-green square arrow sits bottom-centre. The right 14% is the menu: a full-height column of stacked flat colour blocks (blush, sage, then four darkening olives), each holding left-aligned 15px links, sub-items numbered 01 to 04.\",\n  \"type\": \"seasonMix, a low-contrast serif-sans hybrid, light weight, sentence case, near-zero tracking, at 124px for the headline and about 40px for statements; seasonSans 16px for body and menu; supplyMono uppercase at 9 to 12px for buttons, tags and footer data.\",\n  \"colour\": \"#a6b3bc #232323 #b7c8be #d6c4b8 #2c3620 #e2832a — Slate blues and lilac greys from the seascapes dominate; the menu adds blush, sage and olive blocks; the footer flips to a burnt-orange and rust scene. Text stays white.\",\n  \"imagery\": \"Photoreal rendered footage of autonomous boats on glassy water at dusk: symmetrical, low horizon, lots of sky, full-bleed after the hero. Small square-cornered inset stills with mono tag labels float over the scene.\",\n  \"layout\": \"Mostly full-viewport scenes with one centred text block each, at top or bottom, and the wordmark fixed top-left. Only the hero uses the framed panel-plus-menu split. A thin vertical progress line runs down the right edge.\",\n  \"sections\": [\n   {\n    \"role\": \"features\",\n    \"description\": \"A pinned full-bleed scene shot from the boat's deck: the hull forms a dark symmetrical wedge rising from the bottom edge to a mast at centre, horizon at one-third. At top-centre six short statements are stacked, centred, at 16px; one is white and the others half opacity, and the highlight steps down the list on scroll. For each, small photo cards (150 to 220px wide, square corners, mono tag on the top edge) appear left and right of the mast.\"\n   },\n   {\n    \"role\": \"intro\",\n    \"description\": \"A full-bleed aerial view of dark teal water with several small vessels scattered across the lower half and a faint horizon near the top. A single two-line statement in the light serif at about 40px sits centred near the bottom edge. Nothing else is on screen except the wordmark top-left and the thin progress line at right.\"\n   },\n   {\n    \"role\": \"footer\",\n    \"description\": \"Colour inverts to a burnt-orange haze over rust-red terrain, with black silhouettes of hulls and a keel hanging from the top edge as if seen from below the surface. Mid-height: mono readouts at left reporting distance scrolled in metres and scroll speed in knots with a one-line quip; a link list at 16px in the centre; mono contact details at right. The wordmark fills the full width at the bottom, white, about 130px tall.\"\n   }\n  ],\n  \"steal\": [\n   \"Build the menu as a full-height column of stacked flat colour blocks sampled from the imagery, grouping links by block colour instead of by rules or headings.\",\n   \"List every claim at once, centred and dimmed, and move a single full-opacity highlight through the list on scroll while supporting images appear around a fixed subject.\",\n   \"Give the footer its own opposite-temperature scene and a live readout of how far and how fast the visitor scrolled, in the product's own units.\"\n  ],\n  \"media\": \"A dusk render of the vessel on still water, as a still, a 3s muted loop and a canvas layered together, fills an inset card at about 84% of the width beside a colour-band nav panel and goes full bleed once scrolled. Then a scroll-scrubbed frame sequence on a sticky stage with labelled photo cards floating at depth, small video thumbnails that grow into full-bleed chapter loops, a WebGL globe rising as a half-sphere from the bottom edge, and sticky product renders that turn with the scroll; 18 images, 6 videos, 8px corners on the hero frame and cards.\",\n  \"motion\": \"The preloader wordmark's seven letters slide up out of their masks at 50ms steps, the framed hero arrives at 1.2s and the title fades in softly, settling after about 5s, and smooth scroll then runs 34 sticky elements with no pins: the flythrough is a scrubbed image sequence, a fixed background layer changes the ground per chapter, and the nav collapses to a slim right-edge rail. Title characters rise on cubic-bezier(.215,.61,.355,1) (the house ease, 17 uses) with durations that shorten by 12ms per character, so the end of a word catches up with its start.\"\n },\n {\n  \"id\": \"aww-ai-in-design-report-2026\",\n  \"name\": \"Ai in Design Report 2026\",\n  \"url\": \"https://stateofaidesign.com/\",\n  \"source\": \"Awwwards Site of the Day\",\n  \"kind\": \"other\",\n  \"score\": 8.4,\n  \"idea\": \"A research report laid out like a colour-blocked print annual: a thermal-blurred video collage on top, an oversized tight grotesk title, and flat orange, lilac, sage and black blocks carrying stats, quotes and chapters.\",\n  \"mood\": [\n   \"editorial\",\n   \"bold\",\n   \"colour-blocked\",\n   \"assured\",\n   \"contemporary\"\n  ],\n  \"archetype\": \"editorial-masthead\",\n  \"hero\": \"The top 53% is a full-width video band: blurred, heat-map-like abstract footage in orange, lilac and sage, overlaid with four or five hard-edged rectangles of the same footage in grey or green, two tagged with tiny mono labels in white boxes. The header sits flush on top: a black logo block at far left, an orange link tab running to 40% of the width, two plain links at right. Below the band, on white: a two-line deck at about 1.4vw on a 1% left margin, and from 42% across a two-line title at 8.3vw, medium weight, tracking -0.06em. Bottom row: mono credit left, scroll cue and arrow aligned to the title column.\",\n  \"type\": \"Beausite Classic, a grotesk with some stroke contrast, in Medium for titles and Regular for text; sentence case, tracking -0.06em at display size. Geist Mono for small uppercase labels. Steps: 8.3vw title, about 5.5vw numerals, about 3vw statements, 16px body, 10px mono. Footer wordmark near 96vw.\",\n  \"colour\": \"#ffffff #000000 #fe7141 #cdabfe #d1ddd3 #f0ff1c — White base with flat blocks of orange, lilac, sage and black assigned to whole modules (stat tiles, quote panels, chapter bands), all drawn from the hero footage. Text is black, or off-white on black.\",\n  \"imagery\": \"Hero: abstract blurred video with a heat-map grade, cut into overlapping rectangles. Body: warm documentary photos and clips of people at desks in wood-lined rooms, square-cornered, butted directly against flat colour blocks with no gap.\",\n  \"layout\": \"1% margins and a recurring column line at about 42% where most headings and text begin. Open white text passages ruled by hairlines alternate with tight mosaics in which photos and colour blocks share edges. Each chapter opens with a full-width colour band.\",\n  \"sections\": [\n   {\n    \"role\": \"proof\",\n    \"description\": \"A full-width hairline, a tiny mono label at the left, then seven black partner logos evenly spaced across the full width in one row with generous padding above and below, closed by a second hairline. Immediately beneath, another mono label and a three-line statement at about 3vw, flush left and occupying only the left half, followed by a full-width photo strip.\"\n   },\n   {\n    \"role\": \"stats\",\n    \"description\": \"A mosaic with no gutters. A photo of two people at a laptop fills the left two-thirds at roughly 1:1; the right third is split into two stacked flat tiles, lilac above and sage below. Each tile carries a large numeral with a plus sign at about 5.5vw in its top-left corner and a two-line caption directly beneath; the rest of the tile is empty colour.\"\n   },\n   {\n    \"role\": \"testimonial\",\n    \"description\": \"Quote module as two abutting blocks: a black block on the left 40% holding only a small name and a mono role caption, and a sage block on the right 60% with the quotation at about 3vw, top-left aligned with empty sage beneath. Directly below, a full-width orange band opens a chapter: hairline at top, a large two-digit number with the chapter word under it at left, a two-line title and small paragraph starting at the 42% column.\"\n   },\n   {\n    \"role\": \"footer\",\n    \"description\": \"Black footer. A row of three small source counts along the top, separated by vertical hairlines, then the report name in off-white heavy type at nearly full viewport width with a trademark sign at its top-right, then the year at the same size right-aligned on a second line. Two small link columns with mono headings sit lower left beside the year; a hairline and one row of credits and partner logos close it.\"\n   }\n  ],\n  \"steal\": [\n   \"Start most headings and text at a fixed column line about 42% across, leaving the left for small decks, credits and chapter numbers.\",\n   \"Butt flat colour tiles directly against a photograph with no gutter and put one large numeral plus two caption lines in each tile's top-left corner.\",\n   \"Take the page's flat block colours from the hero footage so the abstract video and the layout read as one palette.\"\n  ],\n  \"media\": \"A video collage covers 100% of the screen at load and lifts to the top ~53% to uncover the title on white. Below, a documentary photograph two thirds wide in a sticky frame beside stacked colour stat blocks, a pinned deck of colour cards each with a 10s clip docked bottom-left, and a carousel of equal stills running off the right edge: 12 images and 6 muted videos, all square-cornered.\",\n  \"motion\": \"No preloader, but the collage re-cuts itself for about 4s before the title lands. Framer drives the sticky stacking (a 1350px photo frame and three 900px chapter cards that peel away to uncover the next); there is no split text, links change colour over .2s cubic-bezier(.44,0,.56,1), and one panel slides 610px in over 500ms cubic-bezier(0.44,0,0.37,1).\"\n },\n {\n  \"id\": \"aww-house-of-honey-1\",\n  \"name\": \"House of Honey\",\n  \"url\": \"https://www.houseofhoney.com/\",\n  \"source\": \"Awwwards Site of the Day\",\n  \"kind\": \"studio-portfolio\",\n  \"score\": 8.4,\n  \"idea\": \"A block-heavy wordmark pierced by a hairline script: the bold-against-delicate contrast is repeated at every scale, with giant pink script behind quiet serif statements.\",\n  \"mood\": [\n   \"glamorous\",\n   \"warm\",\n   \"playful\",\n   \"editorial\",\n   \"confident\"\n  ],\n  \"archetype\": \"giant-wordmark\",\n  \"hero\": \"Top 42% is a flat blush-pink band; the bottom 58% is a full-bleed photograph of a bright living room, arched window on the centre axis, butting against the band with no margin. A tiny nav row sits at the very top with 8px side margins: block logo glyph and five links left, contact link with a small square arrow box far right. The wordmark fills the width edge to edge: two words in ultra-black extended caps, about 120px cap height, dark aubergine, with a hairline script 'of' 230px tall between them, overshooting above and below. Directly beneath, two two-line serif uppercase taglines at 31px, one flush left, one flush right.\",\n  \"type\": \"Wordmark in ultra-black extended caps; statements in noeText serif, uppercase, 31–40px, tight tracking; nav and captions in neueHaasGrotesk around 14px; 'canora' hairline script for the connecting word and for cropped background words at 37vw. Three contrasting voices, each with one job.\",\n  \"colour\": \"#edccbe #331917 #0e0e0e #f26fcb #ffffff — Blush pink and dark aubergine-brown alternate as full fields and as each other's text colour. Hot pink appears only in the oversized script and a 2px divider. Photographs bring saturated colour.\",\n  \"imagery\": \"Editorial interior photography, saturated and daylight-lit. Hero is a full-bleed landscape crop; projects are portrait crops about 5:6 in a three-column grid with 4px gutters and square corners.\",\n  \"layout\": \"Edge-to-edge with 8px outer margins. Typographic sections (small centred label, serif statement, cropped giant script) alternate with a three-column image grid. Blush and brown fields swap each section; hairline link rows close blocks. The footer is a full-width logo glyph.\",\n  \"sections\": [\n   {\n    \"role\": \"intro\",\n    \"description\": \"Dark aubergine field under the hero photo, separated by a 2px hot-pink line. A small sans label centred, then a three-line centred serif uppercase statement at about 31px in blush, 45% of the width. Behind it a hot-pink script phrase set near 37vw runs off both sides and is cut by the section's bottom edge, its ascenders rising into the statement. A smaller serif line follows.\"\n   },\n   {\n    \"role\": \"other\",\n    \"description\": \"Title card before the project grid. Blush field, nearly empty screen. A small label and a one-line serif uppercase heading about 40px sit centred at 55% height. The giant pink script returns, cropped by the bottom edge so only its top half shows and running off both sides.\"\n   },\n   {\n    \"role\": \"work\",\n    \"description\": \"Three columns edge to edge with 4px gutters and 8px outer margins. Portrait photos about 500×580px, square corners. Under each: an uppercase sans title at 14px and a grey line of GPS coordinates. Two rows, then a full-width hairline row with a text link left and a small square arrow box at the far right.\"\n   },\n   {\n    \"role\": \"footer\",\n    \"description\": \"Brown field. The logo glyph is enlarged to full width and about a third of the screen: blush rectangles and quarter-circle arcs with 4px gaps, forming an abstract monogram. Below: four columns of small links, a hairline, two addresses in the first two columns, another hairline, then copyright left and a small blush button right.\"\n   }\n  ],\n  \"steal\": [\n   \"Set a wordmark edge to edge in ultra-heavy extended caps and thread a hairline script connecting word through it that overshoots the cap height both ways.\",\n   \"Use an oversized script word in one hot accent colour as a cropped background layer behind small, calm serif statements.\",\n   \"Split a tagline into two halves, flush left and flush right on the same baseline under the wordmark, instead of centring it.\"\n  ],\n  \"media\": \"The lower 58% of the fold is a full-bleed interior photograph that continues for one full viewport as a five-image crossfading slideshow with a pink progress line on its bottom edge. Below: a three-up grid of 4:5 project tiles with 8px gutters sliding over a giant script marquee, a full-bleed tinted feature photograph with its title docked bottom-left, a full-bleed photograph with an inset colour card, and one giant cropped letterform as the footer's picture, the photographs oversized to 110-170% of their frames for drift and no video anywhere.\",\n  \"motion\": \"There is no visible preloader and the page is whole at 400ms; under Lenis, blocks rise 8px and fade in over 800ms ease-out at 0-260ms staggers (39 WAAPI calls), slideshow crossfades take 600ms cubic-bezier(0.7,0,0.25,1), the oversized photographs drift, and script marquees run on CSS time (90-122s per pair). Page changes use a 1s view transition on the same curve; nothing pins, and there is one reduced-motion rule.\"\n },\n {\n  \"id\": \"aww-white-desert\",\n  \"name\": \"White Desert\",\n  \"url\": \"https://white-desert.com/\",\n  \"source\": \"Awwwards Site of the Day\",\n  \"kind\": \"hospitality\",\n  \"score\": 8.4,\n  \"idea\": \"One word, the destination, set a third of the screen tall over footage like a film title card; sheer scale stands in for remoteness.\",\n  \"mood\": [\n   \"cinematic\",\n   \"epic\",\n   \"luxurious\",\n   \"cold\",\n   \"restrained\"\n  ],\n  \"archetype\": \"bottom-anchored-type\",\n  \"hero\": \"Full-bleed video (the view from an aircraft window over an ice shelf, darkly vignetted by the window frame) fills the viewport. Faint vertical hairlines divide it into six columns. Top-left, three outlined rectangular nav buttons about 120 by 40px with 6px gaps; top-right, two more; between them a small white mountain logo over a condensed caps name. One condensed uppercase word spans almost the full width at 17.8vw, white, centred, anchored so its baseline sits about 35px above the bottom edge. At mid-height a two-line italic serif tagline at about 16px hangs on the first column line at left, and a film-play label sits between two hairlines at right.\",\n  \"type\": \"Three voices: Oswald 400 uppercase for the giant word and footer wordmark (up to 22vw); Cardinal Classic Long, a light high-contrast serif, for caps statements near 32px and italic taglines; Inter Tight 14px for nav and body. Body to display is roughly an 18x jump.\",\n  \"colour\": \"#040608 #ffffff #e9e7e1 #1f2b4d #f5821f #95979a — Footage and near-black open the page; content sections flip to pure white with navy serif type and end on a warm grey footer. One small orange tab is the only accent. Cool overall.\",\n  \"imagery\": \"Aerial and wildlife footage and stills of ice, penguins and rust-coloured rock peaks, natural cool grade, always full-bleed with square corners; trips appear as tall vertical image slices set side by side with no gaps.\",\n  \"layout\": \"A six-column grid made visible by faint full-height hairlines runs through every section. Text blocks are small and hung off column lines, often starting at column two or three, with large voids around them. Full-bleed image screens alternate with nearly empty white text screens.\",\n  \"sections\": [\n   {\n    \"role\": \"intro\",\n    \"description\": \"A white screen with the six vertical hairlines still showing. A serif caps paragraph at about 32px, navy, light weight and tight leading, occupies only columns two to four, left-aligned with its first line indented by half the measure. Above its top-left sits a small italic label ringed by a loose hand-drawn pen scribble. An orange vertical tab with rotated text is fixed to the right edge.\"\n   },\n   {\n    \"role\": \"gallery\",\n    \"description\": \"Leaving the hero, the giant word blurs and dissolves into white mist that becomes the next section's background. Later a full-viewport photograph of jagged rock peaks in snow bleeds to all four edges, with a narrow 13px paragraph from the white section above overlapping its top edge at a column line, so text and image interlock rather than stack.\"\n   },\n   {\n    \"role\": \"showcase\",\n    \"description\": \"A serif caps heading at about 40px sits left of centre with a long pencil-like scribble underline that extends well past the words on both sides. Below, a full-width band of four vertical image panels with no gaps and unequal widths, like an accordion; the first panel carries a two-line italic serif title in white at its top-left.\"\n   },\n   {\n    \"role\": \"footer\",\n    \"description\": \"Warm grey field. The top row holds a small logo, three columns of grey link lists with italic serif group headings and, at right, a stack of square-cornered off-white tiles (a video thumbnail, two half-width buttons, one full-width). Beneath, the brand name in navy condensed caps runs edge to edge at about 22vw. A final strip has award badges left, a centred italic quotation and legal links right.\"\n   }\n  ],\n  \"steal\": [\n   \"Set a single place name in condensed caps at about 18vw, centred and anchored to the bottom edge of full-bleed footage, with everything else on screen at 14-16px.\",\n   \"Leave the column grid visible as faint full-height hairlines across video, white and footer sections, and hang small text blocks off those lines.\",\n   \"Ring or underline small serif labels with a loose hand-drawn pen scribble to put one human mark into an otherwise strict layout.\"\n  ],\n  \"media\": \"An 18s muted aerial and ice-cave clip covers the whole first screen under a scrim, with the title docked along the bottom edge. Later pictures dissolve into the white page through fog-like fades, a horizontal accordion opens one trip panel at half width beside blurred slivers, vertical ice strips wipe across the previous photograph, and a long pinned track of inset cards floats on a full-bleed texture ground before a closing photo panel carrying a quotation; 20 images, one video, square corners and a high-key cold grade.\",\n  \"motion\": \"There is no entrance choreography and footage plays from the first frame; under Lenis the hero title blurs and is swallowed by a sticky fog layer growing from 390 to 900px tall, statement lines fill from grey to navy, the camps heading scrubs from 140px down to 60px, and a pinned horizontal track moves the cards at about 0.56px per scrolled pixel over an 8,328px runway. Blocks rise 20rem with opacity over 1.4s cubic-bezier(.16,1,.3,1), and hovers run .3s cubic-bezier(.5,1,.89,1).\"\n },\n {\n  \"id\": \"opl-applied-imagination\",\n  \"name\": \"Applied Imagination\",\n  \"url\": \"https://applied-imagination.gpc.consulting\",\n  \"source\": \"One Page Love\",\n  \"kind\": \"other\",\n  \"score\": 8.3,\n  \"idea\": \"An essay conceived on a flight is read as a descent: an altimeter ticks from 30,000 ft to zero while you scroll down through halftone clouds to mountains at ground level.\",\n  \"mood\": [\n   \"airy\",\n   \"witty\",\n   \"editorial\",\n   \"dreamlike\"\n  ],\n  \"archetype\": \"type-poster\",\n  \"hero\": \"A pale blue sky fading to warm cream fills the viewport, with white clouds shaded in halftone dots. A tiny serif logotype sits top-centre; no nav. The title, two centred lines of black wedge-serif at 8.9vw, occupies the middle half of the screen and about 73% of its width; a cloud layer passes in front of the second line's baseline so the feet of the letters dissolve into dots. A two-line centred deck at 24px sits beneath. A mono byline strip is centred on the bottom edge with a scroll cue bottom-right. On the left edge at mid-height, a short vertical rule carries a two-line mono altitude readout.\",\n  \"type\": \"fsKim, a sturdy wedge-serif display face, regular weight at 128px with -0.01em tracking for the title and pull quotes; gtAmerica at 24px for the deck and about 16px for essay body; gtAmericaMono uppercase around 11px with wide tracking for byline, altitude and tape labels.\",\n  \"colour\": \"#cbe4f2 #f1e3b5 #0a0a0a #ffc013 #8e2f8f #f04e23 — Sky blue melting into sand yellow is the constant ground and text is black. Saturated magenta, orange and yellow arrive only in collage objects, tape labels and the footer contact card.\",\n  \"imagery\": \"Photo-collage cut-outs (parachutes carrying a treasure chest and a burning dumpster, a pair of legs, mountains) given a coarse halftone dot screen, layered in front of and behind the type against painted clouds.\",\n  \"layout\": \"A narrow text column about 38% wide for essay passages, interrupted by full-width display pull quotes and collage objects floating at the edges. One continuous sky instead of sections, with a fixed left-edge altimeter. Nearly 23 screens, ending on a ground-level landscape.\",\n  \"sections\": [\n   {\n    \"role\": \"intro\",\n    \"description\": \"Sky background, no container. A three-line pull quote in black wedge-serif at about 7vw is centred and tightly leaded. Two cut-out parachutes hang over it: a magenta one from the top-left carrying a chest spilling coins, an orange one at lower right carrying a burning dumpster, each overlapping letterforms. Small mono labels on tilted strips of coloured tape are stuck to the objects. Words in the quote turn from grey to black as they are reached.\"\n   },\n   {\n    \"role\": \"other\",\n    \"description\": \"Running essay text in about 16px grotesk, black, in a single column roughly 38% of the viewport wide, positioned left of centre with large sky margins on both sides. Paragraphs are separated by a blank line; serif sub-statements at about 28px introduce passages. The next display quote is seen rising from below, its letters partly hidden behind cloud and blurred.\"\n   },\n   {\n    \"role\": \"contact\",\n    \"description\": \"Ground level: halftone-screened mountains in green and brown rise from both sides, and the title returns at huge scale, cropped by the top edge and tucked behind the peaks. Centred below is a square-cornered two-panel card: a cream left panel with a short form of two fields and a small orange button, and a magenta right panel with a round portrait, name and a yellow subscribe button. Yellow tape-strip credits sit on the bottom edge.\"\n   }\n  ],\n  \"steal\": [\n   \"Tie a persistent numeric readout to scroll position (altitude falling to zero) so the reader's progress becomes part of the story.\",\n   \"Layer an illustration element in front of the bottom of a giant title so the letters sink into the scene instead of sitting on top.\",\n   \"Apply one coarse halftone dot screen to every photo cut-out so collage pieces from different sources read as one illustration set.\"\n  ]\n },\n {\n  \"id\": \"opl-compile\",\n  \"name\": \"Cursor Compile\",\n  \"url\": \"https://cursor.com/compile\",\n  \"source\": \"One Page Love\",\n  \"kind\": \"event\",\n  \"score\": 8.3,\n  \"idea\": \"The event name drawn as seven looping one-line curves in seven colours, more signature than logotype, on an otherwise whisper-quiet off-white page whose images are re-rendered as rows of coloured characters.\",\n  \"mood\": [\n   \"quiet\",\n   \"hand-drawn\",\n   \"warm\",\n   \"technical\",\n   \"restrained\"\n  ],\n  \"archetype\": \"giant-wordmark\",\n  \"hero\": \"Warm off-white field with no header or navigation. Starting about 23% down, a line-drawn wordmark spans from 8% to 92% of the width and about 29% of the height: each letter is a single 2px stroke looping like a Lissajous figure, each in a different colour (orange, green, olive, lilac, black, brown, blue), overlapping its neighbours. Directly beneath, two 14px captions, one flush left in ink and one flush right in grey. After a gap of about 20% of the viewport, three equal columns sit at the bottom, each topped by a hairline: an 18px statement, a grey 14px paragraph, and an email field over a full-width near-black rectangular button.\",\n  \"type\": \"The only large lettering is the drawn wordmark. All real text is CursorGothic regular in two sizes, 18px and 14px (the largest text on the page is 1.8vw), sentence case, with hierarchy made by ink versus mid-grey rather than by size or weight.\",\n  \"colour\": \"#edece8 #26251e #f07a1f #2e9e3a #2f6bf0 #9b8ff0 — Warm paper ground with near-black and grey text. The wordmark's colours return one at a time as the single ink of each character-rendered image (lilac, teal, green, orange). Event photos are dark and warm.\",\n  \"imagery\": \"Two kinds: landmarks and speaker portraits redrawn as rows of tiny characters in one saturated colour on a tint of the same colour; and dark, warm documentary event photos. All are square-cornered rectangles in strict rows.\",\n  \"layout\": \"About 7% side margins on a three-column grid. Each section has a small two-line heading at left (title in ink, subtitle in grey), then a row or carousel of equal tiles with one-line captions beneath. Very large vertical gaps between sections; a denser photo grid near the end.\",\n  \"sections\": [\n   {\n    \"role\": \"list\",\n    \"description\": \"Tour dates as a three-column grid of 3:2 tiles. Each tile is a city landmark rendered entirely in rows of small characters in one colour on a pale tint of that colour: lilac, teal, green, orange. Under each tile, one caption line: city name in ink, date in grey straight after it, and a status word flush right. A fourth tile wraps alone to the left of a second row, leaving two columns empty.\"\n   },\n   {\n    \"role\": \"gallery\",\n    \"description\": \"Session recordings as stacked carousels. A small heading and grey subtitle, then per stage a tiny label at left with two arrow glyphs at far right and a row of 16:9 dark photo tiles, two full tiles visible and a third cropped by the margin. Each tile has a small white event tag in its bottom-left corner. Caption beneath: speaker name in ink followed by the talk title in grey on the same line.\"\n   },\n   {\n    \"role\": \"about\",\n    \"description\": \"Speaker row: one-line heading at left, arrows at right, then four near-square portrait tiles with 8px gaps, each a face drawn in horizontal rows of characters in one colour on its tint (orange, green, lilac, teal). Some tiles show only plain stripes with the face barely emerging, so portraits appear to resolve from lines as they load or on hover.\"\n   },\n   {\n    \"role\": \"cta\",\n    \"description\": \"After a three-column photo grid with mixed landscape and portrait crops and 8px gaps, the page ends on an empty off-white screen holding one centred sentence at 18px and a small dark pill button beneath it. There are no footer columns, links or legal rows.\"\n   }\n  ],\n  \"steal\": [\n   \"Draw the name as one continuous thin looping stroke per letter, each in a different colour, and let it be the only large element on the page.\",\n   \"Keep all text at two small sizes and build hierarchy from ink versus grey on the same line (name in ink, detail in grey right after it).\",\n   \"Re-render photographs as rows of tiny characters in a single saturated colour on a tint of that colour, one colour per tile.\"\n  ]\n },\n {\n  \"id\": \"opl-the-new-industrials\",\n  \"name\": \"The New Industrials\",\n  \"url\": \"https://thenewindustrials.com/\",\n  \"source\": \"One Page Love\",\n  \"kind\": \"other\",\n  \"score\": 8.3,\n  \"idea\": \"A long-read essay laid out inside a visible drafting grid, where colour fields shift as you read and 3D machine parts drift through the margins and finally assemble into the publisher's initials.\",\n  \"mood\": [\n   \"bold\",\n   \"playful\",\n   \"editorial\",\n   \"engineered\",\n   \"saturated\"\n  ],\n  \"archetype\": \"editorial-masthead\",\n  \"hero\": \"A saturated orange page framed by black hairlines 24px from each edge. Top strip: a monogram logo left, a black pill with orange monospaced title centred, a boxed year right. Under it a row of eight empty outlined cells, 62px tall, like a ruler. A cream panel then fills the remaining width and height. Inside, a WebGL scene of pastel low-poly machine parts with visible wireframes sits behind a two-line uppercase title in a tall condensed slab serif, glyphs about 210px high, spanning 83% of the width. Small monospaced uppercase credits flank it at mid-height; reading time is centred below, with two boxed share links on the bottom edge.\",\n  \"type\": \"Title in a tall condensed slab serif at roughly 14vw cap height, black, uppercase. Essay in Albra Book serif: 34px lead paragraph, 18px running text with generous leading. Supply Mono in tiny uppercase for credits and box labels; a narrow typewriter-like face for the pull quote.\",\n  \"colour\": \"#ff8126 #f1ead8 #161615 #4db3ff #c5f53d #ff5fc0 — The page background changes as you read: orange, then a gradient through lilac into sky blue, then acid lime at the end. Type and hairlines stay black; the 3D parts carry rainbow gradients.\",\n  \"imagery\": \"Real-time 3D machine components (cylinders, gears, polyhedra) in matte pastel with coloured wireframe edges and neon gradient caps; they overlap the title, float into text margins and form letters in the footer.\",\n  \"layout\": \"Black hairlines divide the whole page into cells: one wide text cell flanked by narrow empty ones, each chapter tagged with a small numbered box at its corner. The lead paragraph spans the cell, running text is indented into a narrower column, and full-width quote screens interrupt.\",\n  \"sections\": [\n   {\n    \"role\": \"intro\",\n    \"description\": \"On orange, a ruled cell with a small numbered square at its top-right corner. The opening paragraph is set in serif at about 34px, seven lines, filling the cell with 60px padding. A horizontal hairline closes the cell; the next one indents its text by about 180px and drops to 18px, with a vertical rule marking the indent. The side cells stay empty, so the grid reads as margin furniture.\"\n   },\n   {\n    \"role\": \"other\",\n    \"description\": \"Pull quote: a full-viewport interruption where the grid lines stop. The background becomes a vertical gradient from orange through dusty lilac to sky blue. Centred, five lines of a narrow, widely tracked typewriter-style face at about 48px in dark olive-brown, each letter trailing a soft red vertical smear downward like wet ink. The next cell resumes on the blue that the gradient ended on.\"\n   },\n   {\n    \"role\": \"other\",\n    \"description\": \"Body screens: a single serif column about 960px wide between two vertical hairlines, paragraphs separated by a blank line. One 3D object per screen (a grey-green polyhedron with green edges, an orange hexagonal nut) sits half outside the column, crossing the vertical rule and the page edge at a different height each time, so every screen of text has one sculptural interruption.\"\n   },\n   {\n    \"role\": \"footer\",\n    \"description\": \"Acid-lime field. The publisher's three initials are built as a sculpture from the 3D parts seen earlier, about 60% of the viewport tall and spanning nearly the full width, each letter a different assembly of pipes, gears and blocks in clashing gradients. Below, hairlines form two cells holding monospaced uppercase credits at 10px, aligned to the cells' left padding.\"\n   }\n  ],\n  \"steal\": [\n   \"Draw the layout grid as visible black hairlines, including a row of empty cells, and tag each text block with a small numbered box.\",\n   \"Change the page background colour between chapters of a long read so progress is felt as a shift of colour.\",\n   \"Let one family of 3D objects recur at three scales: behind the title, in the margins, and assembled into a monogram at the end.\"\n  ]\n },\n {\n  \"id\": \"opl-wild-as\",\n  \"name\": \"wild\",\n  \"url\": \"https://craft.wild.as\",\n  \"source\": \"One Page Love\",\n  \"kind\": \"agency\",\n  \"score\": 8.3,\n  \"idea\": \"A studio essay on craft versus AI in which everything decorative is drawn on one square-pixel grid: the hero heatmap, the icons, the diagrams, the marquee lettering and the footer equaliser.\",\n  \"mood\": [\n   \"precise\",\n   \"playful\",\n   \"technical\",\n   \"bright\",\n   \"editorial\"\n  ],\n  \"archetype\": \"editorial-masthead\",\n  \"hero\": \"White page with a barely visible graph-paper grid. The top 22% is a masthead band split by a vertical hairline at 60%: at left, a two-line uppercase headline in a light grotesk at 5.2vw, tight leading, starting 9% from the left and nearly touching the top edge; at right, a two-line uppercase tagline with words spread to justify the column, then a pixel logo and a small right-aligned description. Below, a full-bleed canvas about 45% of the viewport tall: thousands of small squares in yellow, red, lime, cobalt and navy form a heatmap that erodes into white along its lower edge. A 3vw intro paragraph begins at the fold.\",\n  \"type\": \"Sneak in one regular-to-light weight does everything: uppercase 75px headline at -0.035em, a 44px sentence-case intro, section headings near 30px, 13px body. Tiny SF Mono uppercase captions with wide tracking sit under headings. A bitmap pixel face appears once, in the closing marquee. No bold anywhere.\",\n  \"colour\": \"#ffffff #0a0a0a #f2b90f #3b55d9 #1e2340 #e8452c — White page, black type, black buttons. Colour lives only inside the pixel graphics, in a fixed set of yellow, cobalt, navy, red and lime, so every illustration looks related. No section changes background.\",\n  \"imagery\": \"Canvas-drawn square-pixel fields: a heatmap band, particle streams that tighten from scattered dots into a dense ribbon, pixel smiley faces, an equaliser strip. Client work appears once, as three plain square-cornered photo cards.\",\n  \"layout\": \"Content runs from 9% to 91% with a constant split: heading in the left third, body in the right two-thirds, a tiny mono caption under the heading. Full-bleed pixel canvases interrupt the text. A small fixed mono link sits top-right; the ending is centred.\",\n  \"sections\": [\n   {\n    \"role\": \"work\",\n    \"description\": \"Three equal cards in one row, each a 6:5 image with square corners (laptop mock-up, product photo, flat illustration) followed by a centred project name at about 20px and a centred two-line description in small text. No borders, shadows or tags; a small round black arrow button overlaps the right edge of the third image to advance the row. Large white space above and below.\"\n   },\n   {\n    \"role\": \"intro\",\n    \"description\": \"Essay rows: a two- or three-line heading at about 2.2vw in the left third with a tiny wide-tracked mono caption below it; in the right two-thirds, two short justified paragraphs at 13px. Under one row, two pixel-art faces built from black squares (a smile and a frown, about 30px) sit side by side, each over a mono label and a three-line centred caption, forming a two-column comparison.\"\n   },\n   {\n    \"role\": \"how-it-works\",\n    \"description\": \"A four-word heading on two lines and a short paragraph at the left, then a wide canvas diagram: scattered pale-blue and navy squares at the left converge into a tight horizontal ribbon in the middle and fan out again in yellow at the right, a pixel funnel. Below it four narrow columns, each with a small round dark marker, a bold one-word label and two lines of small text.\"\n   },\n   {\n    \"role\": \"cta\",\n    \"description\": \"A single line of bitmap lettering scrolls across the full width, each glyph assembled from yellow squares flecked with red, navy and lime. Centred beneath: a black button with stepped pixel corners, two short grey centred paragraphs and an email line. The page ends with a full-width strip of coloured pixel bars like an audio equaliser, a small black play button centred above it.\"\n   }\n  ],\n  \"steal\": [\n   \"Pick one drawing primitive, a square on a fixed grid, and render every non-text element with it (hero art, icons, diagrams, display lettering, footer) in one five-colour set.\",\n   \"Split a masthead band 60/40 with a vertical hairline: oversized light-weight uppercase headline at left, a word-spaced justified tagline and tiny descriptor at right.\",\n   \"Lay out long copy as rows with the heading in the left third and body in the right two-thirds, and put the tiny mono caption under each heading instead of an eyebrow above it.\"\n  ]\n },\n {\n  \"id\": \"aww-hilden-kaira\",\n  \"name\": \"Hildén & Kaira\",\n  \"url\": \"https://www.hildenkaira.fi/\",\n  \"source\": \"Awwwards Site of the Day\",\n  \"kind\": \"agency\",\n  \"score\": 8.3,\n  \"idea\": \"The agency name is cast in liquid chrome across the full width, and the same chrome becomes emoji that float through the page, tying a social-media pitch to one material.\",\n  \"mood\": [\n   \"brash\",\n   \"glossy\",\n   \"editorial\",\n   \"witty\"\n  ],\n  \"archetype\": \"giant-wordmark\",\n  \"hero\": \"Warm light-grey field. The lowercase serif wordmark, rendered as polished chrome 3D letters with a molten ampersand, runs edge to edge across the top quarter (about 220px tall, 16px side margins). A tilted portrait video roughly 180 by 220px covers two of its letters. Directly under the wordmark, four small nav links centred. Then 300px of nothing, with one chrome flame emoji floating at the far left. The headline sits in the bottom third: three centred lines of narrow display serif at 4.4vw, leading so tight that descenders touch ascenders, a two-line 15px sans sub, and two square-cornered buttons, black and pale lime.\",\n  \"type\": \"PP Editorial New 400 for headlines at 63px, -0.02em tracking and leading near 0.9; PP Neue Montreal 13px for nav, body and buttons. The jump is roughly 5:1 with nothing in between. Stat numerals use the sans at about 60px.\",\n  \"colour\": \"#eae9e6 #181818 #ecfdad #b5b5b5 #ffffff #3aa57a — Warm grey and near-black alternate by section. Pale lime is the single accent: secondary buttons, headline text on dark, stat tiles and service cards. Chrome silver recurs as a material.\",\n  \"imagery\": \"Chrome 3D-rendered lettering and emoji objects (flame, heart, dove, microphone, wink) floating free; vertical phone videos of client content shown as fanned, slightly rotated stacks with white borders. Square corners throughout.\",\n  \"layout\": \"Centred statements with large voids, alternating light and dark full-width bands. Content arrives as square-cornered slabs: a white case card on grey, lime service cards stacking over each other on black. Chrome objects break the grid at the edges.\",\n  \"sections\": [\n   {\n    \"role\": \"testimonial\",\n    \"description\": \"Full-viewport near-black band. A two-line centred serif statement in pale lime at about 4vw sits in the upper third with nothing near it. Two small testimonials are pushed to the bottom-left and bottom-right corners: five tiny stars, two lines of 11px sans, name and title, each centred in its own narrow block. The centre bottom is left empty.\"\n   },\n   {\n    \"role\": \"work\",\n    \"description\": \"Horizontal carousel of wide white slabs on the grey ground, the next slide peeking at the right edge. Left half: a two-line serif title top-left, then far below a red-dot label over a thin rule and two flat tiles side by side, a wide lime one and a narrower brushed-chrome one, each with a tiny caption and a 60px sans numeral. Right half: a grey panel with three vertical videos fanned like playing cards.\"\n   },\n   {\n    \"role\": \"features\",\n    \"description\": \"On black, a centred serif section title, then service cards that pin and stack: a lime slab about 55% wide with serif title top-left, grey serif index number top-right, a small paragraph and black button bottom-left and a vertical video inset bottom-right. White and green slabs peek out beneath it, offset downward, and the top card tilts a degree or two as it scrolls.\"\n   },\n   {\n    \"role\": \"footer\",\n    \"description\": \"A full brushed-silver gradient field. The chrome wordmark repeats at full width across the top. Bottom-left, a small serif label over two short link columns; bottom-right, two square translucent tiles each holding a chrome object (microphone, heart) with a serif label above and three tiny square social buttons below. A hairline and a legal row close it.\"\n   }\n  ],\n  \"steal\": [\n   \"Render the wordmark in one physical material and reuse that material for small floating objects, so decoration and logo are the same thing.\",\n   \"Leave a third of the hero empty between a top-edge wordmark and a bottom-third headline; the gap makes both read.\",\n   \"Set a display serif with leading under 1.0 so lines interlock, and pair it with 13px sans for everything else.\"\n  ]\n },\n {\n  \"id\": \"aww-px-push\",\n  \"name\": \"PX PUSH\",\n  \"url\": \"https://pxpush.com/\",\n  \"source\": \"Awwwards Site of the Day\",\n  \"kind\": \"agency\",\n  \"score\": 8.2,\n  \"idea\": \"A design subscription presented as a retro broadcast: the entire site is seen through a CRT screen, with a chrome logo token floating in the sky as its mascot.\",\n  \"mood\": [\n   \"retro-futurist\",\n   \"cool\",\n   \"technical\",\n   \"cinematic\",\n   \"confident\"\n  ],\n  \"archetype\": \"product-object-centre\",\n  \"hero\": \"Full-bleed photograph of deep-blue sky over a cloud bank, the whole viewport under a CRT treatment: horizontal scanlines, slight blur, dark vignette with rounded corners. Top row with 43px margins: thin techno wordmark left; three links and a start link with a green dot right, split by a vertical hairline; full-width hairline beneath. Then one marquee line at 12vw (173px) in off-white grotesk, cropped at both edges, words separated by a solid dot, closed by a second hairline. Dead centre: a chrome 3D ring token about 400px wide. Bottom-left: a 216×144px royal-blue rounded thumbnail with a two-line mono caption. Bottom-right: a four-line mono uppercase paragraph 450px wide.\",\n  \"type\": \"A semi-condensed grotesk (digest name 'SemiSqueezed') at regular weight carries the 173px marquee, 28px paragraphs and 5vw statements; an uppercase monospace at 11–17px handles tags, captions and link rows. Ten-to-one jump between display and labels; no bold anywhere.\",\n  \"colour\": \"#03049c #71737d #1a1a1a #788ca4 #d9dde6 #c8f31d — Each section is a full colour field: sky photo, mid grey, near-black, then saturated royal blue. Text is off-white or pale lavender; acid lime appears only in small thumbnails, green only as a status dot.\",\n  \"imagery\": \"Sky photograph, a chrome 3D logo token, and client work shown as phone UIs on a blue ground and a poster photographed in a street lightbox. Everything sits under the same scanline filter; tiles have small radii.\",\n  \"layout\": \"A narrow left rail (about 17% wide) carries a bullet, a mono section tag and a small pinne\n\n<!-- [TRUNCATED AT 50KB] -->","isInternal":false,"tokens":12426,"sizeBytes":50059},{"name":"type.json","path":"skills/taste-skill/library/type.json","rawUrl":"https://raw.githubusercontent.com/Leonxlnx/taste-skill/HEAD/skills/taste-skill/library/type.json","title":"Library Skill","category":"anthropic-skill","format":"json","content":"[\n {\n  \"id\": \"switzer-semibold\",\n  \"name\": \"Switzer\",\n  \"class\": \"grotesk-tight\",\n  \"display\": {\n   \"family\": \"Switzer\",\n   \"source\": \"fontshare\",\n   \"slug\": \"switzer\",\n   \"weights\": [\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 600 · tracking -0.04em · leading 0.95 · sentence case; charcoal rather than pure black\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=switzer@400,500,600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Switzer\",\n   \"source\": \"fontshare\",\n   \"slug\": \"switzer\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking -0.005em\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=switzer@400,500,600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Suisse Intl\",\n   \"Neue Haas Grotesk\"\n  ],\n  \"note\": \"One neo-grotesk doing everything: semibold headings pulled tight, small regular text, no capitals and no second voice. Suits software, hardware and studio pages that want to look exact and unshowy.\",\n  \"seenIn\": [\n   \"aww-noho\",\n   \"opl-vessa\",\n   \"aww-aspen-search\",\n   \"opl-rows\"\n  ],\n  \"links\": [\n   \"https://api.fontshare.com/v2/css?f[]=switzer@400,500,600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"general-sans-bold\",\n  \"name\": \"General Sans\",\n  \"class\": \"grotesk-tight\",\n  \"display\": {\n   \"family\": \"General Sans\",\n   \"source\": \"fontshare\",\n   \"slug\": \"general-sans\",\n   \"weights\": [\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 700 · tracking -0.02em · leading 0.9 · sentence case; sizes jump straight from 16px text to 10vw and larger\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=general-sans@400,500,700&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"General Sans\",\n   \"source\": \"fontshare\",\n   \"slug\": \"general-sans\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body and lists, 500 for emphasis · leading 1.45 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=general-sans@400,500,700&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"PP Neue Montreal\",\n   \"Aeonik\"\n  ],\n  \"note\": \"A grotesk with slightly geometric bowls, set bold and very large against plain 16px text with nothing in between. Suits studios, type and product launches, and finance or tech brands that lead with the name.\",\n  \"seenIn\": [\n   \"aww-pp-neue-montreal\",\n   \"aww-moto-finance\",\n   \"opl-brikkenco\",\n   \"aww-nothin\"\n  ],\n  \"links\": [\n   \"https://api.fontshare.com/v2/css?f[]=general-sans@400,500,700&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"schibsted-heavy\",\n  \"name\": \"Schibsted Grotesk\",\n  \"class\": \"grotesk-tight\",\n  \"display\": {\n   \"family\": \"Schibsted Grotesk\",\n   \"source\": \"google\",\n   \"weights\": [\n    800\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 800 · tracking -0.05em · leading 0.88 · sentence case or all lowercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Schibsted+Grotesk:wght@400;600;800&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Schibsted Grotesk\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for paragraphs, 600 for navigation and other functional text · leading 1.4 · tracking -0.01em\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Schibsted+Grotesk:wght@400;600;800&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"ABC Diatype\",\n   \"Khteka\"\n  ],\n  \"note\": \"A compact, warm grotesk set heavy with letters almost touching; small text stays in the same family at semibold. Suits music, events and culture pages where the type is the image.\",\n  \"seenIn\": [\n   \"aww-paul-kalkbrenner\",\n   \"opl-rendez-vous-franceclat\",\n   \"aww-monolog\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Schibsted+Grotesk:wght@400;600;800&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"hanken-medium\",\n  \"name\": \"Hanken Grotesk\",\n  \"class\": \"grotesk-tight\",\n  \"display\": {\n   \"family\": \"Hanken Grotesk\",\n   \"source\": \"google\",\n   \"weights\": [\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 500 · tracking -0.05em · leading 0.9 · sentence case; one statement size (about 6vw) used for every heading\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Hanken+Grotesk:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Hanken Grotesk\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.45 · tracking -0.005em\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Hanken+Grotesk:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Akzidenz Grotesk\",\n   \"LayGrotesk\"\n  ],\n  \"note\": \"Medium-weight grotesk statements at one large size against caption-size text: a two-size system with no bold. Suits portfolios, agencies and tools that speak in short declarative lines.\",\n  \"seenIn\": [\n   \"aww-bleibtgleich26\",\n   \"aww-made-with-gsap-1\",\n   \"opl-locker-land\",\n   \"opl-builders-table\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Hanken+Grotesk:wght@400;500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"bricolage-contrast\",\n  \"name\": \"Bricolage Grotesque\",\n  \"class\": \"grotesk-tight\",\n  \"display\": {\n   \"family\": \"Bricolage Grotesque\",\n   \"source\": \"google\",\n   \"weights\": [\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 600 · tracking -0.04em · leading 0.92 · sentence case; leave optical sizing on so large sizes tighten and gain contrast\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:wght@400;500;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Bricolage Grotesque\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:wght@400;500;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Beausite Classic\",\n   \"F37 Analog\"\n  ],\n  \"note\": \"A grotesk with visible stroke contrast and slightly irregular curves, so headings look drawn rather than engineered. Suits reports, consultancies and design-led software that want warmth without a serif.\",\n  \"seenIn\": [\n   \"aww-ai-in-design-report-2026\",\n   \"aww-illoca\",\n   \"opl-ohhmydesign\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:wght@400;500;600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"franklin-source\",\n  \"name\": \"Libre Franklin / Source Serif 4\",\n  \"class\": \"grotesk-tight\",\n  \"display\": {\n   \"family\": \"Libre Franklin\",\n   \"source\": \"google\",\n   \"weights\": [\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 700 · tracking -0.035em · leading 0.92 · uppercase for the title, sentence case for section headings\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Libre+Franklin:wght@700&family=Source+Serif+4:ital,wght@0,400;0,600;1,400;1,600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Source Serif 4\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    600\n   ],\n   \"italic\": true,\n   \"settings\": \"400 for body, 600 for emphasis, italic for quotations · leading 1.55 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Libre+Franklin:wght@700&family=Source+Serif+4:ital,wght@0,400;0,600;1,400;1,600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Founders Grotesk\",\n   \"Die Grotesk\",\n   \"NON Natural Grotesk\"\n  ],\n  \"note\": \"An American gothic for headings over a sober transitional serif for reading, the pairing of a newspaper front page. Suits essays, annual reports, archives and finance pages that have real paragraphs.\",\n  \"seenIn\": [\n   \"aww-dragonfly-redux\",\n   \"aww-trevor-noah\",\n   \"aww-mosbys-files\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Libre+Franklin:wght@700&family=Source+Serif+4:ital,wght@0,400;0,600;1,400;1,600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"switzer-roman\",\n  \"name\": \"Switzer\",\n  \"class\": \"grotesk-light\",\n  \"display\": {\n   \"family\": \"Switzer\",\n   \"source\": \"fontshare\",\n   \"slug\": \"switzer\",\n   \"weights\": [\n    400\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 400 · tracking -0.03em · leading 1.1 · sentence case; headings stay small (28–40px) and at most one line jumps to 5vw\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=switzer@400,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Switzer\",\n   \"source\": \"fontshare\",\n   \"slug\": \"switzer\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for everything, 500 only for names and links · leading 1.45 · tracking -0.01em; hierarchy by ink against mid-grey\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=switzer@400,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Neue Haas Grotesk 55 Roman\",\n   \"Helvetica Now\"\n  ],\n  \"note\": \"A single roman weight of a Swiss neo-grotesk at two or three modest sizes; position and grey value do the work that size and bold usually do. Suits architects, galleries, studios and any quiet page where photographs carry the scale.\",\n  \"seenIn\": [\n   \"aww-revelatio-studio\",\n   \"opl-spatial\",\n   \"aww-pensatori-irrazionali\",\n   \"opl-compile\"\n  ],\n  \"links\": [\n   \"https://api.fontshare.com/v2/css?f[]=switzer@400,500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"archivo-regular\",\n  \"name\": \"Archivo\",\n  \"class\": \"grotesk-light\",\n  \"display\": {\n   \"family\": \"Archivo\",\n   \"source\": \"google\",\n   \"weights\": [\n    400\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 400 · tracking -0.02em · leading 1.0 · sentence case; never bold, inactive items fade to grey\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Archivo:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Archivo\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 600 for buttons and short emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Archivo:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Scto Grotesk A\",\n   \"Cash Sans\"\n  ],\n  \"note\": \"A sturdy grotesque kept at regular weight even at 88px, so the page reads as composed rather than loud. Suits finance, infrastructure and research pages that need to look sober and current.\",\n  \"seenIn\": [\n   \"aww-sharplink\",\n   \"opl-plastic\",\n   \"opl-lovably\",\n   \"opl-berd\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Archivo:wght@400;600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"clash-grotesk-regular\",\n  \"name\": \"Clash Grotesk\",\n  \"class\": \"grotesk-light\",\n  \"display\": {\n   \"family\": \"Clash Grotesk\",\n   \"source\": \"fontshare\",\n   \"slug\": \"clash-grotesk\",\n   \"weights\": [\n    400\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 400 · tracking -0.03em · leading 0.95 · sentence case, or uppercase for one statement\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=clash-grotesk@400,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Clash Grotesk\",\n   \"source\": \"fontshare\",\n   \"slug\": \"clash-grotesk\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.4 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=clash-grotesk@400,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Sneak\",\n   \"ABC Monument Grotesk\"\n  ],\n  \"note\": \"A slightly narrow neo-grotesk with closed apertures, used at regular weight from marquee size down to paragraphs. Suits agencies and digital studios that want large type without heaviness.\",\n  \"seenIn\": [\n   \"aww-px-push\",\n   \"opl-wild-as\",\n   \"aww-sstr-friction-reduction\"\n  ],\n  \"links\": [\n   \"https://api.fontshare.com/v2/css?f[]=clash-grotesk@400,500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"work-sans-light\",\n  \"name\": \"Work Sans\",\n  \"class\": \"grotesk-light\",\n  \"display\": {\n   \"family\": \"Work Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    300\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 300 · tracking -0.035em · leading 1.0 · sentence case\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Work+Sans:wght@300;400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Work Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.55 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Work+Sans:wght@300;400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"ABC Favorit\",\n   \"Clarkson Light\",\n   \"PP Mori\"\n  ],\n  \"note\": \"A light grotesque with open, slightly old-fashioned shapes; large headings look airy and the text weight beneath stays easy to read. Suits AI and research products, fashion houses and calm brand sites.\",\n  \"seenIn\": [\n   \"aww-cerebrium\",\n   \"aww-squarespace-foundations\",\n   \"aww-boc-studio\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Work+Sans:wght@300;400;500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"anton-work\",\n  \"name\": \"Anton / Work Sans\",\n  \"class\": \"condensed-heavy\",\n  \"display\": {\n   \"family\": \"Anton\",\n   \"source\": \"google\",\n   \"weights\": [\n    400\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 400 (single heavy cut) · tracking -0.01em · leading 0.86 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Anton:wght@400&family=Work+Sans:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Work Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 600 for links and short emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Anton:wght@400&family=Work+Sans:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Druk\",\n   \"Thunder\",\n   \"Acme Gothic\"\n  ],\n  \"note\": \"Compressed heavy capitals stacked tight, with a neutral grotesque kept small beneath. Suits fashion drops, sport, nightlife and any page built as a poster.\",\n  \"seenIn\": [\n   \"aww-serotoninn\",\n   \"opl-juggle\",\n   \"opl-lorenzo-bocchi-photography\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Anton:wght@400&family=Work+Sans:wght@400;600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"big-shoulders-public\",\n  \"name\": \"Big Shoulders / Public Sans\",\n  \"class\": \"condensed-heavy\",\n  \"display\": {\n   \"family\": \"Big Shoulders\",\n   \"source\": \"google\",\n   \"weights\": [\n    800\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 800 · tracking -0.005em · leading 0.88 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Big+Shoulders:wght@800&family=Public+Sans:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Public Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 600 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Big+Shoulders:wght@800&family=Public+Sans:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Founders Grotesk Condensed\",\n   \"PP Neue York\",\n   \"Knockout\"\n  ],\n  \"note\": \"A tall American gothic taken from city signage, blunt and civic, over a plain public-service sans. Suits culture indexes, community projects, bars, sport clubs and local campaigns.\",\n  \"seenIn\": [\n   \"aww-mosbys-files\",\n   \"opl-the-sapphic-bar-index\",\n   \"opl-the-deep-end\",\n   \"aww-colonia-zacamil\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Big+Shoulders:wght@800&family=Public+Sans:wght@400;600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"archivo-compressed\",\n  \"name\": \"Archivo\",\n  \"class\": \"condensed-heavy\",\n  \"display\": {\n   \"family\": \"Archivo\",\n   \"source\": \"google\",\n   \"weights\": [\n    800\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 800 at font-stretch 62% (load the wdth axis and use its narrowest setting) · tracking -0.01em · leading 0.86 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Archivo:wdth,wght@62..125,100..900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Archivo\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"normal width · 400 for body, 500 for buttons and emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Archivo:wdth,wght@62..125,100..900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Helvetica Now Display Condensed\"\n  ],\n  \"note\": \"One variable family pushed to its narrowest, heaviest setting for headlines and relaxed to normal width for text, so display and body share a skeleton. Suits sportswear, campaigns and fintech pages that speak in capitals.\",\n  \"seenIn\": [\n   \"aww-decathlon-yestalgia\",\n   \"opl-uglycash\",\n   \"opl-juggle\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Archivo:wdth,wght@62..125,100..900&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"bebas-garamond\",\n  \"name\": \"Bebas Neue / EB Garamond\",\n  \"class\": \"condensed-heavy\",\n  \"display\": {\n   \"family\": \"Bebas Neue\",\n   \"source\": \"google\",\n   \"weights\": [\n    400\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 400 (single cut, capitals only) · tracking -0.02em, tightening to -0.06em above 15vw · leading 0.85 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Bebas+Neue:wght@400&family=EB+Garamond:ital,wght@0,400;0,500;1,400;1,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"EB Garamond\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": true,\n   \"settings\": \"leading 1.45 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Bebas+Neue:wght@400&family=EB+Garamond:ital,wght@0,400;0,500;1,400;1,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Founders Grotesk Condensed\",\n   \"Cardinal Classic Long\",\n   \"Signifier\"\n  ],\n  \"note\": \"Huge condensed capitals against a light old-style serif with italics: an industrial voice and a literary one, with a twenty-fold size gap between them. Suits crafted physical products, spirits, outdoor goods and hospitality.\",\n  \"seenIn\": [\n   \"aww-longbow\",\n   \"aww-white-desert\",\n   \"aww-mosbys-files\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Bebas+Neue:wght@400&family=EB+Garamond:ital,wght@0,400;0,500;1,400;1,500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"barlow-condensed\",\n  \"name\": \"Barlow Condensed / Barlow\",\n  \"class\": \"condensed-heavy\",\n  \"display\": {\n   \"family\": \"Barlow Condensed\",\n   \"source\": \"google\",\n   \"weights\": [\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 700 · tracking -0.02em · leading 0.9 · uppercase for statements, mixed case for item titles\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@700&family=Barlow:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Barlow\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@700&family=Barlow:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"FF DIN Condensed\",\n   \"Helvetica Now Display Condensed\"\n  ],\n  \"note\": \"Road-sign condensed type with squared curves, bold but not compressed into a wall, with its normal-width sibling for text. Suits logistics, motorsport, hardware and directories with many short titles.\",\n  \"seenIn\": [\n   \"aww-julien-calot\",\n   \"opl-medium-rare\",\n   \"opl-uglycash\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@700&family=Barlow:wght@400;500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"panchang-switzer\",\n  \"name\": \"Panchang / Switzer\",\n  \"class\": \"extended-heavy\",\n  \"display\": {\n   \"family\": \"Panchang\",\n   \"source\": \"fontshare\",\n   \"slug\": \"panchang\",\n   \"weights\": [\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 700 · tracking -0.02em · leading 1.0 · uppercase; four words or fewer per line because the face is very wide\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=panchang@700&display=swap\\\" rel=\\\"stylesheet\\\">\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=switzer@400,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Switzer\",\n   \"source\": \"fontshare\",\n   \"slug\": \"switzer\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=panchang@700&display=swap\\\" rel=\\\"stylesheet\\\">\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=switzer@400,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Monument Extended\",\n   \"Owners Wide\",\n   \"Nimbus Sans Extended\"\n  ],\n  \"note\": \"A flat-sided extended grotesk in heavy capitals, wide enough that two words fill the screen, with a neutral sans kept small. Suits portfolios, real estate, travel and brand sites that want a broad, confident wordmark.\",\n  \"seenIn\": [\n   \"opl-belen-jones\",\n   \"aww-lxl-creative\",\n   \"aww-realevate\",\n   \"aww-the-tuscan-journey-begins\"\n  ],\n  \"links\": [\n   \"https://api.fontshare.com/v2/css?f[]=panchang@700&display=swap\",\n   \"https://api.fontshare.com/v2/css?f[]=switzer@400,500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"tiktok-sans-wide\",\n  \"name\": \"TikTok Sans\",\n  \"class\": \"extended-heavy\",\n  \"display\": {\n   \"family\": \"TikTok Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    800\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 800 at font-stretch 150% (load the wdth axis and use its widest setting) · tracking -0.01em · leading 1.0 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=TikTok+Sans:wdth,wght@75..150,300..900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"TikTok Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"normal width · 400 for body, 500 for emphasis · leading 1.45 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=TikTok+Sans:wdth,wght@75..150,300..900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Herokid Wide\",\n   \"At Aero\",\n   \"Wintyr\"\n  ],\n  \"note\": \"One variable grotesk stretched wide and bold for the headline and the closing statement, then returned to normal width for reading. Suits personal portfolios, apps and tech brands that want width without a second family.\",\n  \"seenIn\": [\n   \"aww-haoqi-design\",\n   \"opl-tara\",\n   \"aww-produx-design\",\n   \"opl-proooof\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=TikTok+Sans:wdth,wght@75..150,300..900&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"unbounded-onest\",\n  \"name\": \"Unbounded / Onest\",\n  \"class\": \"extended-heavy\",\n  \"display\": {\n   \"family\": \"Unbounded\",\n   \"source\": \"google\",\n   \"weights\": [\n    800\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 800 · tracking -0.03em · leading 1.0 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Unbounded:wght@800&family=Onest:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Onest\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Unbounded:wght@800&family=Onest:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"IntraNet\",\n   \"Nekst\",\n   \"Owners Wide\"\n  ],\n  \"note\": \"A wide display sans built from rounded squares, heavy and a little architectural, beside a clean text grotesk. Suits architecture indexes, watches, mobility and events that want a title with a constructed feel.\",\n  \"seenIn\": [\n   \"opl-belgrade-architecture\",\n   \"aww-the-watch\",\n   \"aww-risk\",\n   \"aww-house-of-honey-1\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Unbounded:wght@800&family=Onest:wght@400;500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"chivo-black\",\n  \"name\": \"Chivo\",\n  \"class\": \"heavy-black\",\n  \"display\": {\n   \"family\": \"Chivo\",\n   \"source\": \"google\",\n   \"weights\": [\n    900\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 900 · tracking -0.05em · leading 0.88 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Chivo:wght@400;700;900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Chivo\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for paragraphs, 700 for navigation, tags and links · leading 1.35 · tracking -0.01em\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Chivo:wght@400;700;900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Elza\",\n   \"ABC Diatype Heavy\",\n   \"Suisse Intl Black\"\n  ],\n  \"note\": \"A black grotesque in capitals with letters nearly colliding, and only two sizes on the page: enormous and small. Suits agencies, city and culture projects and musicians who want the type to land like a headline.\",\n  \"seenIn\": [\n   \"aww-glitch-grit\",\n   \"opl-city-of-angels\",\n   \"aww-warm-fuzzy\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Chivo:wght@400;700;900&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"cabinet-grotesk-black\",\n  \"name\": \"Cabinet Grotesk\",\n  \"class\": \"heavy-black\",\n  \"display\": {\n   \"family\": \"Cabinet Grotesk\",\n   \"source\": \"fontshare\",\n   \"slug\": \"cabinet-grotesk\",\n   \"weights\": [\n    800\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 800 · tracking -0.035em · leading 0.9 · lowercase or sentence case, one or two words per line\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=cabinet-grotesk@400,500,800&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Cabinet Grotesk\",\n   \"source\": \"fontshare\",\n   \"slug\": \"cabinet-grotesk\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=cabinet-grotesk@400,500,800&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Champ\",\n   \"Uncut Sans\"\n  ],\n  \"note\": \"A heavy sans with tight joins and an eccentric lowercase, friendly but loud. Suits bookshops, food, consumer subscriptions and marketing studios.\",\n  \"seenIn\": [\n   \"aww-aardvark-book-club\",\n   \"opl-protip-marketing\",\n   \"opl-rendez-vous-franceclat\"\n  ],\n  \"links\": [\n   \"https://api.fontshare.com/v2/css?f[]=cabinet-grotesk@400,500,800&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"epilogue-black\",\n  \"name\": \"Epilogue\",\n  \"class\": \"heavy-black\",\n  \"display\": {\n   \"family\": \"Epilogue\",\n   \"source\": \"google\",\n   \"weights\": [\n    900\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 900 · tracking -0.04em · leading 0.9 · sentence case or title case\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Epilogue:wght@400;500;900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Epilogue\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Epilogue:wght@400;500;900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Die Grotesk D\",\n   \"Acme Gothic\",\n   \"FH Oscar\"\n  ],\n  \"note\": \"A broad black grotesque with a slightly uneven rhythm, at its best as a name set very large in mixed case. Suits entertainers, podcasts, consumer apps and blunt SaaS pages; emphasis comes from colour, not from a change of weight.\",\n  \"seenIn\": [\n   \"aww-trevor-noah\",\n   \"opl-juggle\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Epilogue:wght@400;500;900&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"red-hat-black\",\n  \"name\": \"Red Hat Display / Red Hat Text\",\n  \"class\": \"heavy-black\",\n  \"display\": {\n   \"family\": \"Red Hat Display\",\n   \"source\": \"google\",\n   \"weights\": [\n    900\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 900 · tracking -0.03em · leading 0.92 · uppercase; centred three-line stacks work well\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Red+Hat+Display:wght@900&family=Red+Hat+Text:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Red Hat Text\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Red+Hat+Display:wght@900&family=Red+Hat+Text:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"FH Oscar\",\n   \"Futura Bold\"\n  ],\n  \"note\": \"A geometric black with round bowls and flat terminals, cleaner and more even than a grotesque at the same weight. Suits fintech, apps and portfolios that want heavy type with a tidy, technical finish.\",\n  \"seenIn\": [\n   \"aww-risk\",\n   \"aww-leo-parpeix-portfolio-2026\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Red+Hat+Display:wght@900&family=Red+Hat+Text:wght@400;500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"jost-caps\",\n  \"name\": \"Jost\",\n  \"class\": \"geometric\",\n  \"display\": {\n   \"family\": \"Jost\",\n   \"source\": \"google\",\n   \"weights\": [\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 700 · tracking -0.03em · leading 0.9 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Jost:wght@400;500;700&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Jost\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Jost:wght@400;500;700&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Futura Std Bold\",\n   \"Futura PT\"\n  ],\n  \"note\": \"The pointed, circular geometry of the 1920s in bold capitals, with the same family at reading size. Suits space, science, museums, architecture and anything that should feel like a mid-century poster.\",\n  \"seenIn\": [\n   \"aww-21-hrs-on-the-moon\",\n   \"aww-leo-parpeix-portfolio-2026\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Jost:wght@400;500;700&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"stack-sans-light\",\n  \"name\": \"Stack Sans Headline / Stack Sans Text\",\n  \"class\": \"geometric\",\n  \"display\": {\n   \"family\": \"Stack Sans Headline\",\n   \"source\": \"google\",\n   \"weights\": [\n    300\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 300 · tracking -0.022em · leading 1.05 · sentence case; a heading may be two-tone, grey then full ink\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Stack+Sans+Headline:wght@300&family=Stack+Sans+Text:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Stack Sans Text\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Stack+Sans+Headline:wght@300&family=Stack+Sans+Text:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Mluvka\",\n   \"Roobert\"\n  ],\n  \"note\": \"A geometric sans in a light weight at large size, soft and exact at once, with its text cut underneath. Suits consumer apps, utilities and developer tools that want to feel calm and modern.\",\n  \"seenIn\": [\n   \"opl-screentune\",\n   \"opl-dialkit\",\n   \"opl-typewave\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Stack+Sans+Headline:wght@300&family=Stack+Sans+Text:wght@400;500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"albert-sans-semibold\",\n  \"name\": \"Albert Sans\",\n  \"class\": \"geometric\",\n  \"display\": {\n   \"family\": \"Albert Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 600 · tracking -0.035em · leading 1.0 · sentence case\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Albert+Sans:wght@400;500;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Albert Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Albert+Sans:wght@400;500;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"BT Steinhart\",\n   \"TT Norms Pro\",\n   \"Objektiv\"\n  ],\n  \"note\": \"A geometric grotesque with Scandinavian restraint: round letters, even colour, nothing decorative. Suits logistics, health, property and corporate sites that need to look clear and dependable.\",\n  \"seenIn\": [\n   \"aww-united-carriers\",\n   \"aww-likova\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Albert+Sans:wght@400;500;600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"spartan-figtree\",\n  \"name\": \"League Spartan / Figtree\",\n  \"class\": \"geometric\",\n  \"display\": {\n   \"family\": \"League Spartan\",\n   \"source\": \"google\",\n   \"weights\": [\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 700 · tracking -0.04em · leading 0.88 · lowercase or sentence case\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=League+Spartan:wght@700&family=Figtree:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Figtree\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 600 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=League+Spartan:wght@700&family=Figtree:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Degular\",\n   \"Roobert\"\n  ],\n  \"note\": \"A compact bold geometric with a low waist, punchy in short lowercase lines, over a friendly open text sans. Suits newsletters, consumer products, creators and small shops.\",\n  \"seenIn\": [\n   \"opl-lennys-newsletter-product-pass\",\n   \"opl-near\",\n   \"opl-sand-studio\",\n   \"aww-aardvark-book-club\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=League+Spartan:wght@700&family=Figtree:wght@400;600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"pilcrow-rounded\",\n  \"name\": \"Pilcrow Rounded\",\n  \"class\": \"rounded-friendly\",\n  \"display\": {\n   \"family\": \"Pilcrow Rounded\",\n   \"source\": \"fontshare\",\n   \"slug\": \"pilcrow-rounded\",\n   \"weights\": [\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 700 · tracking -0.05em · leading 0.9 · all lowercase, one or two words per line\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=pilcrow-rounded@400,500,700&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Pilcrow Rounded\",\n   \"source\": \"fontshare\",\n   \"slug\": \"pilcrow-rounded\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0; lowercase throughout is fine\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=pilcrow-rounded@400,500,700&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Milling Triplex\",\n   \"Ease\"\n  ],\n  \"note\": \"A sturdy sans with fully rounded stroke ends, set bold and tight in lowercase with one small size for everything else. Suits toys, gadgets, cosmetics and other objects with soft moulded edges.\",\n  \"seenIn\": [\n   \"opl-when-you-wish-upon-a-starboy\",\n   \"opl-anidachi\",\n   \"aww-artem-shcherbakov\"\n  ],\n  \"links\": [\n   \"https://api.fontshare.com/v2/css?f[]=pilcrow-rounded@400,500,700&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw,\n\n<!-- [TRUNCATED AT 50KB] -->","isInternal":false,"tokens":16305,"sizeBytes":50168},{"name":"README.md","path":"skills/taste-skill/README.md","rawUrl":"https://raw.githubusercontent.com/Leonxlnx/taste-skill/HEAD/skills/taste-skill/README.md","title":"Taste-skill Skill","category":"anthropic-skill","format":"markdown","content":"# tasteskill v2 (`design-taste-frontend`)\n\nA design skill for coding agents, built from a study of 247 curated sites (One Page Love and Awwwards\nSites of the Day, October 2026). It gives an agent an art direction instead of letting it fall back on\nthe average landing page, holds it to a strict no-ornament house style, and makes it look at its own\nrender before calling the work done.\n\n## How it works\n\n1. **Inventory.** The agent lists what only this client has: the name and what it means, the street,\n   the numbers, the one constraint, the materials, the hours.\n2. **Draw.** `scripts/draw.mjs` deals three of 20 directions (each an idea engine seen on the\n   strongest studied sites); the agent picks the one that can carry something from the inventory, and\n   the script deals the rest: a hero composition, section compositions, a type system of real free\n   fonts, a palette, photographs, a motion, studied references, and under every blueprint a list of\n   where it disagrees with the house rules. Recent draws are remembered so projects do not repeat.\n3. **Idea and live thing.** One sentence tying the client's own material to the direction's device,\n   checked against the nearest competitor, and one thing the visitor can do on the page.\n4. **Build** from the sheet, words first, full content. When the project has no photographs of its\n   own, `scripts/assets.mjs` finds real pictures of the subject's world in open collections (its\n   street in old postcards, old maps, its materials, engravings of its trade, museum objects of its\n   kind), downloads them into the project and records their credits; the subject is drawn in code\n   only where no honest picture exists.\n5. **Gate.** `scripts/lint.mjs` (source) and `scripts/inspect.mjs` (real browser, 1440 / 768 / 390)\n   measure the house rules: headlines of two lines or fewer, no eyebrow labels, no monospace, no\n   01/02/03, no thin rules, no gradients, no resting shadows, no cream-and-terracotta, no violet, and\n   the faults blind jurors punished: no focal point, empty screens, text covered or cut, long pins,\n   sideways rows, faded text.\n6. **Look.** The inspector saves screenshots; the agent critiques them with an Awwwards-weighted\n   rubric, fixes the top three problems and repeats, at most three rounds.\n\nFive rounds of blind tests against a no-skill baseline and another design skill are recorded in\n`references/research.md` §11.\n\n## Contents\n\n```\nSKILL.md                 the run, the house rules, the laws\nreferences/              copy, type, colour, layout, imagery, motion, critique, tells, research\nscripts/draw.mjs         deal options / a direction / reprint / redraw; --alternatives, --photos, --site\nscripts/assets.mjs       search open image collections (Openverse, Wikimedia Commons, Art Institute of\n                         Chicago, the Met) and, with --video, real footage (Wikimedia Commons, Internet\n                         Archive, NASA); --get downloads with the credit, --credits prints them\nscripts/lint.mjs         static scan for banned patterns and stock phrases\nscripts/inspect.mjs      render, measure, photograph\nscripts/lib/             zero-dependency Chrome DevTools client, the in-page probe, the rules\nlibrary/                 directions (20), heroes, sections, type systems, palettes, photographs,\n                         studied sites, motions\nassets/base.css, base.js an optional neutral foundation\nevals/evals.json         six briefs for testing the skill against a no-skill baseline\n```\n\n## Requirements\n\nNode 22 or newer and an installed Chrome, Edge or Chromium for `inspect.mjs` (it drives the browser\nover the DevTools protocol with Node's built-in WebSocket; nothing is installed). `draw.mjs`,\n`lint.mjs` and `assets.mjs` run on Node 18+; `assets.mjs` needs network access and no API keys. Set\n`CHROME_PATH` if the browser is somewhere unusual.\n\n## Install\n\nCopy this folder to your skills directory, for example `~/.claude/skills/design-taste-frontend/`, or keep it in\na repository under `.claude/skills/`.\n\n## Notes\n\n- Photographs in the library are served by Lorem Picsum from Unsplash, under the Unsplash licence.\n  They are placeholders for atmosphere; replace them with the project's own pictures.\n- Pictures found with `assets.mjs` keep their own licences. By default it offers only CC0, public\n  domain, CC BY and CC BY-SA, and `--get` records the title, creator, licence and source of every\n  download in `assets/credits.json`. The page must carry the credits (`--credits` prints them).\n- `assets.mjs --video` finds short clips of the subject's world, takes a 720p-or-smaller rendition,\n  refuses files over 25 MB unless `--max-mb` is passed, and saves a poster frame with each clip; how\n  to use one on a page (muted loop, poster, stopped under reduced motion) is in\n  `references/imagery.md` §11.\n- Fonts are loaded from Google Fonts and Fontshare. Check each face's licence for your use.\n- The scores in `references/research.md` are model judgements from screenshots, not Awwwards scores.\n- The draw history lives in `~/.taste-skill/history.json` (set `TASTE_SKILL_HISTORY` to move it).\n  Delete it to reset.\n- A build takes an agent roughly 30–45 minutes and a few hundred thousand tokens with the full\n  look-and-fix loop; most of that is finding or drawing pictures when a project has no photographs.\n","isInternal":false,"tokens":1270,"sizeBytes":5345},{"name":"app-screens.md","path":"skills/taste-skill/references/app-screens.md","rawUrl":"https://raw.githubusercontent.com/Leonxlnx/taste-skill/HEAD/skills/taste-skill/references/app-screens.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# App screens\n\nDashboards, admin, analytics, settings, inboxes, wallets and builders: the screens people work in.\nRead this file whole before you start one. The page run in `SKILL.md` does not apply to them.\n\nA generated dashboard is the average of every dashboard template: a dark or tinted sidebar with a\ncoloured pill on the active item, \"Welcome back\" and a waving hand, four KPI cards each with an icon\nin a tinted circle, a green \"+12.5%\" and a sparkline, a gradient area chart, a zebra table under\nuppercase headers. Nothing in it is wrong and none of it was decided.\n\nThis chapter is distilled from a study of 23 real product screens chosen by the owner: 17 products,\n17 light screens and 6 dark, all at desktop width (1440 or 1512px). Each screen was measured from its\npixels and noted for what works and what fails; the numbers below are those measurements and their\nmedians. The products are not named. What separates these screens from the generated kind, in order\nof how much it shows:\n\n1. **Colour goes on data, not chrome.** The median screen has about 3% coloured pixels; 17 of 23 stay\n   at 5% or less. 12 have no filled primary button at all.\n2. **KPIs are type, not tiles.** No screen puts an icon in a coloured circle on a KPI, and none draws a\n   sparkline on one.\n3. **Surfaces are flat.** 17 of 23 give their cards no shadow; separation is a 1px line or one tone\n   step.\n4. **There is no hero header.** 9 screens have no heading over 16px; where there is one, its median is\n   24px.\n5. **Charts carry almost no chrome.** A single series has no legend; gridlines are 3-7 faint lines or\n   none.\n6. **Navigation recedes.** The active item is a neutral grey pill or a change of text colour; a\n   coloured left bar appears once.\n7. **Tables are rules and alignment.** No zebra striping, no header bands, numbers right-aligned.\n8. **Data states are honest.** Zeros print as zeros, missing values as a grey dash, and an empty\n   section keeps its frame.\n\nTaking the template's devices away is half the job, as it is on a page. The other half is substance:\nthe product's real data, a screen that answers its one question first, and a grid whose arithmetic\ncloses.\n\n**A warning learned in testing.** In the first blind round, screens built with this chapter were\nclean, quiet and correct, and they lost to richer screens built without it. The judges' reasons were\nthe same every time, and each is now a rule below:\n\n- **The first screen was thin.** One large chart of a flat line filled it, and half the blocks the\n  brief asked for started below the fold. On a 1440×900 screen, every block the brief names shows its\n  header and its first rows (§2.2).\n- **The product was missing.** No name, no workspace, no mark: the screen could have belonged to\n  anyone. The shell names the product and the scope (§3.2).\n- **Restraint hid meaning.** A latency rise and a request rise were the same grey. Colour on a change\n  says good or bad, not up or down (§5).\n- **There was nothing to do.** No control for the job the screen exists for. The most frequent job is\n  one click from the first screen (§2.2).\n- **Rows ended ragged** and **a style's move was over-applied** (a tray around every card, an icon\n  rail where people needed labels). Keep the move to where it carries meaning.\n\nQuiet is the starting point, not the goal. A screen that a person would trust shows more of the\nproduct than a template does: its people, its objects, its numbers and the one thing to do next.\n\n**Give the product a face.** After four rounds the judges' top complaint was the same on most\nscreens: \"a well-applied kit, not a product with its own identity\" (stock Geist or Inter, a #f8f8f8\nground, white 12px cards, lime on black). The style's tokens make a screen correct; these make it\nthis product's, and choosing them is a step of the run, not a finish (§2.3):\n\n- **One face from the sheet, chosen before you build.** Each style lists two or three ways it takes a\n  face from the brief: a ground tinted from the product's world, a figure face with character, the\n  brand's hue on the main data element. Choose one, write it in your notes next to the screen's\n  question, and check that it shows on the first screenshot.\n- **The dealt typeface, really loaded.** A build that fell back to the default face landed on the\n  default look; the inspector now fails it.\n- **The product's mark and name** at the top of the shell, drawn for this product (a simple\n  monogram or symbol in the accent, from its name or its object), never a black square with a letter.\n- **One element only this product has**, built from its own things: an energy home's power flow, a\n  bakery's sell-out strip, a leave planner's cover against the minimum, the pace groups of a running\n  club as a unit chart, the couple as three lanes, a deploy's commit as the hero of the overview. The\n  sheet lists the library's signature elements whose words appear in the brief; otherwise invent one.\n  Name it in your notes next to the screen's question.\n- **The one chart hue on the main data element**: today's line, the booked bars, the current period,\n  the margin that breaks. A screen whose only hue is a delta reads as a kit, and the inspector warns\n  when a screen with charts carries no hue on its data (`no-data-hue`).\n- **Its people and objects as themselves**: each person gets a stable initial and a pale tint of their\n  own hue, with people listed next to each other at least 60 degrees apart. These tints are identity,\n  not data: they stay pale and out of the chart legends. Products show their thumbnails, cover art\n  shows the cover.\n- **Words of the trade** in labels and empty states (\"Waiting on the customer\", \"Off sick\", \"Due\n  on the 28th\"), never the generic noun of a template (\"Items\", \"Records\", \"Status\").\n\n**Calendars and timelines** (house rule, from testing; the study has none). People down the left on a\nfixed 160-220px column, grouped under a team subheader rather than repeating the team on every row;\ndays across with faint 1px day lines, weekends one tone step darker, and today marked by a 1px line\nin the one data hue with its date in ink. Bars are 20-24px tall at radius 4. One-line names sit on a\n32px pitch; a name with a subline (team, office) needs 40-44px, or the subline touches the next name.\n**Every kind of booking has its own mark**, so sickness reads apart from a holiday at a glance:\nholiday a pale fill, off sick a 1px diagonal hatch, long leave a darker grey step, working away an\noutline, a pending request a dashed outline. A style with a hue budget may add a 3px left edge in the\nhue for the kind the screen is about. Full colour is only for what needs a decision (a request that\nbreaks cover). A label sits inside its bar; a bar too short for it shows the kind's code inside and\nthe full label in its tooltip, or the label after the bar's end, never over the days before it.\nHoliday markers name their office in a multi-office product. Every swatch in the legend is the mark\nitself, scaled down, and lists only kinds on screen: `Charts.timeline(el, rows, kinds)` draws the bars\nand returns that legend from the same kinds map.\n\n## Contents\n\n1. When this applies\n2. The run for an app screen\n3. The shell\n4. The canvas and the page title\n5. KPIs\n6. Charts\n7. Tables and lists\n8. Forms and settings\n9. Type and colour\n10. Density\n11. Empty, zero, loading and error states\n12. The phone\n13. House rules for app screens\n14. Tells of generated dashboards\n\n## 1. When this applies\n\nAn app screen is worked in rather than read. This chapter covers:\n\n- dashboards and overviews: a seller's day, a project's health, a publication's growth;\n- admin and back office: members, orders, events, a catalogue;\n- analytics and reports, including a generated report with no app around it;\n- settings and billing;\n- list screens to work through: inboxes, queues, tables with filters;\n- wallets and finance homes;\n- builders and editors: flow, form and page builders, canvases;\n- the detail page of one object: an event, a deployment, a customer.\n\nA product site that shows its interface is a page; the interface fragments on it follow these rules\nfor their insides (mark each fragment's root with `data-ui`). When a request holds both, build each\nwith its own run and share one palette and one typeface.\n\nThe study is 23 desktop screens. It has no phone screens, no loading or error states, one settings\npage, no inbox and no dense operations table (the densest screen shows about 120 data points). Where a\nrule below goes past the study, it says **house rule**.\n\n## 2. The run for an app screen\n\nDo these in order. The first three steps decide whether the screen is any good.\n\n### 2.1 Inventory the data and the jobs\n\nThe page run inventories the subject's world; an app screen inventories its data. Write in your notes,\nin 8 to 12 lines:\n\n- **the objects** the screen shows (deployments, invoices, members, events, conversations) and their\n  fields, with units;\n- **realistic magnitudes**: how many objects, a typical amount, the range of a rate, how values move\n  over a day, a month, a year, and for a new account how small they really are;\n- **the people**: who opens this screen, how often (a glance once a day, or an eight-hour session),\n  on what device;\n- **the jobs**: what they do next from here (approve, reply, pay, ship, invite), and which job comes\n  up most;\n- **the product's own things**: its name and mark, the workspace or account it is scoped to, the people\n  in it (two partners, a team of six, the club's members), and the objects people recognise by sight\n  (product photographs in a shop, cover art in a media tool, a map of the route). These are what make\n  a screen belong to this product instead of to a template; plan where each one appears.\n\nThen write the data itself: a small dataset in a JSON or JS file that the screen renders from, with\nbelievable names, amounts that add up to their totals, dates in order and a unit on every figure.\nTotals are computed from the rows, never typed in separately. Small numbers stay small: the studied\nscreens show new accounts with 1, 6 or 9 of something, drawn honestly at their real size. Write the\nfigures that must agree as assertions in the data file (`console.assert(sold - cancelled === rsvps)`,\nthe bins sum to the total, the parts to the whole) and read the console: in testing, a ticket table\nthat did not reconcile with its own KPI cost a judge's trust in the whole screen. Checks that need\ncomputed values (allowance after a request, cover per day) go in the script that computes them.\n\n**Data that tells the truth** (house rules, from testing; judges checked every one of these):\n\n- **A fact shown twice is one variable.** A time window, a total or a state that appears in two cards\n  (the battery full 13:30-16:30 in the KPI label, the shaded span and the battery card) is one value in\n  the data file, and the copy and the chart annotation are both built from it. Two cards that\n  disagree by half an hour cost more trust than a missing card.\n- **Totals and deltas come from the parts as shown.** Sum the rounded pennies the screen displays,\n  never round the unrounded total separately: £21.68 + £8.34 − £3.81 is £26.21, and a screen that\n  says £26.22 is caught. A change is the difference of the two values on screen (£5.28 against\n  £5.22 is +£0.06, not +£0.07).\n- **Every relative figure names its baseline** in the same phrase: \"3 h 40 m before close\", \"45 m\n  earlier than last Sunday\", \"+5 on the usual Monday\". \"Early\", \"up\" or a bare \"+5\" next to another\n  time or figure reads as measured against that one.\n- **One name per time.** Shops close at 15:00 and the tills are cashed up at 15:12; the header and\n  the card use the same words for the same moment, and an error state rewrites the status line.\n- **If a caption has to say which bars are which, encode it in the chart instead**: a marked period in\n  a second tone with its own legend entry, a signed axis, a label on the mark.\n\n### 2.2 Name the screen's one question\n\nEvery screen answers one question first: \"Did today's sales come in?\", \"Which deploy broke?\", \"Who is\nwaiting for a reply?\", \"How much of this month's plan is left?\". Write it in one line. It decides\nthree things:\n\n- **what is biggest.** In the study the largest block is always the one that carries the screen's\n  question, whatever form it takes (a chart, a plan, a ring, a list). The same holds for figures:\n  the largest figure on the screen answers the question the title row's sentence answers. In testing,\n  an 88% sun ratio at 32px out-shouted the 24px charging window the title led with;\n- **what comes first** in the reading order;\n- **what is left out.** The studied settings page shows three usage numbers and links to the\n  analytics screen instead of drawing a chart; four screens draw no chart at all because a few\n  numbers say it.\n\nThen name the screen's **one finding**: the fact in today's data that most needs attention (\"9 no-shows\nwhile 8 people waited for a place\", \"the 23:28 deploy doubled the error rate\", \"eating out is £36 over\").\nPut it where it is read first, as the line under the title or the subline of the headline figure,\nnext to the action it drives. In testing, the finding that mattered sat in a 14px caption at the\nbottom of a card and the screen read as flat.\n\n**Do not rebuild a studied screen.** When the product is of the same kind as a screen in the study (a\nfinance home, a deploy overview), its arrangement is the trap: judges recognised the copies at once.\nTake the structure from the product's own things instead: for a couple's budget, Mia, Joint and Tom\nas three columns running through accounts, plan and bills; for a running club, the pace groups.\n\nThen list the screen's blocks as the answers to its next questions, one line each, the way the page\nrun lists claims. A block with no question is deleted. This is how you avoid the stock order of KPI\nrow, big chart, two small charts, table.\n\nThree more lines, each tested:\n\n- **Everything the brief names is on the first screen.** At 1440×900, every block the brief asks for\n  shows its header and its first rows or its figure. Size the headline block to the question (about\n  200-360px tall), cap long lists at 4-6 rows with \"View all\", and put time-sensitive blocks (bills\n  due, SLAs running out, a failed deploy) before long tables. A chart whose line is flat for most of\n  the window does not get the full width: give it two-thirds and put the next answer beside it.\n- **The most frequent job is one click away.** Name it (\"pack the orders due today\", \"reply to the\n  oldest breach\", \"redeploy the failed build\") and put its control where the answer shows: a primary\n  button in the title row, an action on the row that needs it, a \"View logs\" on the failed item. A\n  screen with no control for its main job reads as a report, not as a tool.\n- **Show the evidence beside the answer.** A judge trusts \"Error rate 0.28%\" more with its spike\n  annotated (\"peaked at 3.9% after the 23:28 deploy, reverted\") than with the number alone. One line\n  of explanation on the event that matters is worth more than a second chart.\n\n### 2.3 Choose a style\n\n```bash\nnode <skill>/scripts/draw.mjs --app --kind <kind> --brief \"<one line about the product>\" \\\n  --screens <screens> [--theme light|dark] [--keep palette,type] --options 3\n```\n\nThis deals up to three styles from `library/app.json` (fewer when only two suit the kind and the\ntheme). `draw.mjs --app --list kinds` (or `styles`, `screens` or `signatures`) prints the choices; the\nscreens are `overview`, `analytics`, `list`, `detail`, `settings`, `wallet`,\n`builder`, `inbox`, `home` and `report`. The library holds seven styles, each distilled from the\nstudied screens that share its move:\n\n| Style | Theme | For | The move |\n| --- | --- | --- | --- |\n| `achromatic-ledger` | light | money homes, reports, settings with usage | No colour in the chrome; charts in ink; one small signal where a figure changed |\n| `framed-sheet` | light | B2B analytics, developer platforms, builders | One tinted L-frame; the page on a white sheet inset 8px, no shadow |\n| `accent-ladder` | light | creator and small-business admin with plans | The full hue on small marks only; its pale tints on every area |\n| `editorial-greeting` | light | team and personal homes | The greeting as the h1 in a centred 12-column column; every figure at regular weight |\n| `pastel-consumer` | light | wallets, budgeting | Pale same-hue tiles under one large radius; quiet money polarity |\n| `true-black-flat` | dark | community, events, media | Elevation by lightness alone; colour only on data |\n| `data-terminal` | dark | markets, monitoring | Every selection is the same 1px accent line; signs, not colour, on numbers |\n\nChoose by how the product is used (long sessions or a quick look, money or media, a team or one\nperson, day or night), not by what is most familiar, and write one line on why. Then deal the sheet:\n\n```bash\nnode <skill>/scripts/draw.mjs --app <the same arguments, without --options> --style <id>\n```\n\nThe sheet gives the style's tokens and type, its shell and one pattern for each screen you named.\nKeep the style's one move intact and take every other value from the defaults in this file. Redraw\n(`--redraw style | shell | screen:<name>`) only for a reason you can state: it contradicts the brand,\nor the product is used in a way the style does not suit. With an existing brand, pass\n`--keep palette,type`, map its colours onto the roles in §9 and keep the style's colour budget.\n\n**Then choose its face, before any markup.** The sheet's \"Its face\" list gives two or three ways this\nstyle takes a face from the brief, and \"Signature elements\" lists the library's elements whose words\nappear in the brief (a power flow for an energy home, a sell-out strip for a bakery, a cover matrix\nand a kind-encoded timeline for a leave planner). Write in your notes, next to the screen's question:\nthe face you chose, the signature element (from the sheet, or your own built from the product's\nthings), and where each appears on the first screen. A style dealt to two products must not give them\nthe same face: in four rounds, the screens that skipped this step were scored as the same kit.\n\n### 2.4 Build the shell\n\nBuild the frame first, empty: the sidebar or rail, the top bar if the shell has one, the canvas with\nits gutters, the title row (§3 and §4). `<skill>/assets/app.css` is a neutral start for all of it:\ncopy it into the project and put the sheet's tokens in its `:root`. Look at it at 1440 and at 390 before any data goes in. Do the\ngrid arithmetic now and write it in a comment: the column count, the gutter, and the sum that proves\nthe cards land on the canvas edges.\n\n### 2.5 Put in the data\n\nRender every block from the dataset; draw the charts from it too, with `<skill>/assets/charts.js`\n(`Charts.line`, `Charts.bars`, `Charts.diverging`, `Charts.ring`, `Charts.barList`, `Charts.plan`,\n`Charts.bullet`, `Charts.timeline`, `Charts.matrix`, `Charts.timeStrip`; the file's header lists their\noptions) or your own SVG to the rules of §6, never a chart library's defaults and never a picture of a\nchart. The newer helpers return `{ svg, legend }`: put that legend in the card's header rather than\ndrawing your own, so each swatch is the mark it explains. Format every figure by §7.4: separators, fixed decimals per\nmetric, a sign on every change, units as smaller grey suffixes, tabular figures, right alignment in\ncolumns. Use the product's own words for labels. No placeholder data: the inspector fails lorem ipsum,\nAcme, John Doe and their kind. Proof is not invented here either: no vanity totals, no \"+12%\" on an\naccount that is a week old.\n\n### 2.6 Build the states\n\nFor every block, build its empty, zero, loading and error state (§11); for every row and control, its\nhover, selected, focus and disabled state. Look at each one in the browser. A screen that only works\nwith full data is half built.\n\n### 2.7 The check\n\n```bash\nnode <skill>/scripts/lint.mjs --app <source files or folder>\nnode <skill>/scripts/inspect.mjs --app <url or path/to/index.html>\n```\n\nA sheet dealt with `--app` switches both tools to the app rules by itself. The inspector opens the\nscreen at 1440, 768 and 390 and measures what this chapter asks for: an h1 (and reports it as the\nscreen's hero); a sidebar that folds on the phone; the canvas used to its right edge; panel shadows\nand borders; the number of corner radii; cards in one row that end apart, where a column of cards\nstacked with the gutter counts as one block (`ragged-row`); a blank band inside a card of over 40px,\nor over 64px before a new section's heading (`panel-void`); icons in tinted squares; numeric alignment and tabular figures; chart hues; colour\nshare, and a screen with charts but no hue on its data (`no-data-hue`); placeholder data; text under\n11px; and the page rules that still hold (contrast, gradients, the banned palettes, emoji). Fix every\n`FAIL`. Treat each `WARN` as wrong unless you can defend it to a designer in one sentence.\n\nThen look at the screenshots, every width, and answer these in writing. This is the critique for an\napp screen: the caps in `critique.md` for pictures, motion and the page's live element are page rules\nand do not apply here.\n\n1. Is the screen's question answered by the biggest thing on it, and is that read first? Is the\n   largest figure the one that answers the title row's sentence?\n2. Does every block share the screen's edges? Is there a dead strip on one side, a card stopping\n   short, an orphan cell, a stretched card with a blank band (a legend pinned to its foot, four rows\n   in a card kept at its neighbour's height)?\n3. Is colour only on data, on status and on the one primary action, and does the main data element\n   carry the one hue? Does the face you chose show on the first screen?\n4. Do the numbers add up, and do they line up digit for digit? List every fact that appears twice\n   and check that the copies agree; recompute each total and change from the values as displayed;\n   check that every relative figure names what it is against.\n5. Does every zero look like a zero and every missing value like a dash? Does every count badge sit\n   on a queue that needs action, with its noun clear from the label?\n6. Does every legend swatch match the mark it explains, and does any caption have to say which bars\n   are which (then encode it in the chart)? Does any label collide with a line or another label?\n7. On the phone, is the navigation folded away, and does each block still answer its question?\n\nFix the worst three, inspect again, look again. Three rounds at most. Judge the pictures: if a problem\nshows in a screenshot, it is real, whatever the code says.\n\n### 2.8 Report\n\nTell the user, briefly: the style dealt (name and seed) and any redraws with their reasons; the face\nyou chose and the signature element; each screen's one question; any check you allowed and why (for example `--allow icon-chips` for node-type\ntiles in a builder); and the sample data that must be replaced with real data, listed so it can be\nfound.\n\nApp screens have no motion floor. Motion is feedback: press, hover, focus, a menu or a sheet opening,\na row arriving. Nothing on the screen performs an entrance (house rule).\n\n## 3. The shell\n\n### 3.1 Five archetypes\n\n| Shell | In the study | What it is |\n| --- | --- | --- |\n| **Open plane** | 5 screens | A labelled sidebar on the page ground (or within 1-2% of it), separated by nothing or by one 1px hairline. No top bar: the header and the cards sit on the ground. The canvas is fluid with a 24-64px gutter, or a centred column. |\n| **Tinted frame, white sheet** | 8 screens | Sidebar and top bar share one tinted ground (#f6f6f6-#f9fbfc) with no rule between them; the page sits on a white sheet inset 8px from the window's right and bottom edges, radius 10-16 (median 16), a 1px #eaeaea-#ededed edge and no shadow. Variants: a flush L-frame, the inset sheet, and floating panels inset 8-12px with a 12px gap. |\n| **Ruled T-frame** | 4 screens | A 210-240px sidebar and a 64px top bar on one ground, divided only by 1px rules. The workspace switcher sits at the top bar's right end behind a full-height divider. Three of the four are dark. |\n| **Icon rail** | 3 screens | An unlabelled rail 50-60px wide (median 55); 15-18px icons on a 34-49px pitch; the active item marked by colour or by a 2% tint band; groups split by 20px hairlines. It saves about 180px of width. |\n| **No sidebar** | 3 screens | A 46-48px top bar over a centred 1088-1208px column with 152-212px gutters; the logo sits on the column's left edge. For reports, viewers and products with few destinations. |\n\nAll six dark screens use one ground everywhere, divided by 1px rules of #161616-#232323 or by nothing.\nNo screen in the study puts a dark or saturated sidebar against a light canvas (0 of 17).\n\n### 3.2 Sidebar\n\n- **Width.** Labelled sidebars run 210-292px; the median is 230 and most sit at 224-240. One floating\n  sidebar card appears (280px wide, 40px in from the window edge).\n- **Rows.** A 32px hit area on a 34px pitch is the mode (7 screens); the roomy versions run 40-52px on\n  a 42-60px pitch. Icons are 14-20px, median 16, outline at about 1.5px stroke on 14 of 16 screens.\n  Labels are 14px at 400 on 12 of 16, in ink or in a grey of #4b4d4f-#63666e, about 8-10px after the\n  icon, with the label column at x 36-48.\n- **Active item.** A neutral grey pill with the label unchanged, on 8 screens: radius 4-16 (median 8),\n  inset 8-14px from the sidebar's edges, a fill of about #e9e9e9-#ededed. On dark, brightness alone:\n  the label goes from #bbb to #fff (3 screens). Colour alone on the icon or label (3, all of them\n  rails or a floating card). A tinted accent fill (3). A left accent bar once in 23. The weight\n  changes on 2. Default: the grey pill on light, brightness on dark.\n- **Groups.** Sentence-case grey labels at 12-13px, never uppercase (9 screens), with 22-56px of air\n  above and 13-33px to the first item; or hairlines instead (4). Utilities such as settings and help\n  pushed to the bottom (5).\n- **Top and bottom.** The workspace or account switcher at the top of the sidebar (7 screens), at its\n  bottom (2), or in the top bar. The bottom holds a user row (8) or one upsell (8); one of those\n  upsells is a filled accent button.\n- **The product is named** (house rule, from testing). The product's mark and name sit at the top of\n  the sidebar or rail, and the scope (workspace, team, project, account) is shown as a switcher or a\n  breadcrumb. A screen whose product cannot be named from the screenshot reads as a template.\n- **Counts on nav items** (house rule, from testing). A count appears only on a queue that needs\n  action, and its noun is clear from the label: \"Requests 5\", \"Price changes 3\". A bare \"Range and\n  prices 9\" left the judge asking nine of what.\n- **Labels by default.** A labelled sidebar unless the product has five destinations or fewer and the\n  screen needs the width (a research or monitoring view); an icon rail always carries the product's\n  mark at the top, a tooltip and an accessible name on every icon. Nav items are other screens, never\n  anchors into the current page (a sidebar that scroll-spies one long page was marked down twice).\n\n### 3.3 Top bar\n\n14 of 23 screens have one; the default is none. Heights fall into two groups: 44-51px (median about\n48) on light chrome, and 64px, usually with a 1px rule. A top bar must hold something real: search,\nthe workspace switcher, or the page or object name. Search sits centred on the window at 548x32 with\na shortcut hint (2 screens), or at 457-537x36 in a no-sidebar bar. The right cluster is inset 24-46px\nfrom the edge. Two screens leave about 1070px of their top bar blank; both are flagged for it.\n\n### 3.4 Right rail and pinned columns\n\nOne screen has a right rail: a fixed 384px column in a `1fr 384px` grid with a 24px gap, starting\nlevel with the first card rather than with the title, its section headings outside the cards and 8px\nabove each. Use one only for a stable secondary stream: recent items, the details of the selected\nobject, share links. A pinned left column appears once: a 306px accounts card at the viewport height\nminus 72px, so net worth stays in view while the rest of the screen scrolls.\n\nFive screens float a button (24-56px), and one of those buttons covers the content it sits on and is\nflagged. House rule: no floating button unless it is the screen's one primary action and covers\nnothing at any width.\n\n## 4. The canvas and the page title\n\n### 4.1 Width and gutters\n\n- **Fluid** (14 screens): side padding 17-64px, median 29, with 24 and 36-40 the common values;\n  content 1120-1312px wide, median about 1204.\n- **Centred** (8 screens): 624, 864, 1088, 1100, 1152, about 1190 and 1208px; median about 1126.\n  Data pages land at 1100-1250 either way. Only two personal homes go narrow (624 and 864), and both\n  are flagged for wasting the width.\n- **Top offset**, from the canvas top to the title: 20-88px, median about 36. Tools sit at 20-36;\n  greeting homes at 50-88.\n- **One gutter.** Use one gap value horizontally and vertically. Mixed gutters (12 against 16, 20\n  against 24, 16 against 12) are flagged on 8 screens.\n\n### 4.2 One left edge, one right edge\n\nThe strongest screens run a single left edge from the header to the last row. One indents its page\nheader by the cards' 24px padding, so the title, the card titles, the numbers and the chart all start\non one line. Row rules may bleed 7-8px past the text column while the text stays on it.\n\nThe grid's arithmetic closes: 3 x 372 + 2 x 17 = 2 x 568 + 16 = 1152; 12 x 77 + 11 x 16 = 1100;\n4 x 144 + 3 x 16 = 624; a second-row card exactly as wide as the two cards above it\n(251 + 24 + 515). Write your sum down.\n\nFailures to avoid, all from the study: cards stopping 120px short of the sheet's right edge; a 0px\nright gutter against a 40px left one; a column centred on the window instead of on the area beside\nthe sidebar (204px on its left, 444px on its right); a medallion 108px off the column's axis. The\ninspector warns when the content stops well short of the right edge.\n\n**Dead space from a grid that does not fit the data** is the commonest failure in the study (10\nscreens): four KPI tiles in a three-column grid, orphaning the fourth; one card alone in a\nthree-column row beside 810px of nothing; a card stretched to its neighbour's height with 250px of\nblank under its legend. Choose the column count from the number of items, let a lone card span, and\ndo not stretch a card's frame over empty space.\n\n**Cards that share a row share a bottom edge.** In testing, rows whose cards stopped 26-190px apart\nwere marked down every time, by judges and by the inspector (`ragged-row`). Balance the row by its\ncontent first: move a list's rows so the two columns hold the same number, cap both lists at the same\ncount, or pair blocks of similar height. Two cards stacked in one column beside a tall card count as\none block: they balance when the column ends level. Only when the contents cannot balance, stack the\ntwo blocks, or let the shorter card fill the row height with its content top-aligned and the footer\naction (a \"View all\", a total) pinned to its bottom so the extra height is not a hole.\n\n**A stretched card stretches only when it has content to fill.** Only an action or a total may be\npinned to a stretched card's foot; a legend or a note stays directly under its chart. In testing, a\ncover card stretched to its neighbour with its legend pinned to the bottom left 60px of blank under\nthe last row, and a sell-out card left 45px above its links. When the content is short, let the card\nkeep its own height (`align-items: start` on the row), move its footer link into its header, or give\nthe row a block of similar height. A filtered block shrinks to its rows, or keeps a fixed number of\nrows with one sentence in the empty ones; four rows over 270px of empty card is a hole. The inspector\nwarns on a blank band of over 40px inside a card (`panel-void`).\n\n**Narrow blocks do not span the canvas.** A table of five columns or fewer, or a list of six rows or\nfewer, runs to about 760px at 1440 and pairs with the next block; stretched to 1300px it leaves\n400-600px voids between a name and its first figure.\n\n### 4.3 The title\n\n- **Every screen has one h1**; the inspector fails a screen without one. 14 screens set it in the\n  canvas at 18-48px, median and mode 24, at 600-700 (700 on 8). The rest have nothing over 16px: a\n  breadcrumb or the top bar names the page. Then the breadcrumb's last item is the h1, at 16px, and\n  the screen's name is still the first thing read.\n- **A noun, not a greeting**: \"Analytics\", \"Overview\", the project's or the object's name. 3 of 23\n  greet, and one adds an emoji, which goes. A greeting suits a personal or team home only.\n- **An optional second line**: one 14-16px grey sentence about the data or the object (the finding,\n  the period, the scope), never about the interface (\"the filters narrow every block…\", \"this page\n  shows…\" read as instructions, not a product), or a 12px line\n  naming the data's source.\n- **Right of the title**: actions only when they are real (10 screens); otherwise nothing. A freshness\n  stamp (\"Updated Jul 27, 4:09 PM\", with a refresh button) on 6.\n- **The primary action.** 12 of 23 have no filled primary button; 5 make it near-black (#1d1f20,\n  #1f2937) or inverted white on dark; 4 fill it with the brand hue. One primary per screen.\n\n### 4.4 Tabs, filters and the date range\n\n- **The date range** at page level (7 screens) or on each card (7), never both. A card that states its\n  own period puts it in its header, right-aligned, in grey.\n- **Underline tabs** (8 screens) always sit on a full-width 1px rule; the indicator is 1-4px (median\n  2), as wide as the label or running 8-11px past it.\n- **A segmented track** once: 48px, #f3f4f6, a white 36px active pill, and the date select inside its\n  right end, so tabs and range read as one row. A segmented control is as wide as its options, and full\n  width only below about 480px: three options spread across a 680px tablet card read as a progress bar.\n- **Control height** in title and filter rows: 28-40px, median 34, clustering at 32 and 36.\n- **Order**: scope on the left (the date first, then the filters), utility and refresh on the right.\n- **Compound filters** that read as a sentence (\"Date | Jun 14 - Jul 13 | Daily\"), 28px tall and 8px\n  apart, once.\n- **To the first card**: 13-64px, median 24.\n\n## 5. KPIs\n\n- **No tile of its own.** 11 of the 20 screens with headline numbers give a KPI no tile: bare text on\n  the page or on a card (5), or one container split by 1px hairlines (6). 9 use one card per KPI,\n  61-147px tall (median about 108). The default is one container split by 1px dividers into equal\n  columns. 7 screens have no KPI row at all and put each headline number in the card that explains\n  it, which is often better.\n- **Count.** 1-6 per row, median 3-4. The count matches the grid: four KPIs get four columns.\n- **Size.** Values 16-40px, median 26, mode 24. Values in their own tile run larger (median 30) than\n  in a shared strip (median 24). Nothing at 48px or over. Labels 12-16px, median 14; the value is\n  about 1.7 times the label.\n- **Weight.** An even split: 400 on 8 screens, 600 on 6, 700-800 on 6. A large number at regular\n  weight under a semibold label is the common pattern. Bold for money only.\n- **Order.** Label above the value on 14 screens; labels grey (#6b6b6b-#aaa) on 13; sentence case.\n- **Nothing else.** No icon in a coloured circle (0 of 23), no sparkline (0 of 23), no tinted tile.\n  An info icon beside the label is fine (5 screens). Units are a smaller grey suffix: \"5 mins\" at 24\n  over 14, \"2 m 24 s\", \"5 /10\".\n- **The answer figure leads.** When one figure is the screen's answer (a balance, net worth, the\n  portfolio's value), it is 30-36px and at least 1.3 times its sibling figures (those at 18-24px). In\n  testing, a 24px portfolio value beside two 24px figures left the screen without a lead. No other\n  figure on the screen is larger: the biggest number answers the title row's sentence, so a\n  secondary ratio in another card stays at the siblings' size.\n- **One figure, one place.** A figure shown in the strip is not repeated in a legend beside it, and a\n  KPI strip whose every cell names a panel below (RSVPs, then an RSVPs panel) is dropped: lead each\n  panel with its own number instead.\n- **A second job.** KPIs may be the chart's series tabs or the list's type filter (the selected card\n  takes a 1.5px border). As tabs, the selected one carries a 2px rule or the active fill and an ink\n  label; the others keep a grey label and their value in ink, at 400 against the selected one's 500.\n  A grey value reads as disabled: in testing, three shops' takings set in grey because they were tabs\n  read as secondary, though they were the brief's first ask. When the tabs are the per-entity\n  breakdown the brief asks for, grey nothing and let the rule alone mark the selection. On a phone the\n  tabs become a 2-up grid with the selected cell filled, or a row that scrolls sideways; never an\n  underline floating inside the grid (`app.css` does both).\n\n### Deltas\n\n- Optional: 9 of the 20 KPI screens show one; 11 do not.\n- 10-15px (median 14), never larger than the label. Text or a small glyph on 6 screens; a pale pill\n  on 3.\n- **The window in words**: \"vs prior 30 days\", \"in the last 90 days\", \"from 0 (last 4 weeks)\" (7 of\n  the 9).\n- **Colour only the number**, or set the whole delta in grey.\n- **Colour says good or bad, not up or down** (house rule, from testing). Every metric has a good\n  direction: latency, error rate, cost, churn and time-to-reply are better when they fall. A change\n  in the bad direction puts `--negative` on the number (or a small down-pointing glyph in that\n  colour); a change in the good direction is `--positive` or grey. A judge read a 2.5× rise in errors\n  set in the same grey as a rise in visits as hiding the screen's only bad news.\n- **Zero or undefined change is grey.** The study's commonest KPI failure is a zero or undefined change\n  shown as a signal: three identical green \"up 100%\" pills grown from zero, a \">999%\", a bold red\n  \"0.00%\", a green \"+0\". When the prior period was zero, write \"+4 (new)\"; when there is nothing to\n  compare, a short grey dash where the delta would be.\n\n## 6. Charts\n\n### 6.1 Which chart for which question\n\n| Question | Form | In the study |\n| --- | --- | --- |\n| Is it moving over time? | One line; an area only with a fill of 15% or less | 9 screens |\n| How much per period? | Columns with square corners | 3 |\n| How is it distributed? | A histogram with equal bins | 1 (its unequal bins are flagged) |\n| Who ranks? | A sorted horizontal bar list, or the row's fill as the bar in a one-figure list | 3 |\n| What share? | A thin ring, or a 100% stacked bar with 2px seams; five parts at most | 5 |\n| How far to the target? | A progress bar, both ends labelled, the fill the true ratio | 4 |\n| How much of the plan is used? | A track as long as the plan, the spent part filled, what is already committed as a lighter segment, an overrun past the track's end in the negative colour (`Charts.plan`) | house rule |\n| Has it drifted from its target? | One row per part: the current share as a bar with a 1px tick at the target (`Charts.bullet`); never two stacked bars to compare | house rule |\n| Where? | A map with a list beside it; the list carries the magnitudes | 1 |\n| Per period, and the running total? | The two side by side at equal width, with the same dates | 1 |\n| Which way did it flow, and how much? | Columns above and below one zero line on one scale, the axis signed and captioned on each side (\"Sold\" above, \"Bought\" below), a marked period in a second tone with its own legend entry (`Charts.diverging`) | house rule |\n| Who is away when? | A timeline of people by day, each kind of booking its own mark (`Charts.timeline`) | house rule |\n| Is there enough cover? | A team-by-day matrix of slack against the minimum (+2, +1, 0, −1), one hue ramping toward the negative colour, the headcount on hover (`Charts.matrix`) | house rule |\n| When in the day, against last time? | One row per item on a shared opening-to-closing axis: a 2px grey track, an ink dot for today, a hollow tick for the comparison day (`Charts.timeStrip`) | house rule |\n\nThree more, from testing:\n\n- **The pair of per-period bars and the running total is used once per screen**, and only when the\n  total crosses a line that matters (capacity, a target). Three such pairs in six charts read as one\n  pattern stamped out.\n- **A series that is flat except for one event** gets at most two-thirds of the width and about 140px of\n  height, or a range capped at about twice its reference line with the off-scale peak labelled\n  (`Charts.line({ max })`). A full-width plot that is 85% empty was the biggest block on a first\n  screen and was marked down.\n- **A forecast is not a fact**: after today the line is dashed and the end value is labelled\n  (`Charts.line({ today, endLabel })`), with the gap to the target bracketed when there is one.\n- **What the brief asks to see over time is drawn on the first screen.** KPI cells may switch the chart\n  only between metrics the brief did not name.\n\nWhen there are only a few numbers, draw no chart: four screens skip it, and the settings page links\nto the analytics screen with \"View more\".\n\n### 6.2 One question, one series\n\nOne series per chart is the norm; three is the most any screen draws. To show another metric, switch\nit with a control (a segmented control, a dropdown, the KPIs as tabs) instead of overlaying lines.\nPlots run 112-264px tall (median about 195) and 316-1136px wide (median about 570), an aspect of 1.8\nto 5.2.\n\n### 6.3 Axes and gridlines\n\n- **Gridlines** run horizontally only on 7 of the 12 cartesian charts, both ways on 3, and not at all\n  on 2. Use 3-5 (the study runs 3-7, median 4-5): 1px, solid, about #e5e5e5 on light (range\n  #cfcfd2-#f2f2f2), #2b2b2b on #111. Dashed lines are allowed in chart grids (4 screens: 3/3, 4/4,\n  3/2.5) and nowhere else on the screen.\n- **No y-axis line.** The baseline is the one heavier line (2px on two screens, 1px on one); full axes\n  on one.\n- **Y ticks**: 4-7, median 5, at 11-16px (median 12) in grey (#5f5f5f-#6c6c6c), on the left (8\n  screens) or the right (2). Round, even steps (0/5/10/15%; 0-600 by 150), the top tick above the\n  maximum, integers for counts, and zero as the baseline for bars and counts.\n- **Never without a scale.** Two screens draw no y-scale and show magnitude only on hover; both are\n  flagged. So are uneven ticks (0/3/6/10), a 0.8 tick on a count, a top tick equal to the maximum so\n  the line hits the plot's edge, and a cumulative axis that starts at 1.\n- **Axis text no larger than the data.** 15-16px ticks beside 14px values are flagged as louder than\n  the numbers.\n- **X labels**: 4-8 per chart, flat, never rotated (40 degrees is flagged), the first and last pulled\n  inside the plot, on one step all the way: a forced closing label after 14:00 on a 90-minute step\n  left a short last gap that a judge measured. Choose a step that lands on the end (hourly from 08:00\n  to 15:00) or leave the end unlabelled. Labelling only the two ends hides when things happened. Irregular dates on a\n  categorical axis are flagged: time goes on a time scale.\n\n### 6.4 Marks\n\n- **Lines** 1-3px, median 2, in straight segments. Four screens smooth their lines, and one smoothed\n  curve invents values between daily totals (flagged), so draw straight segments. No point markers,\n  except a hover dot (8px on one screen).\n- **Fill**: none on 7 of 10 time charts. At most a flat tint of about 14%, or a fade from the line to\n  transparent over 150-200px.\n- **Bars** have square corners (4 screens), or at most a 4px top radius with a square bottom on the\n  baseline. Stacked segments are split by a 1-2px seam.\n- **Colour.** One hue per chart. The accent touches only data on 8 screens, and data ink is under 3%\n  of the pixels on most. Neutral series are fine and often better: a near-black line that turns pale\n  grey after the cursor; a white line against a red one; signs instead of colour (\"+$24,000,000\").\n  But the one hue, when the style has one, goes on the screen's main data element (today's series,\n  the booked bars, the current period, the margin that breaks), not on a secondary chart or a delta:\n  in testing, an all-ink screen with no hue on any of its data read as a kit.\n  One subject keeps one hue across the screen: the same subscribers drawn pink in one chart and indigo\n  in the next is flagged. Unrelated hues on one screen (three, five) are flagged every time. Status\n  colours are for status. The inspector warns over four hues and fails over six.\n- **Legends.** None for a single series (9 charts): the title or the dropdown names it. Otherwise five\n  items at most, as a 5-8px dot with a 12-14px grey label in the card's header, or as a small table\n  (dot, name, value, change) that makes the legend carry data. Never list a series that has no data\n  (flagged). Every swatch is the mark it explains, scaled down: the legend dot is the line's colour,\n  a hatched bar's swatch is hatched. A swatch drawn separately from the mark drifted from it in testing\n  (a black outline with a red edge explaining a red outline); the helpers return the legend built from\n  the same style object as the marks.\n- **Rings** only for three to five parts of a whole that are not already listed beside them (a ring\n  redrawing the spent, due and left figures of the tile next to it was marked redundant). Never\n  labelled on the slices; the total sits in the centre or beside the ring. The\n  screens noted for their rings use thin strokes: 3-5px on a 90-154px ring, 8px on 182px. Two others\n  use 28 and 37px.\n- **Progress bars** are 4-24px tall (median 8), fully rounded, with both ends labelled (\"Skilled 200\"\n  and \"Expert 2,000\"); the fill is the true ratio, so 303 on that scale fills 22px of 392. A zero has\n  no stub (a 6px stub at zero is flagged).\n- **Tooltips** are bare text or a plain box without an arrow: label and value on one line.\n- **Annotate the event that matters.** A step or a spike more than about three times the usual change\n  gets a 1px marker and a 12px label naming its cause (\"Deploy a3f09c1\", \"Newsletter featured\");\n  reference lines (a budget, an SLO, a start time) are 1px dashed with their label at the end. In\n  testing, an unexplained jump was the first thing a judge asked about. `Charts.line`,\n  `Charts.bars` and `Charts.diverging` take `annotations` and `reference`.\n- **Labels never collide.** Annotation labels sit in rows above the plot, each beside the top of its\n  own leader line, and no leader line runs through another label; the rows are reserved only when a\n  label exists, so a chart without one has no dead band above it. The \"Now\" label of a forecast goes\n  on whichever side of its line the series does not cross. Lay labels out after the fonts load, or\n  the label set changes between loads (it did in testing). The helpers do all of this; give a label\n  that may not fit a `short` form.\n- **Use the helper, then extend it.** Draw charts with `assets/charts.js` and add what a chart needs to\n  it, rather than writing new axis code: in testing, every chart written from scratch on a phone put\n  its y labels on top of its line.\n- **Short and empty histories are drawn honestly**: a flat zero line with one spike, missing bars for\n  empty periods, no padded y-range, no \"No data\" picture. Do not give one point the screen's largest\n  plot, though: a lone dot in a full-size grid reads as barren (flagged once).\n\n## 7. Tables and lists\n\n### 7.1 Rows\n\n- Single-line data rows: 36-53px, median 45.\n- Two-line rows with media: 56-92px, median 72. The pitch is the media's height plus 24-32px\n  (48 + 24, 48 + 32, 50 + 30).\n- Key-value and legend rows inside cards: 21-32px.\n- In a two-line cell, line 2 sits about 21px below line 1 (19-23), one size smaller (12-14px) and\n  grey. Two-line labels need a 40-44px pitch at least: on a 32px pitch a subline nearly touched the\n  next row's name and the list ran together (house rule, from testing).\n- Overview lists show 2-5 rows.\n\n### 7.2 Header\n\n- 11-14px, median 12, mostly regular weight, grey, sentence case (9 of the 11 headed tables). The one\n  uppercase header in the study is flagged as louder than the data.\n- **No fill band** (0 of 11) and **no rule under it** on 8 of 11. Where there is a rule, it is the\n  strongest line in the table (#e5e7eb over #f3f4f6 row rules).\n- Header row 36-40px.\n- Numeric headers are right-aligned and flush with their values; a header that stops 15px short of\n  its column is flagged. A header over a control aligns with the control it labels (centred over a\n  column of steppers), and a delta beside a stepper gets its own narrow unlabelled column; three\n  alignments in one header row were flagged.\n- A sort glyph on the active column only.\n\n### 7.3 Dividers\n\n- **No zebra striping** (0 of 23).\n- No row dividers on about half the lists; they rely on a 61-92px pitch or on 2-8px gaps between\n  filled rows.\n- When present: 1px, 3-7% darker than the surface (#ededed-#f4f4f4 on white; #161616 on #000,\n  #1b1a1f on #131217).\n- Extent: bleeding 8-9px past the text edge; starting at the text column and skipping the media; or\n  the full inner width. Pick one per screen.\n\n### 7.4 Figures and alignment\n\n- **Numbers right-aligned**, in tabular figures or a monospace. Every left-aligned numeric column and\n  every column of proportional digits in the study is flagged (durations \"00:00:12\" and \"00:00:04\"\n  that jitter, cents that drift).\n- **Fixed decimals per metric**: money 2, percentages 1 or 2, counts none. Thousands separators\n  everywhere (\"$16,531.54\"); abbreviate only in a capacity line (\"12.7k of 20.0k\"). A sign on ever\n\n<!-- [TRUNCATED AT 50KB] -->","isInternal":false,"tokens":13267,"sizeBytes":50062},{"name":"colour.md","path":"skills/taste-skill/references/colour.md","rawUrl":"https://raw.githubusercontent.com/Leonxlnx/taste-skill/HEAD/skills/taste-skill/references/colour.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Colour\n\nThe direction sheet deals a palette with named roles. This file is how to apply it so the page looks\ndecided rather than tinted.\n\n## Contents\n\n1. What the study measured\n2. The roles\n3. Proportion\n4. Surfaces without lines or shadows\n5. Colour fields\n6. Dark pages\n7. Colour and photographs\n8. Contrast\n9. Banned families, and what \"warm\" means here\n\n## 1. What the study measured\n\n- 41% of the studied pages are dark, 59% light. A quarter sit on pure white; 12% on pure black.\n- Schemes, as the panel classed them: monochrome plus one accent 23%, light neutral 22%, dark neutral\n  14%, several flat colours 13%, strictly two-tone 12%, colour carried by photographs 9%, one saturated\n  field 6%.\n- Buttons are neutral (black, white, grey) on 52% of sites. A coloured button is a choice, not a\n  requirement.\n- Gradient fills appear on 22% of the top-scored sites and 52% of the weak ones; gradient text on 2%\n  against 13%.\n- One site in 246 has a terracotta primary button and none has a violet one. Those are colours of\n  generated pages, not of the gallery. Warm off-white grounds do occur (32 sites), nearly always with\n  a dark or green ink rather than an orange accent.\n- Top-scored sites change the page's field colour between sections more often (a median of two section\n  grounds against one).\n\n## 2. The roles\n\n```css\n:root {\n  --bg: …;          /* the ground: most of the surface */\n  --surface: …;     /* one tone step from the ground: filled panels, form fields, tiles */\n  --ink: …;         /* main text and the strongest marks */\n  --muted: …;       /* secondary text; still passes contrast on --bg */\n  --accent: …;      /* the one accent */\n  --accent-ink: …;  /* text on the accent */\n  /* --field-1 … --field-n and their inks, when the palette has section fields */\n}\n```\n\nUse the tokens for every colour in the build. A raw hex in a component is a second palette starting.\nDo not add greys between the roles: if you need a quieter text, it is `--muted`; if you need a quieter\nsurface, it is `--surface`.\n\n## 3. Proportion\n\nDecide the shares before colouring anything and check them in the screenshot:\n\n- **Ground:** 70–90% of the page.\n- **Ink:** text and perhaps one inverted section (ink as ground, ground as ink).\n- **Accent:** under 5% of any screen. It marks the action and at most one other recurring thing. The\n  moment it appears in five places it stops meaning \"here\".\n\nPalettes with fields (flat-loud, pastel) work differently: each section is one field at full strength\nand the proportion rule applies inside each section (field, its ink, nothing else).\n\nThe accent is not for headings, icons, bullets, borders or underlines unless the direction sheet says\nso. A headline is ink.\n\n## 4. Surfaces without lines or shadows\n\nWith rules and shadows banned, a surface is told apart from the ground by tone alone:\n\n```css\n.panel { background: var(--surface); }          /* 2–6 lightness points from --bg */\n.field { background: var(--surface); border: 0; } /* inputs: filled, with a clear focus state */\n.field:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }\n```\n\n- One step is enough. If a panel does not read, increase padding or separate with space before\n  reaching for a second tone.\n- Do not nest a panel inside a panel.\n- Images do not need a frame. If a light photograph melts into a light ground, change the crop or set\n  it on `--surface`, do not outline it.\n- A thick bar (4px or more) in ink or accent is a graphic element, allowed where the direction uses\n  it. A 1px line is not.\n\n## 5. Colour fields\n\nA section that changes the whole ground colour is the strongest colour move available, and it replaces\ndividers, cards and background decoration at once.\n\n- Fields meet edge to edge with a hard line. Nothing fades.\n- Every field has its own assigned ink from the palette. Never put `--muted` on a coloured field; use\n  the field's ink at full strength, or at 70% opacity for secondary text if it still passes contrast.\n- Neighbouring fields should differ in lightness, not only in hue, or the page vibrates.\n- Order them like chapters: open strong, rest, surprise, close dark or very light.\n- The page's meta theme colour and the navigation follow the first field.\n\n## 6. Dark pages\n\n- Put `color-scheme: dark` on the root so form controls and scrollbars follow.\n- The ground is a deep tone with a slight tint from the palette, and the ink is a soft light, not\n  `#fff` on `#000`, unless the palette deals exactly that for a stark two-tone direction.\n- Secondary text is where dark pages fail: check `--muted` against the ground (4.5:1).\n- Depth on dark comes from a lighter surface step, never from glows or coloured light.\n- Use lighter font weights than you would on a light page.\n\n## 7. Colour and photographs\n\n- When photographs carry the colour, the interface stays neutral and takes its ink from the darkest\n  tone in the imagery.\n- Do not wash a photograph with the brand colour. Either leave it alone, or commit to a real treatment\n  for every image on the page (all greyscale, or all untouched).\n- Text over a photograph needs a calm region. If there is none, move the text off the image. A neutral\n  scrim (black or the ink colour, 30–55% opacity, flat or fading over the text area only) is the one\n  gradient the inspector allows.\n- A flat field sampled from a photograph (its sky, its shadow) makes a section sit with that image.\n\n## 8. Contrast\n\n- Body text 4.5:1 or better; display type and large numerals 3:1 or better; the dealt palettes meet\n  7:1 for ink on ground.\n- `inspect.mjs` computes contrast for text on flat grounds and fails anything under 2.6:1. It cannot\n  see text over photographs: check those in the screenshots yourself.\n- Do not lower opacity on text to make it \"soft\" unless you have checked the resulting ratio.\n- Focus states and hover states increase contrast, never reduce it.\n\n## 9. Banned families, and what \"warm\" means here\n\nThe inspector fails these:\n\n- **Cream with terracotta.** A yellow-cream ground (roughly hue 22–62, light and noticeably\n  saturated) with a rust, clay or burnt-orange accent is the house look of AI assistants and of the\n  pages they generate. Either half alone is suspect; together they are unmistakable.\n- **Violet and indigo.** The first wave of generated pages was purple; it still reads that way.\n\nIf the brief wants warmth, get it from a low-chroma stone, bone or putty ground (saturation under\nabout 15%), from a deep green, brown or oxblood ink, from photographs, or from a full warm field\n(mustard, tomato red, pink) used flat and with conviction. Warmth is not beige.\n\nIf the brand itself owns one of the banned colours, it is the brand's and you keep it: use\n`--keep palette`, pass `--allow palette-purple` (or the relevant rule) to the inspector, and note it in\nthe report.\n","isInternal":false,"tokens":1720,"sizeBytes":6853},{"name":"copy.md","path":"skills/taste-skill/references/copy.md","rawUrl":"https://raw.githubusercontent.com/Leonxlnx/taste-skill/HEAD/skills/taste-skill/references/copy.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Words\n\nCopy is the first design decision. A headline that needs four lines cannot be rescued by typography,\nand a page of slogans cannot be rescued by layout. Write the page as plain text before any markup.\n\n## Contents\n\n1. Write the argument first\n2. The two-line headline (with the character budget)\n3. Headline shapes that work\n4. Supporting line, body, buttons\n5. Proof without inventing it\n6. Things that read as generated\n7. Micro-typography\n\n## 1. Write the argument first\n\nAnswer in one line each, in a scratch note:\n\n- Who is reading, and what do they already know?\n- What is this, said the way its maker would say it to a friend?\n- What single thing should the reader believe after one screen?\n- What would make them believe it (a picture of the thing, a number, a name, a demonstration)?\n- What do they do next?\n\nThen list the page as claims, one per section, each with its proof:\n\n```\n1. It is a three-legged oak stool, made to order.             → the stool, large\n2. Each seat is cut from one board, so the grain is yours.    → three close-ups\n3. It takes six weeks, and you can follow it.                 → the stages, photographed\n4. It costs 240 and is delivered by the maker.                → price, button\n```\n\nA section with no claim is filler; delete it. This is also how you escape the stock order of\nhero, logos, features, testimonial, pricing, call to action: the order of the argument is the order of\nthe page.\n\n## 2. The two-line headline\n\nA headline is a title. It is held in one glance. On the studied gallery sites the hero headline has a\nmedian of 5 words and 70% sit on one or two lines at desktop width. Every headline on your page, at\nevery viewport, fits in **two lines or fewer**. `inspect.mjs` measures this at 1440, 768 and 390 pixels\nand fails the page otherwise.\n\nThe constraint is arithmetic, so do it before you fall in love with a sentence:\n\n```\ncharacters per line ≈ line width in px ÷ (font size in px × k)\n\nk ≈ 0.40  condensed faces\nk ≈ 0.50  most grotesks and serifs at display size, tight tracking\nk ≈ 0.58  wide / extended faces, all-caps settings\n```\n\n| Where | Line width | Size | Per line | Two-line budget |\n| --- | --- | --- | --- | --- |\n| Phone 390, 20px gutters | 350px | 44px | ~16 | **~32 characters** |\n| Phone 390, 20px gutters | 350px | 34px | ~21 | ~42 characters |\n| Tablet 768 | 690px | 64px | ~22 | ~44 characters |\n| Desktop, 12-col measure | 1100px | 104px | ~21 | ~42 characters |\n| Desktop, half width | 620px | 72px | ~17 | ~34 characters |\n\nSo a hero headline of **about 32 characters or fewer** (four to six words) survives everywhere at a\nconfident size. Up to about 42 works if the phone size comes down to the mid-30s. Past that you are\nwriting a sentence; move the rest into the supporting line.\n\nControlling the break:\n\n- Give the headline a `max-width` in `ch` so it breaks where you intend, and add\n  `text-wrap: balance` so two lines come out even.\n- Where the break matters (it usually does), author it: `Stools for<br> small kitchens`. Check the\n  phone screenshot; if an authored line wraps there, hide the `<br>` under a breakpoint or shorten.\n- Never fix a long headline only by shrinking it. A timid 28px headline of nine words is worse than\n  five words at 64px.\n- Avoid a single orphan word on line two. Rebalance by cutting a word, not by nudging the width.\n\nSection headings follow the same rule and are shorter: two to five words.\n\n**A statement is not a headline.** An intro sentence or a quotation set large (the manifesto line\nafter the hero, a testimonial) is a paragraph: mark it up as `<p>` or `<blockquote>`, keep it to about\n25 words, and set it at statement size, which the inspector takes as 36px or less on desktop, 32px on\na tablet and 24px on a phone. It may then run to about three lines (four on a phone). Set larger than\nthat, or marked up as a heading, or placed as the main line of the first screen, it is a headline and\ngets two lines. In blind judging, a sentence set big over three or more lines was read as a long\nheadline every time, whatever its markup; if the words matter that much, cut them to a two-line\nheadline instead.\n\n## 3. Headline shapes that work\n\nAll seen repeatedly on the gallery sites. Pick the plainest one that is true.\n\n- **The name.** The brand or the person, set very large, with a one-line description elsewhere.\n  Strongest when the name is short and the subject is visual (studios, restaurants, hotels, people).\n- **What it is.** \"A vinyl shelf in your pocket.\" \"Furniture for small rooms.\" Category, stated with\n  one specific word.\n- **The claim.** \"Your bank won't do this.\" One sentence a competitor could not sign.\n- **The instruction.** \"Understand your money.\" Verb first, short.\n- **The place or the moment.** \"Antarctica.\" \"Lisbon, since 1984.\" For hospitality, events, travel.\n\nShapes to avoid, because they are the average of every landing page:\n\n- The mad-lib: \"The AI-powered platform for modern teams\".\n- The tricolon: \"Fast. Simple. Secure.\" or \"Plan. Build. Ship.\"\n- The correction: \"It's not just a tool, it's a workflow\". Also \"More than a …\".\n- \"X, reimagined / redefined / made simple\". \"Welcome to …\". \"Meet …\" for a product nobody has met.\n- A question the reader did not ask.\n- A headline that needs its colon: \"Ledgerly: invoicing for freelancers\". Drop the name, it is in the\n  navigation.\n- One word of the headline styled differently (italic, serif, coloured, underlined, in a pill).\n\nSentence case. No full stop unless the direction's voice uses them everywhere.\n\n## 4. Supporting line, body, buttons\n\n**Supporting line.** One sentence, at most about 22 words, that says concretely what the thing is and\nwho it is for. It is where the detail cut from the headline goes. It never repeats the headline in\nother words.\n\n**Body.** Short paragraphs of plain statements. Prefer the specific noun and the real number: \"ships\nin a week\" over \"fast delivery\"; \"38 seats\" over \"intimate\". Read every sentence and ask whether a\ndifferent company could print it unchanged; if so, sharpen it or cut it.\n\n**Buttons.** Name the action or the thing: \"Book a table\", \"See the plans\", \"Download for Mac\".\nOne to three words. The primary action keeps one name everywhere on the page. One primary button per\nscreen; a second action is a plain text link. No arrow glyph on every link and button; at most one\narrow, on the primary action, if the direction uses arrows at all.\n\n**Navigation.** The wordmark, up to five plain links, one action. Link labels are single nouns.\n\n## 5. Proof without inventing it\n\nNever invent customers, quotes from named people, press logos, user counts, ratings or benchmarks.\nInvented proof is both dishonest and a recognised tell.\n\nWhen the brief supplies no proof, use what is true by construction:\n\n- Show the thing itself, large. A real demonstration outranks any quote.\n- State how it works, specifically.\n- Use facts from the brief (price, place, year, materials, what is included).\n- If a testimonial or logo section is explicitly requested and no real ones exist, build the section\n  with plainly fictional sample content and say so in your final report so it is replaced before\n  launch. Do not put real company names or real people in it.\n\n**Sample details are different from proof, and they are expected.** Where the brief gives the shape of\nthe content but not every detail (six rooms \"from €140\", \"a short menu\", twelve speakers), write the\nfull set of plausible details: each room with a name, a bed, a view and its own rate; each dish with\nits price; each speaker with a talk title. A design can only be judged at its real density, and a page\nthat shows one rate where six rooms exist looks unfinished. List every sample detail in the report so\nthe client confirms or replaces it.\n\n## 6. Things that read as generated\n\n`lint.mjs` flags most of these.\n\n- Verbs and adjectives of the genre: unlock, unleash, supercharge, elevate, empower, streamline,\n  seamless, effortless, robust, cutting-edge, next-generation, world-class, all-in-one, blazing fast.\n- Labels pretending to be editorial: \"Field notes\", \"The details\", \"Our philosophy\", \"Quietly trusted\n  by\". A section heading can simply be \"Pricing\".\n- Furniture text: locale or time strips, \"Est. 2024\", coordinates, version stamps, \"Scroll\", \"(Scroll\n  to explore)\", fake photo credits, status lines such as \"Available for work\" with a dot, strings of\n  words separated by middle dots or slashes.\n- The em dash as a habit. One or two on a page read as writing; ten read as a model. Use a full stop.\n- Explainer captions that narrate the design: \"A clean, minimal layout for…\".\n- Step labels that duplicate numbers: \"Step 1\", \"Phase 02\".\n- Three parallel items everywhere: three features, three stats, three steps. Use the number the\n  content has.\n\n## 7. Micro-typography\n\n- Curly quotes and apostrophes (“ ” ’), a real ellipsis (…), an en dash for ranges (9–5).\n- Non-breaking space between a number and its unit, and before the last short word of a headline\n  when it would otherwise orphan (`&nbsp;`).\n- `font-variant-numeric: tabular-nums` where numbers line up in columns (prices, tables).\n- `text-wrap: balance` on headings, `text-wrap: pretty` on paragraphs.\n- No all-caps for anything longer than three words; if you set caps, add 0.02–0.06em tracking.\n- No text under 13px. No centred paragraphs longer than three lines. No justified text.\n","isInternal":false,"tokens":2369,"sizeBytes":9436},{"name":"critique.md","path":"skills/taste-skill/references/critique.md","rawUrl":"https://raw.githubusercontent.com/Leonxlnx/taste-skill/HEAD/skills/taste-skill/references/critique.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Critique — judging the render\n\n`inspect.mjs` passing means nothing banned or broken was measured. It says nothing about whether the\npage is good. This file is how you find out. Use it on the screenshots, never on the code: you wrote\nthe code, so you will read your intentions into it. The pictures only show what is there.\n\n## Contents\n\n1. How to look (fourteen passes, a few minutes)\n2. The score\n3. Caps\n4. Writing the critique\n5. What to fix first\n6. When to stop\n\n## 1. How to look\n\nOpen `desktop-fold.jpg`, then the `desktop-page-*.jpg` sheets, then `mobile-fold.jpg` and the mobile\nsheets. Make each pass on its own; do not blend them.\n\n1. **One second, then five.** Glance and look away. What did you see? There should be exactly one\n   answer: a word, an image, an object. If the answer is \"a website\", there is no focal point. Then\n   give the first screen five seconds as a stranger: can you say what this is, who it is for and\n   what to do next? If the title only makes sense after scrolling, it is not a title.\n2. **Squint.** Blur your attention until text becomes grey bars. The page should reduce to two or\n   three large masses with clear size differences. Many small similar masses means everything is\n   medium and nothing leads.\n3. **Cover the logo.** Could this first screen belong to a competitor, or to a different industry?\n   If swapping the name and the noun in the headline would produce an equally valid page, the page has\n   no idea. Go back to the direction sheet; the idea is written there. Then scroll: does the idea reach\n   the pricing, the FAQ and the footer, or does the page turn into stock blocks after the first screen?\n4. **Edges.** Follow the left edge of every text block down the page. Count the distinct x positions.\n   A composed page has two or three, reused on purpose. Six means things were placed one at a time.\n5. **Space and frame.** Are related things close and unrelated things far? Is the gap between sections\n   clearly larger than any gap inside a section? Is any region empty by accident (a hole) rather than\n   by decision (a rest)? A hole usually sits beside a short column or under a removed decoration.\n   Then look at the frame: are the left and right margins of the page the same? Does any section keep\n   its text in one half and leave the other half empty? Is there a stretch of nothing taller than half\n   a screen? Readers name these first (\"it is pushed to the left\", \"random empty space\"), before any\n   detail; in the study of 100 Sites of the Day about 1 section in 100 left half the width empty.\n6. **Type.** Is the jump from body text to headline decisive (three times or more)? Do you see more\n   than five sizes? Any headline with one orphan word on its last line? Any paragraph wider than about\n   75 characters or centred over more than three lines?\n7. **Colour.** Name the proportions: which colour holds most of the surface, which supports, where is\n   the accent? An accent that appears in ten places means nothing. One that appears on the single\n   action and one detail means \"here\".\n8. **Images.** Count the real pictures: are there at least four, and is there a moving one? A page of\n   drawings only, or of type only, looks unfinished next to one with real photographs and footage.\n   Is every image doing a job (showing the thing, setting the place, proving the claim)?\n   Do the crops share ratios? Is anything a grey box, a stretched photo, a fake screen made of bars?\n   Does the photography share one light and one grade, or is it a stock mix?\n9. **Sameness.** Write one word for each section's layout (split, list, full-bleed, grid, statement,\n   index …). The same word twice in a row, or three times on the page, is the template showing.\n10. **Phone.** Is the mobile screen a composition of its own, with its own crop and its own line\n    breaks, or the desktop page squeezed? Is the first screen still one clear thing?\n11. **Fullness.** Go through the desktop sheets screen by screen. Is each screen a composed poster, or\n    is it a narrow column of small text with dead ground either side? Is any statement held on screen\n    for three screens? An austere page is not a restrained one: if the page could be mistaken for an\n    unfinished wireframe (grey shapes, grey text, one small column), it is underbuilt. A single motif or\n    drawing blown up to fill a whole screen with nothing to read is a hole too, however bold it looks.\n12. **Substance.** Does every section the brief asked for deliver its information completely and at a\n    readable size (the full menu, each room, every speaker, the price and what it includes)? Would the\n    visitor leave knowing what they came to find out? Is the primary action a real button on the first\n    screen?\n13. **Collisions.** Is anything lying on top of a headline, a statement or a button at any scroll\n    position? Does any element run off the edge of the phone screen? A row that scrolls sideways on\n    the phone reads as cut off in a screenshot and to most visitors; wrap it unless the cut is\n    plainly deliberate (a partial card showing at the edge).\n14. **The competitor and the live thing.** Put the nearest competitor's name on the page: does the\n    idea still work? Then name the one live thing (what the visitor can do or what differs each visit).\n    If either answer is weak, that is the first problem of the round, ahead of any detail.\n\nA note from testing: in blind comparisons a richer page full of template devices beat a cleaner page\nthat was thin, every time. The house rules remove the devices; passes 11–13 are where you make sure the\npage did not lose its substance with them.\n\n## 2. The score\n\nScore like an Awwwards juror: four criteria, 1–10 each, weighted **design 40%, usability 30%,\ncreativity 20%, content 10%**.\n\n**Design (40%)** — composition, typography, colour, imagery, craft.\n- 9–10: every screen holds as a poster. Nothing could be removed or moved.\n- 8: confident and coherent; one or two soft spots a designer would notice.\n- 7: clean and professional, a clear system, little tension.\n- 6: tidy but anonymous. Reads as a kit.\n- 5 or less: weak hierarchy, accidental spacing, default type, mismatched images.\n\n**Usability (30%)** — orientation in three seconds, readable text, obvious actions, honest mobile.\n- 9–10: you know what it is, who it is for and what to do without scrolling; flawless on a phone.\n- 8: clear and comfortable; minor friction (a long section, a small target).\n- 7: works, with one real problem (weak contrast somewhere, a cramped phone layout).\n- 6 or less: you have to hunt, or something breaks.\n\n**Creativity (20%)** — an idea you can state in a sentence, carried through.\n- 9–10: a concept specific to this subject that you have not seen applied this way.\n- 8: a clear idea with one memorable move.\n- 7: a tasteful execution of a known approach.\n- 6 or less: the category default.\n\n**Content (10%)** — words and pictures that are specific, true-sounding and edited.\n- 9–10: every line could only be about this subject; imagery is the subject.\n- 7–8: clear and concrete, some generic lines.\n- 6 or less: slogans, filler, stock.\n\n`overall = 0.4·design + 0.3·usability + 0.2·creativity + 0.1·content`\n\nFor calibration: real Sites of the Day land around 7.5–8.0 overall from the jury. An honest 8.5 is\nrare. If your first score for your own work is 9, score it again as the juror who did not build it.\n\n## 3. Caps\n\nThese override the arithmetic.\n\n- Any `FAIL` still reported by `inspect.mjs`: overall cannot exceed **6.0**.\n- A headline of three or more lines at any viewport, an eyebrow label, monospace labels, 01/02/03\n  numbering, a decorative gradient, a shadow on a resting element, or a decorative hairline visible in\n  a screenshot: overall cannot exceed **6.5**, whatever else is true.\n- Pass 3 fails (the page could belong to anyone): creativity cannot exceed **6**.\n- The idea passes for the nearest competitor (pass 14): creativity cannot exceed **7**.\n- Fewer than four real pictures (photographs, archival images, footage; drawings do not count):\n  design cannot exceed **6.5**.\n- A page that barely moves (the inspector's `still-page`), or motion that is one identical fade on\n  every block: design cannot exceed **7**.\n- No live thing (pass 14): creativity cannot exceed **7.5**.\n- Any placeholder (grey box, lorem, \"Image here\"): content cannot exceed **5**.\n- Two or more desktop screens that are mostly empty ground, or a page whose running text is small and\n  grey: design cannot exceed **6.5**.\n- A section the brief asked for that is missing or reduced to a few words: content cannot exceed **6**.\n- No real button for the primary action on the first screen: usability cannot exceed **7**.\n- The five-second pass fails (no clear title saying what this is on the first screen): usability\n  cannot exceed **6**.\n- Unequal page margins, a section huddled on one side with the other half empty, or a blank stretch\n  taller than half a screen: design cannot exceed **6.5**.\n- A section of running text with no heading naming it: usability cannot exceed **7**.\n- Anything covering a headline at any scroll position: usability cannot exceed **6**.\n- A blank band where a reveal did not fire, or content clipped off-screen: usability cannot exceed **5**.\n\n## 4. Writing the critique\n\nWrite it down; do not just think it. Use exactly this shape so rounds can be compared:\n\n```\nROUND n\nSeen in one second: …\nIdea (one sentence): …\nLive thing: …\nLayout words by section: hero=… / …=… / …\nScores: design _ · usability _ · creativity _ · content _ → overall _._\nCaps applied: …\nTop three problems (most visible first), each with the screenshot it shows in and the fix:\n1. …\n2. …\n3. …\n```\n\nName problems the way a designer would to a colleague: \"the supporting paragraph starts 40px left of\nthe headline's edge\", \"the testimonial section is the third split layout in a row\", \"the phone hero\ncrops the bottle out of frame\". \"Could be more polished\" is not a finding.\n\n## 5. What to fix first\n\nFix in this order; later items cannot rescue earlier ones.\n\n1. **The idea.** If pass 3 fails, change the hero concept, not the details.\n2. **Hierarchy.** One dominant element per screen. Make the big thing bigger and the small things\n   fewer before touching anything else.\n3. **Composition.** Shared edges, section spacing, variety of layout between sections, holes.\n4. **Typography.** Scale contrast, line breaks, measure, leading.\n5. **Imagery.** Replace weak pictures, unify crops and grade.\n6. **Colour.** Proportion and accent discipline.\n7. **Detail.** States, focus, small alignments, mobile refinements.\n8. **Motion.** Last.\n\nWhen removing something leaves a gap, do not refill it with an ornament. Close the gap, enlarge what\nremains, or let a picture or a colour field take the space.\n\n## 6. When to stop\n\nRun at most three rounds: critique → fix the top three → re-inspect → critique. Stop early when a round\nfinds no problem a stranger would notice. If round three still scores under 7.5, say so plainly in\nyour report, with the remaining problems listed; do not round up.\n","isInternal":false,"tokens":2732,"sizeBytes":11157},{"name":"imagery.md","path":"skills/taste-skill/references/imagery.md","rawUrl":"https://raw.githubusercontent.com/Leonxlnx/taste-skill/HEAD/skills/taste-skill/references/imagery.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Imagery\n\nPictures are where generated pages most obviously give up: a grey box, an icon in a square, a fake\ndashboard, an abstract blob. This file is how to decide what the pictures are, where to find real ones,\nhow to crop and place them, and what to do when there are none.\n\n## Contents\n\n1. What the study measured\n2. Decide what imagery exists\n3. Real pictures from the open collections\n4. The dealt photographs\n5. Cropping and placing\n6. Treatment\n7. Showing software\n8. Drawing the subject\n9. Type and colour alone\n10. Markup and credits\n11. Video\n12. Where pictures and footage go\n\n## 1. What the study measured\n\n- On 60% of the studied sites one piece of media covers at least half of the first screen; on half of\n  them it covers nearly all of it. Top-scored sites: 68% and 56%. Weak sites: 48% and 39%.\n- Only 15% of heroes have no media at all, and those are deliberate typographic statements.\n- Media has square corners on 73% of sites. Where corners are rounded the usual radius is about 12px,\n  applied to every image alike.\n- Top-scored pages carry far more imagery (a median of 37 images against 5 on weak pages): the strong\n  sites show, the weak ones tell.\n- What the imagery is, by the panel's classification: a mix of kinds 32%, photography 14%, generative\n  or WebGL scenes 13%, real product interface 12%, 3D renders 11%, illustration 9%, video 6%, type only\n  3%.\n- Among the 54 sites the panel scored under 6.8, legibility (text lost over a busy image, or too\n  little contrast) was named as a weakness in 13.\n- In the October 2026 study of 91 Awwwards Sites of the Day (section 12), the median page carries 7\n  pictures (top sites 8, the lowest 2) and footage appears on 42% of sites (half of the top ones, one\n  of the 16 lowest).\n- Pictures come in whole screens: 42% of scrolled screens hold none and 19% are 90% picture or more.\n- 94% of pictures have square corners, and on a typical site two ratios hold three-quarters of them.\n\n## 2. Decide what imagery exists\n\nIn order of preference:\n\n1. **The project's own images.** Product shots, the place, the people, the work. Even ordinary\n   photographs of the real thing beat beautiful photographs of something else. Ask what exists; look in\n   the repository.\n2. **Images you can generate** with an image tool in this session. Write prompts as a photographer's\n   brief: subject, angle, light, background, crop ratio, and \"no text\". Generate the hero first and\n   make the rest match its light.\n3. **Real pictures of the subject's world from the open collections** (section 3). Archives,\n   museums and photographers have published millions of pictures anyone may use with a credit: the\n   client's city and street in old postcards, maps of its neighbourhood, its materials, its trade in\n   engravings, museum objects of its kind. Whenever an honest one exists, it beats a drawing of the\n   same thing: it is real, it has detail no drawing in a page's budget reaches, and it carries history.\n   Honest means nobody could take it for the client's own product, room, dish, person or team.\n4. **Pictures you draw in code from the subject itself** (section 8), for what no honest picture\n   exists of: the product's own objects as flat shapes, the place's tiles and windows, a map of its\n   streets, the document a tool produces, the interface of a piece of software. In testing, pages that\n   drew their subject with care beat pages that borrowed unrelated photographs every time, and beat\n   pages that showed nothing.\n5. **The photographs dealt on the direction sheet.** Real photographs of places, light, texture and\n   weather. Use them only where an honestly generic picture fits (the open sea for a house on the sea,\n   fog for a quiet retreat). They cannot stand in for a specific product, dish, room, person or\n   screen: a foggy motorway on a restaurant page reads as stock at once, and jurors notice.\n6. **Type and colour alone,** done on purpose (section 9).\n\nTell `draw.mjs` the truth with `--have`. If you have no product photographs and no image tool, do not\npass `product-photo`; the draw will avoid the directions that depend on showing the object. Pictures\nfound in the open collections are not the project's own: do not pass `photography` for them.\n\n## 3. Real pictures from the open collections\n\n`scripts/assets.mjs` searches four open sources without keys and prints, for each find, a direct image\nURL, the page it comes from, its size, its creator, its licence and a credit line:\n\n- **Openverse**: one index over Flickr, Wikimedia Commons, museums and libraries.\n- **Wikimedia Commons**: archival photographs, old maps, scans of prints and books, places as they\n  look now.\n- **The Art Institute of Chicago** and **The Metropolitan Museum of Art**: public-domain paintings,\n  prints, drawings, photographs, textiles and objects, in large scans.\n\n```bash\nnode <skill>/scripts/assets.mjs \"ghent postcard\"\nnode <skill>/scripts/assets.mjs \"fig\" --source museums --orientation portrait\nnode <skill>/scripts/assets.mjs \"basalt texture\" --min-width 2400 --source openverse,commons\nnode <skill>/scripts/assets.mjs --get commons:36649959,met:707892     # download, record the credits\nnode <skill>/scripts/assets.mjs --credits                             # footer line and report list\n```\n\nBy default it keeps only licences that allow commercial use (CC0, public domain, CC BY, CC BY-SA) and\npictures at least 1000 pixels wide, and checks that every image it prints actually loads.\n`--license pd` keeps only pictures that need no credit; `--orientation`, `--min-width` and `--limit`\nnarrow the list; `--source` picks the sources; `--json` gives the raw results. Each result has a ref\n(`commons:36649959`) that `--get` takes.\n\n**What to search for.** The inventory (SKILL.md step 1), not the category: \"bakery\" finds other\npeople's bakeries. The subject's world is specific:\n\n- **Its place:** the city, the street, the harbour, the valley, in old postcards and photographs\n  (\"ghent postcard\", \"rotterdam harbour 1920\") and as it looks today (\"gent korenmarkt\").\n- **Its maps:** the street plan, the chart of its bay, the geology of its valley (\"ghent old map\",\n  \"nautical chart lisbon\").\n- **Its materials,** close enough to read as a surface: the stone of its quay, the grain of its oak,\n  its glaze, its tiles (\"azulejo tiles\", \"basalt cobblestones\", \"oak grain\").\n- **Its trade's history:** the old tools, the craft in engravings and trade catalogues, patent\n  drawings (\"bread oven engraving\", \"potter's wheel\", \"bicycle patent drawing\").\n- **Museum objects of its kind,** with `--source museums`: a coffee set from about 1810 for a studio\n  that makes coffee sets, a woodblock print of a wave for a surf school, a porcelain plate painted\n  with figs for a fig orchard.\n- **Scientific imagery:** botanical and zoological plates (\"botanical engraving fig\"), star charts,\n  microscope photographs, satellite views of its coast, geological sections.\n\nSearch in the place's own words (azulejo, not \"blue tile\"; Korenmarkt, not \"market square\"), add a\nmedium (postcard, engraving, old map, lithograph, aerial photograph) or a decade, and try two or three\nqueries per idea. The museum sources match best on one or two words (\"fig\", \"harbour\", \"teapot\").\n\n**What makes a good find.**\n\n- It belongs to this subject's world and would not fit the nearest competitor's page.\n- It still reads at the crop the slot needs. Look at it before deciding: `--get` downloads it, then\n  open the file. A title is not a picture.\n- It is large enough: twice the width it is shown at for anything full-bleed (the script prints the\n  largest size available). A 1024-pixel Flickr photograph is a half-width picture at most.\n- It belongs to one family with the others on the page: all engravings, or all photographs from one\n  era, or all close surfaces in one light. A 1900 postcard beside a modern stock photograph beside a\n  botanical plate reads as a scrapbook.\n- No watermark, no burned-in text or logo, no frame or scanner edge you cannot crop away, and no\n  recognisable living person who could be taken for the client's staff or customers.\n\n**Use it creatively.** Found pictures are material, not decoration:\n\n- **One archival photograph as the hero,** full-bleed: the street as it was a century ago, behind the\n  name of the business that stands in it today, with the year in the caption.\n- **A museum engraving enlarged until its line becomes texture,** cropped tight and returning at\n  different scales as the page's one motif (the whole fig plate in the hero, a single leaf of it\n  beside the menu).\n- **An engraving or a map on white paper set with `mix-blend-mode: multiply` on the page's colour\n  field,** so the ink sits on the ground (section 6).\n- **The real map of the street as the contact section,** the door marked, the north and the scale\n  taken from the original.\n- **A material close-up as a whole field:** the quay's stone behind the opening hours.\n- **A run of old postcards or plates as the gallery,** one size, one treatment.\n\nTreatments stay within section 6: untouched, greyscale for the whole set, or multiply on a field.\n\n**Stay honest.**\n\n- **A found picture is never the client's own.** It may show the client's city, its materials, its\n  history, the kind of thing it makes; it may never stand in for the client's product, room, dish,\n  person, team or customers. If a visitor could take it for the client's own (a bakery counter, a\n  plate of pasta, a smiling barista, a guest room), do not use it.\n- **Caption from the source** when a caption helps: what it is and when, as the archive describes it\n  (\"Gand, unloading a steamer, 1905\"). Never write a caption that ties it to the client.\n- **Record and credit every picture.** `--get` writes the source, creator, licence and page of each\n  download to `assets/credits.json`. CC BY and CC BY-SA require a credit with the title, the creator,\n  a link to the source and a link to the licence; `--credits` prints them as one line of HTML for\n  the footer (section 10). Public-domain pictures need no credit; give one anyway.\n- **Respect the licence.** CC BY-SA: an altered version (recoloured, combined with other pictures)\n  must be shared under the same licence. Non-commercial (NC) and no-derivatives (ND) licences are out\n  for a client's site, which is why the script leaves them out unless asked. Read the `note` lines:\n  some pictures carry personality rights or a trademark, are public domain only in the United States,\n  or come with an archive's statement instead of a licence.\n- **Download, do not hotlink.** Save what you use into the project: `--get` puts it in `assets/` at\n  1920 pixels wide (pass `--width 1280` for a picture shown at half the screen, `--width 3840` for a\n  very large hero where the source has it). The page then works offline, does not break when an\n  archive moves a file, and does not load from someone else's server. Every licence the script\n  allows by default permits copying.\n- **List them in the report:** file, title, creator, licence, source page, and where the credit sits.\n  `--credits` prints that list too.\n\nIf two or three honest queries per idea find nothing that fits, draw (section 8). A drawing made for\nthe subject is better than a found picture that is merely nearby. If the script cannot reach any\nsource (no network), draw, and say so in the report. For moving pictures, the same script searches\nreal footage with `--video` (section 11).\n\n## 4. The dealt photographs\n\n- The sheet lists eight from one set so they share a subject and a light. Use three to six.\n- Each line says where the calm area is. Put text there or keep text off the image.\n- More from the same or another set: `node scripts/draw.mjs --photos list`, `--photos <set>`, or\n  `--photos \"fog coast\"` to search descriptions.\n- URLs have the form `https://picsum.photos/id/<id>/<width>/<height>`. Request the exact pixel size you\n  render at twice the CSS size for sharpness, capped around 2400 wide. Add `?grayscale` for\n  black-and-white.\n- These are photographs from Unsplash served by Lorem Picsum under the Unsplash licence. List the ids\n  you used in your report; they are meant to be replaced by the project's own pictures.\n\n## 5. Cropping and placing\n\n- **Choose a small set of ratios and stick to them:** for example 4:5 for portraits, 16:10 for\n  landscapes and 1:1 for details. Random ratios look like a stock dump.\n- **Go large.** A photograph at full width, or at half the screen and full height, has presence. Six\n  small ones in a grid have none. If the image is good, give it the room; if it is not, cut it.\n- **Crop with intent.** Use `object-fit: cover` with an `object-position` chosen per image so the\n  subject sits where the composition needs it (off-centre, on a third, against the text side).\n- **Let images touch edges.** Full-bleed, or bleeding off one side, reads as designed. An image\n  floating with equal margins on all sides reads as placed by default.\n- **Overlap sparingly and on purpose:** a headline whose last line runs over the top edge of the\n  picture, a small image overlapping a large one by a fixed 40–80px. One overlap per screen at most.\n- **Square corners** unless the direction or the one-motif shape says otherwise. If rounded, one radius\n  for every image on the page.\n- **No frames:** no borders, no shadows, no device mock-ups, no browser chrome around pictures.\n- **Captions** are one short line in the small size and soft ink under the image, left-aligned to its\n  edge. Most images need none.\n- Where each picture goes on the page, how large, and what the phone does with it: section 12.\n\n## 6. Treatment\n\nOne treatment for the whole page:\n\n- **Untouched.** The default. Pick images whose light already agrees.\n- **Greyscale.** `filter: grayscale(1) contrast(1.05)`, or `?grayscale` on the URL. Unifies a mixed\n  set instantly and suits editorial and typographic directions. Apply to every image or none.\n- **Multiply on a field.** On a light flat ground, `mix-blend-mode: multiply` makes a white studio\n  background vanish so a product sits directly on the colour.\n- **Darkened for a dark page.** `filter: brightness(0.85) contrast(1.05)` so the image edges sink into\n  the ground.\n\nNot treatments: colour washes over photographs, duotone overlays, blur, grain overlays, vignettes,\ntilted \"polaroid\" frames with shadows.\n\nFor text on a photograph, a neutral scrim covering only the text area: a solid block at 40–55% black,\nor a fade from 55% black to transparent over the lower third. Never a coloured overlay.\n\n## 7. Showing software\n\n- Build a real fragment of the interface in HTML at its true size, with believable content, instead of\n  a shrunken screenshot or a decorative mock-up. Crop to the part that makes the point: one control,\n  one row, one panel.\n- Believable means real labels, real numbers that add up, one item hovered or selected, proper\n  alignment. Grey bars standing in for text are worse than no image.\n- Put the fragment directly on the page or on one flat stage colour. No laptop, no phone frame unless\n  the product is a phone app and the frame is a plain rounded rectangle.\n- Inside a fragment the product's own interface conventions apply (its small radii, its 1px control\n  borders, a shadow on its open menu). Put the attribute `data-ui` on the fragment's root element: the\n  inspector and the linter then leave what is inside alone, and hold the page around it to the house\n  rules. `data-ui` is for cropped fragments only; wrapping a heading or a whole section in it fails.\n  Write the fragment's CSS under a `[data-ui]` selector (`[data-ui] .row { … }`) so the linter can\n  tell it apart from page styles.\n- If the user supplies real screenshots, show them large and uncropped at least once.\n\n## 8. Drawing the subject\n\nWhen nothing real can be photographed and the open collections hold no honest picture of it, draw it,\nand draw it well. Inline SVG and CSS are enough. Drawings and found pictures can share a page: the\nfound ones show the world around the client, the drawings show the client's own things.\n\n- **Draw the subject's own things,** not decoration: the stool's three legs and the grain of its seat,\n  the enamel sign over the bakery door, the hut's two windows and its stove pipe, the street plan, the\n  invoice the tool produces, the festival's stage. If you cannot name what a drawing depicts in the subject's world, it is decoration.\n- **One graphic language for the whole page:** flat filled shapes, no outlines or one consistent\n  stroke weight, the same corner and curve vocabulary everywhere, drawn in the palette's real colours\n  (fields and accent at full strength, not greys). A set of drawings that obviously belong together\n  reads as an identity; a mix of styles reads as clip art.\n- **Colour is the material.** A product sold on its finish is drawn in that finish's colours; a sea house in the\n  sea's blues and the sand; never a page of grey placeholders.\n- **Draw with three levels of detail.** Jurors called simple drawings \"basic\" every time. Give each\n  drawing big shapes that read at a glance, middle shapes that describe the thing (the handle, the\n  window frame, the step), and small details that reward a second look (the maker's mark, the house\n  number, the chipped tile, the hinge, a bird on the roof). Make light with flat tone steps (a lit face\n  and a shaded face of each volume), not gradients. A drawing that would pass as a placeholder icon at\n  full size is not finished.\n- **Draw large and let it work:** the drawing is the hero's dominant element, a full-width band, a set\n  of tiles, the footer mark. Small doodles scattered around read as filler.\n- **Let it carry the idea through the page,** the way a motif does: the same drawn object returns at\n  different scales, the tile grid becomes the opening hours, the map becomes the booking section.\n- **Honesty:** say plainly, in small text near the first drawing or in the footer, that the pictures\n  are drawn until photographs exist, if the client might otherwise be taken to be showing real\n  products. In your report, list which drawings are placeholders for photography.\n- **Not this:** gradient-shaded 3D-looking blobs, isometric clip art, generic line illustrations of\n  people at laptops, abstract floating shapes, icons in squares. Those are the generated look.\n\n## 9. Type and colour alone\n\nThis is a legitimate design, not a gap to disguise. Only 7 of the studied sites use no imagery at all,\nand they hold their own: a median panel score of 7.5 against 7.2 for the whole set.\n\n- Make the typography the image: one statement at 10–14vw, a list set at 5vw, numerals at display size.\n- Use colour at scale: a full field, an inverted section, a two-field split.\n- Use the subject's own shape as one flat motif if the direction calls for it (a circle, an arc, a\n  notch), drawn in CSS, cropped by the viewport.\n- Do not add: icons in squares, abstract gradients, dot grids, wave dividers, floating shapes, emoji,\n  generic line illustrations, or an empty box where a picture \"will go\".\n\n## 10. Markup and credits\n\nA found picture, downloaded into the project with `--get`, used as the hero:\n\n```html\n<img src=\"assets/fig-engraving.jpg\" width=\"1920\" height=\"2807\" fetchpriority=\"high\" decoding=\"async\"\n     alt=\"Hand-coloured engraving of a fig cut open, with its flowers and seeds, in black, pink and green\">\n```\n\nA dealt photograph further down the page:\n\n```html\n<img src=\"https://picsum.photos/id/626/2400/1500\" width=\"2400\" height=\"1500\"\n     alt=\"Red and white lighthouse in a turquoise sea below a chalk cliff\" loading=\"lazy\" decoding=\"async\">\n```\n\nThe credits, as `--credits` prints them, in the footer:\n\n```html\n<p class=\"credits\">Pictures: <a href=\"https://commons.wikimedia.org/wiki/File:Fig_(Ficus_carica_L.);_57_segments_of_flowers_and_fruits_at_Wellcome_V0043000.jpg\">“Fig (Ficus carica L.): 57 segments of flowers and fruits”</a>, <a href=\"https://creativecommons.org/publicdomain/mark/1.0/\">public domain</a>, via Wikimedia Commons.</p>\n```\n\n- Always `width` and `height` (or `aspect-ratio` in CSS) so nothing jumps while loading.\n- `loading=\"lazy\"` on everything except the hero image, which gets `fetchpriority=\"high\"`.\n- `alt` describes the picture in plain words. Decorative repeats get `alt=\"\"`. The script's suggested\n  alt is the archive's title; rewrite it to say what the picture shows.\n- A coloured `background-color` on the image container (the ground or surface tone) so the layout is\n  whole before the image arrives.\n- The credit line is part of the footer's design, at full contrast, with its links. Set it at the body\n  size; one step smaller only on a page with plenty of running text, because a long credit line in\n  small type can become the page's most common text size and fail the inspector's body-size check.\n  One line for all pictures; no credit captions laid over the pictures themselves. Credit only the\n  pictures the page still uses.\n- A broken image fails the inspector. Check every picture in the screenshots.\n\n## 11. Video\n\nA moving picture of the subject's world can carry a section the way a photograph does: the river at\nthe end of the street, the roaster's drum turning, a timber frame going up. `assets.mjs --video`\nsearches real footage without keys: Wikimedia Commons (every video there comes with web-sized\ntranscodes; the best source for short clips), the Internet Archive's Prelinger Archives (industrial,\neducational, city and home films from the 1920s to the 1970s, mostly public domain and mostly long)\nand NASA (the Earth from orbit, launches, aircraft, laboratories). The rest of the Internet Archive is\nleft out: anyone can upload there, and the licence claims are unchecked.\n\n```bash\nnode <skill>/scripts/assets.mjs \"coffee roasting\" --video\nnode <skill>/scripts/assets.mjs \"river\" --video --source commons,nasa --orientation landscape\nnode <skill>/scripts/assets.mjs --get commons:49769620        # the clip, a poster frame, the credit\n```\n\nIt takes a rendition of 720p or smaller (`--res` changes that), lists short clips first, prints each\nclip's length and file size, and flags anything over 25 MB or longer than a minute. `--get` refuses a\nclip over 25 MB unless you pass `--max-mb`, and saves the source's still frame beside it as the\nposter (Commons and NASA; the archive's own stills are too small). An archive film of ten minutes is\ntoo heavy as it stands: trim a few seconds from it with ffmpeg if it is installed, or choose a\nshorter clip. Licences, credits and honesty work exactly as for pictures (section 3).\n\n**Choosing a clip.**\n\n- **Short:** 5 to 20 seconds that loop without a visible jump: water, smoke, a turning drum, traffic,\n  leaves, a crowd from far away. Watch it to the end before choosing.\n- **Light:** under about 5 MB for a section and 10 MB for a hero. In the study sources are 1920×1080\n  (the commonest) or 1280×720, median length 10 s; 720p is plenty behind type. For a full-bleed hero,\n  cut a tall 720×1280 version for the phone, or set `object-position` on the subject.\n- **Clean:** no slate, title card, logo, watermark or burned-in caption. NASA and archive films often\n  open with a slate, and the source's poster frame may be that slate. No recognisable person who could\n  be taken for the client's staff or customers.\n- **Never the client's own:** a found clip of a roastery is not this roastery.\n- **Found clips: one per page, two at most.** A found clip shows the world around the client; a\n  third makes a theme of it. The project's own footage can carry more: in the study a site with\n  footage carries a median of three or four clips. Either way, **one moving picture per screen**;\n  two loops running side by side are noise.\n\n**On the page.**\n\n- Muted, looping, inline, with a poster and a fixed size, as `--get` prints it:\n  `<video autoplay muted loop playsinline preload=\"metadata\" poster=\"assets/river-poster.jpg\"\n  width=\"854\" height=\"480\" aria-hidden=\"true\"><source src=\"assets/river.webm\" type=\"video/webm\"></video>`.\n  No sound and no controls on a decorative loop. `aria-hidden` because it is decoration: whatever the\n  clip says that matters belongs in the text beside it.\n- The poster shows before the clip plays, on slow connections and under reduced motion, so it must\n  work as a picture on its own. If the source's still is a slate or a blur, take a frame from the clip\n  yourself or use a found picture.\n- In the study only 31% of clips had a poster, and the panel recorded the blank and grey boxes\n  before they played as faults. Here every clip has one.\n- Play a clip only while it is in view, and none under `prefers-reduced-motion: reduce`, where the\n  poster shows instead:\n\n  ```html\n  <script>\n    const calm = matchMedia('(prefers-reduced-motion: reduce)');\n    const clips = [...document.querySelectorAll('video[autoplay]')];\n    const inView = new Set();\n    const sync = (v) => {\n      if (calm.matches) return;\n      if (inView.has(v)) v.play().catch(() => {}); else v.pause();\n    };\n    const settle = () => {\n      for (const v of clips) {\n        if (calm.matches) { v.removeAttribute('autoplay'); v.pause(); v.load(); }\n        else if (inView.has(v)) v.play().catch(() => {});\n      }\n    };\n    const watch = new IntersectionObserver((entries) => {\n      for (const e of entries) {\n        if (e.isIntersecting) inView.add(e.target); else inView.delete(e.target);\n        sync(e.target);\n      }\n    }, { threshold: 0.2 });\n    clips.forEach((v) => watch.observe(v));\n    settle();\n    calm.addEventListener('change', settle);\n  </script>\n  ```\n\n- Crop and place it like a photograph (sections 5 and 6): `object-fit: cover`, one ratio, square\n  corners, no frame, a ground-coloured `background-color` while it loads.\n- Never under body text. On a clip put a headline, one line and one action at most, and check the\n  contrast where they sit across the whole loop, not only on the poster: footage that is dark at\n  one second can be bright at the next. If any frame drops below 4.5:1 (3:1 for 24px and up), use the\n  scrim in section 6 or move the text off the clip. Nothing lies on top of a headline or a statement.\n- It is motion: let it be the page's one moving thing, or sit in a section where nothing else moves.\n- Credit it with the pictures: `--credits` prints one footer line for both (\"Pictures and footage:\")\n  and the list for the report, with each clip's length.\n- Where footage goes (hero background, inline loop, the frame that grows, a docked card), and what\n  the study measured about it: section 12. Nothing that matters plays on hover only, and a full film\n  with sound sits behind a play button that opens a player with controls.\n\n## 12. Where pictures and footage go\n\nWhat strong pages do with their pictures, measured on the latest 100 Awwwards Sites of the Day\n(10 July to 17 October 2026, captured at 1440×900 and 390×844). 91 were usable. A panel described where\nevery picture sat and scored each site the Awwwards way, and a script measured how much of each screen\nis picture. \"Top\" means a panel score of 7.5 or more (36 sites), \"lowest\" under 7.3 (16 sites). The\nscores sit close together (6.7 to 7.9) and a single score carries about half a point of noise, so read\nthe links between a placement and the score as leanings, not laws.\n\n### How much of each screen is picture\n\n- **All or nothing.** Counting photographs, footage and picture backgrounds (not canvases), the median\n  scrolled screen in the study is 16% picture, but few screens sit near it: 42% hold no picture and\n  19% are 90% picture or more. Only 19% fall between 20% and 60%. A picture either leads its screen or\n  stays out of it.\n- **About a third, with rests.** On the 67 sites that put pictures in the page, the average screen is\n  36% picture (middle half 18–69%). Top sites sit at 30% and leave 28% of their screens with no picture\n  at all: screens of type are the rests between picture screens.\n- **The first screen.** A picture covers at least half of it on 41% of the sites and nearly all of it\n  on 32%. A full-bleed photograph or film is the whole first screen on 29%; footage is the main hero\n  picture on about a quarter.\n- **A scene is not a picture.** 66 of the 91 keep a WebGL canvas over at least 30% of the screen, so\n  counting canvases the median screen is entirely covered. On the lowest-scored sites that canvas is\n  often all there is: the five lowest usable sites (6.7 to 7.0) draw everything in it and put two\n  pictures at most in the page.\n- **Text is small in area.** The median screen is 8% text. Type is set large and sparse around the\n  pictures, not packed beside them.\n- **Off-centre.** Measured per section across the crawled sites, pictures sit to the left or right\n  939 times, centred 273 times, and full-bleed or behind text 269 times.\n- **The phone carries more picture,** not less: 19% of a phone screen at the median, and 27% of the\n  first phone screen against 17% on desktop. Full-bleed pictures re-crop to portrait and fill the\n  screen; splits put the picture first at full width.\n\n### How many\n\n- **Seven pictures per page** at the median (middle half 1–25). Top sites 8 (middle half 4–27), lowest\n  2 (0–4). The floor in SKILL.md step 6, four and usually six to twelve, is the strong half of the\n  study.\n- **Footage on 42% of sites:** on half of the top sites and half of the middle band, and on one of the\n  16 lowest. A site with footage carries a median of three or four clips.\n- **Three to five placements.** Sites that use two or fewer of the placements below average 7.31;\n  sites that use three or more average about 7.5. The median top site uses four, the median lowest\n  site one. Where the pictures go changes from section to section on a designed page.\n\n### The placements, ranked\n\n| Placement | Sites (of 91) | Top (of 36) | Lowest (of 16) | Mean score with / without |\n| --- | --- | --- | --- | --- |\n| Split: picture in a half or two-thirds | 32 | 17 | 2 | 7.50 / 7.38 |\n| Horizontal gallery | 32 | 13 | 4 | 7.44 / 7.41 |\n| Full-bleed band between sections | 31 | 14 | 3 | 7.48 / 7.40 |\n| Full-bleed picture or film as the first screen | 26 | 10 | 3 | 7.45 / 7.41 |\n| Uneven mosaic | 25 | 11 | 1 | 7.49 / 7.40 |\n| Picture held while text scrolls | 23 | 12 | 1 | 7.52 / 7.39 |\n| Footage behind text | 22 | 8 | 2 | 7.46 / 7.41 |\n| Even grid | 20 | 11 | 2 | 7.48 / 7.41 |\n| Scattered collage | 19 | 6 | 3 | 7.47 / 7.41 |\n| Panel sliding over a held picture | 19 | 8 | 2 | 7.48 / 7.41 |\n| Inset frame that grows | 17 | 7 | 1 | 7.52 / 7.40 |\n| One picture centred on a field | 14 | 5 | 3 | 7.38 / 7.43 |\n| Cut-out object on a flat field | 13 | 7 | 1 | 7.57 / 7.40 |\n| Index with hover preview | 12 | 6 | 1 | 7.49 / 7.41 |\n| 3D gallery | 12 | 4 | 4 | 7.30 / 7.44 |\n| Small card docked in a corner | 11 | 5 | 1 | 7.47 / 7.42 |\n| Picture inside or in front of display type | 11 | 7 | 1 | 7.50 / 7.41 |\n| One small picture beside a statement | 8 | 5 | 0 | 7.56 / 7.41 |\n| Small pictures between words | 6 | 4 | 0 | 7.52 / 7.42 |\n\n- Found on top pages more than their share and almost never on the lowest: the split, the picture held\n  while text scrolls, the uneven mosaic, the inset frame that grows, the cut-out on a flat field, and\n  pictures set with the type (the last three rows together: 24 sites, 16 of them top, 1 lowest).\n- The horizontal gallery is common in every band and lifts nothing. Use it where browsing is the point.\n- The 3D gallery is the one placement that goes with lower scores, and with the lowest usability in the\n  table (5.9 against 6.35 for all sites).\n\n### Each placement\n\nEach entry gives when to use it, the geometry at 1440×900, the phone version and how it fails.\n\n**Split: picture in a half or two-thirds**\n\n- *When.* A claim and the picture that proves it. The commonest way strong pages pair words and a\n  picture.\n- *Geometry.* The picture takes 42% of the width at the median (middle half 33–49%), up to two-thirds,\n  at the full height of its section: 680×850 and 720×900 are typical. 38% of these pictures are\n  portrait, mostly 4:5 or 3:4. The text starts on the 50% line (x = 720) or on the line where the\n  picture ends, top-aligned or docked low, not centred in its half. Let the picture touch the viewport\n  on its outer side: only about 30% do in the study, and the ones with margin on every side read as\n  placed by default (section 5). Alternate sides only across three or more rows.\n- *Phone.* Picture first at full width (4:5, or 4:3 for a landscape), text under it.\n- *Fails.* The same split in three sections running; a picture floating in the middle of its half; a\n  text column narrower than about 30 characters.\n\n**Full-bleed band**\n\n- *When.* One picture carries a whole screen between type screens: the place, the work, the object at\n  full size. One every three or four screens at most.\n- *Geometry.* 100% wide and one to one and a half screens tall (median 900px at 1440×900, middle half\n  890–1,170px; ratios 1.4 to 1.9). For a slow parallax the picture is oversized in its frame by 4–10%\n  (32–72px a side in the study) and travels no further than that. Text is a headline and one line, or\n  nothing, docked 32–64px in from a corner over the calm part of the picture.\n- *Phone.* A portrait re-crop that fills the screen, with `object-position` set on the subject; the\n  text moves to the bottom quarter.\n- *Fails.* 11–14px white text over a bright area; three bands with nothing between them; a band that\n  only decorates.\n\n**Picture held while text scrolls**\n\n- *When.* A list, steps or a long paragraph that all belong to one picture. If the picture changes for\n  each item, it is the index with a preview, below.\n- *Geometry.* A 100vh sticky stage inside a section two to six screens long (runways of 1,800–5,400px\n  are typical in the study). The picture holds one half (685×880 is a typical portrait), two-thirds, or\n  the whole screen with the text passing over it on a solid panel. Text rows about 150px apart, so two\n  or three are in view at once.\n- *Phone.* Release the stick: picture first, text under it. If the picture swaps per item, keep it as\n  a band in the top 40% of the screen.\n- *Fails.* Long runways where the text has faded out and the held picture is all that is left (the\n  panel recorded several empty stages on phones); body copy set on the held picture.\n\n**Inset frame that grows**\n\n- *When.* Once per page, for the film or picture the page is about, as the move from type into\n  picture.\n- *Geometry.* The frame starts centred at 35–50% of the width (549×366, 710×480 and 864×540 in the\n  study) or as a 16px inset round a full screen, and grows to the full width and height over\n  720–2,700px of scroll. Any corner radius goes to 0 as it reaches the edges. A headline sits above it\n  before it starts; nothing else on the screen moves while it grows.\n- *Phone.* Start at full width inside the 16px margins and grow to a full-bleed portrait, or skip the\n  growth.\n- *Fails.* The growth is the only thing on screen for three scrolls; a loading spinner or a blank box\n  in the first frame (give it a poster, start loading before it enters); used twice.\n\n**Uneven mosaic**\n\n- *When.* A body of work, or one place seen several ways: five to twelve pictures.\n- *Geometry.* Two columns, or rows of three on a 24-column grid. Two or three picture widths (for\n  example 32%, 48% and 65% of the width, or 5, 7 and 12 columns), neighbours offset vertically by\n  120–190px, 130–450px between rows, one or two ratios, a caption under each.\n- *Phone.* One column alternating full width and about 70% width, or two columns of 120–180px tiles\n  that keep the offsets.\n- *Fails.* Random ratios with random offsets, which read as a stock dump. Captions in 9–12px mono with\n  index numbers, the award-site habit: here the caption is one line in the text face at body size, with\n  no number.\n\n**Horizontal gallery**\n\n- *When.* A set people browse in any order: products, rooms, events, a team.\n- *Geometry.* Cards 25–35% of the width (435×326 with 20px gaps at 1440: three in full and a fourth\n  cut by the edge), or a strip at one fixed height with mixed widths (576px tall in the study), or a\n  slider whose centre slide is about 73% of the width with 170–180px of each neighbour showing. Always\n  cut by the right edge so it reads as more. A marquee of pictures moves slowly: 60–120s per loop.\n- *Phone.* One card at 75–80% of the width (290–300px of 390) with the next one showing; swipe.\n- *Fails.* Arrows and no drag or swipe; a marquee of things people need to read; a carousel holding the\n  page's one important picture.\n\n**Panel sliding over a held picture**\n\n- *When.* A change of chapter: the picture holds, and the next section rises over it.\n- *Geometry.* The picture is sticky at 100vh; the next section's ground slides up over it at full width,\n  its top edge straight or shaped from the subject (the study has the arch of a building's windows).\n  Here it is a solid panel with square corners: no rounded sheet tops, no frosted glass.\n- *Phone.* Unchanged.\n- *Fails.* Decks of five or six cards whose earlier cards linger as slivers; stacking for its own sake.\n\n**Even grid**\n\n- *When.* An archive only (layout.md §5): a shop range, the team, a menu, the full list of work.\n- *Geometry.* Two, three or four across, equal cells, 8–16px gaps, one ratio (4:5 is the commonest),\n  the caption under each picture.\n- *Phone.* Two across for products, one for work and people.\n- *Fails.* Three equal cards as \"features\". Cards with a dark gradient at the foot so the label can sit\n  on the picture, common in the study: here the label goes under the picture.\n\n**Index with hover preview**\n\n- *When.* A list of eight or more projects or clients where the names matter as much as the pictures.\n- *Geometry.* Rows on a 45–80px pitch, names at 30–60px. One picture at a time, about a third of the\n  width at 16:9 or a portrait 300–450px tall, at a fixed place (the right half from the 50% line, or\n  the centre), swapped within 0.3s. A version that needs no mouse: the names scroll across a picture\n  fixed at the centre and the picture shows whichever name is crossing it. In the study the picture\n  sits on top of the names; here nothing lies on top of large type, so the names pass in front of it.\n- *Phone.* No hover. Give each row a thumbnail about 100px wide, or use the scroll version.\n- *Fails.* Pictures that never appear on a touch screen. Rows divided by hairlines, the award-site\n  habit: here rows are separated by space, and the active row by ink or a change of ground.\n\n**One picture on a field, or one small picture beside a statement**\n\n- *When.* A pause in the page: a single portrait or object. Or a small picture that gives a statement\n  a face.\n- *Geometry.* A single centred picture at 3:4 and 75% of the viewport height, on a ground taken from\n  the picture. Or a small picture 7–26% of the width (108–374px) beside, above or between the lines\n  of a 48–136px statement, aligned to one of its lines.\n- *Phone.* The picture above the statement at 60–100% of the width.\n- *Fails.* Used as the default for every picture: a picture with equal margins on all sides reads as\n  placed by default (section 5).\n\n**Small pictures between words**\n\n- *When.* A statement about the things themselves (materials, people, products), on a screen of its\n  own.\n- *Geometry.* Two to four chips in the statement, from the cap height to three-quarters of the type\n  size tall and one to one and a half times as wide (50×46px in a 60px line; 113×75px between the two\n  words of a 150px name), all from one shoot, square corners. Give them a width and height so the lines\n  do not jump while they load.\n- *Phone.* Keep them inline at the height of the text.\n- *Fails.* More than four; chips from different shoots; a chip that carries information the words do\n  not.\n\n**Picture inside or behind display type**\n\n- *When.* The object is the subject: a product, a building, a person.\n- *Geometry.* A small picture window sits inside a block of 150–200px display type and later opens\n  into the next screen; or the object stands behind the type, showing between and around the letters;\n  or it touches the edge of the word without covering a letter. In the study the object more often\n  stands in front and covers one or two letters, or a line of type runs behind a square picture; here\n  nothing lies on top of a headline (the inspector fails large text a fifth or more hidden), so the\n  type stays in front.\n- *Phone.* Keep it, with the type at about 15vw, and check the word still reads.\n- *Fails.* An object over the letters; type displaced or glitched by the picture.\n\n**Cut-out object on a flat field**\n\n- *When.* Products and objects. The highest mean score in the table, on 7 of the 36 top sites.\n- *Geometry.* The object at 35–60% of the width on a flat ground taken from its own colours, standing\n  on the bottom edge or running off one side, with the type behind or beside it.\n- *Phone.* The object at 80–90% of the width under the headline.\n- *Fails.* A render floating in a void with no ground; a drop shadow added to a cut-out (no resting\n  shadows here; keep a contact shadow only if it was photographed).\n\n**Scattered collage**\n\n- *When.* Archives, ephemera, a festival of many small things. Sparingly: it is about as common on the\n  lowest pages as on the top ones.\n- *Geometry.* Six to sixteen pictures of 100–300px at a few sizes around a centred heading, never over\n  it.\n- *Phone.* Re-stack as overlapping pairs in one column.\n- *Fails.* Tilted prints and stickers with offset shadows, common in the study and not a treatment\n  here (section 6); pictures crossing the text.\n\n**Small card docked in a corner**\n\n- *When.* A standing pointer to the reel or to the next thing.\n- *Geometry.* About 216×144 to 240×140, 30–43px from the corner; one per page.\n- *Phone.* Drop it, or move it into the flow.\n- *Fails.* Content scrolling under it; a second one.\n\n**3D gallery**\n\n- *What.* Pictures on a ring, sphere, helix or tunnel in a WebGL scene, turned by the wheel or by\n  dragging.\n- *In the study.* 12 sites, 4 of them among the 16 lowest; mean score 7.30 against 7.44, usability 5.9\n  against 6.35.\n- *Here.* Do not build one. Show the same pictures as an index with previews or a horizontal gallery.\n\n### Footage\n\n**What the study measured.**\n\n- Footage on 38 of 91 sites (42%): 18 of the 36 top sites, 19 of the 39 in the middle, 1 of the 16\n  lowest. A site with footage carries a median of three or four clips (middle half 1–8).\n- Footage covers at least half of the first screen on about a quarter of the sites, and is full-bleed\n  on nearly all of them.\n- Clips are short: median 10s, middle half 5–14s; 61% run 10s or less and 88% 20s or less.\n- Every decorative clip is muted, loops, plays inline and has no controls. The autoplay attribute is on\n  44% of clips; the rest are started by script, mostly as they come into view.\n- Only 31% of clips have a poster (13 of the 38 sites). The rest show a blank or grey box until they\n  play, and the panel recorded those as blank first paints. Here a poster is required (section 11).\n- Sources: 1920×1080 is the commonest, then 1280×720; tall clips at 450×800 or 540×960 for phones and\n  portrait tiles. Median source width 1,080px.\n- On the page: 16:9 41%, square 19%, portrait (4:5 to 9:16) 25%, 4:3 or 3:2 12%. Corners square on 75%\n  (the rest 8px or less, or 20–32px). `object-fit: cover` on 84%, contain on 16% (product strips, letterboxed\n  films).\n\n**Where it goes.**\n\n- **Hero background:** full-bleed, cover, often oversized by 1–25% so a drift or zoom never shows an\n  edge. Either one slow take or a montage cutting every second or two.\n- **Inline, as a picture:** in splits, tiles and cards, at about a third of the width (median 33%,\n  middle half 24–45%); a third of these clips are under a quarter of the width and fewer than one in\n  ten is full width. Slow, near-still subjects (water, skin, light, a turning object) read as living\n  photographs and sit well among stills.\n- **The frame that grows** (above), for a reel.\n- **A docked card** (above): one small clip in a corner.\n- **On hover:** only two or three sites play clips on hover, all of them in an index or list. Nothing\n  that matters should play on hover only; phones have no hover.\n- **Full films:** about ten sites offer a full film behind a play button that opens a player with\n  controls. None autoplays it.\n- **Sound:** six sites offer sound behind a toggle; no clip starts with sound.\n\n**How text sits on it.**\n\n- Of about 30 sites with a full-bleed picture or film behind text on the first screen, about 14 set the\n  type straight on it and rely on the footage being graded dark where the type sits; about 10 dim it\n  (to half brightness, under a 30–40% dark layer, or with a dark fade along the bottom 180–590px);\n  about 6 keep the text off the picture, above it or on a solid card.\n- What goes on footage in the study is the name or a headline at 47–136px and one short line, docked\n  bottom-left or centred. Where body text at 11–14px went on footage or a busy photograph, the panel\n  named it as a fault, on top-scored sites too.\n- Here: one headline, one line and one action on footage at most, and never body text. Check contrast\n  where the type sits across the whole loop, not only on the poster; if any frame drops below 4.5:1\n  (3:1 for type of 24px and up), use the scrim in section 6 or a solid band.\n\n**On the phone.** Footage re-crops to a full-screen portrait (a separate tall source, or\n`object-position` on the subject); inset frames go full-bleed. One site in the study adds a 40% scrim\non the phone only, where the type covers more of the picture.\n\n### Crops and treatment\n\n- **Ratios.** Of 1,356 pictures and clips measured: 4:5 21%, 16:9 19%, 1:1 16%, 16:10 10%, 3:2 7%, 2:3\n  5%, 4:3 5%, 5:4 4%, 3:4 3%, wider than 2:1 6%, 9:16 or taller 3%. Landscape 52%, portrait 33%,\n  square 15%.\n- **Two ratios do most of the work.** On sites with four pictures or more, the two commonest ratios\n  hold 76% of the pictures. The others (five ratios in all at the median) are exceptions with a reason:\n  one tall portrait in a run of landscapes, one wide band.\n- **Square corners** on 94% of pictures; 62 of the 68 sites with pictures in the page keep at least 80%\n  of them square. Where corners are rounded, it is 5px or less on two-thirds of them, or 20–32px on\n  card interfaces, one value per site.\n- **Cover.** `object-fit: cover` on 78%, contain on 10% (a product on a tile, a letterboxed film).\n- **Untouched.** CSS filters touch pictures on only 9 sites, mostly for hover states. A handful use\n  black-and-white photography as a set; two multiply scanned paper onto the ground. Several keep the\n  interface black, white and grey and let the photographs carry all the colour.\n- **Common in the study, not treatments here** (section 6): a fixed grain layer over the whole page\n  (about a third of the sites), duotone or tinted photographs, blurred copies behind a picture as a\n  glow, tilted prints and stickers with offset shadows.\n- **Oversize only by the distance it moves.** 22 sites move pictures with the scroll, oversizing them by\n  1–25%. Oversize by the travel and no more, on one picture per screen.\n- **Resolution.** The study serves pictures at a median 1.9 times their CSS width, but 17% are served\n  smaller than they are shown and full-width pictures at a median of only 1,440px. Here: twice the CSS\n  width, capped at about 2,400px (section 4).\n\n### Text over pictures\n\n- In the study, text sits on pictures often and is checked rarely: about 28 notes record text set\n  straight on a picture with no scrim, and the faults of 16 sites include text lost over pictures: 8–14px\n  labels and body over photographs, and navigation in a difference blend or with no backing passing\n  over them.\n- Where it works, the text is display size and sits over the calm part (sky, a dark wall, the shadow\n  side), docked in a corner or along one edge. Two other forms in the study: a solid card in the\n  ground colour inset over the photograph and carrying the heading, and text on the white of a picture\n  that fades into the page.\n- Here: on a picture put only display text, one short line and one action. Body text, captions and\n  labels go beside or under it. Measure contrast at the text's own position (4.5:1, or 3:1 for 24px and\n  up). If it fails, move the text to a calmer part, put it on a solid card in the ground colour, or use\n  the scrim in section 6. A fixed navigation that passes over pictures gets a solid band, or hides\n  while scrolling down.\n\n### Rules for a generator\n\n1. **About a third of the page is picture.** Across the scrolled screens, pictures fill 30–40% of the\n   area, and at least one screen in four carries no picture (top sites: 30% and 28%).\n2. **A picture leads its screen or stays small.** A leading picture takes at least 60% of its screen;\n   an accent stays under 10% of it. Avoid screen after screen of pictures at 20–40%: in the study 42% of\n   screens are 0% and 19% are 90% or more.\n3. **Three to five placements per page,** and no two neighbouring sections with the same one. Sites\n   with two or fewer average 7.31, sites with three or more about 7.5.\n4. **Six to twelve pictures, never fewer than four.** Study median 7; top sites 4–27; lowest 2.\n5. **Two ratios for at least 75% of the pictures** (76% in the study), a third only for a deliberate\n   exception. Defaults: 4:5 for portraits, 16:9 or 3:2 for landscapes.\n6. **Square corners on every picture** (94% in the study). If the direction rounds them, one radius of\n   4px for every picture and clip.\n7. **Split pictures take 42–50% of the width, or two-thirds,** at the full height of the section and\n   touching the viewport on their outer side; the text starts on the 50% line. On the phone the\n   picture goes first, full width.\n8. **Full-bleed bands are 100% wide and 100–150vh tall,** one every three or four screens, oversized by\n   10% at most for parallax, with text only in one corn\n\n<!-- [TRUNCATED AT 50KB] -->","isInternal":false,"tokens":13134,"sizeBytes":50169},{"name":"layout.md","path":"skills/taste-skill/references/layout.md","rawUrl":"https://raw.githubusercontent.com/Leonxlnx/taste-skill/HEAD/skills/taste-skill/references/layout.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Layout\n\nHow the page is put together: margins, the grid, where text sits, how sections differ, navigation,\nendings and the phone. The direction sheet gives the specific compositions; this file gives the habits\nbehind them, taken from the panel's notes on the 114 studied sites that scored 7.3 or higher (counts\nbelow are hand tallies from those notes, so read them as \"about\").\n\n## Contents\n\n1. What strong pages do\n2. Margins and the grid\n3. Where text sits\n4. Empty space\n5. The frame: margins, balance and titles\n6. Sections: carry the idea, vary the arrangement\n7. Navigation\n8. Endings\n9. The phone is a second composition\n10. How pages fail\n\n## 1. What strong pages do\n\n- **Tight margins, content to the edges.** About 45 of 114 use outer margins of 32px or less; only\n  about 8 use 80px or more. The centred 1100–1300px container is the minority among strong sites and\n  the usual frame of the ones the panel called stock.\n- **Text hangs from an off-centre line.** About 22 anchor text to one fixed line that is neither the\n  centre nor the margin: a third across, 42%, the midpoint.\n- **Two or three type sizes with nothing between** (about 30): one very large with one small, or\n  everything small with the scale given to the image.\n- **One thing per screen** (about 20): one statement, one object, one project.\n- **Sections told apart by their ground.** About 20 change the whole background colour at each\n  section; about 12 alternate light and dark; about 10 never change and separate by space alone.\n- **Sections recomposed, not repeated.** About 14 rearrange every section; about 12 alternate a\n  full-bleed image screen with a near-empty type screen.\n- **The system broken once, on purpose** (about 14): one centred line on a split page, one paper card\n  on a dark page, colour held back until the last screen.\n- **Often no navigation bar** (about 45), and endings that are a designed scene rather than link\n  columns.\n- **Few words.** Median 575 on the whole study; some of the best carry under 200.\n\n## 2. Margins and the grid\n\n```css\n:root {\n  --margin: clamp(1rem, 2.2vw, 2rem);   /* 16–32px: tight, so content reaches the edges */\n  --gutter: clamp(0.75rem, 1.4vw, 1.5rem);\n}\n.wrap { padding-inline: var(--margin); }\n.grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gutter); }\n```\n\n- One pair of margins and one grid for the whole page. Every left edge is a column line.\n- Do not wrap the page in a `max-width: 1200px; margin: auto` container by reflex. Let large things\n  (type, images, colour fields) run the full width, and constrain only the measure of running text\n  (`max-width` in `ch` on the paragraph, not on the page).\n- On very wide screens cap the layout at about 1760–1920px, or let type sized in `vw` stop growing with\n  a `clamp()`.\n- Directions that call for wide margins (uneven photographs, the quiet instrument) say so on the\n  sheet; follow the sheet.\n- Never draw the grid. Column lines, crosshairs and guides are banned ornaments here even though they\n  are fashionable; the grid is felt through alignment.\n\n## 3. Where text sits\n\n- **Pick the anchor line and reuse it.** If the hero headline starts at column 5, the section\n  headings, the pricing figure and the footer links start there too. Two or three anchor lines on a\n  whole page; six means nothing was decided.\n- **Off-centre beats centred.** A heading in the left third with its paragraph in the far-right\n  column on the same baseline and nothing between; a headline in the bottom third under a deliberate\n  void; text docked in corners with the middle given to the picture.\n- **Opposite ends.** Two short texts at opposite ends of one baseline (name left, one-line description\n  right) is the commonest alternative to the centred stack.\n- **Centred is a decision.** When a strong page centres, it uses one axis with wide empty flanks and a\n  single element per screen, not a centred stack of heading, paragraph and two buttons.\n- **Rows for long copy:** heading in the left third, body in the right two-thirds, the same split for\n  every row on the page.\n- Stagger sparingly: a second line indented by a third so a two-line headline steps across the screen.\n\n## 4. Empty space\n\nEmpty space is placed, not left over. In the study of 97 Sites of the Day captured in October 2026,\nreaders judged every large empty area either a rest, which something closes, or a hole, which nothing\ncloses. Strong sites have plenty of rests. About half of them still leave at least one hole, and the\nholes are what visitors name (\"big random blank spaces\").\n\n**A void is placed when something closes it.** In the readers' notes the closer is, most often:\n\n- the picture itself (sky, ground, the object, the film) with the type docked at its edge;\n- a picture across the void: the photograph at the far side of an empty band, the full-width row\n  rising under a statement, the opposite picture in a stagger;\n- the type: a headline large enough to span the space, or two short texts at the two ends of one\n  baseline;\n- on a one-screen page, the wordmark, the navigation and one fact in the corners, like a mount around\n  a print.\n\nAbout one closer in five in the study is a hairline or grid line. That device is banned here; close the\nvoid with the picture, the type, a step in ground tone or a field of flat colour.\n\n**Where holes come from.** In order of frequency in the study:\n\n1. A gap between sections stretched too far: bands of 250–760px of plain ground.\n2. Text in one half of a section and nothing in the other.\n3. Content that arrives late: a reveal not yet fired, so the visitor scrolls onto bare ground while the\n   words fade in.\n4. A short block stretched to a full screen: a footer padded to the viewport height, a section title\n   alone on a whole screen.\n5. A pinned scene that holds almost nothing for several screens.\n6. Pictures of different heights top-aligned in a row, leaving a hole under the short one.\n\n**Rules**\n\n- Decide where the void is and name what closes it. If nothing does, it is a hole: move the section's\n  picture into it, make the main element bigger, or take the space out.\n- Keep the void clean: no stray caption, no decorative shape, no faint watermark, no grid lines.\n- Sections sit 120–240px apart on desktop, counted from the last line of one to the first line of the\n  next (the median in the study is about 230–250px), and 72–112px on a phone. A change of ground\n  colour lets the gap be a little smaller. More than about 40% of a screen of plain ground between two\n  sections is a hole.\n- The gap between sections is clearly larger than any gap inside one. Related things sit close and\n  unrelated things far; a heading has at least twice as much space above it as below.\n- No stretch of the page taller than about half a screen holds nothing at all. In the study, runs of a\n  screen or more with nothing in the page were almost always scroll distance for a pinned scene; the\n  pinned stage must then hold something at every scroll position.\n- Content is in place on the first paint. An entrance moves what is already there (see `motion.md`);\n  it never leaves a screen of bare ground while the words arrive.\n- Size a section to its content. `min-height: 100vh` belongs to a section that fills the screen, not\n  to a footer or a lone heading.\n- In a row of pictures of different heights, align the bottoms or put something under the short one,\n  or crop the row to one ratio.\n- A rest is one thing on a screen: a single line, one object, one picture or a field of colour. Once\n  per page at most. A screen of nothing is never a rest, and the inspector fails two near-empty screens.\n- When a section looks empty, the answer is almost never \"add something\". Make the main element\n  bigger, or cut the section.\n\n## 5. The frame: margins, balance and titles\n\nThe frame is what readers judge before any detail: \"no good margin\", \"everything is shifted to one\nside\", \"no clear title\", \"random unclear sections\". The inspector measures each of these. The numbers\nare from the study of 97 Sites of the Day (October 2026).\n\n**One pair of equal margins.**\n\n- The left and right margins are the same, at every width. On the studied sites with scrolling\n  sections the two sides match to a few pixels: 16 and 16, 20 and 21, 32 and 32, 140 and 137. No\n  strong page in the study was pushed to one side.\n- The usual margin is tight: median about 28px at 1440, half the sites between about 18 and 45px, a\n  few at 80px or more. Here it is 16–32px (section 2), and never under 16px at any width, on the phone\n  included. About one award site in seven sets text 8–15px from the edge; that studio habit is\n  excluded here.\n- The navigation sits on the same margins as the content. The commonest small fault in the study is a\n  header on one inset and the page on another (40px against 20px, or 34px on the left against 10px on\n  the right).\n- A bleed is deliberate and starts from the margin: a row of pictures that runs off the right edge\n  begins on the left margin; a display line that bleeds starts or ends on one. A bleed never moves the\n  margin.\n- Asymmetry belongs inside the frame: an off-centre anchor line (a third across, 42%, the centre line)\n  on symmetric margins.\n\n**Use the width the page has set up.**\n\n- In the study about one text section in a hundred leaves half the width empty. Text that sits in one\n  half is common, in roughly one site in three, but the other half then holds the section's own\n  picture (most often), a full-bleed picture behind the text, a second column, a list or a figure.\n- When the text takes one side, put the picture, the second column, the list or the large number on\n  the other. Never leave the other half to plain ground.\n- The middle counts too: a card at the left edge and a lone button at the right with the middle third\n  empty is the same hole.\n- The first screen counts too. When the sentence and the button take the left third above a name\n  docked at the foot, the upper right holds something (the picture or film, one fact, the action) or\n  the name grows up to meet them; in testing, 60% of a first screen left as plain ground under the\n  navigation read as a hole, and the inspector now warns when one empty block takes 28% of the first\n  screen or more.\n- A display line fitted to the width is fitted by measurement (a small script that sets its size from\n  the content box, or SVG text with `textLength`), never by a size guessed for one face: a name that\n  starts on the margin and runs a few pixels off the other edge reads as a mistake.\n- A centred composition has one axis, equal flanks and one thing on it, not a stack of heading,\n  paragraph and two buttons.\n\n**A title that says what this is, on the first screen.**\n\n- Asked whether a stranger could say what the page is within five seconds, readers found that 40 of\n  the 97 first screens say it in words, 42 say it only through pictures, small print or a bare name,\n  and 15 do not say it at all. The last group lost usability and content points, not design points.\n- Size alone does not do it: 66 of the 97 first screens carry a display-size line, but 26 of those are\n  a name, a slogan or a place with nothing saying what is offered.\n- The first screen has one `h1`, at display size (32px or more on desktop; on the clear first\n  screens in the study mostly 50–150px), two lines at most, that says what this is: the name with\n  what it does, the product with what it is for, the event with its date and place. If the `h1` is\n  the name, the line under it, at 18px or more, says what the thing is.\n- It is there on the first paint. About a third of the studied pages still showed a loader or nothing readable 4.5\n  seconds.\n\n**A heading on every section.**\n\n- 82% of the text sections on the studied sites open with a heading: median 57px (40–96px for the\n  middle half), about three and a half times the body size, one or two lines.\n- Headings start on the outer margin or on the page's inner anchor line (in the study about a third\n  each) and in the same place for every section. About a quarter of the headings in the study are\n  centred; centre one moment per page here.\n- Where a studied section has no heading, the usual stand-in is a small label: caps, mono or a number\n  in brackets. All three are banned here. Put the label's words in a heading in the heading face at the\n  section size (\"The rooms\", \"How it works\", \"Prices\"), set them on the anchor line, and let the first\n  sentence carry the rest.\n- A statement can open a section as its heading only when it names what the section holds.\n\n## 6. Sections: carry the idea, vary the arrangement\n\nThe most common failure in every score band is a distinctive first screen followed by stock blocks:\nicon cards, a three-up row, an accordion, a link-column footer. About 25 of the studied sites lose\npoints this way, including several above 7.5.\n\n- **The idea survives to the last pixel.** Ask of each section, pricing and FAQ included: what does\n  the page's idea do here? If the page is a menu, the prices are menu lines. If the name is a\n  monument, the footer is the name again. If the object's shape is the motif, the button and the image\n  masks carry it.\n- **No two neighbours share a layout.** Use the shape of each dealt blueprint (list, split, statement,\n  full-bleed, mosaic, table, strip, pinned …). Count them in the screenshot; a shape used three times\n  is the template showing.\n- **Alternate dense and empty, image and type, light and dark** so the scroll has rhythm.\n- **A repeated module is for archives only** (a work index, a menu, a schedule). Anywhere else,\n  repetition reads as a kit.\n- **Break the system once.** After the page has established its rule, one planned exception (a single\n  centred line, one inverted section, one image at a different scale) is what makes the rule visible.\n- **Short pages are fine.** A quarter of the studied sites are one or two screens. Do not add sections\n  to seem complete; each one must carry a claim (see `copy.md` §1).\n\n## 7. Navigation\n\n- The plain form: the wordmark at one end, three to five text links, one action, all at text size on\n  the page ground with no bar, border or background. Median link count in the study is 3.\n- It is also normal to have less: small links in the corners, a single action, or the navigation\n  folded into the content (a list of section titles that is itself the index).\n- If it stays fixed, it must never sit on top of content: check every scroll position in the\n  screenshots, especially on the phone. Floating pill bars are where the panel most often recorded a\n  nav covering text.\n- On a phone: wordmark and one action in view; the links go in a simple full-screen sheet opened by a\n  text button (\"Menu\"), or move to the footer when there are only three.\n- Navigation is small furniture, however it is drawn. On desktop it takes no more than about a tenth\n  of the first screen; on a phone it is one row. A blueprint that builds the navigation as a column of\n  colour blocks or a stack of tabs gets that treatment on desktop only, and collapses to one row on\n  the phone so the headline, the supporting sentence and the action stay in the first screen. In\n  blind tests a nav that ate the hero cost a whole point of usability.\n\n## 8. Endings\n\n- The page should end on a designed scene. In the study: the name at full width (about 18 of 114), the\n  hero repeated in inverted colours (about 12), a closing scene of its own such as the one contact\n  fact set as a headline (about 14), or simply one quiet line (about 22). Link-column footers appear\n  in the panel's notes only as criticism.\n- The full-width name is strong but already a studio habit; use it when the direction is name-led,\n  otherwise prefer the blueprint dealt for the footer.\n- Put the practical facts (address, hours, email, legal line) in the text face at a readable size, on\n  the same anchor lines as the rest of the page.\n\n## 9. The phone is a second composition\n\nDesign the 390px screen as its own page, not the desktop page squeezed. Strong sites that neglect this\nlose usability points; weak ones are often just broken.\n\n- Each blueprint on the sheet has its own phone paragraph. Build it.\n- Keep one dominant thing on the first screen. A wordmark that was 20vw wide on desktop might stack on\n  two lines at 26vw on the phone and be even stronger.\n- Re-author line breaks; re-crop images to portrait (`object-position` per breakpoint, or a different\n  crop size in the image URL); keep unevenness with alternating widths rather than making everything\n  full width.\n- Margins 16–20px. Body text 16–18px. Touch targets at least 44px high.\n- Check 390px in the inspector's screenshots for every round: sideways scroll and three-line headlines\n  usually appear here first.\n\n## 10. How pages fail\n\nFrom the panel's notes on the 54 sites scoring under 6.8 (counts out of 54):\n\n- The whole page is the category's stock template; swap the logo and it could be any competitor\n  (about 20).\n- Centred headline, pill badge, two buttons, screenshot or tile grid below (about 9).\n- A distinctive hero, then stock modules in the usual order (about 8, and about 17 more in the middle\n  band).\n- A default typeface with no character (about 13).\n- Text too small or too low in contrast (about 13); legibility lost over busy photographs (about 9).\n- An undersized headline and no focal point (about 9).\n- The page never says what the thing is, or shows no work (about 12 and 7).\n- Thin content stretched over many screens, or a single gag (about 11).\n- Gates, preloaders and entry pop-ups before any content (about 9).\n- A phone layout that is the desktop shrunk, or broken (about 8).\n- Fixed elements sitting on content; careless details such as colliding lines (about 7 and 5).\n\nAnd the faults of the best sites, which are not to be copied: body text at 9–13px (about 24 of the 90\nsites at 7.5 or more), information hidden behind the concept (about 20), the idea running out\nmid-page (about 15), text over footage with no scrim (about 12), gates and blank first paints (about\n12), floating elements colliding with content (about 11), and a first screen with no statement of what\nthis is and no action (about 9). Say what the thing is, and offer the action, on the first screen.\n","isInternal":false,"tokens":4556,"sizeBytes":18315},{"name":"motion.md","path":"skills/taste-skill/references/motion.md","rawUrl":"https://raw.githubusercontent.com/Leonxlnx/taste-skill/HEAD/skills/taste-skill/references/motion.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Motion\n\nRead this before adding any animation. The static page must already be finished and passing\n`inspect.mjs`; motion is the last pass, never a way to rescue a weak layout.\n\n## Contents\n\n1. The budget\n2. What strong pages do with motion\n3. Four questions before any animation\n4. Tokens\n5. Scroll behaviours, ranked\n6. Recipes (copy, then adapt)\n7. Signature moves\n8. Reduced motion and performance\n9. What gives generated motion away\n10. Rules for motion\n\n## 1. The budget\n\nA page that does not move reads as a mock-up; the inspector counts what moves while the page loads and\nscrolls, and fails it under eight elements. The motion layer has five parts:\n\n- **Two or three scroll scenes:** the big, scroll-driven moments award sites are remembered for (a\n  camera flying through a field of pictures, a picture that grows from a window to the whole screen,\n  type that crosses a held stage, cards that deal out and stack). The direction sheet deals them from\n  `library/scenes.json` when the library has scenes for the brief; `references/scenes.md` says how to\n  fill and fit them. They are where the page is bold; everything else stays quiet so they land.\n\n- **One signature moment:** the thing a visitor would describe an hour later: the headline that rises\n  out of a mask, the image that opens like a shutter, the wordmark that scales with the scroll. The\n  direction sheet from `draw.mjs` names one. Build that one well; it is the only move allowed to be\n  loud.\n- **Section entrances, choreographed per section:** the parts of each section arrive in reading order\n  (heading, text, picture, details), staggered 60–90ms, rising 16–32px with opacity, once. Vary the\n  manner with the content instead of stamping one preset everywhere: a list arrives row by row, a\n  picture opens from a mask or settles from a slight scale, a figure counts up once, a statement rises\n  line by line.\n- **Feedback under the hand:** buttons that give on press, links that answer the pointer, cards and\n  pictures that respond on hover, a menu that opens from where it was clicked.\n- **One moving picture:** a found clip as a muted loop with a poster frame, a slow drift or scale on\n  a large photograph, or a scroll-linked move on the hero picture.\n\nWhat is still banned: the same fade-and-slide-up with the same timing on every block, which is the most\ncited motion tell of generated pages; motion that hides content until a script runs, with no fallback;\nbounce and elastic easing; anything that animates layout properties. Uniform motion says nobody decided\nanything; choreographed motion with one protected moment says somebody did.\n\n## 2. What strong pages do with motion\n\nMeasured on the latest 99 Awwwards Sites of the Day (July to October 2026), at 1440 and 390, with\nthe transitions, tweens and scroll triggers recorded while each page loaded and was scrolled. Where\nthe gallery does something the house rules ban, the house version follows.\n\n- **The stack.** Two in three use a smooth-scroll library and three in five ship Three.js; GSAP is\n  named on 56. The quiet layer below (reveals, line rises, the ink fill) needs none of it: CSS scroll\n  timelines and view transitions do that work, though only 3 and 6 of the sites use them. The big\n  scroll scenes are built on GSAP ScrollTrigger, as on the award sites, through the shared stage in\n  `assets/scenes/` (`references/scenes.md`).\n- **Curves.** The curves that really ran are strong ease-outs: expo out (`.16,1,.3,1` and\n  `.19,1,.22,1`) ran on 14 sites, cubic out on 13, quint out on 7, and by number of transitions the\n  quint and expo outs lead every chosen curve. In-out curves are kept for wipes and things that\n  travel (cubic and quart in-out, about 15 sites each). Ease-in appears only for exits, short, before\n  a slow arrival. Colour changes use plain `ease` (46 sites). Overshoot sits in 19 stylesheets and\n  ran on 2.\n- **Durations.** Hover colour 200-300 ms; small interface moves 300-450 ms; reveals and line rises\n  600-1,000 ms; picture openings and wipes 1,100-1,600 ms. The median of everything that ran on a\n  site is 420 ms.\n- **Staggers.** 20-40 ms between characters, 75-120 ms between lines, 50-100 ms between list items.\n- **Scroll-linked motion is locked to the scrollbar.** Of the sites that scrub, 14 of 18 lock it with\n  no smoothing; the other four smooth it by 0.1-3 s. Reveals fire when the element's top is 80-95% of the way\n  down the viewport, once.\n- **How much moves.** A median of 130 elements are moved by script on a page, but they come from a\n  few gestures: one split heading is 20-60 elements. The inspector's floor (8, warning under 16) is a\n  floor, not a target.\n- **Waiting is the most common cost.** 60 of 99 open on a loading screen, 26 of them with a counter.\n  Half the usable pages were still unreadable 2.5 s after the browser said the page had loaded, a\n  third at 4.5 s. The preloaders were not covering slow pages (their documents loaded faster than the\n  rest) and the readers' design marks were the same whatever the wait; only usability fell. House\n  version: no preloader, the message readable on the first frame, the load sequence over by 1.2 s.\n- **Pins cost length.** Two in three scrolling pages hold something sticky or pinned. Those pages\n  are twice as long (a median 16.6 screens against 7.5) for fewer words per screen (27 against 46).\n  House version: at most two held stages, about one screen per step, three screens per stage.\n- **Reduced motion is mostly missing.** 35 of 99 have any `prefers-reduced-motion` rule, 16 have\n  three or more; 5 of 26 scroll-scrubbed scenes have one. Every recipe here keeps the finished state\n  as the reduced state.\n\n## 3. Four questions before any animation\n\n1. **How often will someone see it?** Once per visit (hero load, a section reveal): it can take its\n   time. Many times per visit (hover, menu, accordion): fast and small. Hundreds of times (keyboard\n   actions, typing): no animation.\n2. **What is it for?** Valid answers: it shows where something came from, it confirms an action, it\n   keeps a change from being jarring, it explains how the product works, it is the signature moment.\n   \"It looks nice\" is only valid for the signature moment.\n3. **Which easing?** Entering or leaving: ease-out, so movement starts the instant the eye arrives.\n   Moving between two places on screen: ease-in-out. Colour and opacity on hover: `ease`. Constant\n   travel (marquee, progress): `linear`. `ease-in` makes interfaces feel slow because the first frames\n   barely move; do not use it. The CSS keyword curves are weak, so use the tokens below.\n4. **How long?** Press feedback 100–160ms. Hover 150–200ms. Menus and popovers 150–250ms. Dialogs and\n   drawers 250–450ms. Section and hero reveals 500–900ms. Leaving is quicker than arriving (about 70%).\n\n## 4. Tokens\n\n```css\n:root {\n  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);        /* entrances, moving hovers, UI under 600ms */\n  --ease-expo: cubic-bezier(0.16, 1, 0.3, 1);        /* new: reveals of 800ms and longer, line rises, openings */\n  --ease-in-out: cubic-bezier(0.76, 0, 0.24, 1);     /* wipes, panels, things that travel while visible */\n  --ease-soft: cubic-bezier(0.33, 1, 0.68, 1);       /* slow scale and drift on photographs */\n  --ease-exit: cubic-bezier(0.55, 0.055, 0.675, 0.19); /* new: something leaving for good, short */\n  --t-press: 140ms;\n  --t-hover: 180ms;\n  --t-ui: 240ms;\n  --t-reveal: 800ms;\n  --t-open: 1200ms;                                  /* new: picture openings and clip wipes */\n  --stagger-line: 90ms;                              /* new */\n  --stagger-item: 70ms;                              /* new */\n}\n```\n\nHow the study bears on each:\n\n- `--ease-out` (quint out) is in 28 stylesheets with its near twin and is the single most frequent\n  chosen curve among transitions that ran. Keep it.\n- `--ease-expo` is new. Expo out (`.16,1,.3,1` and `.19,1,.22,1`) is in 28 stylesheets and ran on 14\n  sites, more than any other chosen family, and it is the curve the long reveals use: line rises,\n  picture openings, card entrances of 0.9-1.6 s. Use it for anything at `--t-reveal` or longer; it\n  replaces `--ease-out` in the masked headline and the reveal-on-scroll recipes.\n- `--ease-in-out` (quart in-out) matches its family (14 stylesheets, 7 ran). Keep it for wipes,\n  shutters, menus and page transitions.\n- `--ease-soft` (cubic out) matches the cubic-out family (21 stylesheets, 13 ran), but the study uses it\n  for interface moves of 0.3-0.8 s, where `--ease-out` already serves. Narrow it to slow scale and\n  drift on photographs.\n- `--ease-exit` is new. Ease-in is right for exactly one job: something that leaves for good (an\n  outgoing caption, a replaced slide, a closing panel), short, at about 60-70% of the matching\n  entrance. Never for anything the visitor is waiting to see.\n- Not adopted: `.4,0,.2,1` (38 stylesheets) is a framework default, and overshoot curves (19) stay\n  banned on interface elements.\n- `--t-hover` stays at 180ms. The study's colour hovers run 200-300ms; a little quicker reads as\n  more exact. A hover that moves something (a label roll, an arrow) takes `--t-ui` to 400ms.\n\n## 5. Scroll behaviours, ranked\n\n| Behaviour | Pages of 99 | What it serves | House version |\n| --- | --- | --- | --- |\n| Smooth-scroll library | 67 | A feeling of weight; makes scrubbed scenes easier to build | Optional, through `Stage.smooth()`: Lenis at lerp 0.1-0.14, off for touch and reduced motion |\n| Held (sticky or pinned) stage | 44 | One picture or object carries several claims; chapters | Yes: the scroll scenes (`references/scenes.md`), two or three per page, one to four screens each; other sticky stages three screens at most |\n| Split text | 40 | Lines and words arriving as they are read; hover rolls | Lines for headings and statements; words only for the ink fill; characters only for a heading of one to three words |\n| Colour by chapter | 34 | Tells chapters apart without padding bands | Yes, as hard cuts at section edges; the header ink follows in 300ms |\n| Scroll-scrubbed scene (camera, object, image sequence) | 26 | Explains a product by moving it | Yes, from the scene library, built on the shared stage with a finished composition for reduced motion |\n| Parallax depth | 24 | Depth in collages; pictures drifting inside oversized frames | Travel under 8% of the element, pictures held at 106-110% in their frames |\n| Marquee | 21 | Life on a static band | Existing \"Edge-to-edge marquee\": one per page, pausable |\n| Masked line or word rise | 18 | Headings that arrive like set type | Yes: \"Masked line reveal\" on load, \"Lines that rise on scroll\" below the fold |\n| Wheel drives a scene, no page scroll | 16 | Browsing one object | Not used (see 2.6) |\n| Blur-in | 15 | Soft arrival | At most 8px of blur, 600ms, gone once settled; never on body text |\n| Picture from inset frame to full-bleed | 14 | The hand-over from a type screen to the big picture | Yes: \"Opening window\", about one screen of scroll |\n| Grey-to-ink text fill | 14 | Paces one statement | Yes, once per page, starting at 45% ink: \"Ink fill\" |\n| Sheet slides over a held layer | 11 | Page-turn rhythm between chapters | Yes: new move \"Sheet over a held picture\" |\n| Scramble or decode | 11 | A \"code\" voice | Not used (see 2.6) |\n| Header ink by chapter | 10 | The fixed header stays legible | Yes, with colour by chapter |\n| Horizontal track pinned to vertical scroll | 8 | Walking through rooms or a collection | Native drag row first; pinned only when the row is under three screens long, with keyboard support: \"Sideways gallery\" |\n| Curtain footer | 8 | The page ends as a scene | Existing move |\n| Rolling digits | 6 | Figures that arrive | Yes, for pages whose case is a handful of numbers: \"Rolling figures\" |\n| Index with hover preview | 5 | Navigating work by name | Existing move, upgraded recipe |\n\nText, split by unit: characters on about 20 pages, lines on about 14, words on about 11. Character\nsplits serve short headings and button rolls; on long statements they leave fragments mid-scroll.\n\n## 6. Recipes\n\nAll recipes keep the content visible when JavaScript is off, put every hidden state inside\n`prefers-reduced-motion: no-preference`, and use the tokens above. Two notes that apply to several:\n\n- **Scroll timelines need a scroller to watch.** `animation-timeline: view()` takes the nearest scroll\n  container, and `overflow: hidden` makes one. A picture inside an `overflow: hidden` frame therefore\n  never animates. Use `overflow: clip` on frames, or name the timeline on the section\n  (`view-timeline-name: --hero`) and point the children at that name. This also applies to the\n  existing \"Scroll-linked progress\" recipe.\n- **Scroll-linked means linear.** The scroll is the easing. 14 of the 18 scrubbing sites in the study\n  lock motion to the scrollbar, which is what CSS scroll timelines do.\n\nAll recipes keep content visible when JavaScript is off or slow: the hidden state only applies under\n`html.js`, which a one-line inline script sets.\n\n```html\n<script>document.documentElement.classList.add('js')</script>\n```\n\n### Load sequence in 1.2 seconds\n\nEverything is in the HTML and painted on the first frame; the sequence only adds arrival. Nothing\nwaits for the load event, and nothing in the navigation animates.\n\n```html\n<header class=\"hero\">\n  <h1 class=\"display lines\">\n    <span class=\"line\"><span data-line style=\"--i:0\">Stools for</span></span>\n    <span class=\"line\"><span data-line style=\"--i:1\">small kitchens</span></span>\n  </h1>\n  <p class=\"lead\" data-load style=\"--d:420ms\">…</p>\n  <a class=\"button\" data-load style=\"--d:480ms\" href=\"#stools\">See the stools</a>\n  <figure class=\"hero__picture\" data-open><img src=\"stool.jpg\" alt=\"…\" fetchpriority=\"high\"></figure>\n</header>\n```\n\n```css\n.hero__picture { overflow: clip; margin: 0; }\n@media (prefers-reduced-motion: no-preference) {\n  .js .hero [data-line] { transform: translateY(105%); animation: load-line 800ms var(--ease-expo) forwards; animation-delay: calc(100ms + var(--i) * var(--stagger-line)); }\n  .js .hero [data-load] { opacity: 0; transform: translateY(12px); animation: load-rise 500ms var(--ease-out) forwards; animation-delay: var(--d); }\n  .js .hero [data-open] { clip-path: inset(0 0 100% 0); animation: load-open 1000ms var(--ease-in-out) 150ms forwards; }\n  .js .hero [data-open] img { transform: scale(1.08); animation: load-settle 1100ms var(--ease-expo) 100ms forwards; }\n}\n@keyframes load-line { to { transform: none; } }\n@keyframes load-rise { to { opacity: 1; transform: none; } }\n@keyframes load-open { to { clip-path: inset(0); } }\n@keyframes load-settle { to { transform: none; } }\n```\n\nThe timeline: the headline's lines rise from 100 to 990 ms, the picture opens from 150 to 1,150 ms,\nthe sentence and the button arrive from 420 to 980 ms. All settled by 1.2 s, four things at most.\nPreload the display font (`<link rel=\"preload\" as=\"font\" type=\"font/woff2\" crossorigin>`) so the lines\nrise in the real face, and give the picture `fetchpriority=\"high\"` and a ground colour sampled from it,\nso a slow image opens onto its own colour rather than a blank box. Study: 22 of 91 pages were readable\nat the first intro frame and 11 more by 1.2 s; the intros the readers called respectful finished in\nabout 1-1.2 s; a third of the pages were still unreadable at 4.5 s.\n\n### Masked line reveal (the classic gallery headline)\n\nEach line slides up from behind its own baseline. Because headlines are capped at two lines, you set\nthe line breaks yourself and wrap each line.\n\n```html\n<h1 class=\"lines\">\n  <span class=\"line\"><span data-line style=\"--i:0\">Stools for</span></span>\n  <span class=\"line\"><span data-line style=\"--i:1\">small kitchens</span></span>\n</h1>\n```\n\n```css\n.lines .line { display: block; overflow: hidden; padding-bottom: 0.08em; margin-bottom: -0.08em; }\n.lines [data-line] { display: block; }\n@media (prefers-reduced-motion: no-preference) {\n  .js .lines [data-line] {\n    transform: translateY(105%);\n    animation: line-up 900ms var(--ease-out) forwards;\n    animation-delay: calc(var(--i) * 110ms + 150ms);\n  }\n}\n@keyframes line-up { to { transform: none; } }\n```\n\nThe `padding-bottom` / negative margin pair stops descenders (g, y, p) being clipped by the mask.\nOn a narrow phone the two authored lines may each wrap; check the mobile screenshot, and if they do,\nauthor a shorter mobile break with a `<br class=\"only-wide\">` pattern or reduce the size.\n\n### Reveal on scroll (once)\n\nFor the two or three sections that deserve it, not for every block.\n\n```css\n@media (prefers-reduced-motion: no-preference) {\n  .js [data-reveal] { opacity: 0; transform: translateY(24px); transition: opacity 700ms var(--ease-out), transform 900ms var(--ease-out); }\n  .js [data-reveal].is-in { opacity: 1; transform: none; }\n}\n```\n\n```js\nconst io = new IntersectionObserver((entries) => {\n  for (const e of entries) if (e.isIntersecting) { e.target.classList.add('is-in'); io.unobserve(e.target); }\n}, { rootMargin: '0px 0px -12% 0px', threshold: 0.1 });\ndocument.querySelectorAll('[data-reveal]').forEach((el) => io.observe(el));\n```\n\nNever attach reveals with a scroll listener, never replay them when the element re-enters, and never\nleave anything at `opacity: 0` if the observer fails to fire (the `html.js` gate handles no-JS; the\n`unobserve` handles replays).\n\n### Image shutter\n\nAn image opens from one edge while scaling down slightly inside its frame. Gallery staple; use it for\nthe one hero or showcase image.\n\n```css\n.shutter { overflow: hidden; }\n@media (prefers-reduced-motion: no-preference) {\n  .js .shutter { clip-path: inset(0 0 100% 0); transition: clip-path 1100ms var(--ease-in-out); }\n  .js .shutter img { transform: scale(1.12); transition: transform 1500ms var(--ease-soft); }\n  .js .shutter.is-in { clip-path: inset(0); }\n  .js .shutter.is-in img { transform: none; }\n}\n```\n\n### Press and hover\n\n```css\n.button { transition: transform var(--t-press) var(--ease-out), background-color var(--t-hover) ease, color var(--t-hover) ease; }\n.button:active { transform: scale(0.97); }\n.link { text-decoration: underline; text-decoration-color: transparent; text-underline-offset: 0.2em; text-decoration-thickness: 0.07em; transition: text-decoration-color var(--t-hover) ease; }\n@media (hover: hover) and (pointer: fine) {\n  .button:hover { background-color: var(--accent-strong); }\n  .link:hover { text-decoration-color: currentColor; }\n}\n```\n\nHover styles go behind `(hover: hover)` because touch devices fire hover on tap and leave it stuck.\nHover should raise contrast, never lower it. Do not change font weight on hover (the text reflows).\nDo not lift or scale every card on hover; one consistent, small response is enough.\n\n### Scroll-linked progress without JavaScript\n\nFor a wordmark that scales as the hero leaves, an image that drifts a few percent, or a progress bar.\nWrap in `@supports` so browsers without scroll timelines get the static state.\n\n```css\n@supports (animation-timeline: view()) {\n  @media (prefers-reduced-motion: no-preference) {\n    .drift { animation: drift linear both; animation-timeline: view(); animation-range: entry 0% exit 100%; }\n    @keyframes drift { from { transform: translateY(-4%); } to { transform: translateY(4%); } }\n  }\n}\n```\n\nKeep the travel small (under 8% of the element). Large parallax makes text hard to read and looks\ndated.\n\n### Pinned story\n\nA section whose heading stays put while items pass. Use `position: sticky`; do not hijack scrolling.\n\n```css\n.story { display: grid; grid-template-columns: 5fr 7fr; gap: var(--gutter); align-items: start; }\n.story__title { position: sticky; top: 18vh; }\n@media (max-width: 800px) { .story { grid-template-columns: 1fr; } .story__title { position: static; } }\n```\n\n### Index with preview, anchored to the row\n\nRows of names; pointing at a row or tabbing to it opens one frame level with that row. The frame\nfollows the row, never the pointer.\n\n```html\n<section class=\"index\">\n  <ul class=\"index__list\">\n    <li><a class=\"index__row\" href=\"/work/harbour-house\" data-preview=\"/img/harbour-house.jpg\">\n      <span class=\"index__name\">Harbour House</span><span class=\"index__year\">2025</span>\n      <img class=\"index__thumb\" src=\"/img/harbour-house-small.jpg\" alt=\"\" loading=\"lazy\" width=\"640\" height=\"400\">\n    </a></li>\n    <!-- … -->\n  </ul>\n  <div class=\"index__frame\" aria-hidden=\"true\"><img alt=\"\"></div>\n</section>\n```\n\n```css\n.index { position: relative; }\n.index__list { list-style: none; margin: 0; padding: 0; }\n.index__row { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: 0 var(--gutter); padding-block: 0.3em; font-size: var(--step-head); color: inherit; text-decoration: none; transition: opacity var(--t-hover) ease; }\n.index__thumb { order: -1; flex-basis: 100%; width: 100%; height: auto; margin-bottom: 0.4rem; }\n.index__frame { display: none; }\n@media (hover: hover) and (pointer: fine) {\n  .index__list { max-width: 62%; }\n  .index__thumb { display: none; }\n  .index__list:has(.index__row:hover, .index__row:focus-visible) .index__row:not(:hover, :focus-visible) { opacity: 0.4; }\n  .index__frame { display: block; position: absolute; top: 0; right: var(--margin); width: 30%; aspect-ratio: 4 / 3; z-index: 1; pointer-events: none; clip-path: inset(100% 0 0 0); transition: clip-path 320ms var(--ease-out), transform 360ms var(--ease-out); }\n  .index__frame.is-open { clip-path: inset(0); }\n  .index__frame img { width: 100%; height: 100%; object-fit: cover; }\n}\n@media (prefers-reduced-motion: reduce) { .index__frame { transition: none; } }\n```\n\n```js\n(() => {\n  const root = document.querySelector('.index');\n  if (!root) return;\n  const frame = root.querySelector('.index__frame');\n  const picture = frame.querySelector('img');\n  const fine = matchMedia('(hover: hover) and (pointer: fine)');\n  let warmed = false;\n  const show = (row) => {\n    if (!fine.matches) return;\n    if (!warmed) { warmed = true; root.querySelectorAll('[data-preview]').forEach((a) => { new Image().src = a.dataset.preview; }); }\n    picture.src = row.dataset.preview;\n    const y = row.offsetTop + row.offsetHeight / 2 - frame.offsetHeight / 2;\n    const max = root.offsetHeight - frame.offsetHeight;\n    const opening = !frame.classList.contains('is-open');\n    if (opening) frame.style.transitionProperty = 'clip-path';   // open in place, do not slide in from the top\n    frame.style.transform = `translateY(${Math.min(max, Math.max(0, y))}px)`;\n    if (opening) { frame.getBoundingClientRect(); frame.style.transitionProperty = ''; }\n    frame.classList.add('is-open');\n  };\n  const hide = () => frame.classList.remove('is-open');\n  root.querySelectorAll('.index__row').forEach((row) => {\n    row.addEventListener('pointerenter', () => show(row));\n    row.addEventListener('focus', () => show(row));\n  });\n  root.addEventListener('pointerleave', hide);\n  root.addEventListener('focusout', (e) => { if (!root.contains(e.relatedTarget)) hide(); });\n})();\n```\n\nOn touch screens each row shows its own picture above the name. Study: 5 pages navigate work this way;\nframes from about 470x270 to large plates behind the list; the other rows dimmed to about 0.3 (0.4 here, the floor for dimmed text). The\nimage trails and cursor-borne previews seen elsewhere in the study are the gimmick version.\n\n### Lines that rise on scroll\n\nFor a section heading or a statement whose line breaks you do not control. Splits after the fonts\nload, reveals once, then gives the plain text back so it rewraps normally. Plain text only (no links or\nemphasis inside).\n\n```html\n<h2 class=\"head\" data-lines>Turned by hand in one small workshop</h2>\n```\n\n```css\n[data-lines] .line { display: block; overflow: clip; padding-bottom: 0.12em; margin-bottom: -0.12em; }\n[data-lines] .line > span { display: block; }\n@media (prefers-reduced-motion: no-preference) {\n  .is-split .line > span { transform: translateY(110%); }\n  .is-split.is-in .line > span { transform: none; transition: transform 900ms var(--ease-expo) calc(var(--i) * var(--stagger-line)); }\n}\n```\n\n```js\n(() => {\n  const els = [...document.querySelectorAll('[data-lines]')];\n  if (!els.length || !('IntersectionObserver' in window) || matchMedia('(prefers-reduced-motion: reduce)').matches) return;\n  const restore = (el) => { el.textContent = el.dataset.text; el.classList.remove('is-split', 'is-in'); };\n  const split = (el) => {\n    const text = el.textContent.trim().replace(/\\s+/g, ' ');\n    el.dataset.text = text;\n    el.textContent = '';\n    const words = text.split(' ').map((word) => {\n      const s = document.createElement('span');\n      s.style.display = 'inline-block';\n      s.textContent = word;\n      el.append(s, ' ');\n      return s;\n    });\n    const lines = [];                                   // group the words by the line they landed on\n    for (const w of words) {\n      const last = lines.at(-1);\n      if (last && Math.abs(last.top - w.offsetTop) < 4) last.words.push(w.textContent);\n      else lines.push({ top: w.offsetTop, words: [w.textContent] });\n    }\n    el.textContent = '';\n    lines.forEach((line, i) => {\n      const mask = document.createElement('span');\n      const inner = document.createElement('span');\n      mask.className = 'line';\n      inner.style.setProperty('--i', i);\n      inner.textContent = line.words.join(' ');\n      mask.append(inner);\n      el.append(mask, ' ');\n    });\n    el.classList.add('is-split');\n  };\n  const io = new IntersectionObserver((entries) => {\n    for (const e of entries) {\n      if (!e.isIntersecting) continue;\n      io.unobserve(e.target);\n      e.target.classList.add('is-in');\n      e.target.querySelector('.line:last-of-type > span')\n        .addEventListener('transitionend', () => restore(e.target), { once: true });\n    }\n  }, { rootMargin: '0px 0px -12% 0px' });\n  document.fonts.ready.then(() => els.forEach((el) => { split(el); io.observe(el); }));\n  let width = innerWidth;                               // a width change before the reveal: give the text back\n  addEventListener('resize', () => {\n    if (innerWidth === width) return;\n    width = innerWidth;\n    els.filter((el) => el.matches('.is-split:not(.is-in)')).forEach((el) => { io.unobserve(el); restore(el); });\n  });\n})();\n```\n\nStudy: masked rises from 100-120% below the line, 0.6-1.2 s, 75-120 ms between lines, triggered when\nthe block's top is 80-95% down the viewport. Reduced motion: the script does not run; the text is plain.\n\n### Opening window\n\nThe hand-over from a type screen to the one big picture: the picture first shows as a window in the\nmiddle of a held stage and opens to full-bleed over about one screen of scroll.\n\n```html\n<section class=\"opening\">\n  <div class=\"opening__stage\">\n    <img src=\"workshop-wide.jpg\" alt=\"The workshop at first light, benches cleared\" width=\"2400\" height=\"1500\">\n  </div>\n</section>\n```\n\n```css\n.opening__stage { height: 100svh; overflow: clip; }\n.opening__stage img { display: block; width: 100%; height: 100%; object-fit: cover; }\n@supports (animation-timeline: view()) {\n  @media (prefers-reduced-motion: no-preference) {\n    .opening { height: 200svh; view-timeline-name: --opening; --inset-y: 20%; --inset-x: 28%; }\n    .opening__stage { position: sticky; top: 0; animation: opening-window linear both; animation-timeline: --opening; animation-range: contain 0% contain 75%; }\n    .opening__stage img { animation: opening-settle linear both; animation-timeline: --opening; animation-range: contain 0% contain 75%; }\n  }\n}\n@media (max-width: 700px) { .opening { --inset-y: 18%; --inset-x: 8%; } }\n@keyframes opening-window { from { clip-path: inset(var(--inset-y) var(--inset-x)); } to { clip-path: inset(0); } }\n@keyframes opening-settle { from { transform: scale(1.15); } to { transform: none; } }\n```\n\nThe section is two screens tall; the stage is held for one, and the window is fully open after three\nquarters of it, so the full-bleed picture rests for a moment before the page moves on. Study: 14 pages;\nstart windows 38-60% of the width; runways 600-1,800 px, and the readers asked for one to two screens.\nWithout scroll timelines, and under reduced motion, the picture is a full-bleed screen.\n\n### Held picture, passing captions\n\nThe pinned story built for photographs: the picture holds on one side while short captions pass on\nthe other; the caption at the middle of the screen is lit and its picture is shown.\n\n```html\n<section class=\"steps\">\n  <figure class=\"steps__media\">\n    <div class=\"steps__pictures\">\n      <img src=\"seasoning.jpg\" alt=\"Ash boards stacked to season\" class=\"is-on\">\n      <img src=\"turning.jpg\" alt=\"A leg being turned on the lathe\">\n      <img src=\"finish.jpg\" alt=\"Oil rubbed into a finished seat\">\n    </div>\n    <figcaption class=\"steps__count\" aria-hidden=\"true\"></figcaption>\n  </figure>\n  <ol class=\"steps__list\">\n    <li class=\"steps__item\"><h3>Seasoned for a year</h3><p>…</p></li>\n    <li class=\"steps__item\"><h3>Turned by hand</h3><p>…</p></li>\n    <li class=\"steps__item\"><h3>Finished with oil</h3><p>…</p></li>\n  </ol>\n</section>\n```\n\n```css\n.steps { display: grid; grid-template-columns: 7fr 5fr; column-gap: var(--gutter); }\n.steps__media { margin: 0; align-self: start; }           /* a stretched grid item cannot stick */\n.steps__pictures img { display: block; width: 100%; height: auto; }\n.steps__list { list-style: none; margin: 0; padding: 0; }\n.steps__item { min-height: 80svh; display: flex; flex-direction: column; justify-content: center; }\n.js .steps__media { position: sticky; top: 0; height: 100svh; display: flex; flex-direction: column; justify-content: center; gap: 0.75rem; }\n.js .steps__pictures { position: relative; aspect-ratio: 4 / 5; max-height: 80svh; }\n.js .steps__pictures img { position: absolute; inset: 0; height: 100%; object-fit: cover; opacity: 0; transition: opacity 500ms ease; }\n.js .steps__pictures img.is-on { opacity: 1; }\n.js .steps__item { opacity: 0.4; transition: opacity var(--t-ui) ease; }\n.js .steps__item.is-active { opacity: 1; }\n@media (max-width: 800px) {\n  .steps { display: block; }                               /* the section, not a grid area, contains the sticky picture */\n  .js .steps__media { height: auto; z-index: 1; background: var(--bg); padding-block: 0.5rem; }\n  .js .steps__pictures { aspect-ratio: 3 / 2; max-height: 42svh; }\n  .steps__item { min-height: 60svh; }\n}\n@media (prefers-reduced-motion: reduce) { .js .steps__pictures img, .js .steps__item { transition: none; } }\n```\n\n```js\n(() => {\n  const root = document.querySelector('.steps');\n  if (!root || !('IntersectionObserver' in window)) return;\n  const items = [...root.querySelectorAll('.steps__item')];\n  const pictures = [...root.querySelectorAll('.steps__pictures img')];\n  const count = root.querySelector('.steps__count');\n  const show = (i) => {\n    items.forEach((el, k) => el.classList.toggle('is-active', k === i));\n    pictures.forEach((el, k) => el.classList.toggle('is-on', k === i));\n    if (count) count.textContent = `${i + 1} of ${items.length}`;\n  };\n  const io = new IntersectionObserver((entries) => {\n    for (const e of entries) if (e.isIntersecting) show(items.indexOf(e.target));\n  }, { rootMargin: '-45% 0px -45% 0px' });                 // a band across the middle of the screen\n  items.forEach((el) => io.observe(el));\n  show(0);\n})();\n```\n\nWithout JavaScript the pictures and captions are two plain columns. Study: inactive items at 20-40%\n(dims of 10-15% read as missing text, so the floor here is 40%), crossfades of 400-600 ms, about one\nscreen per step; the readers asked for a visible count on any held sequence of more than two steps.\nThe count is a plain sentence in the body face, not a zero-padded numeral.\n\n### Sideways gallery\n\nA row of pictures that the vertical scroll moves sideways while the stage is held, for a short\ncollection (eight items or fewer). The native drag row is the base; the pinned version is added only\non wide screens with motion allowed, and only when the row is under three screens long.\n\n```html\n<section class=\"gallery\">\n  <div class=\"gallery__stage\">\n    <h2 class=\"head\">Eight kitchens, one stool</h2>\n    <ul class=\"gallery__track\">\n      <li class=\"gallery__item\"><a href=\"/kitchens/leith\"><img src=\"leith.jpg\" alt=\"A narrow galley kitchen in Leith\" width=\"1200\" height=\"1500\"><span>Leith</span></a></li>\n      <!-- … -->\n    </ul>\n  </div>\n</section>\n```\n\n```css\n.gallery__track { display: flex; gap: var(--gutter); list-style: none; margin: 0; padding: 0 var(--margin); overflow-x: auto; scroll-snap-type: x mandatory; scroll-padding-inline: var(--margin); }\n.gallery__item { flex: 0 0 min(72vw, 28rem); scroll-snap-align: start; }\n.gallery__item img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover; }\n.gallery.is-pinned .gallery__stage { position: sticky; top: 0; height: 100svh; display: flex; flex-direction: column; justify-content: center; gap: 2rem; overflow: clip; }\n.gallery.is-pinned .gallery__track { overflow: visible; scroll-snap-type: none; }\n.gallery.is-pinned .gallery__item { flex-basis: calc(62svh * 0.8); }\n```\n\n```js\n(() => {\n  const root = document.querySelector('.gallery');\n  if (!root) return;\n  const track = root.querySelector('.gallery__track');\n  const wide = matchMedia('(min-width: 900px) and (prefers-reduced-motion: no-preference)');\n  let dx = 0, queued = false;\n  const place = () => {\n    queued = false;\n    if (!root.classList.contains('is-pinned')) return;\n    const p = Math.min(1, Math.max(0, -root.getBoundingClientRect().top / dx));\n    track.style.transform = `translate3d(${(-p * dx).toFixed(1)}px, 0, 0)`;\n  };\n  const measure = () => {\n    root.classList.add('is-pinned');                     // measure the row as it would be when pinned\n    track.style.transform = '';\n    dx = track.scrollWidth - track.clientWidth;\n    const pin = wide.matches && dx > 0 && dx < innerHeight * 3;\n    root.classList.toggle('is-pinned', pin);\n    root.style.height = pin ? `${innerHeight + dx}px` : ''; // one pixel of scroll moves the row one pixel\n    place();\n  };\n  track.addEventListener('focusin', (e) => {             // keyboard: bring the focused item into view\n    if (!root.classList.contains('is-pinned')) return;\n    const item = e.target.closest('.gallery__item');\n    const x = Math.min(dx, Math.max(0, item.offsetLeft - parseFloat(getComputedStyle(track).paddingLeft)));\n    scrollTo({ top: root.getBoundingClientRect().top + scrollY + x, behavior: 'instant' });\n  });\n  addEventListener('scroll', () => { if (!queued) { queued = true; requestAnimationFrame(place); } }, { passive: true });\n  addEventListener('resize', measure);\n  addEventListener('load', measure);\n  wide.addEventListener('change', measure);\n  measure();\n})();\n```\n\nStudy: 8 pages pinned a horizontal track; their pages ran a median 25 screens, and the readers' worst\ncases spent 9 screens on three cards and 10,000-23,000 px of wheel on one track. Here the speed is 1:1\nand the hold ends when the last picture reaches the margin. Phones, narrow windows, reduced motion and\nlong rows all get the native row with snapping, which also works with touch, trackpads and the\nkeyboard. Never put the only copy of a call to action inside the moving row.\n\n### Receding hero\n\nAs the first screen leaves, its picture sinks a little and darkens while the words lift away a little\nfaster, so the hero recedes instead of simply scrolling off.\n\n```html\n<header class=\"hero\">\n  <img class=\"hero__picture\" src=\"kitchen.jpg\" alt=\"…\" width=\"2400\" height=\"1600\" fetchpriority=\"high\">\n  <div class=\"hero__copy\"><h1 class=\"display\">…</h1><p class=\"lead\">…</p></div>\n</header>\n```\n\n```css\n.hero { position: relative; min-height: 100svh; overflow: clip; display: grid; align-items: end; view-timeline-name: --hero; }\n.hero__picture { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }\n.hero::after { content: ''; position: absolute; inset: 0; background: var(--ink); opacity: 0; pointer-events: none; }\n.hero__copy { position: relative; z-index: 1; padding: var(--margin); }\n@supports (animation-timeline: view()) {\n  @media (prefers-reduced-motion: no-preference) {\n    .hero__picture { animation: hero-sink linear both; animation-timeline: --hero; animation-range: exit 0% exit 100%; }\n    .hero::after { animation: hero-dim linear both; animation-timeline: --hero; animation-range: exit 0% exit 100%; }\n    .hero__copy { animation: hero-lift linear both; animation-timeline: --hero; animation-range: exit 0% exit 70%; }\n  }\n}\n@keyframes hero-sink { to { transform: translateY(8%) scale(1.06); } }\n@keyframes hero-dim { to { opacity: 0.35; } }\n@keyframes hero-lift { to { transform: translateY(-6%); opacity: 0; } }\n```\n\nThe `exit` range runs from the moment the hero's top meets the top of the screen until its bottom\ndoes, which for a first screen is the first screen of scroll. Study: hero pictures that sink and dim as\nthey leave, a heading scrubbed from 140 to 60 px, a title card that scales down on the phone; the\nreaders called it quiet and the page \"one sheet\". Travel stays under 8%; the overlay is a flat ink at\nup to 35%, not a gradient. Static where unsupported or reduced.\n\n\n\n\n\n### Page to page\n\nNavigation between pages of the site with the browser's own view transitions: the old page fades\nquickly, the new one rises in, and the picture the visitor clicked travels into place as the new\npage's hero. No library, no full-screen curtain.\n\n```css\n/* on every page */\n@view-transition { navigation: auto; }\n@media (prefers-reduced-motion: reduce) { @view-transition { navigation: none; } }\n::view-transition-old(root) { animation: vt-leave 200ms var(--ease-exit) both; }\n::view-transition-new(root) { animation: vt-arrive 380ms var(--ease-out) 60ms both; }\n::view-transition-group(*) { animation-duration: 480ms; animation-timing-function: var(--ease-in-out); }\n::view-transition-image-pair(*.picture) { overflow: clip; }\n::view-transition-old(*.picture), ::view-transition-new(*.picture) { height: 100%; object-fit: cover; }\n@keyframes vt-leave { to { opacity: 0; } }\n@keyframes vt-arrive { from { opacity: 0; transform: translateY(16px); } }\n```\n\n```html\n<!-- on the index: the card picture of one project -->\n<img src=\"/img/leith.jpg\" alt=\"…\" style=\"view-transition-name: kitchen-leith; view-transition-class: picture\">\n<!-- on that project's page: its hero picture -->\n<img src=\"/img/leith-wide.jpg\" alt=\"…\" style=\"view-transition-name: kitchen-leith; view-transition-class: picture\">\n```\n\nEach name may appear once per page. Browsers without cross-document view transitions simply navigate.\nStudy: 16 pages load a page-transition library and run full-screen curtains of 0.7-2.4 s; 6 use view\ntransitions. The new page should be readable within half a second.\n\n### Ink fill\n\nOne statement that fills from part-ink to full ink as it rises through the screen, line by line. It is\nreadable before it fills; the fill only sets the pace.\n\n```html\n<p class=\"statement head\" data-fill>Nine people, one workshop, no catalogue: every stool is made for the kitchen it goes to.</p>\n```\n\n```css\n[data-fill] { --fill: var(--ink); color: var(--fill); }\n@supports (animation-timeline: view()) {\n  @media (prefers-reduced-motion: no-preference) {\n    .is-filling > span { display: inline-block; color: color-mix(in oklab, var(--fill) 45%, transparent); animation: ink-fill linear both; animation-timeline: view(); animation-range: cover 20% cover 45%; }\n  }\n}\n@keyframes ink-fill { to { color: var(--fill); } }\n```\n\n```js\n(() => {\n  if (!CSS.supports('animation-timeline: view()') || matchMedia('(prefers-reduced-motion: reduce)').matches) return;\n  document.querySelectorAll('[data-fill]').forEach((el) => {\n    const words = el.textContent.trim().split(/\\s+/);\n    el.textContent = '';\n    words.forEach((word, i) => {\n      const s = document.createElement('span');\n      s.textContent = word;\n      el.append(s, i < words.length - 1 ? ' ' : '');\n    });\n    el.classList.add('is-filling');\n  });\n})();\n```\n\nEach word watches its own position, so the words of a line fill together as the line moves from three\nquarters of the way down the screen to just past half way. Set `--fill` on a dark chapter to its ink.\nStudy: 14 pages scrub a statement from grey to ink; unread words started at about 25-30% and settled\nframes still caught statements half pale, which reads as disabled text. Here: one statement per page,\nthree to five lines, 32px or larger, starting at 45% (about 3:1 against the ground, enough for large\ntext). Full ink without scroll timelines or under reduced motion.\n\n### Rolling figures\n\nFor pages whose case is a handful of numbers: each digit rolls up to its value once, the columns a\nbeat apart. The real number stays in the text for screen readers and search.\n\n```html\n<p class=\"figure\"><span class=\"display\" data-roll>1987</span> the year the first stool was sold</p>\n```\n\n```css\n.roll__digits { display: inline-flex; font-variant-numeric: tabular-nums; line-height: 1; }\n.roll__col { display: inline-block; height: 1em; overflow: clip; }\n.roll__strip { display: flex; flex-direction: column; transform: translateY(calc(var(--d) * -1em)); }\n.roll__strip > span { height: 1em; }\n@media (prefers-reduced-motion: no-preference) {\n  .roll:not(.is-in) .roll__strip { transform: none; }\n  .roll.is-in .roll__strip { transition: transform 1100ms var(--ease-expo) calc(var(--i) * var(--stagger-item)); }\n}\n```\n\n```js\n(() => {\n  const els = [...document.querySelectorAll('[data-roll]')];\n  if (!els.length) return;\n  els.forEach((el) => {\n    const value = el.textContent.trim();\n    const said = Object.assign(document.createElement('span'), { className: 'sr-only', textContent: value });\n    const shown = Object.assign(document.createElement('span'), { className: 'roll__digits' });\n    shown.setAttribute('aria-hidden', 'true');\n    let i = 0;\n    for (const ch of value) {\n      if (!/\\d/.test(ch)) { shown.append(ch); continue; }\n      const col = Object.assign(document.createElement('span'), { className: 'roll__col' });\n      const strip = Object.assign(document.createElement('span'), { className: 'roll__strip' });\n      strip.style.setProperty('--d', ch);\n      strip.style.setProperty('--i', i++);\n      for (let n = 0; n < 10; n++) strip.append(Object.assign(document.createElement('span'), { textContent: n }));\n      col.append(strip);\n      shown.append(col);\n    }\n    el.classList.add('roll');\n    el.replaceChildren(said, shown);\n  });\n  if (!('IntersectionObserver' in window)) { els.forEach((el) => el.classList.add('is-in')); return; }\n  const io = new IntersectionObserver((entries) => {\n    for (const e of entries) if (e.isIntersecting) { e.target.classList.add('is-in'); io.unobserve(e.target); }\n  }, { rootMargin: '0px 0px -15% 0px' });\n  els.forEach((el) => io.observe(el));\n})();\n```\n\nStudy: 6 pages roll digit columns (stats, a year, coordinates), about 0.9-1.1 s per column on an\nexpo-out, staggered by column. Use it for three or four figures at display size, never in running text\nand never for a value that changes after load. Reduced motion: the figure is set at its value.\n\n### Accordion\n\n```css\n.acc__panel { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 320ms var(--ease-out); }\n.acc__panel > div { overflow: hidden; }\n.acc[open] .acc__panel, .acc__item.is-open .acc__panel { grid-template-rows: 1fr; }\n```\n\nAnimating `grid-template-rows` from `0fr` to `1fr` opens to the content's real height without measuring\nit in JavaScript.\n\n### Menu or dialog\n\n```css\n.menu { transform-origin: top right; transition: opacity var(--t-ui) var(--ease-out), transform var(--t-ui) var(--ease-out); }\n.menu[hidden], .menu.is-closed { opacity: 0; transform: scale(0.97) translateY(-6px); pointer-events: none; }\n```\n\nThings open from where they were triggered (`transform-origin` at the trigger). Nothing enters from\n`scale(0)`; start at 0.95–0.98. A centred dialog is the one case that scales from its centre.\n\n## 7. Signature moves\n\nThe direction sheet names one. Each of these was seen repeatedly on the studied gallery sites.\n\n| Move | What happens | Build with |\n| --- | --- | --- |\n| Masked headline | Lines rise from behind their baselines on load | Masked line reveal recipe |\n| Shutter image | Hero or showcase image opens from an edge, settling from 1.12 scale | Image shutter recipe |\n| Scaling wordmark | A giant wordmark shrinks or grows a few percent as the hero scrolls out | Scroll-linked recipe on `scale` |\n| Pinned story | A heading holds while its items scroll past | Sticky recipe |\n| Index with preview | Text rows; the hovered row shows its image | Index with preview, anchored to the row |\n| Curtain footer | The last section is revealed from under the page as you reach the end | `position: sticky; bottom: 0` footer under a main with a background and `z-index` |\n| Slow crossfade | Hero image crossfades through 3–4 photographs, 5–6s each | Stacked images, opacity keyframes, pause when the tab is hidden |\n| Edge-to-edge marquee | One line of very large type travels sideways, slowly | Duplicate the content, `translateX(-50%)` linear loop, pause on hover and under reduced motion |\n| Drag row | A horizontally scrollable row of large images with scroll snapping | `overflow-x: auto; scroll-snap-type: x mandatory`, no library |\n| Colour by chapter | Each chapter is its own full-bleed colour field, so the ground changes at section edges; a fixed header takes the ink of the chapter beneath | Section backgrounds in CSS; `base.js` sets `--header-ink` from `data-ink`. Never recolour the whole page from an observer |\n| Opening window | A type screen hands over to the big picture: a window in the middle of a held stage opens to full-bleed over about one screen | Opening window recipe |\n| Ink-fill statement | One statement fills from 45% to full ink as it rises through the screen | Ink fill recipe |\n| Sheet over a held picture | A full-bleed photograph holds for one screen; the next chapter slides up over it as an opaque sheet | A 100svh `position: sticky; top: 0` figure followed by a section with its own background and a higher `z-index`; no script |\n| Sideways gallery | A short row of pictures moves sideways while the vertical scroll holds the stage | Sideways gallery recipe |\n| Pushed line | One line of very large type is pushed sideways by the scroll, reading whole at the middle of its run | `animation-timeline: view()` on the line, `translateX` from 12% to -12%, linear; static where unsupported |\n| Rolling figures | The few figures that make the case roll up to their values once | Rolling figures recipe |\n| Carried picture | The picture clicked in a list travels into place as the next page's hero | Page to page recipe |\n\nPick by subject. A portfolio wants the index with preview; a restaurant wants the slow crossfade; a\nproduct wants the shutter on its hero object. If the move says nothing about the subject, it is\ndecoration and the page is better without it.\n\nPick by subject, as before: the opening window for a product or a place with one great photograph; the\nsheet for chapters that each own a picture; the sideways gallery for a short set of rooms, kitchens or\npieces; the pushed line for a brand whose claim is a word; rolling figures for a report, a fund or a\npractice that leads with numbers; the carried picture for a portfolio whose index and case pages are\nboth built.\n\n## 8. Reduced motion and performance\n\n- `prefers-reduced-motion: reduce` means fewer and gentler, not none: keep opacity and colour changes,\n  drop travel, scale, parallax and autoplay. All recipes above are written inside\n  `no-preference` blocks so the reduced state is simply the finished state.\n- Animate `transform`, `opacity` and `clip-path`. Animating `width`, `height`, `top`, `left`, `margin`\n  or `padding` forces layout on every frame. `grid-template-rows` for accordions is the accepted\n  exception because it is short and rare.\n- Do not drive many children from one changing CSS variable on a parent; set the transform on the\n  element that moves.\n- `will-change` only on an element that is about to animate, removed afterwards.\n- Pause loops when off screen or when the tab is hidden.\n- No scroll hijacking and no custom cursor. They cost usability, which is 30% of an Awwwards score and\n  the line most winners score lowest on. Smoothing only through `Stage.smooth()`, which stays off for\n  touch and reduced motion.\n\n## 9. What gives generated motion away\n\n- The same fade-up on every block.\n- A dozen staggered entrances in the hero.\n- Hover lift or zoom on every card and image.\n- Bounce or elastic easing on interface elements.\n- Infinite loops that mean nothing: pulsing dots, floating shapes, shimmering text, rotating badges.\n- A reveal that never fires and leaves a blank band in the page. Run `inspect.mjs` after the motion\n  pass and look at every screenshot for missing content.\n\n### Seen in the latest Sites of the Day\n\nSeen in the study, with how often, and what the house does instead.\n\n- **Preloaders and counters (60 of 99; 26 with a counter).** Half the usable pages were unreadable\n  2.5 s after load, a third at 4.5 s; the preloaders sat mostly on pages that had already loaded, and\n  25 of the 29 that loaded in under 3 s still showed nothing readable at 4.5 s. Counters stalled,\n  outlasted the load or were tweens with nothing behind them. House: no preloader. If a scene must\n  load, the HTML first screen (headline, picture, action) is there at once and the scene fades in\n  behind it when ready.\n- **Gates (10 of 99): enter, sound, age or gesture before any content.** House: none. Sound is a\n  control on the page, off by default.\n- **Scroll hijacking (16 wheel-driven scenes, 9 of them endless, plus 14 single screens where the wheel\n  does nothing).** The visitor cannot tell where they are, how much is left or how to get out, and the\n  keyboard and screen readers get nothing. Usability 6.01 against 6.50 for pages that scroll. House:\n  native scroll; any scene is \n\n<!-- [TRUNCATED AT 50KB] -->","isInternal":false,"tokens":13222,"sizeBytes":50074},{"name":"research.md","path":"skills/taste-skill/references/research.md","rawUrl":"https://raw.githubusercontent.com/Leonxlnx/taste-skill/HEAD/skills/taste-skill/references/research.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# The study\n\nEverything numeric in this skill comes from here. Cite these figures; do not round them up or invent\nothers.\n\n## Contents\n\n1. Method and its limits\n2. Scores\n3. Where the idea comes from\n4. Headlines\n5. Type\n6. Devices: what separates strong from weak, and what does not\n7. Colour and shape\n8. Imagery and page structure\n9. What the inspector says about the gallery itself\n10. The 25 highest-scored sites and their ideas\n11. How the skill was tested\n12. The October 2026 study: 100 Sites of the Day\n13. The app-screen study\n\n## 1. Method and its limits\n\n- **Sample.** 248 sites collected on 5 October 2026: 156 from One Page Love (the latest gallery pages\n  and the category listings) and 92 Awwwards Sites of the Day (the three most recent listing pages).\n  247 loaded; 246 were re-measured with the final probe.\n- **Capture.** Headless Chrome at 1440×900 and 390×844. For each site: the first viewport, five more\n  frames while scrolling with real wheel input, the mobile first viewport, and a measurement pass in\n  the page (computed styles, text geometry, colours, fonts actually loaded).\n- **Panel.** 21 model reviewers each studied about 12 sites from the screenshots and the measurements,\n  described them (idea, hero, type, colour, imagery, layout, sections) and scored them the Awwwards\n  way: design 40%, usability 30%, creativity 20%, content 10%. These are model judgements from still\n  frames, not human jurors and not the real Awwwards scores. Batches mixed both sources so each\n  reviewer saw a spread.\n- **Usable sets.** 235 sites were usable for the panel (12 showed only a preloader, an entry gate or a\n  bot wall). 202 were measurable for typography (a page with at least 25 words and a detectable\n  headline). \"Top\" below means panel score 7.5 or higher (82 measurable sites); \"weak\" means under 6.5\n  (23 measurable sites).\n- **Limits.** One capture per site on one day. Some heroes were caught mid-animation or behind a cookie\n  notice. WebGL-heavy sites are under-described by text measurements. The eyebrow detector counts any\n  small short label directly above a large heading, so it over-counts against the panel's stricter\n  reading (60% measured against 35% observed). Motion was inferred from frames, not watched. The sample\n  is whatever the two galleries had recently featured; it is fashion as much as quality.\n\n## 2. Scores\n\n| | All 235 | One Page Love (151) | Awwwards (84) |\n| --- | --- | --- | --- |\n| Median overall | 7.2 | 7.1 | 7.5 |\n| Middle half | 6.8–7.6 | | |\n| 8.0 or higher | 25 sites (11%) | | |\n| 7.5 or higher | 90 sites (38%) | | |\n| Under 6.5 | 29 sites | | |\n\nMedian by criterion: design 8, usability 7, creativity 7, content 7. Among the top 25: design 9,\nusability 7, creativity 8, content 8. Usability is the one line that does not rise with the rest: the\nbest sites are no easier to use than the average one. Do not copy their gates, preloaders, tiny text\nor hidden navigation.\n\n## 3. Where the idea comes from\n\nThe clearest pattern in the panel's notes: high scores go with a concept taken from the subject, and\nlow scores go with its absence. The weakest entries' ideas were recorded in words like \"none beyond the\nstandard dark SaaS launch formula\", \"no visual idea beyond clarity\", \"no strong idea\". The strongest\nwere sentences only that subject could own (section 10).\n\nRecurring engines among the 7.3+ sites, each the basis of a direction in the library:\n\n- **The product demonstrates itself.** A colour picker's loupe reads the page's own background; a list\n  tool is sold with tiny working lists; a photo app's page is a wall of its own output.\n- **The page is an artefact from the subject's world.** A wedding site that is the invitation; an\n  archive as tabbed folders; a coupon with a cut line; a portfolio as a contact sheet.\n- **The name is the hero.** Wordmarks as wide as the screen, a photograph set inside the name like a\n  letter, a name split to opposite corners with the page between.\n- **One motif from the subject drives everything.** A tool's octagonal section as button, mask and\n  loader; two circles for two accounts; a café's stripes.\n- **Dressed as another category.** A money app as a streetwear drop; an industrial roaster as a design\n  object; a parcel service as a fairground.\n- **The place carries it.** One full-bleed view and a name along the bottom edge.\n- **A fixed stage.** A title or object stays put while content swaps beneath it.\n- **One section, one colour.** Flat fields as chapters.\n- **Radical understatement.** A 27px headline and tiny live demonstrations, carried through completely.\n\nHero types, by the panel's classification (top sites against weak sites): full-bleed media with type\nover it 16% / 10%; giant wordmark 14% / 0%; typographic poster 13% / 7%; text beside media 10% / 3%;\n**centred statement with media below 7% / 24%**. The centred headline over a screenshot is the weak\nsites' signature layout.\n\n## 4. Headlines\n\n| Hero headline | All | Top | Weak |\n| --- | --- | --- | --- |\n| Words, median | 5 | 5 | 5 |\n| Words, middle half | 3–9 | 2–8 | 3–8 |\n| Characters, median | 32 | | |\n| One line at 1440 | 47% | | |\n| Two lines or fewer at 1440 | 70% | 71% | 83% |\n| Two lines or fewer at 390 | 57% | | |\n| Three lines or fewer at 390 | 82% | | |\n\nAwwwards heroes are shorter (median 4 words, 76% within two lines) than One Page Love's (6 words, 66%).\nSection headings have a median of 3 words. Length does not separate strong from weak; nearly everyone\nin the gallery writes short headlines. The two-line limit in this skill is a house rule that most of\nthe gallery already meets on desktop and that takes care to meet on a phone.\n\n## 5. Type\n\n| | All | Top | Weak |\n| --- | --- | --- | --- |\n| Hero size, median | 72px (5.0vw) | 6.0vw | 4.7vw |\n| Hero size, middle half | 3.0–7.6vw | 2.5–9.7vw | 2.7–6.1vw |\n| Largest text on the page, median | 6.4vw | 8.4vw | 5.0vw |\n| Largest text, upper quarter starts at | 10.4vw | 12.5vw | 6.7vw |\n| Hero on a phone, median | 40px | | |\n| Hero tracking, median (middle half) | -0.01em (-0.03 to 0) | | |\n| Hero leading, median (middle half) | 1.0 (0.95–1.1) | | |\n| Body size, median (middle half) | 16px (14–18) | | |\n| Headline ÷ body, median | 4.3 | 4.7 | 4.0 |\n| Typefaces carrying 3%+ of text | one 31%, two 45%, three 22% | | |\n| Distinct font sizes, median | 8 | | |\n\nHero weight: regular 48%, medium 18%, semibold 6%, bold or heavier 22%, light 6%. Capitals 24%.\nCentred 39% overall, 52% on weak sites. Display classes by the panel: neo-grotesk 48%, transitional\nserif 11%, geometric sans 10%, condensed 6%, extended 6%, old-style serif 4%, custom lettering 4%.\n\nStrong sites push the extremes: their biggest type is bigger and their range is wider. Weak sites\ncluster in the middle.\n\n## 6. Devices: what separates strong from weak, and what does not\n\nMeasured in the page unless marked (panel).\n\n**More common on weak sites (the data supports avoiding them):**\n\n| Device | Top | Weak |\n| --- | --- | --- |\n| Icon-topped feature cards (panel) | 1% | 28% |\n| Rows of identical cards with a small icon (measured) | 7% | 26% |\n| Pill badges (panel) | 14% | 34% |\n| Pill-shaped label above a heading (measured) | 5% | 26% |\n| Tiny uppercase letter-spaced labels, any | 16% | 57% |\n| Tiny uppercase letter-spaced labels, three or more | 6% | 43% |\n| Gradient fills (not counting scrims) | 22% | 52% |\n| Gradient text | 2% | 13% |\n| Shadows on resting elements, any | 24% | 48% |\n| Shadows, five or more | 10% | 30% |\n| Emoji in the page | 10% | 26% |\n| Eyebrow labels (panel) | 32% | 45% |\n\n**No real difference:**\n\n| Device | Top | Weak |\n| --- | --- | --- |\n| Backdrop blur anywhere | 32% | 39% |\n| Italic-serif accent word (panel) | 4% | 7% |\n| Thin rules, any | 61% | 52% |\n\n**More common on strong sites (banned here anyway, as house style):**\n\n| Device | Top | Weak |\n| --- | --- | --- |\n| Monospace labels (panel) | 44% | 24% |\n| Monospace anywhere outside code (measured) | 45% | 26% |\n| Index numbering (panel) | 38% | 21% |\n\nMonospace captions, index numbers and ruled grids are the present fashion of award sites. They are\nexcluded from this skill by the owner's choice, not by the data: they are the devices generators copy\nfirst, and a page that cannot lean on them has to find structure in space, tone and scale.\n\n## 7. Colour and shape\n\n- Dark page ground 41%; pure white 25%; pure black 12%; a warm off-white 13%.\n- Scheme (panel): monochrome plus one accent 23%, light neutral 22%, dark neutral 14%, several flat\n  colours 13%, two-tone 12%, photographic 9%, one colour field 6%.\n- Primary buttons are neutral (black, white, grey) on 52% of sites. One site in 246 has a terracotta\n  button; none has a violet one.\n- Median number of distinct section grounds: 2 on top sites, 1 on weak sites.\n- Button shape: top sites square (0–2px) 52%, fully round 23%, small radius 19%, medium (9–16px) 6%.\n  Weak sites fully round 59%, medium 24%, square 18%.\n- Media corners are square on 73% of sites; where rounded, the median radius is 12px.\n- Buttons in the first viewport: none on 55% of top sites and 39% of weak ones.\n\n## 8. Imagery and page structure\n\n- Hero media covers at least half the first viewport on 60% of sites (top 68%, weak 48%) and nearly\n  all of it on 50% (top 56%, weak 39%). No hero media: 15%.\n- Video is present on 49% of sites and a canvas element on 49% (top 62%, weak 35%).\n- Images per page, median: 24 overall, 37 on top sites, 5 on weak ones.\n- Imagery kind (panel): mixed 32%, photography 14%, generative or WebGL 13%, product interface 12%,\n  3D render 11%, illustration 9%, video 6%, type only 3%. Median panel score is lowest for\n  illustration-led (6.9) and product-interface-led (7.1) pages and highest for video and type-only\n  (7.5).\n- Page length, median: 8.7 screens and 575 words (middle half 1.6–14.4 screens, 250–956 words). A\n  quarter of the sites are a single screen or two.\n- Navigation: a median of 3 links; fixed or sticky on 66%.\n- Density (panel): airy 46%, balanced 45%, dense 9%. Alignment: centred 33%, mixed 31%, left-anchored\n  17%, modular grid 13%, free 6%.\n- Asked to describe each site's most interesting sections, the panel picked a pricing, testimonial or\n  FAQ section only 7, 12 and 9 times across 235 sites. Where strong sites have them at all, they are\n  not where the design effort goes, and they avoid the stock form.\n\n**From the panel's written notes on the 114 sites scoring 7.3 or more** (hand tallies, approximate;\n`layout.md` turns these into practice):\n\n- Outer margins of 32px or less on about 45; 80px or more on about 8. A centred 700–1300px container\n  on about 15, several of them the pages the panel called stock.\n- Text anchored to a fixed off-centre line on about 22. Text docked in corners or at opposite ends of\n  a baseline on about 25 and 15.\n- Two or three type sizes with nothing between on about 30; no note describes a graded five-step\n  scale.\n- One thing per screen on about 20. A full background colour per section on about 20; alternating\n  light and dark on about 12.\n- Every section recomposed on about 14; one planned exception to the page's own system on about 14.\n- No conventional top navigation bar on about 45; small corner links on about 22; a single link or\n  button on about 10.\n- Endings: the name at full width about 18, the hero repeated inverted about 12, a closing scene of\n  its own about 14, no footer or a single line about 22. Link-column footers are mentioned only as\n  criticism.\n- Motion (inferred from frames): autoplaying video about 50; pinned or fixed stages about 40; text\n  reveals about 30 (blur-in 10, masked line rises 8, scroll-tied word colouring 7); horizontal strips\n  about 27; marquees about 26; media swapped behind a fixed element about 15; scroll-linked scaling\n  about 12. Rare: hover effects (4 mentions), parallax (6), accordions (5), bounce or spring motion\n  (none). About 10 strong sites show little or no motion at all.\n- How weak sites fail (54 sites under 6.8): the category's stock template about 20; centred headline,\n  pill badge, two buttons and a screenshot about 9; stock modules after a distinctive hero about 8,\n  plus about 17 in the middle band; a characterless default typeface about 13; text too small or too\n  faint about 13; never saying what the thing is about 12.\n- Faults of the best sites (90 at 7.5 or more), not to be copied: text at 9–13px about 24;\n  information hidden behind the concept about 20; the idea running out mid-page about 15; text over\n  footage with no scrim about 12; gates, preloaders and blank first paints about 12.\n\n## 9. What the inspector says about the gallery itself\n\nRunning this skill's own `inspect.mjs` rules over the 202 measurable gallery sites: the median site\nhas 4 `FAIL`s and only 4% have none. The rules that fire most: headline over two lines somewhere on\nthe page 60%, eyebrow-like label 60%, thin rules 50%, monospace 37%, shadows 32%, gradients 29%, index\nnumbering 29%.\n\nSo the house style is deliberately stricter than the gallery. It is not a description of award sites;\nit is a narrower target inside what they do: their scale, their ideas, their imagery and restraint,\nwithout the ornaments that have since become a uniform.\n\n## 10. The 25 highest-scored sites and their ideas\n\nThe panel's one-sentence reading of each. Notice that every one names something only that subject\ncould own. (Several use devices this skill bans; take the idea, not the ornament.)\n\n| Site | Source | Score | Idea |\n| --- | --- | --- | --- |\n| PP Neue Montreal | Awwwards | 8.6 | A typeface specimen dressed as a vintage city travel guide: the font named after Montreal is sold through guidebook titling, postcards and old tourist footage. |\n| Seasats | Awwwards | 8.4 | Calm, dusk-lit seascapes sell autonomous boats as serene instruments, and the navigation is a column of stacked colour swatches taken from that sea-and-sand palette. |\n| AI in Design Report 2026 | Awwwards | 8.4 | A research report laid out like a colour-blocked print annual: a video collage on top, an oversized tight grotesk title, and flat orange, lilac, sage and black blocks carrying stats, quotes and chapters. |\n| House of Honey | Awwwards | 8.4 | A block-heavy wordmark pierced by a fine script: the bold-against-delicate contrast is repeated at every scale, with giant pink script behind quiet serif statements. |\n| White Desert | Awwwards | 8.4 | One word, the destination, set a third of the screen tall over footage like a film title card; sheer scale stands in for remoteness. |\n| Applied Imagination | One Page Love | 8.3 | An essay conceived on a flight is read as a descent: an altimeter ticks from 30,000 ft to zero while you scroll down through clouds to mountains at ground level. |\n| Cursor Compile | One Page Love | 8.3 | The event name drawn as seven looping one-line curves in seven colours, more signature than logotype, on an otherwise whisper-quiet off-white page. |\n| The New Industrials | One Page Love | 8.3 | A long-read essay laid out inside a drafting grid, where colour fields shift as you read and machine parts drift through the margins and finally assemble into the publisher's initials. |\n| Wild | One Page Love | 8.3 | A studio essay in which everything decorative is drawn on one square-pixel grid: the hero heatmap, the icons, the diagrams, the lettering and the footer. |\n| Hildén & Kaira | Awwwards | 8.3 | The agency name is cast in liquid chrome across the full width, and the same chrome becomes the objects that float through the page, tying the pitch to one material. |\n| PX Push | Awwwards | 8.2 | A design subscription presented as a retro broadcast: the entire site is seen through a CRT screen, with a chrome logo token as its mascot. |\n| Illoca | Awwwards | 8.2 | Software for architects sold as a drafting table: a two-colour illustrated studio on graph paper that the scroll pushes into until the drawing fills the screen. |\n| Aspen Search | Awwwards | 8.2 | The page is a tile system with no margins: the two-word name is split across cells that alternate type, dithered image, black and one mint green. |\n| Dragonfly Redux | Awwwards | 8.2 | A crypto fund presented as a terminal artefact: every picture is rendered in characters, framed by four letters of the name pinned to the viewport corners. |\n| Monolog | Awwwards | 8.2 | A studio pitch run as an asymmetric sheet: a narrow left column carries the sales talk while a wide right column stacks a very heavy headline and the proof. |\n| The Queue | One Page Love | 8.1 | An essay on queueing where the queue is the ornament: a line of drawn figures stands along the bottom of the hero and returns between chapters in changing period dress. |\n| Paul Kalkbrenner | Awwwards | 8.1 | Swiss poster typography for a techno artist: the name as one black line with a photo set inside it like a glyph, then every chapter gets its own flat colour. |\n| Vero New York | Awwwards | 8.1 | A keepsake treated like couture: a slow close-up film opens, then a white sculpture of a dress stays pinned at centre while one sentence passes over it. |\n| Depo Luxe | Awwwards | 8.1 | A film production roster shown as a full-screen reel in which every step is one film with only a title, a director and a client, set like credits at body size. |\n| Longbow | Awwwards | 8.1 | The page is built on a visible four-column construction grid, and cars, cards and a giant condensed marquee are slotted into its cells like objects on an artboard. |\n| Mosby's Files | Awwwards | 8.0 | An archive of architects presented as a physical stack of coloured index-tab file folders that you flip through. |\n| Sarah & Matt Wedding | One Page Love | 8.0 | The site is the invitation: a letterpress-style card opens the page, and its ornaments and small typographic parts become the components for everything after it. |\n| Zara Webb | One Page Love | 8.0 | A one-woman newborn-care practice presented like a hand-made keepsake: a mascot rabbit, scalloped and flower-shaped cut-outs, candid film photographs. |\n| Noho | Awwwards | 8.0 | Furniture sold through people misusing it (wearing, balancing on, hiding behind chairs on flat colour backdrops) while the interface stays quiet. |\n| Juggle | One Page Love | 8.0 | The headline literally drowns: a flat blue field rises to half height and the lines below the waterline change colour. |\n\nFull notes on any studied site: `node scripts/draw.mjs --site <id>` (ids appear on direction sheets).\n\n## 11. How the skill was tested\n\nSix client briefs (an invoicing tool, a restaurant, a designer's portfolio, a ceramic product, a\nguesthouse, a design conference), each with no photographs. For every brief a fresh agent built the\npage three ways: with no skill (baseline), with another published design skill (atelier, three briefs)\nand with this skill. Every build was photographed by `inspect.mjs` in the same way and judged blind\nby a separate agent with the juror brief (Awwwards weights, anonymous A/B/C folders, screenshots\nonly). The skill was revised after each round from the jurors' reasons and the builders' notes.\n\n| Round | Briefs | This skill | Baseline | Atelier | Wins |\n| --- | --- | --- | --- | --- | --- |\n| 1 | 4 | 6.6 | 7.7 | 6.8 | 1 of 4 |\n| 2 | 3 | 7.1 | 8.0 | | 0 of 3 |\n| 3 | 3 | 7.5 | 7.5 | | 1 of 3 |\n| 4 (unseen briefs) | 3 | 6.9 | 7.9 | 7.5 | 0 of 3 |\n| 5 (same three) | 3 | 7.7 | 7.8 | 7.2 | 2 of 3 |\n\nUnder the inspector, the final builds measured 0 FAIL each; the baselines measured 8 to 13 FAIL each\n(eyebrows, monospace labels, 01/02/03 numbering, hairlines, gradients, shadows, three-line headlines,\ntext under 13px).\n\nWhat the jurors rewarded, in the order they named it: an idea that belongs to this client and not to\nthe category (the competitor test); one live thing on the page; full content at a readable size; a\nfirst screen with one dominant element and a real button; drawings of the subject with detail. What\nthey punished: a quiet page that read as empty, a small headline, text sliding over pictures or cut\nat the top, a page recoloured mid-section, rows cut at the right edge, a large sentence over three or\nmore lines (read as a long headline whatever its markup), navigation that took over the first screen.\nEach of these is now a rule in SKILL.md or a check in the inspector.\n\nLimits: one juror per brief per round, so single scores carry about half a point of noise; the round-5\nbriefs had been seen in round 4; jurors are models, not people.\n\n## 12. The October 2026 study: 100 Sites of the Day\n\nA second study, made for v2.1, of the latest 100 Awwwards Sites of the Day (10 July to 17 October\n2026), with a different aim from the first: where the pictures and footage sit, how pages move, and\nthe frame (margins, balance, empty space, titles). About three in four of these sites were also in\nthe first study.\n\n- **Capture.** Headless Chrome at 1440×900 and 390×844 on 18 October 2026: four frames of the first\n  4.5 seconds after load, every screen while scrolling with real wheel input (one frame at rest per\n  step; the mid-step frames were cut from the top of the document instead of the viewport, so they\n  were not used), five phone screens, and a measurement pass in the page: every picture and\n  clip with its box, ratio, fit and corners; every section's content edges and pictures; blank runs;\n  the CSS that loaded (curves, durations, keyframes, breakpoints, feature counts); the animations,\n  transitions and script-driven moves that actually ran; GSAP tweens and scroll triggers where the\n  page exposed them. Nothing a site owns (code, copy, pictures) is reproduced in the skill; only\n  measurements and descriptions in our own words.\n- **Panel.** One model reader per site studied its frames and measurements, described the idea, the\n  first screen, the frame, every section, where each picture sits, the motion and what not to copy,\n  and scored it the Awwwards way. 91 of 99 captures were usable (the rest showed a gate, a bot wall or\n  a firewall page). Scores ran 6.7 to 7.9 (median 7.45); \"top\" means 7.5 or more (36 sites), \"lowest\"\n  under 7.3 (16).\n- **What it changed.** Where pictures and footage go: `imagery.md` §12. What strong pages do with\n  motion, new tokens, recipes and the gimmicks to avoid: `motion.md` §2, §4–6 and §9–10. Empty space\n  and the frame: `layout.md` §4–5. New compositions in `library/heroes.json` and `sections.json` and\n  notes on media and motion in `library/sites.json` (`draw.mjs --site <id>`).\n- **Headline numbers.** Pictures fill a median 16% of a scrolled screen, but in whole screens: 42% of\n  screens hold none and 19% are 90% picture or more. The median page carries 7 pictures (top 8,\n  lowest 2) and 42% carry footage (half of the top sites, one of the 16 lowest). 94% of pictures have\n  square corners. Strong ease-outs are the curves that ran (expo and quint out); the median of all\n  that ran on a site is 420ms. 60 of 99 open on a loading screen, and a third of the usable pages were\n  still unreadable 4.5 seconds after load, with no gain in the design marks. About 1 text section in\n  100 leaves half the width empty; the outer margins of strong pages match to a few pixels; 82% of\n  text sections open with a heading; 15 of 97 first screens never say what the thing is, and those\n  lose usability points.\n- **Limits.** One capture per site on one day; a WebGL scene can render blank in a headless browser;\n  the scroll-linked frames are partly an artefact of smooth-scroll libraries; one reader per site, so\n  single scores carry about half a point of noise.\n\n## 13. The app-screen study\n\nFor dashboards and app screens (v2.1), a separate study of 23 real product screens chosen by the\nowner (17 products, 17 light and 6 dark, at 1440–1512px): each screen measured from its pixels by a\nreader with full-resolution crops, six cross-cutting reports (shell, data and charts, tables and\nforms, visual language, taste, styles), and a synthesis into `references/app-screens.md` and\n`library/app.json` (seven styles, five shells, screen patterns). The screenshots stay private; the\nskill carries only the measurements and the rules. Blind test rounds of app screens built with and\nwithout the skill then shaped the warnings at the top of that file.\n","isInternal":false,"tokens":6567,"sizeBytes":24262},{"name":"scenes.md","path":"skills/taste-skill/references/scenes.md","rawUrl":"https://raw.githubusercontent.com/Leonxlnx/taste-skill/HEAD/skills/taste-skill/references/scenes.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Scroll scenes\n\nThe big moments of a page: stretches of scroll where the page stops being a column of sections and\nbecomes a scene. A camera flies through a field of pictures, a picture grows from a window to the whole\nscreen, a word buckles under the scroll, a set of photographs orbits and lands in a grid. These are what\nvisitors remember from award sites, and what a page built from tidy sections alone never has.\n\nThe scene library is taken apart from recent Awwwards Sites of the Day (October 2026: 43 sites recorded\nframe by frame while scrolling, 261 scenes described, 30 types), rebuilt from scratch in our own code,\ntested frame by frame at desktop and phone width and under reduced motion, and reviewed against the\nscenes it came from. Nothing a site owns is in them. Until `library/scenes.json` ships the draw deals\nnone; a page that needs a scene builds one on the stage (section 8), with every rule here.\n\n## Contents\n\n1. What a scene is\n2. Putting a scene on a page\n3. Filling it\n4. Fitting it to the page\n5. The phone, reduced motion, no script\n6. Checking it\n7. Rules for scenes\n8. When no scene in the library fits\n9. The catalogue\n\n## 1. What a scene is\n\nA tall section whose stage holds still while the page scrolls past it. The stage is\n`position: sticky`; the section is (hold + 1) screens tall, so the stage is held for `hold` screens;\na GSAP timeline is scrubbed from 0 to 1 by that scroll. Nothing captures the wheel: the scrollbar always\ntells the truth, the keyboard and the trackpad work as everywhere else, and the scene ends.\n\nWhat a scene is not: a fade-up, a small parallax, a sticky footer, a marquee. Those are the quiet layer\n(`references/motion.md`). A scene changes the whole screen.\n\nThe direction sheet deals two or three (section 9 of the sheet), from different families, each placed\non the section of the argument it can carry. Build them in step 6, with that section: a scene is\ncomposition, not decoration added at the end.\n\n## 2. Putting a scene on a page\n\nCopy the shared stage and the dealt scene's files into the project (`assets/scenes/stage.css`,\n`stage.js`, `<id>.css`, `<id>.js`). Each scene file's header comment lists the markup it expects and\nits options; `assets/scenes/demo/<id>.html` is a complete working page to read beside it.\n\n```html\n<head>\n  <script>document.documentElement.classList.add('js')</script>\n  <link rel=\"stylesheet\" href=\"scenes/stage.css\">\n  <link rel=\"stylesheet\" href=\"scenes/<id>.css\">\n</head>\n<body>\n  …\n  <section class=\"scene\" data-scene=\"<id>\" data-options='{\"hold\": 3}' aria-label=\"…\">\n    <div class=\"scene-stage\">\n      <!-- the markup from the scene file's header, filled with this page's content -->\n    </div>\n  </section>\n  …\n  <script src=\"https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js\"></script>\n  <script src=\"https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/ScrollTrigger.min.js\"></script>\n  <script src=\"https://cdn.jsdelivr.net/npm/lenis@1.3.26/dist/lenis.min.js\"></script>\n  <script src=\"scenes/stage.js\"></script>\n  <script src=\"scenes/<id>.js\"></script>\n  <script>Stage.smooth(); Stage.init();</script>\n</body>\n```\n\n- Load SplitText (`gsap@3.15.0/dist/SplitText.min.js`) only when a scene file says it needs it.\n- `Stage.smooth()` adds weighted wheel scrolling (Lenis at lerp 0.12). It stays off for touch and for\n  reduced motion. Leave it out on a quiet page; the scenes work either way.\n- `Stage.init()` starts every `[data-scene]` on the page. A page with two scenes loads both files.\n- The versions are pinned. Do not change them to `@latest` or an unpinned major.\n\n## 3. Filling it\n\nA scene is only as strong as what goes in it. The scene file's header and the sheet's \"Content\" line\nsay how many pictures and words it takes; these hold for all of them:\n\n- **Pictures of one family.** Same light, same grade, same kind of subject: a field of mismatched stock\n  photographs breaks the illusion of one space faster than any timing error. Real pictures of the\n  subject's world (`assets.mjs`), the project's own, or the dealt photographs, in that order\n  (`references/imagery.md`). Size each to its largest display size, set `width` and `height`.\n- **Words that read in a breath.** A held statement is 4 to 12 words; captions are one to four words in\n  the text face, sentence case. One statement on screen at a time.\n- **The scene says something about the subject.** A fly-through of the studio's work, the route a\n  shipment really takes, the four rooms of the house, the product's change of state. A scene filled\n  with unrelated pictures is a gimmick and reads as one.\n- **Real content only.** If the scene needs eight pictures of the subject and there are three, take the\n  `--redraw scenes`, never pad it with stand-ins.\n\n## 4. Fitting it to the page\n\n- The scene files read the page's tokens: `--ground`, `--ink`, `--muted`, `--accent`,\n  `--font-display`, `--font-text` (with fallbacks). Set them on `:root` from the sheet and the scene\n  takes the page's colour and type. Check the demo against your page, not the other way round.\n- Display type in a scene uses the dealt display face and the two-line headline rule; statements stay\n  at statement size.\n- Leave a quiet section between two scenes (a text section, a list, a plain picture) so each one lands.\n  Two scenes back to back read as one long ride and the second loses.\n- A scene on the first screen must be readable at progress 0: the title, the sentence and the action are\n  there on the first frame (motion rule 1), and the scene starts moving only when the visitor scrolls.\n- Give the section a heading. If the design has no visible heading in the scene, the section still\n  carries one (`aria-label` on the section and a real heading in the finished composition).\n\n## 5. The phone, reduced motion, no script\n\n- **The phone.** Each scene has a phone plan in its file: the same scene with changed numbers, a\n  simpler version, or `phone: 'rest'`, where the phone shows the finished composition. Touch scrolling\n  is never smoothed. Look at the phone sheet as carefully as the desktop one.\n- **Reduced motion and no script.** The section is an ordinary section showing the finished\n  composition: the same content, laid out to read without motion. Nothing is hidden waiting for a\n  script. The inspector's `reduced-hidden` check and the reduced sheet of `scenes.mjs` show it.\n- **A failed CDN** falls back to the finished composition too (the stage adds `.is-rest`). The\n  inspector fails a scene that rests on desktop (`scene-not-live`), so a broken script cannot pass.\n\n## 6. Checking it\n\n```bash\nnode <skill>/scripts/scenes.mjs <page>        # every scene at 0, 10 … 100%, desktop and phone, and reduced motion\nnode <skill>/scripts/inspect.mjs <page>       # the gate; with scenes on the sheet it also films the scroll\n```\n\n`scenes.mjs` writes one contact sheet per scene and width to `.taste-skill/scenes/`. Read every one.\nAt every frame ask: is there one clear thing to look at; can the statement on screen be read; is\nanything popping, blank, cut off or crossing the words; is it as bold as it should be? The inspector's\n`desktop-film-NN.jpg` shows the whole page's scroll a third of a screen at a time: check that the\nscenes and the quiet sections between them make a rhythm, and that nothing between them is empty.\n\n## 7. Rules for scenes\n\n1. **Two or three per page,** from different families, a quiet section between them. The inspector\n   warns over four (`many-scenes`) and when scenes hold more than 60% of the page (`scene-heavy`).\n2. **Each holds one to four screens:** about one screen per beat of the story; a hold with nothing new\n   to show is cut, not padded.\n3. **Native scroll only.** No wheel capture, no locking the page, no scenes that only run on a click.\n   Smoothing only through `Stage.smooth()`.\n4. **Readable at its rest points.** The statement on screen reads whole; nothing passes over text while\n   it is being read; text on a picture has a flat scrim or a calm area under it.\n5. **Inside a scene the scene's numbers apply** (motion rule 7): a picture may grow from a window to the\n   whole screen, type may cross the stage, a camera may fly through pictures. Outside scenes, the quiet\n   limits of `references/motion.md` hold.\n6. **Transform, opacity, clip-path.** Nothing that forces layout on every frame. Pictures decoded before\n   they move.\n7. **The house rules hold inside scenes:** no monospace captions, no 01/07 counters (a plain \"3 of 7\" if\n   a count is needed), no gradients (flat scrims), no shadows or glows, no hairline decoration, no\n   decorative particles, no violet.\n8. **The finished composition is designed,** not an afterthought: it is what reduced motion, a failed\n   script and some phones see.\n\n## 8. When no scene in the library fits\n\nRedraw first (`--redraw scenes`). If the brief really needs a scene the library does not have, build it\non the same stage so it inherits the guards:\n\n```js\nScenes['my-scene'] = (root, opts = {}) => Stage.scene(root, {\n  hold: opts.hold ?? 2,          // screens the stage is held for\n  scrub: opts.scrub ?? true,     // true when Lenis runs; 0.4-0.8 without it reads as weight\n  phone: 'same',                 // or 'rest', or { hold, build } for a phone plan\n  build(tl, { q, phone }) {      // positions are fractions of the scene, 0-1\n    tl.fromTo(q('.picture'), { clipPath: 'inset(30% 30% 30% 30%)' }, { clipPath: 'inset(0% 0% 0% 0%)', duration: 0.6 }, 0)\n      .to(q('.title'), { yPercent: -40, autoAlpha: 0, duration: 0.25 }, 0.7);\n  },\n});\n```\n\nand write its CSS finished composition first, then the live layout under `.scene.is-live`. Check it\nwith `scenes.mjs` like any other.\n\n## 9. The catalogue\n\n(Generated from `library/scenes.json`; the draw deals from it. `node <skill>/scripts/draw.mjs --list\nscenes` prints it.)\n","isInternal":false,"tokens":2540,"sizeBytes":9817},{"name":"tells.md","path":"skills/taste-skill/references/tells.md","rawUrl":"https://raw.githubusercontent.com/Leonxlnx/taste-skill/HEAD/skills/taste-skill/references/tells.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Tells — the dated registry\n\nA tell is a device that makes a page read as generated. Tells are not bad design in themselves; most\nbegan as good ideas on good sites. They became tells by being produced by default, everywhere, without\na reason. That is why this registry is dated, and why it never names a replacement font, colour or\ncomponent: every published \"use this instead\" list has become the next wave of tells within months.\nReplacements here are procedures (draw from the library, derive from the subject), not products.\n\n`scripts/inspect.mjs` and `scripts/lint.mjs` detect most entries. Status: **banned** means the\ninspector fails the page; **warned** means it flags it and you need a reason.\n\n## Contents\n\n1. First wave (2023–2024)\n2. Second wave (2025)\n3. Third wave (2025–2026): the \"fix\" that became the look\n4. Gallery fashion, banned as house style\n5. Structural tells\n6. Copy tells\n7. Motion tells\n8. Why removal is not enough\n\n## 1. First wave (2023–2024)\n\n| Tell | Status | Do instead |\n| --- | --- | --- |\n| Violet / indigo gradients on hero, buttons and glows | banned | The dealt palette; flat colour |\n| Gradient-filled headline text | banned | Solid ink |\n| Glass panels: backdrop blur, translucent cards | warned (2 or more) | Opaque surfaces one tone step from the ground |\n| Glowing or gradient \"Get started\" button | banned | Flat button named for its action |\n| Soft grey drop shadow under every card | banned | Tone step, or no box |\n| Three identical feature cards, each with an icon in a rounded square | banned | The dealt section blueprint |\n| Emoji as icons or bullets | banned | Words, or a real picture |\n| Centred headline, subtitle, two buttons, screenshot below | no rule; the draw avoids it | The dealt hero |\n| The same typeface on every generated page | warned (lint: default-font) | The dealt type system |\n\n## 2. Second wave (2025)\n\n| Tell | Status | Do instead |\n| --- | --- | --- |\n| Eyebrow / kicker: tiny tracked uppercase label above every heading | banned | Fold it into the heading, or delete |\n| Pill badge above the hero headline (\"New\", \"Beta\", \"Introducing\") | banned | Say it in the supporting sentence |\n| One word of the headline in italic serif, colour or underline | warned | One face, one colour |\n| Bento grid of rounded tiles as the feature section | warned as card rows | A composed section; tiles only in the dense-tiles direction, filled, strict sizes |\n| Near-black ground with one neon accent and a glow | banned via shadow, gradient | A dealt dark palette, no glow |\n| Floating rounded pill navigation with blur | warned | A plain bar |\n| Fake dashboard hero built from grey bars and donut charts | no rule; see imagery.md §7 | A real interface fragment, or no image |\n| Decorative status dot (\"Available for work\", pulsing \"live\") | lint: bounce | Remove |\n| Fade-and-rise on every section | no rule; see motion.md | One signature move |\n\n## 3. Third wave (2025–2026): the \"fix\" that became the look\n\nThe remedy published for the first two waves was \"warm it up and make it editorial\". Models adopted\nthe remedy wholesale and it is now the most recognisable generated look of all.\n\n| Tell | Status | Do instead |\n| --- | --- | --- |\n| Yellow-cream ground + terracotta / rust / clay accent | banned together; terracotta banned alone; cream warned | The dealt palette. Warmth from a low-chroma stone, a deep ink, a photograph, or a full warm field |\n| High-contrast or soft serif display as the shortcut to \"premium\" | no rule | The dealt type system, whatever class it is |\n| Oversized italic serif headline | no rule | As dealt |\n| Broadsheet cosplay: hairline rules everywhere, zero radius, dense columns | banned via hairline | Structure from space and tone |\n| \"Field notes\", \"Quietly trusted by\", \"On our desks\": performative labels | lint: copy | Plain section names |\n\n## 4. Gallery fashion, banned as house style\n\nThese are common on award sites right now. In the study they appear *more* often on the top-scored\nsites than on the weak ones (panel observations: monospace labels 44% against 24%, index numbering 38%\nagainst 21%; measured thin rules 61% against 52%). They are banned here regardless, by the owner's\ndecision: they are the first things a generator copies from the gallery, they carry no information,\nand a page built without them has to find real structure.\n\n| Tell | Status | Do instead |\n| --- | --- | --- |\n| Monospace micro-labels, mono as a \"technical\" voice, mono captions | banned | The text face; tabular figures for data |\n| Index numbering: 01 / 02 / 03, (001), \"Step 02\", numbered section markers | banned | Order by position, scale, or the words; `<ol>` when it is truly a list |\n| Thin rules: hairline dividers, ruled grids, 1px outlined boxes and tiles | banned (boxes: 3 or more) | Space, tone steps, filled shapes, a thick bar if a bar is the idea |\n| Design-tool chrome as ornament: crosshairs, crop marks, selection handles, dashed guides, rulers | banned via hairline, dashed | Remove |\n| Agency micro-meta: local time, coordinates, weather, version stamps, \"©2026 — Scroll\", middle-dot strings | lint: copy; micro-label | Remove |\n| Tiny uppercase letter-spaced captions scattered around the viewport | banned (3 or more) | Sentence case at readable size, placed with the content it describes |\n\nTiny tracked capitals are the one item in this group the data condemns as well: 16% of top sites\nagainst 57% of weak ones.\n\n## 5. Structural tells\n\n| Tell | Status | Do instead |\n| --- | --- | --- |\n| Headline as a full sentence at display size, three or four lines | banned (over two lines) | A title of about five words; the rest goes below |\n| Stock section order: hero, logos, features, testimonial, pricing, CTA | no rule; see copy.md §1 | The order of the argument |\n| Every section the same layout family | critique.md pass 9 | Different composition per section, from the sheet |\n| Everything centred | warned over 72% | Left-anchored, one centred moment |\n| One medium border radius (12–16px) on everything | none | Square or fully round, chosen once |\n| Nine nearly equal font sizes | warned over 9 | Five sizes, far apart |\n| Invented social proof: logos, quotes, star rows, \"10,000+ teams\" | copy.md §5 | Real proof, or none |\n| Text or a CSS box where a picture belongs | critique.md cap | A real picture, or a design that needs none |\n\n## 6. Copy tells\n\nFlagged by `lint.mjs`: the genre's verbs and adjectives (unlock, supercharge, seamless, elevate,\neffortless, cutting-edge, all-in-one …); the correction (\"not just X, it's Y\"); tricolon headlines;\n\"Get started\" and \"Learn more\" as labels; more than a handful of em dashes; lorem ipsum. See\n`copy.md` §6.\n\n## 7. Motion tells\n\nIdentical fade-up on every block; a dozen staggered hero entrances; hover lift on every card; bounce\neasing; infinite loops that mean nothing; reveals that fail and leave a blank band. See `motion.md` §9.\n\n## 8. Why removal is not enough\n\nA page with every tell removed and nothing put in their place is an empty page with good manners, and\nthat is a tell too (the \"avoidance aesthetic\": anyone could guess it from the category plus the list of\nthings to avoid). The tells were filling a gap where an idea should have been. The order of work in\n`SKILL.md` exists to fill that gap first: the idea from the subject, the dealt composition, real\npictures or committed type, and only then the checks.\n","isInternal":false,"tokens":1805,"sizeBytes":7420},{"name":"type.md","path":"skills/taste-skill/references/type.md","rawUrl":"https://raw.githubusercontent.com/Leonxlnx/taste-skill/HEAD/skills/taste-skill/references/type.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Type\n\nTypography is most of what a visitor sees and most of what makes a page look designed or assembled.\nThe direction sheet deals you a type system (faces, weights, settings). This file is how to use it.\n\n## Contents\n\n1. What the study measured\n2. The scale: few sizes, far apart\n3. Setting display type\n4. Setting text\n5. Loading the fonts properly\n6. One family or two\n7. Details that separate set type from typed text\n8. Mistakes the inspector cannot see\n\n## 1. What the study measured\n\nFrom 202 measurable sites out of the 247 studied (Chrome, 1440×900 and 390×844):\n\n| | Median | Middle half | Note |\n| --- | --- | --- | --- |\n| Hero headline size | 72px (5.0vw) | 43–109px | Top-scored sites: 6.0vw median |\n| Largest type on the page | 6.4vw | up to 10.4vw | Top-scored sites 8.4vw, weak sites 5.0vw |\n| Hero headline on a phone | 40px | 32–59px | |\n| Hero tracking | -0.01em | -0.03 to 0 | Tighter as size grows |\n| Hero leading | 1.0 | 0.95–1.1 | |\n| Body size | 16px | 14–18px | |\n| Headline ÷ body size | 4.3 | | Top-scored sites 4.7 |\n| Typefaces in real use | 2 | 31% use one, 45% two, 22% three | |\n| Hero weight | regular 48%, medium 18%, bold or heavier 22% | | Big type does not need to be bold |\n| Hero in capitals | 24% | | |\n| Hero centred | 39% | | 52% on the weak sites |\n\nTwo things to take from it. First, size contrast is the main lever and the best sites pull it harder.\nSecond, weight is not: half of the heroes are set in a regular weight. Scale and spacing make type\nconfident; bold is one option among several.\n\n## 2. The scale: few sizes, far apart\n\nThe panel described about 30 of the 114 strongest sites as using two or three type sizes with nothing\nin between, and none as using a graded five- or six-step scale. So: one display size, one text size\nand a small size carry the page; a lead size and a heading size exist for when they are needed. Five\nis the ceiling. The common failure is nine sizes that are all near each other (16, 18, 20, 24, 28,\n32…), which reads as mush. Choose steps that are clearly different:\n\n```css\n:root {\n  --step-small: clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem);   /* 13–14px  captions, legal */\n  --step-body:  clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem);    /* 17–19px  paragraphs */\n  --step-lead:  clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem);      /* 20–26px  supporting line, large body */\n  --step-head:  clamp(2rem, 1.3rem + 3.2vw, 4rem);             /* 32–64px  section headings */\n  --step-display: clamp(3rem, 1rem + 9vw, 9rem);               /* set by the hero blueprint */\n}\n```\n\n- `--step-display` belongs to the direction. A monument wordmark is 16–24vw; a quiet instrument's\n  headline is 28px. Use the size the hero blueprint gives, as a `clamp()` so it scales with the\n  viewport but is bounded on phones and very wide screens.\n- Keep the gap: the display size should be at least four times the body size on desktop, and nothing\n  should sit between `--step-lead` and `--step-head` unless the design truly needs a sixth size.\n- Resist a \"subheading\" size for every card and label. If two sizes look almost the same, make them\n  the same.\n\n## 3. Setting display type\n\nLarge type exposes spacing that is invisible at text size. Apply all of these to anything over 40px:\n\n```css\n.display {\n  font-size: var(--step-display);\n  line-height: 0.95;              /* 0.85–1.05; tighter for capitals and condensed faces */\n  letter-spacing: -0.035em;       /* -0.02 to -0.05em; use the value on the direction sheet */\n  font-kerning: normal;\n  text-wrap: balance;\n  max-width: 14ch;                /* choose the measure so lines break where you want */\n  margin: 0;\n}\n```\n\n- **Tracking scales with size.** The larger the type, the tighter it needs to be; a value right for\n  120px will choke 32px. Set tracking per step, not once for all headings.\n- **Leading below 1.0 needs checking.** Look for collisions between descenders and the ascenders or\n  accents of the next line. Two-line headlines make this easy to verify by eye.\n- **All capitals** want slightly open tracking (0 to +0.03em) even at display size, and leading around\n  0.9.\n- **Optical alignment.** Big letters with round or diagonal left edges (O, C, A, T, W) look indented.\n  Pull the headline left by about 0.04–0.06em (`margin-left: -0.05em`) so it aligns optically with the\n  text beneath it.\n- **Viewport-wide type.** For a line that must span the screen, size it in `vw` and verify at 390 and\n  1440; set `white-space: nowrap` and let the container clip rather than wrap. Calculate the size from\n  the character count: `font-size ≈ container width ÷ (characters × k)` with k from `copy.md` §2.\n- Never add a text shadow, an outline stroke, or a gradient fill to display type.\n\n## 4. Setting text\n\n```css\nbody { font-size: var(--step-body); line-height: 1.5; font-kerning: normal; text-rendering: optimizeLegibility; }\np { max-width: 62ch; text-wrap: pretty; margin: 0; }\np + p { margin-top: 0.9em; }\n.lead { font-size: var(--step-lead); line-height: 1.35; max-width: 40ch; }\nsmall, .caption { font-size: var(--step-small); line-height: 1.45; }\n```\n\n- Measure: 45–75 characters. Wider than that and the eye loses the next line; the inspector warns\n  past about 88.\n- Leading: 1.45–1.6 for body, tighter (1.3–1.4) for the larger lead size, looser for long reading.\n- Secondary text is the same face in a softer ink (`--muted`), not a lighter weight and not smaller\n  than 13px.\n- Do not centre paragraphs longer than three lines. Do not justify.\n- Light text on a dark ground looks heavier: drop one weight step or add 0.01em tracking, and raise\n  leading slightly.\n\n## 5. Loading the fonts properly\n\nThe sheet gives a `<link>` tag. Use it exactly; do not swap in a face you prefer.\n\n```html\n<link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\n<link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin>\n<link href=\"…from the direction sheet…\" rel=\"stylesheet\">\n```\n\n```css\n:root {\n  --font-display: \"Family From Sheet\", \"Helvetica Neue\", Arial, sans-serif;\n  --font-text: \"Family From Sheet\", Georgia, serif;\n}\n```\n\n- Request only the weights you use (usually two or three in total).\n- Always give a fallback stack of the same broad kind (sans for sans, serif for serif).\n- In a framework, use its font loader with the same family and weights (`next/font/google`, or a\n  self-hosted `@font-face` with `font-display: swap`). Fontshare faces load from the\n  `api.fontshare.com` stylesheet on the sheet.\n- After building, `inspect.mjs` reports the families that actually rendered. If it warns that a face\n  did not load, the screenshots show a fallback and nothing you judge from them is real. Fix the link\n  first.\n\n## 6. One family or two\n\nA third of the studied sites use a single family for everything, and it is the safest way to look\ncoherent. When the dealt system has two faces:\n\n- Give each a job and never swap them: one sets headlines, the other sets everything else.\n- Do not introduce a third face for labels, numbers or quotes.\n- Do not mix two faces inside one headline.\n- Italic is for titles of works and real emphasis inside paragraphs, never as decoration.\n\n## 7. Details that separate set type from typed text\n\n- Curly quotes and apostrophes, real dashes, a real ellipsis (see `copy.md` §7).\n- `font-variant-numeric: tabular-nums` for prices, tables, dates in columns; `oldstyle-nums` suits\n  serif body text.\n- `text-underline-offset: 0.18em; text-decoration-thickness: 0.07em` on links, so underlines clear the\n  descenders.\n- `hyphens: none` on headings. `overflow-wrap: anywhere` only on long URLs or emails.\n- A heading belongs to the text after it: space above a heading is at least twice the space below.\n- `::selection { background: var(--accent); color: var(--accent-ink); }` and a visible\n  `:focus-visible` outline in the accent, so even the browser's own states belong to the design.\n- Do not change weight on hover; the line reflows.\n\n## 8. Mistakes the inspector cannot see\n\n- A headline that passes the two-line rule but breaks badly: one orphan word on line two, or a break\n  that splits a phrase (\"Stools for small / kitchens\"). Author the break.\n- Display type so tight that letters touch, or so loose it falls apart.\n- A confident hero followed by section headings almost as large. Keep one size dominant per screen.\n- Body text set in the display face when that face was drawn for large sizes only.\n- Everything bold. If every line is emphasised, none is.\n","isInternal":false,"tokens":2370,"sizeBytes":8495},{"name":"SKILL.md","path":"skills/taste-skill/SKILL.md","rawUrl":"https://raw.githubusercontent.com/Leonxlnx/taste-skill/HEAD/skills/taste-skill/SKILL.md","title":"design-taste-frontend","category":"anthropic-skill","format":"markdown","content":"---\nname: design-taste-frontend\ndescription: >-\n  tasteskill v2, the anti-slop frontend skill. Art direction for websites, distilled from a study of\n  247 curated gallery sites (One Page Love, Awwwards Sites of the Day). Deals researched directions\n  (idea, composition, type, palette, photographs, section blueprints) from a library, enforces a strict\n  no-slop house style with a real-browser inspector, and runs a look-and-fix loop on screenshots. Use\n  this whenever you build, design, redesign, restyle, polish or review a landing page, marketing site,\n  portfolio, product page, one-pager, hero or any public-facing web page, in any stack (HTML/CSS, React,\n  Next.js, Vue, Svelte, Astro, Tailwind) — also when the user says a page looks generic, templated,\n  \"AI-made\", sloppy, or asks to make it look designed, premium, award-level or less like every other\n  site. Also for app screens: dashboards, admin and analytics views, settings, inboxes and other screens\n  people work in, with their own run and rules.\n---\n\n# tasteskill v2\n\nA page built by a model usually looks like the average of every page the model has seen: a centred\nheadline over three lines, a little label above it, a row of icon cards, a soft gradient, a few thin\nrules and a monospace caption. Nothing in it is wrong and nothing in it was decided.\n\nThis skill replaces those defaults with decisions, in four ways:\n\n1. **A script deals the directions, you choose among them.** Asked to invent a look, a model picks\n   the category default every time. `scripts/draw.mjs` deals three of twenty researched directions;\n   you choose the one that carries the subject's idea, and the script then deals its type system,\n   palette, hero and section compositions from a library distilled from 247 real sites.\n2. **The idea comes from the subject.** In the study, what separated the best sites from the forgettable\n   ones was a concept taken from the thing itself, not the styling.\n3. **A house style with no ornaments,** measured in a real browser by `scripts/inspect.mjs`, so the\n   rules are checked rather than hoped for.\n4. **You look at what you made.** Screenshots at three widths, a juror's rubric, fix, look again.\n\nOne warning learned in testing. Taking the ornaments away is only half the job; a page that has lost its\nlabels, rules and cards and gained nothing in their place reads as thin, and blind jurors rightly prefer\na richer page with tells over an empty page without them. The other half is substance: type set\nlarger, whole fields of colour, real pictures of this subject's world (found or drawn), and every\nsection carrying its full content. The skill is built to give you that; do not trade it for restraint.\n\nIn the commands below `<skill>` is this skill's folder. Run them from the project's root, so the\nworking files land in `.taste-skill/` there. The scripts need Node 22+ and an installed Chrome, Edge\nor Chromium, and install nothing. `assets.mjs` also needs network access; it uses no API keys.\n\n## Page or app screen\n\nDecide first which of two kinds of work this is.\n\n- **A page** is read and scrolled: a landing page, a marketing or product site, a portfolio, an\n  event, a restaurant, a one-pager. It follows **the run** below.\n- **An app screen** is worked in: a dashboard, an admin or analytics view, settings, billing, an inbox\n  or queue to work through, a wallet, a list with filters, an editor or builder. It follows\n  **`references/app-screens.md`**: its own run, its own draw (`draw.mjs --app`), its own house rules\n  (quiet borders, small labels and repeated panels are normal there; gradients, glows, icons in tinted\n  squares, rainbow charts and invented vanity numbers are not) and `inspect.mjs --app`. Read that file\n  whole before you start; the page run below does not apply.\n\nA product site that shows its app is a page; the interface fragments on it follow the app-screen\nrules for their insides. Deal the product's app style once, in its own folder, with the page's colours\nand type kept:\n\n```bash\nnode <skill>/scripts/draw.mjs --app --kind <kind> --brief \"<the product>\" --keep palette,type --out .taste-skill/app\n```\n\nand build every fragment the page shows (the hero's live screen, a feature's crop, a chart) as a real\npiece of that app: `assets/app.css` for its panels, tables and controls, `assets/charts.js` for its\ncharts, real data that adds up, one finding stated, cropped and scaled the way the page's blueprint\ntreats a picture. A fragment that looks like a working product is the strongest picture a software page\nhas; grey bars and lorem numbers are the weakest. When a request mixes both (a landing page and the\ndashboard behind it), build each with its own run and one shared palette and typeface.\n\n## The run\n\nDo these in order. Steps 1–5 take a few minutes and decide whether the page is any good.\n\n### 1. Read the brief and the project\n\nFind out what is real: the subject, the audience, the one thing the page must get someone to do, the\nstack, any existing brand (colours, fonts, logo), and above all **what imagery truly exists**: the\nproject's own photographs or product shots, a real interface that can be shown, an image generation\ntool you can call, or nothing. Do not plan around pictures you do not have. Nothing of its own is\nrarely nothing at all: the subject's city, street, materials and history are in open archives and\nmuseums, free to use with a credit (step 6, `scripts/assets.mjs`).\n\nIf the request is vague, decide and state your reading in one line instead of asking. Ask only when a\nmissing fact blocks the work (for example, no product name).\n\nThen **inventory the subject** in your notes: eight to twelve things that belong to this client and to\nno competitor. Look for its name and what the name means; its address, door number, street and\nneighbourhood, and what that place looks like (its tiles, signs, paint colours, typefaces on its shop\nfronts, its light, its weather); the numbers in the brief (seats, rooms, minutes to the sea, the\nprice, the year); the constraint it lives with (only one batch a month, closed in winter, by\nappointment); its materials and colours; its rituals and hours (the oven lit at five, the ferry at\nseven); the printed things of its world (a timetable, a label, a ticket, a sign). This list is where\nthe idea comes from in step 4. In blind tests, the page that won each brief was built from an item on\nsuch a list (the client's name and what it means, the street it stands in, the one constraint that\nmakes it what it is), and the pages that lost had a good composition with a category idea. The list\nis also your picture search: each place, material and printed thing on it is a query for step 6.\n\n### 2. Write the argument\n\nBefore any design, list the page as claims with their proof, one line per section, the way\n`references/copy.md` §1 shows. The claims decide which sections exist and in what order. Delete any\nsection that has no claim. This is how you avoid the stock sequence of hero, logos, three features,\ntestimonial, pricing, call to action.\n\n### 3. Draw the direction\n\n```bash\nnode <skill>/scripts/draw.mjs --sector <sector> --brief \"<one line about the subject>\" \\\n  --sections <roles in the order of your argument> [--tone <tone>] [--have <assets>] [--keep palette,type] \\\n  --options 3\n```\n\nThis deals three directions and prints a short summary of each. Hold each one against your inventory:\nwhich way of composing can carry something only this client has? Choose that one, not the most\nfamiliar, and write one line in your notes on why. In testing, a single random direction that did not\nsuit the subject was the commonest cause of a weak page. Then deal the full sheet:\n\n```bash\nnode <skill>/scripts/draw.mjs <the same arguments, without --options> --direction <chosen id>\n```\n\n- `--sector`: `node <skill>/scripts/draw.mjs --list sectors`. Pick the closest.\n- `--sections`: roles from `--list roles` (features, showcase, how-it-works, testimonial, proof, stats,\n  pricing, faq, cta, footer, intro, about, work, gallery, list, contact). The hero is implied.\n- `--tone` (optional): quiet, bold, warm, technical, playful, luxury, editorial. Only pass it when the\n  brief clearly asks for one.\n- `--have`: assets that really exist, comma-separated: `photography` (the project's own photographs of\n  the place, people or work), `product-photo` (photographs of the specific product, or an image tool\n  that can make them), `product-ui` (real screenshots), `illustration`, `video`. Leave it out if you\n  have none: the draw then avoids compositions that depend on them and the sheet says how to fill\n  picture slots honestly (software shows its own interface built in HTML; a product with no photographs\n  is drawn and set among real pictures of its world, never a fake product shot). Pictures you will\n  find in the open collections are not the project's own; leave them out of `--have`.\n- `--keep palette,type`: when the brand already fixes colours or typefaces. The draw then deals only\n  the composition, and you map the brand's values onto the roles.\n\nThe command prints a **direction sheet**. It is the art direction for this build:\n\n- **Adopt it.** Do not blend it with the layout you would have made anyway. If it feels unfamiliar,\n  good: the familiar layout is the one this skill exists to prevent.\n- Redraw one slot (`--redraw hero | type | palette | photos | scenes | section:<role> | direction`) only for a\n  reason you can state: it contradicts a stated brand constraint, or needs an asset that does not\n  exist. Never redraw to get something more comfortable. Record every redraw in your report.\n- When a dealt section cannot hold the real content (it compares three plans and there is one price;\n  it wants five quotations and there are none), do not bend the content to fit. List the others with\n  `--alternatives <role>`, pick the one whose assumptions match the content, and take it with\n  `--redraw section:<role>=<id>`.\n- **Check the palette against the subject.** A dealt palette is a set of proportions (one ground, one\n  ink, one accent, fields) as much as a set of colours. If its colours fight the subject's own material\n  (candy pastels for a peat whisky, neon for a mountain hut), redraw the palette once; if the subject\n  has unmistakable colours of its own (its material, the paint of its street, the landscape outside\n  its windows), keep the dealt proportions and take the colours from the subject instead, and say so\n  in the report.\n- Reprint it any time with `node <skill>/scripts/draw.mjs --show`. In a long session, re-read it before each\n  section you build.\n\n### 4. Find the idea\n\nThe direction is a way of composing. The idea is what makes the page belong to this subject and no\nother. Write this sentence in your notes and do not start building until both blanks are filled from\nthe subject itself:\n\n> On this page, **[something that belongs to the subject]** becomes **[the device the direction calls for]**.\n\nPlaces to look for the first blank:\n\n- **Its output.** What does the thing produce? Put the real output on the page as material. (A camera\n  that prints poems delivered its copy as paper slips.)\n- **Its object or shape.** What does it physically look like, in cross-section, in silhouette?\n  Enlarge it, crop it, make it the frame or the one motif.\n- **Its name.** Can the letters hold a photograph, stack into a wall, split to two corners?\n- **Its place.** Is there one view that makes someone want to be there?\n- **Its ritual.** Is there a sequence the page can perform as it scrolls?\n- **Its artefact.** What printed thing already exists in its world: ticket, menu, label, receipt,\n  invitation, folder, manual?\n- **Its opposite.** Which other category owns the feeling this one lacks?\n\nFill the first blank from your inventory (step 1), not from the category. **The competitor test:** put\nthe nearest real competitor in the sentence (the bakery two streets away, another oak furniture maker,\nanother hut on the same mountain). If the sentence still works, the idea belongs to the category: a\nloaf of bread is every bakery; the seven doors of the street this one is named after are only this one.\n\"Clean and modern\" is not an idea. The sites the study's panel scored lowest were the ones whose idea\nwas recorded as \"none beyond the standard formula\".\n\n**One live thing.** Give the page one thing the visitor can do, or that is different for each visit,\nmade from the idea: pick a wood and see the chair in it; type your name and see it cut in the\nfoundry's letters; set the loan and read the real monthly figure; see whether the hut's stove is lit\nright now and how long until the last ferry; choose a size and see it against the room. In blind tests every winning page had one and the jurors named it first. Rules: it uses the subject's real content, it works on a phone with a thumb, it has a plain\nfallback without script, it never blocks reading, and it is one thing, not a playground. It is\nbuilt in step 6 as part of the page, not added as motion in step 9.\n\n**The scenes carry the idea too.** The scroll scenes on the sheet are devices waiting for a subject.\nDecide what each one shows from your inventory before building: the fly-through passes through this\nstudio's own title cards, the route is the road this shipment really takes, the picture that opens to\nthe whole screen is the room the guest will wake up in. A scene filled with pictures that could belong\nto anyone is a screensaver.\n\n### 5. Write the words\n\nWrite the whole page as a copy deck (plain text) before markup, following `references/copy.md`:\n\n- **Every headline fits in two lines or fewer at every width.** Do the arithmetic in copy.md §2 before\n  committing to a sentence: about 32 characters is safe everywhere at a confident size. The studied\n  gallery heroes have a median of 5 words and 32 characters.\n- One supporting sentence, directly under the headline (32–48px below it) and shown with it, never\n  docked at the foot of the first screen or held back by an animation. When the headline is a name or\n  a figure of speech, this sentence says plainly what the thing is. One primary action, named for what\n  it does, as a real button on the first screen.\n- **The first screen answers the visitor's first question in large type.** For an event: what it is,\n  when and where (the dates belong in the headline or at the second size, never only in small text).\n  For a product: what it is and what it costs or does. For a person: who and what they do. Every\n  section the visitor came for (the line-up, the menu, the rooms, the price) has its own heading and\n  its own place in the navigation.\n- **Write the full content.** Every section the brief asks for delivers its information completely:\n  the whole menu with prices, each room with its own details, every speaker and talk, the price with\n  what it includes, an answer for each real question. Thin sections are the commonest reason a clean\n  page loses to a busier one.\n- Sample details are expected where the brief leaves gaps (dish names, room names and rates, project\n  titles) so the design is seen at full density; list them in the report for the client to confirm.\n  Proof is never invented: no customers, quotes, reviews, press, logos or business statistics.\n\n### 6. Build it, still\n\nBuild the page with motion switched off in your head; a page that needs animation to look finished is\nnot finished. Order of work:\n\n1. **Tokens.** Colour and type roles from the sheet as CSS custom properties. Everything downstream\n   references tokens only. `<skill>/assets/base.css` is a neutral foundation you may start from (reset, token\n   names, fluid type steps, grid, focus and selection styles, the motion helpers); it has no look of\n   its own.\n2. **The hero, exactly as the blueprint describes it,** at desktop and at phone width. Get the big\n   thing big and the small things small before anything else exists.\n3. **Each section from its blueprint,** with this project's content. Keep the geometry, change the\n   subject. Neighbouring sections must not share a layout. **Carry the idea into every section,**\n   pricing, FAQ and footer included: the commonest failure in the study, even among good sites, is a\n   distinctive first screen followed by stock blocks.\n4. **Imagery,** in this order of preference:\n   1. the project's own;\n   2. generated, if you have an image tool;\n   3. **real pictures of the subject's world from the open collections,** whenever an honest one\n      exists. Search them with `node <skill>/scripts/assets.mjs \"<query>\"` (Openverse, Wikimedia\n      Commons, the Art Institute of Chicago and the Met; only licences that allow commercial use, by\n      default). Search the inventory, not the category: its street in old postcards, an old map of the\n      neighbourhood, its material up close, its trade in engravings, a museum object of its kind, a\n      botanical plate, a star chart. Use them large and with intent: one archival photograph as the\n      hero, an engraving enlarged into the page's motif, the real map of the street as the contact\n      section. Look at each before choosing; `--get <ref>` downloads it into `assets/` and records\n      its source and licence, and `--credits` prints the credit line for the footer. A found picture\n      shows the world around the client and is never presented as the client's own product, room,\n      dish, person or team;\n   4. **drawn in code from the subject itself,** for what no honest picture exists of (its objects,\n      its tiles, its windows, its product's interface, made as one consistent flat graphic language in\n      the palette's real colours);\n   5. the photographs dealt on the sheet, only where an honestly generic picture fits (the sea for a\n      sea house), never as a stand-in for the subject;\n   6. type and colour alone.\n\n   When the project has footage or a real picture of its own process or product, the first screen\n   shows it, large (about 40% of the screen or more). Never write a sentence on the page about where\n   the pictures come from or what they are not (\"none of these shows our bar\"): a caption says what\n   the picture is, and the credit line sits small in the footer. A portfolio whose work is invented\n   for the brief draws each piece as a finished still of that work (its title card with its own type,\n   an end frame, a poster), with real detail, never as a pictogram of the client's product.\n\n   **The floor, which the inspector checks:** at least four real pictures on the page, usually six to\n   twelve (photographs, archival images, maps, engravings, footage, raster artwork; for software, its\n   cropped interface fragments count too). SVG drawings do not count toward the floor: draw what no\n   picture exists of, and still carry real pictures. Add one moving picture wherever an honest clip\n   exists: search it with `assets.mjs --video \"<query>\"` and use it as a muted loop with a poster\n   frame. Models skip pictures and footage because finding them is work; the page fails without them.\n\n   `references/imagery.md` covers searching, licences and credits, video, drawing, crops and treatments.\n5. **The live thing** from step 4, built into the section where it proves the claim (often the hero\n   or the booking), with real content, a thumb-sized phone version and a plain fallback.\n6. **The scroll scenes,** when the sheet deals them (section 9), each with the section it carries: the page's big\n   moments, the camera that flies through the work, the picture that opens to the whole screen, the\n   word that buckles under the scroll. Copy the shared stage and the scene's files from\n   `<skill>/assets/scenes/`, fill the scene with this project's own pictures and words, and set the\n   page's tokens so it takes the page's look. A scene is composition: it decides how long the page is\n   and what each screen shows, so it is built now and seen in every look round, not added at the end.\n   `references/scenes.md` says how to put one on a page, fill it, fit it and check it;\n   `assets/scenes/demo/<id>.html` is a working example of each.\n7. **Fullness.** Look at each desktop screen as a poster: one dominant thing and the content it\n   carries. A screen that is mostly empty ground is an underbuilt section, not a rest; one deliberate\n   rest per page is the limit, and the inspector fails a page with two or more near-empty screens.\n   Running text is in the full ink at 16px or more; grey is for secondary notes.\n8. **The frame.** The page has one pair of equal outer margins at every width, and every section uses\n   the width the page has set up: when its text sits in the left half, the right half holds its\n   picture, its second column, its list or its figure, never nothing. Asymmetry lives inside the grid,\n   never in the frame: a void is placed only when something closes it on the far side. No stretch of\n   the page taller than about half a screen holds nothing at all; sections are 120–240px apart on\n   desktop. Every section the visitor came for opens with a heading that names it, and the first\n   screen carries the page's title in an `h1`. These are what readers name first when a page looks\n   wrong (\"no clear title\", \"random empty space\", \"everything is pushed to one side\"), and the\n   inspector measures each of them.\n9. **States and semantics.** Real links and buttons, visible focus, alt text, a phone layout that is\n   its own composition.\n\nRead `references/type.md`, `references/colour.md` and `references/layout.md` when you need the detail\nbehind a decision; the laws below are the short form.\n\n### 7. Gate\n\n```bash\nnode <skill>/scripts/lint.mjs <source files or folder>\nnode <skill>/scripts/inspect.mjs <url or path/to/index.html>\nnode <skill>/scripts/scenes.mjs <url or path/to/index.html>     # when the page has scroll scenes\n```\n\n`scenes.mjs` photographs every scroll scene at 0, 10 … 100% of its hold, on desktop and on a phone,\nand the reduced-motion page; with scenes on the sheet, `inspect.mjs` also films the whole scroll\n(`desktop-film-NN.jpg`). A scene that never started or rests on desktop is a `FAIL`.\n\n`lint.mjs` scans source for banned patterns and stock phrases. `inspect.mjs` opens the page in a real\nbrowser at 1440, 768 and 390 pixels, measures it (headline line counts, type sizes, fonts actually\nloaded, colours, rules, shadows, gradients, contrast, overflow, and the frame: equal margins, sections\nhuddled on one side, blank stretches, the title, untitled sections, text against the screen edge) and\nsaves screenshots to `.taste-skill/inspect/`. Fix every `FAIL`. Treat each `WARN` as wrong unless you can defend it to a\ndesigner in one sentence. Re-run until there are no `FAIL`s. Do not argue with the meter and do not\nhide things from it. The inspector serves local files over a throwaway local server; if the page must\nalso open straight from the file system, open `index.html` that way once before you finish.\n\n### 8. Look\n\nPassing the gate means nothing banned was measured. It does not mean the page is good. Open the\nscreenshots the inspector lists (every viewport, with your image viewer or Read tool) and critique them\nwith `references/critique.md`: the fourteen passes, the Awwwards-weighted score, the caps. Write the critique\ndown in its format, fix the top three problems, run the inspector again, look again. Three rounds at\nmost.\n\nJudge only the pictures. If a problem is visible in a screenshot, it is real, whatever the code says.\n\n### 9. Move\n\nNow build the motion layer. It is required, and it is more than one fade: the inspector counts the\nelements that really move while the page loads and is scrolled, and fails a page under eight (it warns\nunder sixteen). Any scroll scenes are already built (step 6); around them the layer has four parts:\n\n1. **The signature move** named on the sheet: one, done well (a dealt scene can be it).\n2. **An entrance for the parts of every section:** the heading, then the text, then the picture,\n   staggered by 60–90ms, rising 16–32px with opacity, triggered once as the section enters. Not one\n   fade for the whole block, and never content that stays hidden if the script fails.\n3. **Feedback on every control:** press, hover and focus on buttons, links, cards and the live thing.\n4. **One moving picture:** a found clip as a muted loop, a slow scale or drift on a photograph, or a\n   scroll-linked move on the hero picture.\n\nTransform and opacity only; every move has a `prefers-reduced-motion` fallback that keeps the content\nand drops the travel. A move that changes the colour or the layout of whole screens (colour by\nchapter, a pinned story) is part of the composition, so build it in step 6 and let every look round see\nit. `references/motion.md` has the tokens and tested recipes. Then run the inspector once more and check\nevery screenshot for content that failed to appear.\n\n### 10. Report\n\nDo not report until all of these are true; each one was skipped in a test run that came out badly:\n\n- `inspect.mjs` shows **0 FAIL** at 1440, 768 and 390, on the final version of the page.\n- You opened every screenshot it listed after the last change, not only the first screen.\n- With scroll scenes: `scenes.mjs` ran on the final page with no problems, and you read every sheet\n  (desktop, phone, reduced motion).\n- A stranger reading the first screen for five seconds can say what this is and what to do.\n- Every section has a heading; the margins match on both sides; no stretch of the page is empty.\n- The critique of your last round is written down in the shape of `references/critique.md` §4.\n\nTell the user, briefly: the direction dealt (name and seed) and any redraws with reasons; the idea\nsentence and the live thing; the final scores from your last critique round and what still falls short;\nevery found picture and clip with its title, creator, licence and source page (`assets.mjs --credits` prints\nthe list) and where its credit sits on the page; which bundled photographs and which drawings stand in\nfor photography (so they can be replaced); and any sample content that must be swapped before launch.\nDo not claim a check you did not run.\n\n## House rules\n\nThese hold on every build, whatever the direction. `inspect.mjs` measures them.\n\n| Rule | Instead |\n| --- | --- |\n| **Headlines: two lines or fewer, at every width.** Every `h1`–`h6`, and the main line of the first screen whatever its tag. | Cut words. Then widen the measure. Size last. |\n| **A clear title on the first screen**, in the page's one `h1`, and a heading on every section. | Say what this is: the name with what it does, the product with what it is for, the event with its date and place. |\n| **Equal outer margins; no section huddled on one side** with the other half of the screen empty. | Close every void with something on its far side: the section's picture, a second column, a list, a figure. |\n| **No blank stretches** taller than about half a screen. | The normal section gap. A deliberate rest is a placed picture or a field of colour, once per page. |\n| **Statements are paragraphs.** An intro sentence or a quotation set large is marked up as `<p>` or `<blockquote>`, stays at statement size (36px or less on desktop, 24px on a phone) and runs to about 25 words, three lines. | Larger than that it is a headline and the two-line rule applies. In blind tests jurors read a 42px sentence over four lines as a four-line headline. |\n| **No eyebrows.** No small label above a heading, no pill badge above the headline, no \"New ·\" chip. | Put the information in the heading or the first sentence, or drop it. |\n| **No monospace** outside real code blocks. | The text face. Tabular figures where numbers align. |\n| **No index numbering.** No 01 / 02 / 03, no (001), no \"Step 2\". | Order shown by position, size, or the words. A real `<ol>` if order matters. |\n| **No thin rules.** No hairline dividers, no 1px outlined boxes, no grid lines, crosshairs or crop marks. | Space. A step in background tone. A change of scale. A filled shape. |\n| **No gradients.** Not as backgrounds, not on buttons, not in text. | Flat colour, or a real photograph. A neutral scrim under text on a photo is the one exception. |\n| **No shadows on things at rest.** No glows. | A tone step between surfaces. Shadows only on what truly floats: a menu, a dialog. |\n| **No assistant palette.** No yellow-cream ground with terracotta or rust; no violet or indigo. | The dealt palette. |\n| **No tiny uppercase letter-spaced labels.** | Sentence case at a readable size. |\n| **No icon-topped feature cards, no rows of identical cards.** | The dealt section blueprint. |\n| **No glass.** No backdrop blur panels, no floating pill navigation. | A plain bar: wordmark, a few links, one action. |\n| **No emoji, no gradient blobs, no decorative shapes, no fake dashboards of grey bars.** | A real picture, a real interface fragment, or nothing. |\n| **No styled accent word** in a headline (italic, serif, coloured, underlined). | One face, one colour. The words carry the emphasis. |\n| **Two typefaces at most,** usually one. | The dealt type system. |\n\nThree places keep their own conventions and are left alone by the inspector: real code in\n`<pre>`/`<code>` (monospace is correct there), real tables and form fields (they may have lines), and\na real interface fragment whose root carries the attribute `data-ui` (the product's own borders and\nmenus; see `references/imagery.md` §7).\n\nWhy these, honestly. Some are what the study measured: among the 247 sites, those the panel scored\n7.5 or higher used icon feature cards 1% of the time against 28% for sites under 6.5, pill badges 14%\nagainst 34%, gradients 22% against 52%, shadows 24% against 48%, tiny tracked caps 16% against 57%.\nOthers are the owner's taste and go against current gallery fashion: monospace labels, index numbers\nand hairline grids are actually *more* common on award sites than on weak ones, which is exactly why\ngenerators imitate them and why they now read as costume. They are banned here without exception.\n`references/tells.md` keeps the dated registry.\n\nRemoving ornament leaves space. Never fill it with another ornament. Fill it with scale (make the main\nthing larger), with the full content, with a picture made for this subject, or with a field of flat\ncolour. Leave it empty on purpose once per page at most.\n\n## Laws of the craft\n\nShort form. Numbers are from the study unless marked as house style.\n\n**Type**\n- Two or three sizes do the visible work: one very large, one small, nothing in between. Median\n  headline-to-body ratio on the studied sites is 4.3; the best go far beyond (largest type: median\n  8.4vw on the top sites against 5.0vw on the weak ones).\n- Display type: tracking -0.02 to -0.05em, leading 0.85–1.05. Text: 16–20px, leading 1.45–1.6,\n  45–75 characters per line.\n- Five sizes on a page is the ceiling. One family is normal (a third of the studied sites); two is the\n  limit.\n- Left-aligned by default. Centre at most one moment.\n\n**Space**\n- One grid, one pair of tight margins (16–32px), used everywhere; large things run to the edges. Text\n  blocks share two or three left edges on the whole page.\n- Asymmetry inside the grid, never in the frame: the two outer margins are equal, and an off-centre\n  heading is answered by something at the far side of the grid.\n- The gap between sections is clearly larger than any gap inside one: 120–240px on desktop (the study's median is about 240).\n- Each section has a different composition from its neighbours; none is a card grid.\n\n**Colour**\n- One ground, one ink, one accent. The accent appears on the action and perhaps one other thing.\n- Running text in the full ink. A page set in soft grey reads unfinished.\n- Surfaces are separated by a small step in tone, never by a line or a shadow.\n- A section may change the whole field colour. Nothing fades into anything.\n\n**Imagery**\n- One dominant image beats six small ones. On the top-scored sites the hero media covers at least half\n  the first screen 68% of the time.\n- Same crop ratios, same treatment, square corners unless the direction says otherwise (73% of the\n  studied sites leave media square).\n- No image is better than a placeholder, an icon, or an abstract shape. A picture drawn for this\n  subject, in its colours and with care, is better than either. A real picture of its world, found\n  and credited, is better still.\n- Every found picture is downloaded into the project, credited on the page and listed in the report.\n  None is presented as the client's own.\n- Nothing ever lies on top of a headline or a statement (the inspector fails it).\n\n**Components**\n- Buttons: flat, one fill colour, either square-cornered or fully round, decided once (top sites: 52%\n  square, 23% pill; the 9–16px \"soft\" radius is the weak-site default). Most strong heroes have no\n  button at all, or one.\n- Navigation: wordmark, three to five plain links, one action. No bar chrome.\n- The footer is a designed close, not a sitemap: on most strong sites the name returns at full width.\n\n## Special cases\n\n**An existing brand or design system.** Pass `--keep palette,type`, map the brand's colours and faces\nonto the roles, and take only composition from the draw. The house rules still apply; if the brand\nitself requires a banned device (its logo sits in a gradient, its accent is violet), keep the brand\nasset, say so in the report, and pass `--allow <rule>` to the inspector for that rule only.\n\n**Redesign, restyle or review of an existing page or app screen.**\n\n1. **Record the before.** Run the project as it is and inspect it into its own folder\n   (`inspect.mjs <url> --out .taste-skill/before`, with `--app` for an app screen) and lint its\n   source. Read the code: the framework, the styling method (Tailwind v3 or v4, CSS modules,\n   styled-components, plain CSS), the components, and what must survive: routes, forms, data,\n   behaviour, the brand's own assets.\n2. **A review stops here.** Critique the before screenshots with `references/critique.md`, list the\n   findings with the inspector's measurements, and name the three changes that would move the page\n   most.\n3. **Keep the stack, the content and what works.** No framework or styling-library migration; check the\n   dependency file before adding anything. A restyle keeps the layout and takes type, colour and\n   components from a dealt direction (`--keep` whatever the brand fixes); a redesign deals a full\n   direction and rebuilds the sections from its blueprints inside the existing components. Either way\n   proceed from step 2 of the run with the page's real content.\n4. **Order of work, biggest effect for least risk:** type (faces and scale), colour (one ground, one\n   ink, one accent), the frame (margins, section rhythm, a title on the first screen and a heading on\n   every section), states (hover, focus, loading, empty, error), then the stock components (icon\n   cards, pill badges, gradient blobs, card grids) replaced by the dealt blueprints.\n5. **Prove it.** Inspect again into `.taste-skill/after`, compare before and after at every width,\n   click through every link, form and menu that worked before, and report the before and after\n   measurements side by side.\n\n**A component or a single section, not a page.** Skip the draw unless there is no direction to follow.\nMatch the surrounding design, apply the house rules and the laws, and still inspect the result.\n\n**No checkout, no form backend.** The primary button goes to the real destination when the brief names\none. Otherwise it opens an email with a written subject and body (`mailto:` with the visitor's choices\nfilled in), or, for a shop, it points at `#checkout` and the report says it must be wired before\nlaunch. Never fake a payment form.\n\n**No Chrome or Node 22.** Run `lint.mjs` (Node 18+), take screenshots with whatever browser tool you\nhave, and critique those. Say in the report that the inspector could not run.\n\n**No network.** If `assets.mjs` reaches no source, draw the pictures and say in the report that the\nopen collections could not be searched.\n\n## Files\n\n| File | Read it when |\n| --- | --- |\n| `references/app-screens.md` | Any dashboard, admin, settings or other app screen: its own run, rules, tokens and checks. |\n| `references/copy.md` | Writing the argument and the copy deck (steps 2 and 5). The two-line arithmetic. |\n| `references/type.md` | Setting type: scales, tracking, measure, loading fonts, pairing. |\n| `references/colour.md` | Applying the palette: roles, proportions, tone steps, dark pages, contrast. |\n| `references/layout.md` | Grid, margins, rhythm, section variety, navigation, footer, the phone composition. |\n| `references/imagery.md` | Choosing, finding, crediting, cropping and treating pictures; what to do with none. |\n| `references/motion.md` | Step 9. Budget, tokens, recipes, reduced motion. |\n| `references/scenes.md` | Step 6, when the sheet deals scroll scenes: putting one on a page, filling, fitting, the phone, checking, the catalogue. |\n| `references/critique.md` | Step 8. How to look, how to score, what to fix first. |\n| `references/tells.md` | The dated registry of generated-page tells and what each is replaced by. |\n| `references/research.md` | The study: method, numbers, what the best and worst sites do. Cite it, do not guess. |\n| `scripts/draw.mjs` | Deals and reprints the direction; `--photos`, `--site <id>` for more references; `--app` deals an app style instead. |\n| `scripts/assets.mjs` | Step 6: searches open collections for real pictures of the subject's world; `--get` downloads with the credit, `--credits` prints them. |\n| `scripts/lint.mjs` · `scripts/inspect.mjs` | The gate. |\n| `scripts/scenes.mjs` | The gate for scroll scenes: each scene at 0-100% of its hold, desktop, phone, reduced motion. |\n| `assets/base.css` · `assets/base.js` | An optional neutral foundation to build on. |\n| `assets/scenes/` | The scroll scenes: the shared stage (`stage.js`, `stage.css`) and, for each scene in the library, its `.js`, `.css` and a working demo page in `demo/`. |\n| `assets/app.css` · `assets/charts.js` | For app screens: a neutral shell, panels, tables and controls, and small SVG charts drawn to the app rules. |\n| `library/` | The data the draw reads: directions, heroes, sections, type systems, palettes, photographs, studied sites, motions, scroll scenes (`scenes.json`), and the app styles, shells and screen patterns (`app.json`). Do not read it whole; use the script. |\n","frontmatter":{"name":"design-taste-frontend","description":"tasteskill v2, the anti-slop frontend skill. Art direction for websites, distilled from a study of 247 curated gallery sites (One Page Love, Awwwards Sites of the Day). Deals researched directions (idea, composition, type, palette, photographs, section blueprints) from a library, enforces a strict no-slop house style with a real-browser inspector, and runs a look-and-fix loop on screenshots. Use this whenever you build, design, redesign, restyle, polish or review a landing page, marketing site, portfolio, product page, one-pager, hero or any public-facing web page, in any stack (HTML/CSS, React, Next.js, Vue, Svelte, Astro, Tailwind) — also when the user says a page looks generic, templated, \"AI-made\", sloppy, or asks to make it look designed, premium, award-level or less like every other site. Also for app screens: dashboards, admin and analytics views, settings, inboxes and other screens people work in, with their own run and rules."},"isInternal":false,"tokens":9286,"sizeBytes":38458},{"name":"marketplace.json","path":".agents/plugins/marketplace.json","rawUrl":"https://raw.githubusercontent.com/Leonxlnx/taste-skill/HEAD/.agents/plugins/marketplace.json","title":"taste-skill","category":"marketplace","format":"json","content":"{\n  \"name\": \"taste-skill\",\n  \"interface\": {\n    \"displayName\": \"Taste Skill\"\n  },\n  \"plugins\": [\n    {\n      \"name\": \"taste-skill\",\n      \"source\": {\n        \"source\": \"url\",\n        \"url\": \"https://github.com/Leonxlnx/taste-skill.git\",\n        \"ref\": \"main\"\n      },\n      \"policy\": {\n        \"installation\": \"AVAILABLE\",\n        \"authentication\": \"ON_INSTALL\"\n      },\n      \"category\": \"Design\"\n    }\n  ]\n}\n","frontmatter":{"name":"taste-skill","interface":{"displayName":"Taste Skill"},"plugins":[{"name":"taste-skill","source":{"source":"url","url":"https://github.com/Leonxlnx/taste-skill.git","ref":"main"},"policy":{"installation":"AVAILABLE","authentication":"ON_INSTALL"},"category":"Design"}]},"isInternal":false,"tokens":119,"sizeBytes":410},{"name":"marketplace.json","path":".claude-plugin/marketplace.json","rawUrl":"https://raw.githubusercontent.com/Leonxlnx/taste-skill/HEAD/.claude-plugin/marketplace.json","title":"taste-skill","category":"marketplace","format":"json","content":"{\n  \"name\": \"taste-skill\",\n  \"description\": \"tasteskill: art direction for coding agents, for websites, product pages, dashboards and app screens, checked in a real browser.\",\n  \"owner\": {\n    \"name\": \"leonxlnx\",\n    \"email\": \"hello@tasteskill.dev\"\n  },\n  \"plugins\": [\n    {\n      \"name\": \"taste-skill\",\n      \"description\": \"tasteskill v2: art direction for websites, product pages, dashboards and app screens, with a library of researched directions, real pictures from open collections and a real-browser inspector.\",\n      \"version\": \"2.1.4\",\n      \"source\": \"./\",\n      \"skills\": [\"./skills/taste-skill\"],\n      \"author\": {\n        \"name\": \"leonxlnx\",\n        \"email\": \"hello@tasteskill.dev\"\n      },\n      \"homepage\": \"https://github.com/Leonxlnx/taste-skill\",\n      \"repository\": \"https://github.com/Leonxlnx/taste-skill\",\n      \"license\": \"MIT\",\n      \"keywords\": [\"skills\", \"frontend\", \"design\", \"taste\", \"ui\", \"dashboard\"]\n    }\n  ]\n}\n","frontmatter":{"name":"taste-skill","description":"tasteskill: art direction for coding agents, for websites, product pages, dashboards and app screens, checked in a real browser.","owner":{"name":"leonxlnx","email":"hello@tasteskill.dev"},"plugins":[{"name":"taste-skill","description":"tasteskill v2: art direction for websites, product pages, dashboards and app screens, with a library of researched directions, real pictures from open collections and a real-browser inspector.","version":"2.1.4","source":"./","skills":["./skills/taste-skill"],"author":{"name":"leonxlnx","email":"hello@tasteskill.dev"},"homepage":"https://github.com/Leonxlnx/taste-skill","repository":"https://github.com/Leonxlnx/taste-skill","license":"MIT","keywords":["skills","frontend","design","taste","ui","dashboard"]}]},"isInternal":false,"tokens":264,"sizeBytes":945},{"name":"plugin.json","path":".codex-plugin/plugin.json","rawUrl":"https://raw.githubusercontent.com/Leonxlnx/taste-skill/HEAD/.codex-plugin/plugin.json","title":"taste-skill","category":"plugin-manifest","format":"json","content":"{\n  \"name\": \"taste-skill\",\n  \"version\": \"2.1.4\",\n  \"description\": \"tasteskill v2: art direction for websites, product pages, dashboards and app screens, checked in a real browser.\",\n  \"author\": {\n    \"name\": \"leonxlnx\",\n    \"url\": \"https://github.com/Leonxlnx\"\n  },\n  \"homepage\": \"https://github.com/Leonxlnx/taste-skill\",\n  \"repository\": \"https://github.com/Leonxlnx/taste-skill\",\n  \"license\": \"MIT\",\n  \"keywords\": [\n    \"skills\",\n    \"frontend\",\n    \"design\",\n    \"taste\",\n    \"ui\"\n  ],\n  \"skills\": \"./skills/\",\n  \"interface\": {\n    \"displayName\": \"Taste Skill\",\n    \"shortDescription\": \"Art direction for websites, dashboards and app screens.\",\n    \"longDescription\": \"tasteskill v2 from Leonxlnx/taste-skill: researched directions, real pictures and a real-browser inspector for websites, product pages, dashboards and app screens.\",\n    \"developerName\": \"leonxlnx\",\n    \"category\": \"Design\",\n    \"capabilities\": [],\n    \"websiteURL\": \"https://github.com/Leonxlnx/taste-skill\",\n    \"defaultPrompt\": [\n      \"Design a distinctive frontend without generic AI patterns.\",\n      \"Redesign this interface while preserving its brand.\",\n      \"Build the dashboard for this product with real data and charts.\"\n    ]\n  }\n}\n","frontmatter":{"name":"taste-skill","version":"2.1.4","description":"tasteskill v2: art direction for websites, product pages, dashboards and app screens, checked in a real browser.","author":{"name":"leonxlnx","url":"https://github.com/Leonxlnx"},"homepage":"https://github.com/Leonxlnx/taste-skill","repository":"https://github.com/Leonxlnx/taste-skill","license":"MIT","keywords":["skills","frontend","design","taste","ui"],"skills":"./skills/","interface":{"displayName":"Taste Skill","shortDescription":"Art direction for websites, dashboards and app screens.","longDescription":"tasteskill v2 from Leonxlnx/taste-skill: researched directions, real pictures and a real-browser inspector for websites, product pages, dashboards and app screens.","developerName":"leonxlnx","category":"Design","capabilities":[],"websiteURL":"https://github.com/Leonxlnx/taste-skill","defaultPrompt":["Design a distinctive frontend without generic AI patterns.","Redesign this interface while preserving its brand.","Build the dashboard for this product with real data and charts."]}},"isInternal":false,"tokens":329,"sizeBytes":1218}],"systemPromptSnippet":"<yakaai_skills repo=\"Leonxlnx/taste-skill\">\n<!-- File: skills/taste-skill/evals/evals.json (Tokens: ~1947 | Category: anthropic-skill) -->\n{\n  \"skill_name\": \"design-taste-frontend\",\n  \"how_to_run\": \"For each eval, give the prompt to a fresh agent that has this skill, and to a second fresh agent without it (the baseline). Render both with scripts/inspect.mjs and have a judge who does not know which is which score the screenshots with references/critique.md. Record inspector FAIL counts for both. Evals 7 to 10 are app screens: inspect them with --app (a sheet dealt by draw.mjs --app switches it on by itself) and judge them with the app-screen passes in references/critique.md.\",\n  \"evals\": [\n    {\n      \"id\": 1,\n      \"name\": \"saas-invoicing\",\n      \"prompt\": \"Build a landing page for Ledgerly, an invoicing tool for freelance designers. What it does: you write an invoice in under a minute, the client pays by card or bank transfer, and it sends polite reminders by itself when an invoice is overdue. It costs 9 euros a month flat, with a 14-day free trial and no card needed. Include pricing and a short FAQ. There is no existing brand and no screenshots; the product name is all we have. Plain static HTML, CSS and JS in one folder.\",\n      \"expected_output\": \"A static landing page with a clear idea drawn from invoicing itself, headlines of two lines or fewer at 1440/768/390, no eyebrow labels, no monospace, no index numbering, no thin rules, no gradients or shadows, a non-default palette and type system, a pricing section that is not three cards, and no invented customers or statistics.\",\n      \"files\": []\n    },\n    {\n      \"id\": 2,\n      \"name\": \"restaurant-osteria\",\n      \"prompt\": \"Make a one-page website for Osteria Nove, a 38-seat Italian restaurant in Alfama, Lisbon. Handmade pasta, a short natural wine list, dinner only, Tuesday to Saturday from 19:00. Address: Rua dos Remédios 9. Reservations by phone (+351 21 000 0009) or email (mesa@osterianove.pt). The page needs the menu (invent a believable short one: antipasti, pasta, dolci, with prices in euros), hours, address and how to book. We have no photographs yet. Static HTML/CSS/JS.\",\n      \"expected_output\": \"A one-page restaurant site with a specific idea (for example the page as the menu itself), the menu set typographically without divider lines, practical information easy to find, bundled photographs used only as atmosphere and listed for replacement, and all house rules met.\",\n      \"files\": []\n    },\n    {\n      \"id\": 3,\n      \"name\": \"portfolio-designer\",\n      \"prompt\": \"I'm Mara Lindqvist, a product designer in Stockholm with eight years in fintech and health apps. I need a portfolio homepage: six selected projects (make up plausible names, clients, years and one-line descriptions), a short about paragraph, and a way to contact me (mara@lindqvist.studio). I don't have project images ready, so design it so it still looks finished without them, or use placeholders that I can swap. Static HTML/CSS/JS.\",\n      \"expected_output\": \"A portfolio page that looks finished without project imagery (a typographic index, a name-led hero, or atmosphere photographs clearly marked for replacement), with a designed footer, a phone layout that is its own composition, and all house rules met.\",\n      \"files\": []\n    },\n    {\n      \"id\": 4,\n      \"name\": \"product-ceramics\",\n      \"prompt\": \"Launch page for Kiln, a ceramic pour-over coffee set (dripper, carafe and two cups) that is hand-glazed in small batches in Porto. It costs 84 euros and ships across the EU within a week. The glaze is mixed by hand so no two sets are identical. We have not shot product photos yet, so there are no images of the set. One page, with a way to buy (a button is enough). Static HTML/CSS/JS.\",\n      \"expected_output\": \"A product page that does not fake product photography: it either commits to type and colour, uses one shape from the object as a motif, or uses atmosphere photographs honestly, with the price and purchase action clear, and all house rules met.\",\n      \"files\": []\n    },\n    {\n      \"id\": 5,\n      \"name\": \"guesthouse-ericeira\",\n      \"prompt\": \"Website for Casa Mirante, a six-room guesthouse on the cliffs above Ericeira, Portugal. Rooms from 140 euros a night with breakfast included; ten minutes' walk to the surf at Ribeira d'Ilhas; open March to November. One page: what it is, the rooms, what's nearby, and how to book (email reservas@casamirante.pt). We have no photographs yet. Static HTML/CSS/JS.\",\n      \"expected_output\": \"A calm, photograph-led or type-led one-pager whose hero is one clear thing, with rooms and booking information easy to find, bundled coast photographs used as atmosphere and listed for replacement, and all house rules met.\",\n      \"files\": []\n    },\n    {\n      \"id\": 6,\n      \"name\": \"conference-format\",\n      \"prompt\": \"Landing page for Format, a two-day design conference in Rotterdam on 14 and 15 May 2027. Twelve speakers (invent plausible names and talk titles), 400 seats, tickets at 390 euros, venue: Maassilo. Sections: what it is, the line-up, the schedule in brief, tickets, and a short FAQ. No brand exists yet beyond the name. Static HTML/CSS/JS.\",\n      \"expected_output\": \"An event page with a strong typographic or colour idea, the line-up and schedule set as structured text without divider lines or index numbers, a ticket section that is not three cards, and all house rules met.\",\n      \"files\": []\n    },\n    {\n      \"id\": 7,\n      \"name\": \"app-budget-overview\",\n      \"prompt\": \"Build the main screen of Ledgerly, a budgeting app for couples who share money: the October overview with their accounts and balances, the spending plan (planned against spent by category), bills due in the next 14 days and recent transactions. Two people use it, Mia and Tom. Desktop first, and it must work on a phone. Static HTML/CSS/JS.\",\n      \"expected_output\": \"An app screen, not a landing page: a quiet shell (sidebar or rail), a clear screen title, numbers that add up and are right-aligned with tabular figures, one chart per question, colour spent on data and status only, no icons in tinted squares, no gradients or glows, no placeholder names, and a phone layout where the navigation folds away. inspect.mjs --app passes.\",\n      \"files\": []\n    },\n    {\n      \"id\": 8,\n      \"name\": \"app-deploy-dashboard\",\n      \"prompt\": \"Dashboard for Relay, an edge deployment platform for web teams: one project's overview with recent deployments (status, branch, commit message, author, duration, region), requests and p95 latency over the last 24 hours, the error rate, and usage against the plan's limits. Dark theme. Static HTML/CSS/JS.\",\n      \"expected_output\": \"A dense, readable dark screen on a neutral (not navy) ground: one surface step or one hairline between regions, a deployments table with honest statuses and aligned numbers, charts with few gridlines and one series each, IDs in monospace at most, no rainbow series, no glow, and app inspector checks passing.\",\n      \"files\": []\n    },\n    {\n      \"id\": 9,\n      \"name\": \"app-settings-billing\",\n      \"prompt\": \"Workspace settings for Proofline, a design-review tool: general settings, members and roles (a members table with an invite form), billing (current plan, seats, invoices) and notifications. Static HTML/CSS/JS, desktop and phone.\",\n      \"expected_output\": \"A settings screen with a label column beside its fields (or stacked fields on a phone), labels above inputs, one control height, quiet borders, honest disabled states, a members table with right-aligned figures and one status pill per row, and no decorative icons or gradients.\",\n      \"files\": []\n    },\n    {\n      \"id\": 10,\n      \"name\": \"app-support-queue\",\n      \"prompt\": \"The queue screen of Hearth, a support inbox for a six-person SaaS team: the list of conversations with assignee, priority, channel and time to the SLA, the open conversation with the customer's details beside it, plus filters and saved views. Static HTML/CSS/JS.\",\n      \"expected_output\": \"A three-region work screen (navigation, list, conversation) that stays readable at 1440 and folds to one region at a time on a phone, with status shown once per row, times in words, no tinted icon squares or emoji, and app inspector checks passing.\",\n      \"files\": []\n    }\n  ]\n}\n\n<!-- File: skills/taste-skill/library/app.json (Tokens: ~13188 | Category: anthropic-skill) -->\n{\n  \"version\": 1,\n  \"about\": \"App-screen library for tasteskill: styles (directions), shells and screen patterns, distilled from the study of 23 desktop product screens (17 light, 6 dark, 17 products) chosen by the owner. Every number is a measurement from the study or a median over it, except where a note says a value was moved for contrast or for the house palette bans. Reference products are not named; the screenshots stay private.\",\n  \"styles\": [\n    {\n      \"id\": \"achromatic-ledger\",\n      \"name\": \"Achromatic ledger\",\n      \"theme\": \"light\",\n      \"basis\": \"4 screens: a seller home, a per-agent insights page, a generated report, a settings page with usage numbers\",\n      \"suits\": [\n        \"finance\",\n        \"commerce\",\n        \"devtools\",\n        \"support\",\n        \"report\",\n        \"workspace\",\n        \"builder\"\n      ],\n      \"idea\": \"The chrome holds no colour at all; money and counts are set in ink, the one chart hue marks the screen's main data element, and the only other hue is a small signal where a figure changed.\",\n      \"colourBudget\": \"under 1% coloured pixels; the chrome is ink, the one chart hue goes on the main data element, and the only other hue is a small change signal\",\n      \"tokens\": {\n        \"ground\": \"#f8f8f8\",\n        \"surface\": \"#ffffff\",\n        \"raised\": \"#eeeeee\",\n        \"border\": \"#e6e6e6\",\n        \"rule\": \"#f0f0f0\",\n        \"control\": \"#d4d4d4\",\n        \"text\": \"#0a0a0a\",\n        \"muted\": \"#6b6b6b\",\n        \"accent\": \"#141414\",\n        \"positive\": \"#2e7d32\",\n        \"negative\": \"#c4242a\",\n        \"warning\": \"#92400e\",\n        \"chart\": [\n          \"#141414\",\n          \"#8a8a8a\",\n          \"#1d5fbf\"\n        ],\n        \"pills\": {\n          \"positive\": [\n            \"#dcfae5\",\n            \"#04250e\"\n          ],\n          \"negative\": [\n            \"#ffedea\",\n            \"#831c1e\"\n          ],\n          \"warning\": [\n            \"#fffbeb\",\n            \"#92400e\"\n          ],\n          \"neutral\": [\n            \"#eeeeee\",\n            \"#3d3d3d\"\n          ]\n        },\n        \"radius\": {\n          \"card\": 8,\n          \"control\": 6\n        },\n        \"font\": {\n          \"family\": \"Geist\",\n          \"second\": \"Geist Mono, for IDs and keys only\",\n          \"fallback\": \"Inter, system-ui, sans-serif\",\n          \"sizes\": {\n            \"title\": 24,\n            \"section\": 16,\n            \"kpi\": 30,\n            \"body\": 14,\n            \"small\": 12\n          },\n          \"weights\": [\n            400,\n            500,\n            700\n          ],\n          \"note\": \"700 is for money figures only; every other number is 400-500.\"\n        },\n        \"density\": \"sparse\",\n        \"rowHeight\": 44,\n        \"sidebarWidth\": 256,\n        \"gap\": 12,\n        \"pad\": 24,\n        \"controlHeight\": 36\n      },\n      \"shell\": \"open-plane\",\n      \"shellAlternatives\": [\n        \"icon-rail\",\n        \"no-sidebar\"\n      ],\n      \"signature\": \"No brand colour anywhere in the chrome: the one primary action is near-black (a grey pill, #e5e5e5, is the secondary), the main data element (today's series, the booked bars, the current period) takes the one chart hue, #1d5fbf, and everything else is drawn in ink with the comparison or the part after the cursor in grey, zero balances are set in grey, and the only hue on the screen is a small triangle or a short coloured number where a figure changed.\",\n      \"identity\": [\n        \"A ground from the product's world in place of #f8f8f8, one level off white and low in chroma: a stone (#f4f3f1) for a bakery or a shop, a sage (#f2f5f2) for a garden or a greenhouse, a blue-grey (#f2f4f7) for a ledger or a meter. Cards stay white; a warm tint stays under the cream check (saturation under about 15%).\",\n        \"The one chart hue (#1d5fbf, or the brand's own hue at 3:1 or more on white) on the screen's main data element: today's line, the booked bars, the current period's column, the margin that breaks. The chrome stays ink and the hue stays under 1% of the screen.\",\n        \"Every figure in Geist Mono, as the style's decision, so money and counts read as a ledger's columns while the text stays Geist. Lint and the inspector flag mono; give the reason in the report.\"\n      ],\n      \"avoid\": [\n        \"a brand-coloured primary button\",\n        \"tinted cards or tinted KPI tiles\",\n        \"a coloured chart where one series in ink says it\",\n        \"bold on anything but money\",\n        \"a chart with no y-scale (the study's one example of this look hid magnitude behind hover and was flagged)\",\n        \"a grey pill as the only button for the screen's main job: in testing an Approve repeated in grey on every row left the screen without a primary\"\n      ],\n      \"notes\": \"The studied screens of this kind used 11-12px card radii, which §9.4 counts among the rare middle values; the library sets the tight pair (8 and 6) so the style lands on the bimodal rule. After testing, the chart hue moved from an unused third series colour onto the main data element: a screen whose only hue was a delta read as a kit.\"\n    },\n    {\n      \"id\": \"framed-sheet\",\n      \"name\": \"Framed sheet\",\n      \"theme\": \"light\",\n      \"basis\": \"6 screens: a developer platform overview, an analytics overview, an events analytics tab, a list detail, a reports dashboard, a flow builder\",\n      \"suits\": [\n        \"analytics\",\n        \"devtools\",\n        \"builder\",\n        \"smb-admin\",\n        \"support\",\n        \"commerce\",\n        \"report\"\n      ],\n      \"idea\": \"The app chrome is one tinted L-shaped frame; the work sits on a white sheet with a hairline edge and soft corners, so depth comes from a single tone step and no shadow.\",\n      \"colourBudget\": \"under 3%; the brand shrinks to the logo and a 2px tab underline, the data carries the chroma\",\n      \"tokens\": {\n        \"ground\": \"#f9fbfc\",\n        \"surface\": \"#ffffff\",\n        \"raised\": \"#f4f6f8\",\n        \"active\": \"#ebedee\",\n        \"border\": \"#e8eaec\",\n        \"rule\": \"#f0f1f2\",\n        \"control\": \"#cdced1\",\n        \"text\": \"#131416\",\n        \"muted\": \"#5d5f60\",\n        \"accent\": \"#1b6c80\",\n        \"positive\": \"#1e7b4f\",\n        \"negative\": \"#c4242a\",\n        \"warning\": \"#92400e\",\n        \"chart\": [\n          \"#1b6c80\",\n          \"#2f70bb\",\n          \"#a86f0c\"\n        ],\n        \"pills\": {\n          \"positive\": [\n            \"#dcfae5\",\n            \"#04250e\"\n          ],\n          \"negative\": [\n            \"#ffedea\",\n            \"#831c1e\"\n          ],\n          \"warning\": [\n            \"#fffbeb\",\n            \"#92400e\"\n          ],\n          \"neutral\": [\n            \"#ebedee\",\n            \"#353736\"\n          ]\n        },\n        \"radius\": {\n          \"card\": 8,\n          \"control\": 6,\n          \"sheet\": 16\n        },\n        \"sheetInset\": 8,\n        \"font\": {\n          \"family\": \"IBM Plex Sans\",\n          \"second\": \"IBM Plex Mono, for IDs and keys only\",\n          \"fallback\": \"Inter, system-ui, sans-serif\",\n          \"sizes\": {\n            \"title\": 22,\n            \"section\": 16,\n            \"kpi\": 28,\n            \"body\": 14,\n            \"small\": 12\n          },\n          \"weights\": [\n            400,\n            500,\n            600\n          ],\n          \"note\": \"KPI values at 400; the semibold goes on the label and the active tab.\"\n        },\n        \"density\": \"medium\",\n        \"rowHeight\": 48,\n        \"sidebarWidth\": 228,\n        \"gap\": 24,\n        \"pad\": 24,\n        \"controlHeight\": 32\n      },\n      \"shell\": \"framed-sheet\",\n      \"shellAlternatives\": [],\n      \"signature\": \"One tinted frame holds the sidebar and the 48px top bar with no rule between them; the page is a white sheet inset 8px from the window's right and bottom edges, with a 1px edge, 16px corners and no shadow. The active tab is a 2px underline in ink or the accent; everything else in the chrome is grey.\",\n      \"identity\": [\n        \"The frame tinted from the product's colour in place of #f9fbfc: one low-chroma step of its hue (a green-grey for a climate or farm tool, a blue-grey for an observability tool, a stone for a print shop). The sheet stays white.\",\n        \"The brand's own hue from the brief as --chart-1 in place of the dealt teal, on the main series and the one selected state, at 3:1 or more on white, never violet or indigo.\",\n        \"IBM Plex Mono for IDs, keys and the figures in tables (one job): its figures have their own drawing, and a developer reads them as the product's.\"\n      ],\n      \"avoid\": [\n        \"a border between the sidebar and the top bar\",\n        \"a shadow under the sheet\",\n        \"cards whose border is heavier than the sheet's (#cdcfcf on cards read as heavy in the study)\",\n        \"a fourth nesting level: frame, sheet and card are enough\",\n        \"different gutters for the KPI row and the chart row (20 against 24 was flagged)\"\n      ],\n      \"notes\": \"The study's second data hue in this style was an orange (#e88e46) that falls inside the house terracotta range; the third chart colour here is an amber moved out of that range and darkened to 3:1 on white.\"\n    },\n    {\n      \"id\": \"accent-ladder\",\n      \"name\": \"Accent ladder\",\n      \"theme\": \"light\",\n      \"basis\": \"3 screens: a newsletter home, a network analytics overview, a cap-table company home\",\n      \"suits\": [\n        \"creator\",\n        \"smb-admin\",\n        \"community\",\n        \"analytics\"\n      ],\n      \"idea\": \"One brand hue at full strength only on small marks, and its pale tints doing all the area work: the active nav row, a plan card, badges and progress tracks.\",\n      \"colourBudget\": \"3-10%, nearly all of it as pale tints of the one hue\",\n      \"tokens\": {\n        \"ground\": \"#f9fafb\",\n        \"surface\": \"#ffffff\",\n        \"raised\": \"#f3f4f6\",\n        \"border\": \"#e5e7eb\",\n        \"rule\": \"#f2f2f2\",\n        \"control\": \"#d1d5db\",\n        \"text\": \"#111827\",\n        \"muted\": \"#5f6672\",\n        \"accent\": \"#b8336a\",\n        \"accentSoft\": \"#fdf2f7\",\n        \"accentTrack\": \"#f8dbe8\",\n        \"accentInk\": \"#6b1d3e\",\n        \"positive\": \"#247b50\",\n        \"negative\": \"#c4242a\",\n        \"warning\": \"#92400e\",\n        \"chart\": [\n          \"#b8336a\",\n          \"#6b7280\",\n          \"#d4618f\"\n        ],\n        \"pills\": {\n          \"positive\": [\n            \"#dcfce7\",\n            \"#14532d\"\n          ],\n          \"negative\": [\n            \"#ffedea\",\n            \"#831c1e\"\n          ],\n          \"warning\": [\n            \"#fffbeb\",\n            \"#92400e\"\n          ],\n          \"neutral\": [\n            \"#f3f4f6\",\n            \"#374151\"\n          ],\n          \"accent\": [\n            \"#fdf2f7\",\n            \"#6b1d3e\"\n          ]\n        },\n        \"radius\": {\n          \"card\": 8,\n          \"control\": 6\n        },\n        \"font\": {\n          \"family\": \"DM Sans\",\n          \"second\": null,\n          \"fallback\": \"Inter, system-ui, sans-serif\",\n          \"sizes\": {\n            \"title\": 32,\n            \"section\": 18,\n            \"kpi\": 24,\n            \"body\": 14,\n            \"small\": 12\n          },\n          \"weights\": [\n            400,\n            500,\n            600,\n            700\n          ],\n          \"note\": \"700 for the page title only.\"\n        },\n        \"density\": \"sparse\",\n        \"rowHeight\": 45,\n        \"sidebarWidth\": 230,\n        \"gap\": 24,\n        \"pad\": 24,\n        \"controlHeight\": 32\n      },\n      \"shell\": \"open-plane\",\n      \"shellAlternatives\": [\n        \"ruled-t-frame\"\n      ],\n      \"signature\": \"The full hue goes only on small marks: the one filled-button style, the data series and the active nav icon. Its 50-200 tints carry every area: the active nav row (tint fill with the dark ink of the hue), the plan or trial card, badges and progress tracks. The primary action may instead be near-black, as on the study's newsletter home.\",\n      \"identity\": [\n        \"The ladder built from the brand's own hue (its logo, the brief's object) in place of the dealt raspberry: the full hue on small marks, its pale tints on areas, never violet or indigo.\",\n        \"The product's objects in the lead block: the newsletter's latest issue as its cover, the shop's products as 40px thumbnails, the course's lessons with their own art.\",\n        \"A ground one level toward the hue's palest tint (#fbf7f8 for the raspberry) in place of #f9fafb, so the page and the tints read as one family.\"\n      ],\n      \"avoid\": [\n        \"the full hue on large areas\",\n        \"a second accent family (four families on one screen was flagged in the study)\",\n        \"a gradient on the trial chip or upgrade button\",\n        \"a left accent bar on the active nav row on top of the tint (seen once in 23 screens)\",\n        \"violet or indigo\"\n      ],\n      \"notes\": \"All three studied screens of this kind used violet, purple or pink as the one hue. The move does not depend on the hue, so the house's violet and indigo ban holds and the library deals a raspberry instead.\"\n    },\n    {\n      \"id\": \"editorial-greeting\",\n      \"name\": \"Editorial greeting\",\n      \"theme\": \"light\",\n      \"basis\": \"2 screens: a team workspace home and a personal insights home\",\n      \"suits\": [\n        \"workspace\",\n        \"creator\"\n      ],\n      \"idea\": \"A personal or team home that opens with a typeset greeting in a centred column; every number below it is set at regular weight on tonal panels.\",\n      \"colourBudget\": \"under 2% for the accent; tonal panels carry the structure\",\n      \"tokens\": {\n        \"ground\": \"#ffffff\",\n        \"surface\": \"#f9f9f9\",\n        \"raised\": \"#ffffff\",\n        \"border\": \"#eaeaea\",\n        \"rule\": \"#f3f3f3\",\n        \"control\": \"#d9d9d6\",\n        \"text\": \"#1f201d\",\n        \"muted\": \"#636361\",\n        \"accent\": \"#1b6e66\",\n        \"positive\": \"#2e7d32\",\n        \"negative\": \"#b42318\",\n        \"warning\": \"#92400e\",\n        \"chart\": [\n          \"#1f201d\",\n          \"#1b6e66\",\n          \"#8c8c88\"\n        ],\n        \"pills\": {\n          \"positive\": [\n            \"#dcfae5\",\n            \"#04250e\"\n          ],\n          \"negative\": [\n            \"#fdecea\",\n            \"#7a1d14\"\n          ],\n          \"warning\": [\n            \"#fffbeb\",\n            \"#92400e\"\n          ],\n          \"neutral\": [\n            \"#f3f3f3\",\n            \"#3d3d3a\"\n          ]\n        },\n        \"radius\": {\n          \"card\": 22,\n          \"control\": 999\n        },\n        \"font\": {\n          \"family\": \"Instrument Sans\",\n          \"second\": \"Instrument Serif, for the greeting only\",\n          \"fallback\": \"Inter, system-ui, sans-serif\",\n          \"sizes\": {\n            \"title\": 48,\n            \"section\": 14,\n            \"kpi\": 32,\n            \"body\": 14,\n            \"small\": 12\n          },\n          \"weights\": [\n            400,\n            500,\n            600\n          ],\n          \"note\": \"The 48px title is the serif greeting; set in the sans it is 24/400. Every figure is 400.\"\n        },\n        \"density\": \"sparse\",\n        \"rowHeight\": 63,\n        \"sidebarWidth\": 224,\n        \"gap\": 16,\n        \"pad\": 20,\n        \"controlHeight\": 38\n      },\n      \"shell\": \"open-plane\",\n      \"shellAlternatives\": [\n        \"framed-sheet\"\n      ],\n      \"signature\": \"The greeting is the h1, in a centred 1100px column on a real 12-column grid (77px columns, 16px gutters), with spans that change by row but share column lines (3/3/3/3, then 9/3, then 6/6, so every internal edge meets one above it). Every figure below is set at regular weight on tonal panels, one layer each: a panel one step off white holds its title and its content directly; a white inner card is used once, for the main chart.\",\n      \"identity\": [\n        \"The greeting names this team or household and today's one fact, set from the data (\\\"Morning, Okoro house. The car is ready by 06:10.\\\"), never \\\"Welcome back\\\".\",\n        \"Each person's stable hue as a pale tint on their avatar and their own lane or column (a couple and their joint account as three lanes): identity, not data, so it stays out of the chart legends.\",\n        \"A surface from the product's world in place of #f9f9f9, one level toward its material (a sage for a garden, a stone for a kitchen, a blue-grey for a studio), with the page white kept.\"\n      ],\n      \"avoid\": [\n        \"an emoji in the greeting\",\n        \"a tracked uppercase date above the greeting (put the date after it or in the grey line below)\",\n        \"a 624-864px column on a desktop screen (both were flagged as wasted width)\",\n        \"a tray around every card (a grey panel with a white card 6px inside it, on every block, read as a bento template in testing)\",\n        \"red as the accent: in testing red marked a record week of upgrades and read as an alarm; red is for the failing fact only\"\n      ],\n      \"notes\": \"One studied screen set its greeting in a serif at 48/700 and its counts in a mono; the other set the greeting at 24/400 in the sans. The red is the second screen's chart red moved two degrees of hue out of the house terracotta range. After testing, the studied red accent was replaced by a deep teal: red on good news read as an alarm.\"\n    },\n    {\n      \"id\": \"pastel-consumer\",\n      \"name\": \"Pastel consumer\",\n      \"theme\": \"light\",\n      \"basis\": \"2 screens: a wallet home and a personal finance home\",\n      \"suits\": [\n        \"wallet\",\n        \"finance\"\n      ],\n      \"idea\": \"Categories are coded by pale tints whose ink is the dark of the same hue, all under one large radius, and each headline sum sits inside the card that explains it.\",\n      \"colourBudget\": \"5-8%, as pale tiles and data marks\",\n      \"tokens\": {\n        \"ground\": \"#f3f5f7\",\n        \"surface\": \"#ffffff\",\n        \"raised\": \"#f2f8fd\",\n        \"border\": \"#e6e6e6\",\n        \"rule\": \"#f4f4f4\",\n        \"control\": \"#d6d9dd\",\n        \"text\": \"#1b1d1f\",\n        \"muted\": \"#5c6064\",\n        \"accent\": \"#1d5fd6\",\n        \"accentSoft\": \"#dcf1ff\",\n        \"accentInk\": \"#0a3a80\",\n        \"positive\": \"#2f7a45\",\n        \"negative\": \"#c41c29\",\n        \"warning\": \"#92400e\",\n        \"chart\": [\n          \"#1d5fd6\",\n          \"#b45309\",\n          \"#2a8798\"\n        ],\n        \"pills\": {\n          \"positive\": [\n            \"#dcfae5\",\n            \"#04250e\"\n          ],\n          \"negative\": [\n            \"#ffedea\",\n            \"#831c1e\"\n          ],\n          \"warning\": [\n            \"#fffbeb\",\n            \"#92400e\"\n          ],\n          \"neutral\": [\n            \"#eef1f4\",\n            \"#3a3d40\"\n          ],\n          \"accent\": [\n            \"#dcf1ff\",\n            \"#0a3a80\"\n          ]\n        },\n        \"radius\": {\n          \"card\": 20,\n          \"control\": 10\n        },\n        \"font\": {\n          \"family\": \"Manrope\",\n          \"second\": null,\n          \"fallback\": \"Inter, system-ui, sans-serif\",\n          \"sizes\": {\n            \"title\": 28,\n            \"section\": 20,\n            \"kpi\": 32,\n            \"body\": 16,\n            \"small\": 14\n          },\n          \"weights\": [\n            400,\n            500,\n            600\n          ],\n          \"note\": \"Money at 24-32px; card titles regular; semibold for net worth, bill amounts and actions.\"\n        },\n        \"density\": \"medium\",\n        \"rowHeight\": 72,\n        \"sidebarWidth\": 240,\n        \"gap\": 24,\n        \"pad\": 24,\n        \"controlHeight\": 40\n      },\n      \"shell\": \"open-plane\",\n      \"shellAlternatives\": [\n        \"icon-rail\"\n      ],\n      \"signature\": \"Pale category tiles with the dark of their own hue as ink (#dcf1ff with #0a3a80), one large radius (20px on cards, stepping down to 10, 8 and 5 inside), and quiet money polarity: income green with a plus sign, spending in ink, no red on ordinary outgoings. Tints go on small tiles, avatars and chips; a panel that holds a list stays white. When the product has people (two partners, a family), each gets one hue, at least 60 degrees from the next.\",\n      \"identity\": [\n        \"The tile hues from the account's own colours (the card's colour, each pot's colour in the app) in place of the dealt cobalt, each tile pale with the dark of its own hue as ink.\",\n        \"The money's own objects: the card art at its real ratio, merchant marks at 24px in the rows, the goal's picture on its pot.\",\n        \"Manrope's figures carry the balance: 30-36px at 600 with tabular figures and the pence in a smaller grey, so the number itself is the face.\"\n      ],\n      \"avoid\": [\n        \"a gradient balance card\",\n        \"two data palettes on one page (flagged in the study)\",\n        \"red on every outgoing amount\",\n        \"a 624px phone-width column on a desktop screen (flagged as a stretched phone screen)\",\n        \"a KPI strip on top: the sums belong in their cards\",\n        \"whole panels tinted per person or category beside white cards (two surface languages on one screen)\"\n      ],\n      \"notes\": \"The two studied screens used a pure #0000ff and an indigo #4723f5 as their brand colour, and pastels such as #7cbecf that fall under 3:1 on white. The library uses a cobalt that reads as blue rather than indigo, and data colours darkened to at least 3:1 on the card.\"\n    },\n    {\n      \"id\": \"true-black-flat\",\n      \"name\": \"True-black flat\",\n      \"theme\": \"dark\",\n      \"basis\": \"5 screens: an events back office, an event analytics tab, a community overview, an artist studio home, an artist insights page\",\n      \"suits\": [\n        \"community\",\n        \"creator\",\n        \"markets\"\n      ],\n      \"idea\": \"Night mode on true black: sidebar, top bar and page share one ground, elevation is a lightness step alone, and colour is confined to data marks.\",\n      \"colourBudget\": \"at or under 3%; the accent never touches buttons, tabs or nav\",\n      \"tokens\": {\n        \"ground\": \"#000000\",\n        \"surface\": \"#111111\",\n        \"raised\": \"#2a2a2a\",\n        \"border\": \"#1a1a1a\",\n        \"rule\": \"#161616\",\n        \"control\": \"#444444\",\n        \"text\": \"#ffffff\",\n        \"muted\": \"#b4b4b4\",\n        \"faint\": \"#949494\",\n        \"accent\": \"#c6f24e\",\n        \"positive\": \"#c6f24e\",\n        \"negative\": \"#e5484d\",\n        \"warning\": \"#e5a93b\",\n        \"chart\": [\n          \"#c6f24e\",\n          \"#e6e6e6\",\n          \"#6b6b6b\"\n        ],\n        \"pills\": {\n          \"positive\": [\n            \"#222a10\",\n            \"#c6f24e\"\n          ],\n          \"negative\": [\n            \"#2c1a20\",\n            \"#e5566f\"\n          ],\n          \"warning\": [\n            \"#2b2414\",\n            \"#e5a93b\"\n          ],\n          \"neutral\": [\n            \"#222222\",\n            \"#ffffff\"\n          ]\n        },\n        \"radius\": {\n          \"card\": 20,\n          \"control\": 999\n        },\n        \"font\": {\n          \"family\": \"Inter\",\n          \"second\": null,\n          \"fallback\": \"system-ui, sans-serif\",\n          \"sizes\": {\n            \"title\": 20,\n            \"section\": 16,\n            \"kpi\": 24,\n            \"body\": 14,\n            \"small\": 12\n          },\n          \"weights\": [\n            400,\n            500,\n            600\n          ],\n          \"note\": \"Nothing above 600; inactive nav labels #bbb, active #fff.\"\n        },\n        \"density\": \"medium\",\n        \"rowHeight\": 80,\n        \"sidebarWidth\": 210,\n        \"gap\": 14,\n        \"pad\": 22,\n        \"controlHeight\": 36\n      },\n      \"shell\": \"ruled-t-frame\",\n      \"shellAlternatives\": [\n        \"no-sidebar\"\n      ],\n      \"signature\": \"Elevation by lightness alone (#000 ground, #111 card, #2a2a2a nested panel) with no borders or shadows on cards; the active nav item is marked only by its label going from #bbb to #fff; the primary control is made primary by inversion, a white 36px pill with black text.\",\n      \"identity\": [\n        \"The one data hue from the product's world in place of the dealt lime: a solar amber (#f2b33d) for an energy home, a sky blue (#4cb3f0) for water or weather, a lime only for sport. It is still the only hue on data and never touches buttons, tabs or nav. A green or yellow-green hue is also --positive; an amber that sits beside --warning leaves the warning to its pill pair.\",\n        \"A ground with the product's temperature: the studied #000 for media and events, a warm near-black (#0e0d0c) for a home, a cool one (#0c0d0f) for a monitor, with cards one lightness step above it (#181716, #15171a). Never navy or slate.\",\n        \"A signature element from the product's world as the lead: the energy home's power flow (sun, house, battery and grid with their live kW), an event's doors against capacity, an artist's release with its cover.\"\n      ],\n      \"avoid\": [\n        \"a navy or slate dark theme\",\n        \"glow, neon borders or shadows\",\n        \"a hue per chart (five hues across four charts was flagged)\",\n        \"the accent on buttons, tabs or nav\",\n        \"a 64px top bar left empty across most of its width (flagged twice)\"\n      ],\n      \"notes\": \"The studied screens of this kind used a violet-magenta (#dd6cff) and an orange (#ff5500) as their one data hue. The library deals a lime, which keeps the move and stays clear of the violet ban; because the lime is a yellow-green, it is also the positive colour (a second, mint green beside it read as two greens). The greys are #b4b4b4 for secondary text and #949494 for meta, 32 levels apart rather than the 20 of the measured #aaa and #969696, which read as one grey; #949494 still holds 4.5:1 on the #2a2a2a nested panel.\"\n    },\n    {\n      \"id\": \"data-terminal\",\n      \"name\": \"Data terminal\",\n      \"theme\": \"dark\",\n      \"basis\": \"1 screen: a stock research view. Keep it narrow.\",\n      \"suits\": [\n        \"markets\",\n        \"devtools\"\n      ],\n      \"idea\": \"A research or monitoring screen read in long sessions: cards darker than the ground, tabular digits that stack, signs instead of colour, and every selection marked by the same 1px accent line.\",\n      \"colourBudget\": \"under 3%; the accent is never more than a 1px line\",\n      \"tokens\": {\n        \"ground\": \"#171719\",\n        \"surface\": \"#131217\",\n        \"raised\": \"#212023\",\n        \"border\": \"#222224\",\n        \"rule\": \"#1b1a1f\",\n        \"control\": \"#3a3a3e\",\n        \"text\": \"#ffffff\",\n        \"muted\": \"#8a8c92\",\n        \"accent\": \"#4a8ad6\",\n        \"positive\": \"#44a282\",\n        \"negative\": \"#e5566f\",\n        \"warning\": \"#d9a441\",\n        \"chart\": [\n          \"#f2f2f3\",\n          \"#e5566f\",\n          \"#4a8ad6\"\n        ],\n        \"pills\": {\n          \"positive\": [\n            \"#1b2828\",\n            \"#5fc39c\"\n          ],\n          \"negative\": [\n            \"#2c1a20\",\n            \"#e5566f\"\n          ],\n          \"warning\": [\n            \"#2a2416\",\n            \"#d9a441\"\n          ],\n          \"neutral\": [\n            \"#212023\",\n            \"#bdbdc0\"\n          ]\n        },\n        \"shadow\": \"0 12px 28px rgba(0,0,0,.2)\",\n        \"radius\": {\n          \"card\": 6,\n          \"control\": 999\n        },\n        \"font\": {\n          \"family\": \"Public Sans\",\n          \"second\": null,\n          \"fallback\": \"Inter, system-ui, sans-serif\",\n          \"sizes\": {\n            \"title\": 26,\n            \"section\": 20,\n            \"kpi\": 20,\n            \"body\": 13,\n            \"small\": 12\n          },\n          \"weights\": [\n            400,\n            500,\n            600,\n            700\n          ],\n          \"note\": \"Section titles 20/400 in the muted grey; card titles 16/600; tabular figures everywhere.\"\n        },\n        \"density\": \"dense\",\n        \"rowHeight\": 42,\n        \"sidebarWidth\": 50,\n        \"gap\": 24,\n        \"pad\": 32,\n        \"controlHeight\": 34\n      },\n      \"shell\": \"icon-rail\",\n      \"shellAlternatives\": [],\n      \"signature\": \"Every selection (tab, toggle, range, nav item) is a 1px accent line exactly as wide as its label, placed on the nearest existing edge; numbers stay white or grey and carry their sign in the text ('+$24,000,000').\",\n      \"identity\": [\n        \"Every figure in a monospace as the style's decision (IBM Plex Mono or JetBrains Mono for each price, count and time, digits that stack), with the text in Public Sans. Lint and the inspector flag mono; give the reason in the report.\",\n        \"The one accent line from the product's world in place of the dealt blue (the exchange's or the team's hue): still the only selection mark, never violet or indigo.\",\n        \"A signature of the market or the system as the lead: an order book's depth as two mirrored bar lists, an incident as a minute-by-minute strip, a region map with the list beside it.\"\n      ],\n      \"avoid\": [\n        \"filled pill tabs or a coloured segmented control\",\n        \"a chart with no scale and no dates (the studied screen had none and was flagged)\",\n        \"tertiary text under 4.5:1 (#4c4c4f read at about 2:1 in the study)\",\n        \"lighter cards with borders and a glow\",\n        \"green and red on every number; the one column whose job is \\\"what moved today\\\" and a negative headline figure may carry the polarity colours\"\n      ],\n      \"notes\": \"The studied screen's muted grey #82848a and red #d4405d were lifted to #8a8c92 and #e5566f so text passes 4.5:1 on the card. Its card list rows sit on a 28px pitch and its table rows on 42px.\"\n    }\n  ],\n  \"shells\": [\n    {\n      \"id\": \"open-plane\",\n      \"name\": \"Open plane\",\n      \"basis\": \"5 of 23 screens\",\n      \"suits\": [\n        \"finance\",\n        \"wallet\",\n        \"workspace\",\n        \"creator\",\n        \"analytics\"\n      ],\n      \"numbers\": {\n        \"sidebarWidth\": \"230-256 (230, 240, 256 in the study; 280 and 292 with a built-in icon rail)\",\n        \"separation\": \"none, or one 1px hairline; the sidebar sits on the page ground or within 1-2% of it\",\n        \"navPitch\": 34,\n        \"navRowHeight\": 32,\n        \"navIcon\": \"16px outline, about 1.5px stroke\",\n        \"navLabel\": \"14px, 400, grey or ink\",\n        \"activeItem\": \"neutral grey pill, radius 6-12, inset 8-12px from the sidebar edges (#e9e9e9-#ededed)\",\n        \"topBar\": \"none\",\n        \"canvas\": \"fluid with a 24-64px gutter, or a centred 1100px column\"\n      },\n      \"blueprint\": \"The labelled sidebar sits on the page ground with nothing or one hairline between it and the canvas; there is no top bar, and the page header and cards sit straight on the ground about 32-36px from the top. Workspace or account switcher at the top of the sidebar, primary nav on a 34px pitch, groups under 12-13px sentence-case grey labels with 22-56px of air above, utilities and the user row pushed to the bottom. Cards are white on the off-white ground (or the sidebar is white with a 1px border on a #f9fafb canvas). The canvas is fluid with one gutter value, or a centred column for personal homes.\",\n      \"phone\": \"The sidebar folds into a 48px top bar holding the screen's name, a menu button that opens a full-screen sheet with the nav and the switcher, and at most one action. Content takes the full width with 16px margins.\"\n    },\n    {\n      \"id\": \"framed-sheet\",\n      \"name\": \"Tinted frame, white sheet\",\n      \"basis\": \"8 of 23 screens, in three variants\",\n      \"suits\": [\n        \"analytics\",\n        \"devtools\",\n        \"builder\",\n        \"smb-admin\",\n        \"support\"\n      ],\n      \"numbers\": {\n        \"chrome\": \"#f6f6f6-#f9fbfc (a warm #f7f6f2 once)\",\n        \"sheetInset\": \"8px from the window's right and bottom edges (12 and 16 once each)\",\n        \"sheetRadius\": \"10-16, median 16\",\n        \"sheetEdge\": \"1px #eaeaea-#ededed, no shadow\",\n        \"sidebarWidth\": \"220-263 (228 on two screens)\",\n        \"topBar\": \"48px on the chrome ground with no rule; search 548x32 centred on the window with a shortcut hint\",\n        \"contentPadding\": 24,\n        \"floatingVariant\": \"both panels inset 12px with a 12px gutter, radius 10\"\n      },\n      \"blueprint\": \"Sidebar and top bar share one tinted ground with no rule between them, forming an L; the page lives on a white sheet. Variant one: the sheet butts against the sidebar and the top bar and is inset 8px from the right and bottom edges, 16px radius, 1px edge. Variant two: a flush L-frame with no inset, the frame marked by one rule. Variant three: sidebar and content are two floating panels inset 12px from every edge with a 12px gutter. The top bar, when present, is 48px and holds a centred search, the account button and a help or AI icon. Inside the sheet the content has 24px padding and starts with the breadcrumb or title row.\",\n      \"phone\": \"The frame disappears: the sheet becomes the screen, with a 48px top bar (menu button, title, one action) on the chrome tint. The search moves into the menu sheet or behind an icon.\"\n    },\n    {\n      \"id\": \"ruled-t-frame\",\n      \"name\": \"Ruled T-frame\",\n      \"basis\": \"4 of 23 screens (3 dark, 1 light)\",\n      \"suits\": [\n        \"community\",\n        \"creator\",\n        \"smb-admin\"\n      ],\n      \"numbers\": {\n        \"sidebarWidth\": \"210-240\",\n        \"topBar\": \"64px with a 1px bottom rule\",\n        \"rules\": \"1px; #1a1a1a on #000, #f2f2f2 on white\",\n        \"navPitch\": \"34 (dark) or 40 (light)\",\n        \"switcher\": \"at the top bar's right end, behind a full-height 1px divider\",\n        \"contentGutter\": \"29px from the sidebar rule and the window edge\"\n      },\n      \"blueprint\": \"A 210-240px sidebar and a 64px top bar share one ground, divided only by 1px rules. The workspace or community switcher sits at the right end of the top bar behind a full-height divider; the sidebar holds the wordmark and the nav on a 34px pitch with sentence-case group labels. On dark, the active item is its label going from #bbb to #fff. The top bar must carry something real (search, the back link and object name, the switcher): two studied screens left about 1070px of it blank and were flagged.\",\n      \"phone\": \"The top bar stays at 48-56px with the switcher reduced to its mark; the sidebar becomes a full-screen menu sheet or a bottom bar of four or five destinations.\"\n    },\n    {\n      \"id\": \"icon-rail\",\n      \"name\": \"Icon rail\",\n      \"basis\": \"3 of 23 screens\",\n      \"suits\": [\n        \"markets\",\n        \"devtools\",\n        \"finance\",\n        \"wallet\"\n      ],\n      \"numbers\": {\n        \"railWidth\": \"50-60, median 55\",\n        \"icon\": \"15-18px outline\",\n        \"pitch\": \"34-49\",\n        \"active\": \"icon colour alone, or a full-bleed 50px band at a 2% tint, or a 1px accent bar on the rail's border\",\n        \"groups\": \"short 20px hairlines, no labels\",\n        \"utilities\": \"pushed to the bottom after a gap of about 200px\"\n      },\n      \"blueprint\": \"An unlabelled rail of 50-60px carries the brand mark at the top and 15-18px outline icons on a 34-49px pitch; groups are split by 20px hairlines, utilities sit at the bottom. The rail sits on the page ground with a 1px edge, or is white with a faint 4px shadow on a grey ground. It saves about 180px of width against a labelled sidebar, so it suits products with few destinations and screens that need the width. Icons need tooltips and an accessible name.\",\n      \"phone\": \"The rail becomes a bottom bar with the same four or five icons, each with a short label under it.\"\n    },\n    {\n      \"id\": \"no-sidebar\",\n      \"name\": \"No sidebar\",\n      \"basis\": \"3 of 23 screens\",\n      \"suits\": [\n        \"report\",\n        \"creator\",\n        \"community\"\n      ],\n      \"numbers\": {\n        \"topBar\": \"46-48px on the page ground, no border\",\n        \"column\": \"centred, 1088-1208px\",\n        \"gutters\": \"152-212px at a 1512px window\",\n        \"logo\": \"on the column's left edge\",\n        \"links\": \"14-15px semibold grey\"\n      },\n      \"blueprint\": \"A 46-48px top bar on the page ground over a centred 1088-1208px column; the logo sits exactly on the column's left edge and the bar's right cluster ends near its right edge, so header and content share one column. Three to five text links, a 36px search, the account. Use it for generated reports, viewers and products with few destinations; with a sticky bar on the same ground, give it a 1px rule when content scrolls under it (the studied bar without one sliced content off).\",\n      \"phone\": \"The bar keeps the logo, a search icon and a menu button; the links move into the menu sheet. The column becomes the full width with 16px margins.\"\n    }\n  ],\n  \"patterns\": [\n    {\n      \"id\": \"kpi-strip-chart-rail\",\n      \"name\": \"KPI strip, main chart and a side rail\",\n      \"screen\": \"overview\",\n      \"kinds\": [\n        \"creator\",\n        \"smb-admin\",\n        \"community\",\n        \"analytics\"\n      ],\n      \"basis\": \"a newsletter home; a community overview\",\n      \"blueprint\": \"Title row: a 24px noun or the product's name at 600-700, an optional 14-16px grey line under it, and the one primary action on the right, bottom-aligned with that line. 16-24px below, the scope row: section tabs and the date range in one row of 32-36px controls, or a 48px segmented track with the range select inside its right end. Then a grid of 1fr and a fixed 384px rail with a 24px gap. Main column: one KPI container split by 1px dividers into 3-5 equal cells (14px grey label, 24px value at 400-600, a 12px caption naming the baseline and window), then the main chart card, which is the largest thing on the screen, then the next card, all 16px apart. Rail: 16px headings outside their cards, 8px above each and 16px after the previous card; a recent-items list of 3-5 rows on a 45px pitch with 1px rules, closed by a 30px outlined 'View all' button instead of pagination. The rail starts level with the first card, not with the title.\",\n      \"phone\": \"The rail moves below the main column; the KPI container becomes a 2-column grid; tabs scroll inside their own row.\"\n    },\n    {\n      \"id\": \"kpi-tabs-chart\",\n      \"name\": \"KPIs as the chart's tabs\",\n      \"screen\": \"overview\",\n      \"kinds\": [\n        \"finance\",\n        \"commerce\"\n      ],\n      \"basis\": \"a seller home\",\n      \"blueprint\": \"One card per subject, 8-16px apart: the main chart card runs full width, and any card holding a table of five columns or fewer, or a short list, pairs with its neighbour in two columns, the page header indented by the card padding so the title, the card titles, the numbers and the plot share one left edge. Balances that do not change during the day go first, in one container split by 1px dividers into equal columns; a zero balance is grey and its caption becomes the next step. In the main card, 2-4 KPIs sit in a row and act as the chart's series tabs: the selected one carries a 2px rule and an ink label, the others keep a grey label and their value in ink at a lighter weight (a grey value reads as disabled); when the tabs are the per-entity breakdown the brief asks for (takings by shop), nothing is greyed and the rule alone marks the selection. Choosing one swaps the series. Under them, one line chart as wide as the card's content (about 1136x220 in the study): 3-4 solid 1px gridlines, 4-6 round y ticks at 12px, a 2-3px line in ink with straight segments and no fill, an 8px hover dot with a 1px dashed guide and the line after the cursor in pale grey. Close with a 2-3 row comparison table on a 36px pitch, value and change columns right-aligned under a 14px grey header such as 'vs prior Monday'.\",\n      \"phone\": \"KPI tabs become a 2-up grid above the chart, with the selected cell marked by a fill (never an underline floating inside the grid) or a row of tabs that scrolls sideways; the chart is full width, 160-200px tall, with 4 x labels; the comparison table keeps its two right-aligned columns.\"\n    },\n    {\n      \"id\": \"chart-pairs\",\n      \"name\": \"Per-period and running-total pairs\",\n      \"screen\": \"analytics\",\n      \"kinds\": [\n        \"community\",\n        \"smb-admin\",\n        \"analytics\"\n      ],\n      \"basis\": \"a network analytics overview\",\n      \"blueprint\": \"Title at 24-32px with one sentence under it saying what the filters do, then one filter row of 36-38px controls (one filled or near-black, the rest borderless or text, a reset link last) and 16-24px to the KPIs. KPI row: 3 equal cards in the content column (3 x 372 + 2 x 17 = 1152 in the study) or one divided container; a 16px label over the value with the change written as a phrase on the value's baseline ('+8 in the last 90 days'), grey when it is zero. Then one row per metric: the per-period column chart on the left and its cumulative line on the right, at equal width (2 x 568 + 16 = 1152) and with the same x ticks; square bars, a 2px straight line, integer ticks from zero, no legend because each chart has one series. One gap value horizontally and vertically.\",\n      \"phone\": \"Pairs stack, the cumulative chart directly under its per-period chart; KPI cards become a single column of label-value rows.\"\n    },\n    {\n      \"id\": \"insights-share-tables\",\n      \"name\": \"Insights with share tables\",\n      \"screen\": \"analytics\",\n      \"kinds\": [\n        \"analytics\",\n        \"devtools\",\n        \"builder\"\n      ],\n      \"basis\": \"a per-agent insights page\",\n      \"blueprint\": \"No cards: sections are carried by whitespace and a 16/500 heading with one 14px grey sentence under it saying what the section shows. A row of up to 6 KPIs on a fixed pitch (12px grey label over a 30px tabular value, no boxes, no dividers), then one full-width time chart (about 218px plot, 5 hairline gridlines, 11-12px grey ticks, a dot legend under the title, a 'Compare to previous period' text button on the right). Then a 2 x 2 grid of small tables with a 24px gutter whose rows align across the two columns. Each table: a header of 12px grey labels with no fill and no rule, 44px rows with 2px gaps whose rounded fill (#f5f7f9, radius 8) is the data bar, its width the row's share divided by the largest share; Share in 12px grey and Count in 14px ink, both right-aligned. An empty table keeps its header and shows one dashed 1px box about 38px tall with one sentence ('No Slack channel usage in this range.').\",\n      \"phone\": \"KPIs become a 2 x 3 grid; the chart is full width; the share tables stack in one column and keep their row bars.\"\n    },\n    {\n      \"id\": \"table-filter-bar\",\n      \"name\": \"Table with tabs and a filter bar\",\n      \"screen\": \"list\",\n      \"kinds\": [\n        \"community\",\n        \"devtools\",\n        \"commerce\",\n        \"support\",\n        \"smb-admin\"\n      ],\n      \"basis\": \"an events back office, a tracks studio, a sessions overview\",\n      \"blueprint\": \"Title row: an 18-24px title on the left, at most an outlined secondary and the one primary (36px) on the right. Underline tabs for the list's states on a full-width 1px rule with a 2px indicator as wide as the label; 22-32px below, the toolbar: a search of about 252-316 x 32-36 on the left, the count ('7 events') and the sort on the right. The table sits on the panel or page ground with no card around it: a header of 12-13px grey sentence-case labels with no fill and no rule, rows on a 48-56px pitch for one line or 72-92px with a thumbnail (media height plus 24-32px), 1px rules 3-7% darker than the ground or no rules at all, the identity column given the most width, numbers right-aligned in tabular figures with the unit muted ('5 /10'), one status mark per row and one kebab at the far right. Drop a column that is empty in every row (a blank co-host column left a 300px dead band). On an overview, cap the rows and link to the full list; on the full list, state the total and load more at the end.\",\n      \"phone\": \"Rows become two-line items: identity and the key number on line 1, the secondary fields in 13px grey on line 2, the kebab at the right. Tabs scroll in their own row; the search becomes a full-width field.\"\n    },\n    {\n      \"id\": \"count-cards-filter\",\n      \"name\": \"Count cards that filter\",\n      \"screen\": \"list\",\n      \"kinds\": [\n        \"community\",\n        \"commerce\",\n        \"support\"\n      ],\n      \"basis\": \"an events back office\",\n      \"blueprint\": \"Above a list, 3-5 equal count cards (61px tall, 12px padding, a 13px grey label over a 16/600 value, 8px gap) are the type filter: the selected card gets a 1.5px accent border and a pale accent fill, and the list below shows that type only. Zero counts print as '0' in the same style; no deltas, no icons. This is one place where a row of identical small cards is right: the cards are peers and each one does work.\",\n      \"phone\": \"The count cards become a horizontally scrolling row of chips with the count inside each, or a select above the list.\"\n    },\n    {\n      \"id\": \"settings-two-column\",\n      \"name\": \"Settings in two columns\",\n      \"screen\": \"settings\",\n      \"kinds\": [\n        \"devtools\",\n        \"smb-admin\",\n        \"support\",\n        \"workspace\",\n        \"commerce\",\n        \"analytics\",\n        \"finance\",\n        \"wallet\",\n        \"creator\",\n        \"community\",\n        \"builder\",\n        \"markets\",\n        \"report\"\n      ],\n      \"basis\": \"one settings page; stacking from a narrow rail card. The basis is thin.\",\n      \"blueprint\": \"A centred column of about 1152px. Each section is one row: a label column of about 450px (16/500 title, 14px grey description; the title's cap top 6-8px below the panel top, level with the panel's first line) beside a panel of about 700px with a #fafafa fill, 16px radius, 16px padding, no border and no shadow. Sections are split by a full-width 1px rule with 32px above and below. Inside a panel: field labels 14/500 above 40px white inputs (1px #e8e8e8, radius 10), 8px from label to field, 16px between fields, 24px from the description to the first label, 16px to the Save button; switch rows with a 14/500 title, a 20px status badge 8px after it, a 14px grey description and a 28x16 toggle 16px from the right edge, centred on the title line. A plan-gated feature shows a 48px tinted strip with a 32px button directly above its panel, and the panel stays readable. When a panel runs much taller than its label, put the section's help or a summary of the current values in the label column rather than 250px of nothing.\",\n      \"phone\": \"Each section stacks: title and description, then the panel at full width. Inside, label, 8-10px, field, 16-26px to the next pair; toggles stay on the right of their title.\"\n    },\n    {\n      \"id\": \"settings-with-usage\",\n      \"name\": \"Settings with usage on top\",\n      \"screen\": \"settings\",\n      \"kinds\": [\n        \"devtools\",\n        \"smb-admin\",\n        \"support\"\n      ],\n      \"basis\": \"one settings page\",\n      \"blueprint\": \"Use this only when usage is the question of the view (a plan, billing or quota view), and show only numbers no section below repeats, at a size below the h1. When a settings screen also reports usage, put 3-4 usage numbers in one row on top (a 14px grey label, a 30px regular value, a 12px change pinned to the card bottom with its window in words, a grey dash where there is no comparison) and link out to the analytics screen ('View more') instead of drawing a chart. Below, the two-column settings rows. One dark primary per screen. Keep upsell to one surface: the studied settings page carried three nags (a top banner, a setup button and a gated strip) and was flagged for it.\",\n      \"phone\": \"The usage row becomes a 2-column grid of label-value pairs; settings rows stack.\"\n    },\n    {\n      \"id\": \"wallet-balance-actions-assets\",\n      \"name\": \"Balance, actions and assets\",\n      \"screen\": \"wallet\",\n      \"kinds\": [\n        \"wallet\",\n        \"finance\"\n      ],\n      \"basis\": \"a wallet home\",\n      \"blueprint\": \"One column whose every element snaps to its two edges. A balance card (1px border, 16px radius, about 134px tall) holding one 32px figure and one line under it in which only the change is coloured ('-$0.09 in the last 30 days'); the title says what the figure is, so it needs no label. 32px below, 4 equal action tiles in a pale tint with dark same-hue icon and 12-14px label (4 x 144 + 3 x 16 = 624 in the study; scale the column and keep the arithmetic). 32-40px below, text tabs for the asset kinds on a 1px rule with a 2px ink indicator as wide as the word, a network or account select on the right of the same row. Then the asset table: 72px rows (48px round icon plus 24px), no dividers, two-line cells pairing a 16px value with a 14px grey unit amount, numeric columns right-aligned to shared edges, change as a small solid triangle and a coloured percentage, zero change grey, a missing share a grey em dash. On a desktop do not leave the column at phone width: the study's 624px column was flagged as a stretched phone screen; widen it to 864-1100 or give it a second column.\",\n      \"phone\": \"This pattern is phone-first: the same column at full width with 16px margins, the 4 tiles in one row, the table as two-line rows with the value right-aligned.\"\n    },\n    {\n      \"id\": \"finance-home-pinned-rail\",\n      \"name\": \"Finance home with a pinned accounts column\",\n      \"screen\": \"overview\",\n      \"kinds\": [\n        \"finance\",\n        \"wallet\"\n      ],\n      \"basis\": \"a personal finance home\",\n      \"blueprint\": \"No page header and no KPI strip: cards start 36px from the top and each headline sum sits in the card that explains it. On the left, a 306px accounts card pinned at the viewport height minus the 36px margins opens with net worth (16/600 label left, value right) and holds the account tree with no dividers: groups 16px ink, categories 14px ink, leaves 14px grey indented 8px, values right-aligned, a 30px pitch and about 45px between groups; an empty group is a bordered box with an '+ Add account' link instead of $0.00. On the right, a 2-column grid with 24px gaps of cards that answer this month's questions, each with its own period caption: the plan (spanning both columns; a ring with an empty hole, a dot legend, the available figure beside it with a per-day line), recent spending as 61px two-line rows (payee over category, amount over date, right-aligned) and upcoming bills. Income is green with a plus sign; spending stays in ink.\",\n      \"phone\": \"Net worth becomes the first card; the account tree collapses to its groups with totals; the month cards stack.\"\n    },\n    {\n      \"id\": \"builder-canvas\",\n      \"name\": \"Builder canvas\",\n      \"screen\": \"builder\",\n      \"kinds\": [\n        \"builder\"\n      ],\n      \"basis\": \"a flow builder in analytics mode\",\n      \"blueprint\": \"No global navigation: a 44px top bar on the window ground with no rule (an exit arrow, the object's name at 16/600 with a status pill, and on the right 16px icon buttons on a 40px pitch, a secondary and a near-black primary, split by 1px dividers). Below, two panels on the ground with 8px outer margins and a 12px gap, both wi\n\n<!-- [TRUNCATED AT 50KB] -->\n\n<!-- File: skills/taste-skill/library/directions.json (Tokens: ~12547 | Category: anthropic-skill) -->\n[\n {\n  \"id\": \"name-as-monument\",\n  \"name\": \"The name as a monument\",\n  \"sectors\": [\n   \"agency\",\n   \"studio-portfolio\",\n   \"personal-portfolio\",\n   \"hospitality\",\n   \"restaurant\",\n   \"music\",\n   \"culture\",\n   \"fashion\",\n   \"event\",\n   \"architecture\",\n   \"real-estate\",\n   \"physical-product\",\n   \"consumer-app\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"bold\",\n   \"editorial\",\n   \"luxury\"\n  ],\n  \"needs\": [],\n  \"idea\": \"The name is the headline. Set it so large that it becomes architecture: as wide as the viewport, cropped by an edge, or stacked to fill the screen. Nothing else on the first screen competes; the description of what this is drops to a single small sentence. The idea comes from treating the name's letters as material. Ask what the subject can do to its own name: a photograph of the work sits inside a counter or replaces a letter, the name repeats down the page like a reel, the letters are split to opposite corners and the page happens between them. In the study this was the single most common device among sites scoring 7.5 or more.\",\n  \"composition\": \"First screen: the wordmark spans 88–100% of the viewport width (font-size 16–24vw, set with a clamp so it never wraps), anchored either to the bottom edge with its descenders nearly touching it, or dead centre with everything else pushed to the corners. One line of supporting text at 16–20px sits in a corner on a shared margin; navigation is three or four words in the opposite corner. After the hero the page is deliberately small and calm: a narrow text column or a simple two-column grid, so the contrast with the monument holds. The name returns once more at full width as the footer, in the inverse colours. Margins are tight (20–32px) so the type reaches the edges. Two type sizes do nearly all the work: the monument and a small text size, with one mid size for section headings.\",\n  \"typography\": \"One family. The display cut must survive enormous sizes: tight tracking (-0.04 to -0.07em), leading 0.8–0.9, optical kerning on. Section headings are modest (28–40px) on purpose.\",\n  \"typeClasses\": [\n   \"grotesk-tight\",\n   \"condensed-heavy\",\n   \"extended-heavy\",\n   \"heavy-black\",\n   \"serif-display\"\n  ],\n  \"colour\": \"Two values carry the page (ground and ink). The accent, if used at all, appears on one thing only: the single action or the inset image frame. The footer inverts ground and ink.\",\n  \"paletteTags\": [\n   \"light-neutral\",\n   \"dark-neutral\",\n   \"two-tone\",\n   \"mono-accent\"\n  ],\n  \"imagery\": \"Few images, used as inserts in the typography rather than as illustrations beside it: one photograph inside or behind the name (a 4:5 or 1:1 frame replacing a letter, or tucked between two words), then a short run of large full-width or half-width photographs further down. Square corners. No collage of small thumbnails.\",\n  \"sectionTags\": [\n   \"type-led\",\n   \"quiet\",\n   \"poster\"\n  ],\n  \"motion\": \"scaling-wordmark\",\n  \"richness\": \"Scale. The size of the name against the smallness of everything else is the entire visual event, so protect both ends: do not shrink the name to make room, and do not let body text creep above 20px.\",\n  \"pitfalls\": \"A long name set small is just a logo. If the name has more than about 12 characters, stack it on two lines or crop it with the viewport edge; never drop below 12vw. Do not add a second big headline under the name. Do not decorate the letters.\",\n  \"seenIn\": [\n   \"aww-nothin\",\n   \"opl-kereliott\",\n   \"aww-paul-kalkbrenner\",\n   \"opl-nia-creative\",\n   \"aww-house-of-honey-1\",\n   \"aww-produx-design\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"sentence-as-layout\",\n  \"name\": \"The sentence is the layout\",\n  \"sectors\": [\n   \"agency\",\n   \"saas\",\n   \"ai-product\",\n   \"dev-tool\",\n   \"nonprofit\",\n   \"culture\",\n   \"education\",\n   \"physical-product\",\n   \"consumer-app\",\n   \"finance\",\n   \"health\",\n   \"event\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"bold\",\n   \"editorial\"\n  ],\n  \"needs\": [],\n  \"idea\": \"One short sentence, set at poster scale, is the composition. The trick that makes it an idea rather than a big headline: something from the subject sits inside the sentence where a word would be. A strip of photograph fills the gap between two words; a small live fragment of the product replaces the noun; the object the sentence names is pictured at the size of a letter. Write the sentence first, find the word that can be shown instead of said, and put the showing in its place. The reader completes the sentence with their eyes.\",\n  \"composition\": \"The sentence is four to seven words and runs as one or two full-width lines at 9–13vw. Inline with the type, on the baseline, sits one media slot: a rounded-rectangle or square frame exactly one line-height tall and two to three ems wide, holding a photograph or a looping crop. Above and below the sentence the screen is empty except for a small navigation line and one supporting sentence set small, both on the same left margin. Later sections repeat the grammar at smaller scale: each is a short statement on the left six columns with its proof (image, figure, list) on the right, so the page reads as a series of sentences with evidence. Generous vertical space (160px or more) between sections.\",\n  \"typography\": \"Display weight with real presence (medium to bold), tracking -0.03 to -0.05em, leading 0.95–1.0 so two lines sit close. The inline frame aligns to cap height and baseline exactly; set it with em units so it scales with the type.\",\n  \"typeClasses\": [\n   \"grotesk-tight\",\n   \"serif-display\",\n   \"condensed-heavy\",\n   \"serif-light-large\"\n  ],\n  \"colour\": \"A calm ground with ink at full contrast. The only colour comes from the photograph inside the sentence; if the palette has an accent, use it once, on the action.\",\n  \"paletteTags\": [\n   \"two-tone\",\n   \"light-neutral\",\n   \"single-field\",\n   \"mono-accent\"\n  ],\n  \"imagery\": \"One strong, simple photograph that reads at small size (a face, an object, a texture, a horizon), cropped to a wide strip inside the sentence. The same image may open to full width in the next section, so the small slot feels like a window onto something larger.\",\n  \"sectionTags\": [\n   \"type-led\",\n   \"poster\",\n   \"quiet\"\n  ],\n  \"motion\": \"masked-headline\",\n  \"richness\": \"The collision of big type and one live image inside it. Because there is only one image on the first screen, choose it with care and give it perfect alignment to the letters.\",\n  \"pitfalls\": \"The sentence must be short enough for two lines on a phone, where the inline frame drops to its own line between the two halves. Do not style one word differently to fake the device. Do not use more than one slot per sentence.\",\n  \"seenIn\": [\n   \"aww-colonia-zacamil\",\n   \"aww-bleibtgleich26\",\n   \"opl-spatial\",\n   \"aww-coffeetech-r\",\n   \"opl-midnight-2\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"pinned-poster\",\n  \"name\": \"The pinned poster\",\n  \"sectors\": [\n   \"culture\",\n   \"music\",\n   \"event\",\n   \"fashion\",\n   \"personal-portfolio\",\n   \"studio-portfolio\",\n   \"physical-product\",\n   \"ecommerce\",\n   \"hospitality\",\n   \"consumer-app\"\n  ],\n  \"tones\": [\n   \"bold\",\n   \"editorial\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Something stays put while everything else changes. A title holds its place across the viewport and the images beneath it swap; the name is split to two opposite corners and the page passes between the halves; a single frame stays centred while its contents change. Every scroll step is a new cover of the same magazine. The idea suits subjects that are a series (a book of portraits, a line-up, a collection, a set of projects): the fixed element says what the series is, the changing element shows its members.\",\n  \"composition\": \"A sticky layer holds the fixed element for the height of two to three viewports: usually the title at 10–14vw across the middle or top of the screen, or two words pinned to the top-left and bottom-right corners. Under it, a stack of full-height panels scrolls by, each a single large photograph (portrait 4:5, centred, 40–50% of the viewport wide) with one line of caption at the same small size everywhere. The title sits above the images in the stacking order and uses `mix-blend-mode: difference` or a solid colour that reads on every panel. When the pinned run ends, the page releases into ordinary flowing sections with a narrow measure. Build with `position: sticky`; never hijack the scroll.\",\n  \"typography\": \"The pinned title is the only large type on the page. Captions and body share one small size (15–17px). Tight tracking and solid weight so the title reads over photographs.\",\n  \"typeClasses\": [\n   \"grotesk-tight\",\n   \"condensed-heavy\",\n   \"heavy-black\",\n   \"extended-heavy\"\n  ],\n  \"colour\": \"One strong title colour against a pale or dark ground. Each panel may take its own flat ground colour sampled from its photograph.\",\n  \"paletteTags\": [\n   \"two-tone\",\n   \"photographic-neutral\",\n   \"single-field\"\n  ],\n  \"imagery\": \"A series of photographs with the same crop ratio and the same framing (all portraits, all objects, all rooms), so that swapping them reads as one image changing. Five to eight in the pinned run.\",\n  \"sectionTags\": [\n   \"photo-led\",\n   \"poster\",\n   \"type-led\"\n  ],\n  \"motion\": \"pinned-story\",\n  \"richness\": \"Repetition with change. The fixed title makes each new photograph feel like an event, so the photographs must be good and consistent.\",\n  \"pitfalls\": \"If the title is not legible over every panel, the idea fails: test each one. Keep the pinned run under six viewports or it feels like a trap. On a phone the title shrinks to 16–18vw and stays pinned at the top; panels become full-width. A pin longer than three screens, or one where the screens under it are nearly empty, read in blind tests as a stuck page. Every screen under the pin needs its own content, and nothing may pass over the pinned words.\",\n  \"seenIn\": [\n   \"opl-city-of-angels\",\n   \"aww-normal-is-boring\",\n   \"aww-glitch-grit\",\n   \"aww-revelatio-studio\"\n  ],\n  \"allow\": [],\n  \"needsPictures\": true\n },\n {\n  \"id\": \"colour-chapters\",\n  \"name\": \"Colour chapters\",\n  \"sectors\": [\n   \"agency\",\n   \"music\",\n   \"event\",\n   \"education\",\n   \"nonprofit\",\n   \"saas\",\n   \"consumer-app\",\n   \"culture\",\n   \"physical-product\",\n   \"health\",\n   \"finance\",\n   \"ai-product\"\n  ],\n  \"tones\": [\n   \"bold\",\n   \"playful\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Every section is a chapter with its own flat colour, floor to ceiling. The page reads like a set of posters hung in a row, held together by one typeface and one grid. The colours are not decoration: they come from the subject (the brand's packaging, the artist's record sleeves, the product's own colour ways, the categories of the content) and each chapter's colour means that chapter. Decide the sequence like a designer orders a book: a strong opener, a quiet second, a surprise in the middle, a dark or very light closer.\",\n  \"composition\": \"Sections are full-bleed fields, each at least 90svh tall, butted directly against each other with no gap and no divider. Inside every field the same 12-column grid and the same margins apply, and each field holds one thing: a huge heading (8–12vw) with a small paragraph, or one photograph with a caption, or one list. Text colour is chosen per field for strong contrast (ink or paper, never grey). Headings start on the same left edge in every chapter, so the eye feels the system as colours change. The navigation and the footer take the colours of the first and last chapter.\",\n  \"typography\": \"One typeface in two weights. Headings very large and tight; body 18–20px. Because colour is loud, the type stays plain: no italics, no second face.\",\n  \"typeClasses\": [\n   \"grotesk-tight\",\n   \"heavy-black\",\n   \"geometric\",\n   \"rounded-friendly\"\n  ],\n  \"colour\": \"Four to six flat fields used at full strength, one per section, each with its assigned text colour. No tints, no gradients between them: the hard edge where two fields meet is the look.\",\n  \"paletteTags\": [\n   \"flat-loud\",\n   \"pastel-fields\"\n  ],\n  \"imagery\": \"Sparing. One photograph or object per chapter at most, either cut out and sitting directly on the colour, or a plain rectangle with generous colour around it. Photographs should be simple enough not to fight the field.\",\n  \"sectionTags\": [\n   \"colour-field\",\n   \"type-led\",\n   \"poster\"\n  ],\n  \"motion\": \"colour-on-scroll\",\n  \"richness\": \"Colour at scale. A whole screen of one saturated colour is rich on its own, so a chapter needs few elements; it still needs its content at full size, because a coloured screen with one small line on it reads as empty.\",\n  \"pitfalls\": \"Check contrast on every field with the palette's assigned ink. Do not put cards on the fields. Do not use more than six colours. Two neighbouring fields should differ clearly in lightness as well as hue.\",\n  \"seenIn\": [\n   \"aww-warm-fuzzy\",\n   \"aww-paul-kalkbrenner\",\n   \"opl-anidachi\",\n   \"aww-aardvark-book-club\",\n   \"aww-ai-in-design-report-2026\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"place-carries-it\",\n  \"name\": \"The place carries it\",\n  \"sectors\": [\n   \"hospitality\",\n   \"restaurant\",\n   \"real-estate\",\n   \"architecture\",\n   \"event\",\n   \"health\",\n   \"culture\",\n   \"nonprofit\"\n  ],\n  \"tones\": [\n   \"quiet\",\n   \"luxury\",\n   \"warm\"\n  ],\n  \"needs\": [],\n  \"idea\": \"For a place, the photograph is the argument. One full-bleed image of where you would be standing fills the first screen, and the design steps back: the name sits along the bottom edge like a film title, or small in a corner, and nothing else interrupts the view. The page that follows keeps that restraint: few words, large pictures, long pauses. The designer's work here is editing: choosing the one frame that makes someone want to be there, and then not covering it.\",\n  \"composition\": \"First screen: a single photograph at 100vw by 100svh, focal point kept clear of text. The name is set either very large (14–20vw) hugging the bottom edge with 16–24px of margin, or small (20–28px) top-left with a one-line description bottom-left. Navigation is two to four words in the top corners in the same small size. If text sits on the image, a soft neutral scrim under the text area only. Below, sections alternate between a short centred or left-set paragraph in a narrow column (max 52ch) with wide empty margins, and photographs shown large: one full-bleed, then a pair at different sizes, then one portrait offset to the right. Practical information (hours, address, rates, booking) is gathered once near the end in a plain two-column block.\",\n  \"typography\": \"A face with some grace for the name; small, calm, well-spaced text everywhere else. Sentence case. Body 17–19px with leading around 1.55.\",\n  \"typeClasses\": [\n   \"serif-display\",\n   \"serif-light-large\",\n   \"condensed-heavy\",\n   \"grotesk-light\"\n  ],\n  \"colour\": \"Neutral paper or deep neutral ground chosen to flatter the photographs; text ink drawn from the darkest tone in the imagery. Colour lives in the pictures.\",\n  \"paletteTags\": [\n   \"photographic-neutral\",\n   \"dark-neutral\",\n   \"earth\"\n  ],\n  \"imagery\": \"The dealt set is the palette. Choose four to six photographs with the same light. The hero image must have a calm area for the name. Full-bleed or large with square corners; never thumbnails, never a carousel of ten.\",\n  \"photoTreatment\": \"Leave photographs ungraded. If text overlays one, darken only the area behind the text with a neutral scrim.\",\n  \"sectionTags\": [\n   \"photo-led\",\n   \"quiet\"\n  ],\n  \"motion\": \"slow-crossfade\",\n  \"richness\": \"The photographs, at full size, uninterrupted. Empty paper around short text makes the next image land harder.\",\n  \"pitfalls\": \"A weak hero photograph cannot be fixed by typography; pick again. Do not stack a headline, a paragraph and two buttons on the image. Do not use a booking bar that covers the bottom of the view; one small action is enough.\",\n  \"seenIn\": [\n   \"aww-white-desert\",\n   \"opl-eagles-nest\",\n   \"aww-tengile-malamala-collection\",\n   \"aww-izanami\",\n   \"aww-seasats\"\n  ],\n  \"allow\": [],\n  \"needsPictures\": true\n },\n {\n  \"id\": \"page-is-the-object\",\n  \"name\": \"The page is the object\",\n  \"sectors\": [\n   \"restaurant\",\n   \"event\",\n   \"hospitality\",\n   \"culture\",\n   \"music\",\n   \"physical-product\",\n   \"ecommerce\",\n   \"nonprofit\",\n   \"education\",\n   \"personal-portfolio\",\n   \"consumer-app\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"warm\",\n   \"playful\",\n   \"editorial\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Find the printed or physical artefact that already exists in the subject's world and build the page as that thing. A wedding site is the invitation card. A restaurant is its menu. A conference is the ticket; a record is its sleeve; a shop is the receipt or the swing tag; an archive is a stack of tabbed folders; a course is the syllabus sheet. The artefact supplies everything a template would otherwise invent: its proportions, its typographic manners, its way of grouping information. Visitors recognise the object instantly, which is why these pages feel specific.\",\n  \"composition\": \"The first screen shows the artefact as a single filled panel (paper colour on a contrasting ground) centred or offset, with believable proportions: a card at 5:7, a ticket at about 2.2:1 with a notch cut by `clip-path`, a menu as a tall sheet. All primary content lives on it, set the way that object is set: centred and symmetrical for an invitation, in tidy aligned columns for a menu or ticket. The ground behind is a flat colour or one full-bleed photograph. As the page continues, each section is another piece of the same stationery: a second card, a tear-off stub, a folded panel, always filled shapes with real edges (straight, notched, scalloped, perforated by a dotted `border` of round dots at 4px or more), never outlined boxes. The footer is the back of the object.\",\n  \"typography\": \"Take the manners of the artefact: a bookish serif with small caps avoided, or a blunt condensed face for tickets and posters. Sizes stay within what print would use relative to the panel; the name is large on the panel, details are small and exact.\",\n  \"typeClasses\": [\n   \"serif-text\",\n   \"serif-display\",\n   \"slab\",\n   \"condensed-heavy\",\n   \"grotesk-tight\"\n  ],\n  \"colour\": \"Paper and ink plus the ground the paper sits on. Two or three flat colours in total, like a two-colour print job.\",\n  \"paletteTags\": [\n   \"two-tone\",\n   \"earth\",\n   \"light-neutral\"\n  ],\n  \"imagery\": \"Optional. One photograph behind the object, or small photographs placed on it like tipped-in plates. The object itself is the image.\",\n  \"sectionTags\": [\n   \"object-led\",\n   \"type-led\",\n   \"colour-field\"\n  ],\n  \"motion\": \"curtain-footer\",\n  \"richness\": \"Recognition. The shaped edges, the print-like alignment and the limited inks make a familiar object out of plain HTML.\",\n  \"pitfalls\": \"Choose an artefact that truly belongs to the subject, or it becomes costume. Shape the edges with fills and `clip-path`; an outlined rectangle with a thin border is not an object. Keep text sizes readable on a phone, where the object becomes full width with its shaped edge kept at top and bottom.\",\n  \"seenIn\": [\n   \"opl-sarah-matt-wedding\",\n   \"aww-mosbys-files\",\n   \"opl-the-deep-end\",\n   \"opl-weeksync\",\n   \"opl-le-petit-bleu\",\n   \"opl-archiv\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"one-motif\",\n  \"name\": \"One motif\",\n  \"sectors\": [\n   \"saas\",\n   \"finance\",\n   \"consumer-app\",\n   \"ai-product\",\n   \"dev-tool\",\n   \"health\",\n   \"physical-product\",\n   \"restaurant\",\n   \"education\",\n   \"nonprofit\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"playful\",\n   \"technical\",\n   \"warm\",\n   \"bold\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Take one shape from the subject and let it run the whole system. A drilling tool's octagonal cross-section becomes the buttons, the image masks and the loader. A two-account money app becomes two circles that recur as icon, inline dot and section colour. A café's striped awning becomes every band on the page. Look at the product, the logo, the object or the word in the headline and find the simplest geometry in it (a circle, an arc, a chamfer, a stripe, a notch, a ring). Then use only that shape, at three or four very different scales, everywhere a designer would normally reach for a generic rounded rectangle.\",\n  \"composition\": \"Hero: the motif appears once at enormous scale as a flat filled shape, cropped by the viewport (a circle 120vh across entering from the right, a chamfered block filling the lower half), with a short headline at 6–8vw and one supporting sentence set on the remaining ground, left-aligned on a shared margin. Through the page the motif returns as: the mask for every photograph (via `clip-path` or `border-radius` made from the same geometry), the shape of the primary button, the bullet beside list items at text size, and one full-width band that separates the two halves of the page. Sections use simple two-column or single-column layouts so the shape is the only thing with character.\",\n  \"typography\": \"A clean geometric or grotesk face that echoes the shape (round bowls for circles, squared terminals for chamfers). Medium weight; headings 6–8vw in the hero and 3–4vw after.\",\n  \"typeClasses\": [\n   \"geometric\",\n   \"grotesk-tight\",\n   \"rounded-friendly\"\n  ],\n  \"colour\": \"The motif carries the accent colour at large scale, flat. Everything else is ground and ink. A second motif colour is allowed only if the subject has a real pair (two accounts, two modes).\",\n  \"paletteTags\": [\n   \"mono-accent\",\n   \"two-tone\",\n   \"pastel-fields\"\n  ],\n  \"imagery\": \"Photographs appear inside the motif's shape. If there is product interface to show, it sits on a flat colour stage shaped by the motif. Draw the shape with CSS or a simple inline SVG path; do not draw illustrations.\",\n  \"sectionTags\": [\n   \"colour-field\",\n   \"object-led\",\n   \"type-led\"\n  ],\n  \"motion\": \"shutter-image\",\n  \"richness\": \"One shape at many sizes. The giant cropped shape gives the hero mass and colour without a single image.\",\n  \"pitfalls\": \"One motif means one. A circle here, a hexagon there and a blob behind is the generated look this replaces. The motif must come from the subject and you must be able to say from where in one clause.\",\n  \"seenIn\": [\n   \"aww-sstr-friction-reduction\",\n   \"opl-tara\",\n   \"opl-boaxt\",\n   \"opl-midnight-2\",\n   \"opl-superlocal-2026\",\n   \"opl-billow\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"product-performs\",\n  \"name\": \"The product performs\",\n  \"sectors\": [\n   \"saas\",\n   \"dev-tool\",\n   \"ai-product\",\n   \"consumer-app\",\n   \"finance\"\n  ],\n  \"tones\": [\n   \"technical\",\n   \"quiet\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Software is most convincing when it is doing its job in front of you. Instead of describing features, put small, true, working fragments of the product on the page: the actual control, with real content, responding to the pointer. A colour picker's loupe reads the page's own background and prints its value. A list tool lets you tick an item right there. A type-scale plugin sets the page's own headings. Find the one interaction that is the product and make the hero that interaction; then show each further capability as another fragment at real size. No dashboard collage, no browser frame, no screenshots shrunk until unreadable.\",\n  \"composition\": \"Hero: a short plain headline (4–6vw, left-aligned, upper-left third) and one sentence; the rest of the first screen is the main fragment at actual interface size, sitting directly on the page or on one flat stage colour, large enough to read every label. The fragment is built in HTML and works. Below, capabilities are a single-column sequence, each a row of two parts on a 5/7 split: a two-line statement on one side and the relevant fragment on the other, with the fragments varying in size and shape so the column never becomes a zigzag of equal blocks. Fragments are cropped pieces of interface (a menu, a row, a control, a panel edge), not whole windows. One section pins a fragment while three short statements change it.\",\n  \"typography\": \"The marketing type matches the product's interface type so the fragments and the page feel like one thing. Headline modest; interface text at its true size (13–15px) inside fragments.\",\n  \"typeClasses\": [\n   \"grotesk-tight\",\n   \"grotesk-light\",\n   \"geometric\"\n  ],\n  \"colour\": \"Neutral ground. The product's own interface colours provide the colour. At most one flat stage colour behind fragments.\",\n  \"paletteTags\": [\n   \"light-neutral\",\n   \"dark-neutral\",\n   \"mono-accent\"\n  ],\n  \"imagery\": \"The interface fragments are the main imagery: build them carefully with real labels, real numbers and sensible states (one hovered, one selected). Around them, two or three real pictures of the customer's world (found with scripts/assets.mjs), never stock of people at laptops.\",\n  \"sectionTags\": [\n   \"ui-led\",\n   \"quiet\"\n  ],\n  \"motion\": \"pinned-story\",\n  \"richness\": \"Fidelity. A fragment with believable content and a real hover state is more interesting than any illustration. Spend the effort there.\",\n  \"pitfalls\": \"A fake interface made of grey bars and circles is the worst outcome; if you cannot build a believable fragment, change direction. Mark each fragment's root element with the attribute data-ui: inside it the product's own conventions apply (1px control borders, small radii, a shadow on its open menu) and the inspector leaves them alone; outside it the house rules hold as usual. data-ui is for cropped fragments only, never for a page wrapper. Do not put the fragment in a browser or laptop frame.\",\n  \"seenIn\": [\n   \"opl-dabbit\",\n   \"opl-rows\",\n   \"opl-typewave\",\n   \"opl-shelf\",\n   \"opl-uni\",\n   \"opl-kontu\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"quiet-instrument\",\n  \"name\": \"The quiet instrument\",\n  \"sectors\": [\n   \"saas\",\n   \"dev-tool\",\n   \"ai-product\",\n   \"personal-portfolio\",\n   \"consumer-app\",\n   \"finance\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"quiet\",\n   \"technical\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Radical understatement. Where every competitor shouts, this page almost whispers: a headline barely larger than body text, a narrow column, small exact demonstrations, and a great deal of untouched space. The restraint is the claim. It says the thing is simple, finished and sure of itself. This only works when it is carried through completely; one loud element breaks it. In the study, a tool for simple lists sold itself with a 27px headline and 12–14px copy and was one of the most confident pages in the set.\",\n  \"composition\": \"A single column 440–560px wide, placed left of centre (starting at about 22% of the viewport width) or dead centre, running the whole page. The headline is the one large thing on the first screen: two lines at display size (5–7vw), medium weight, starting on the column's left edge and allowed to run wider than the column. The supporting paragraph follows at body size (17–19px) in the full ink. One small primary button and one text link. Below, each point is a short paragraph followed by a compact demonstration or image no wider than the column. Sections are separated only by space (96–140px). Nothing spans the full width until the footer, which is a single quiet line. The first screen is mostly empty and that emptiness is composed: the column's top edge sits at about 30% of the viewport height.\",\n  \"typography\": \"One family, two weights. A display size for the headline (5–7vw), one heading size for section titles (about 32–40px), body at 17–19px, a small size for captions (14–15px). Leading 1.5 for text. Letter-spacing near zero. The typeface must be handsome at small sizes.\",\n  \"typeClasses\": [\n   \"grotesk-light\",\n   \"serif-text\",\n   \"geometric\"\n  ],\n  \"colour\": \"Paper and two inks (full and soft). One accent used on exactly one element per screen.\",\n  \"paletteTags\": [\n   \"light-neutral\",\n   \"mono-accent\"\n  ],\n  \"imagery\": \"Precise rather than loud: cropped interface details at true size, and real photographs of the customer's world held to the column width, each doing one job. One short looping clip can sit at column width too. Never a large stock hero image.\",\n  \"sectionTags\": [\n   \"quiet\",\n   \"ui-led\",\n   \"type-led\"\n  ],\n  \"motion\": \"stillness\",\n  \"richness\": \"Precision. With so little on the page, alignment, spacing and the exact size relationships are the design. Every element shares the column's left edge.\",\n  \"pitfalls\": \"This is the one direction where a small headline is right; the inspector will not object, but do not mix it with a large display line. Emptiness must look decided: keep the column edges exact and the vertical rhythm even. Not suitable when the subject needs emotion or photography to sell. Quiet is not thin: the column must still deliver every piece of content the brief asks for, in full, at 16px or more in the full ink. In blind tests the quiet version lost every time it was quiet everywhere: a small headline beside an empty panel read as unfinished. Quiet means few things, not small things: the headline and the demonstration are large, and every screen holds content.\",\n  \"seenIn\": [\n   \"opl-rows\",\n   \"opl-compile\",\n   \"opl-plastic\",\n   \"opl-bueno-fyi\",\n   \"aww-gil-huybrecht\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"hero-object\",\n  \"name\": \"The object, large\",\n  \"sectors\": [\n   \"physical-product\",\n   \"ecommerce\",\n   \"consumer-app\",\n   \"fashion\",\n   \"finance\",\n   \"health\",\n   \"restaurant\",\n   \"music\"\n  ],\n  \"tones\": [\n   \"bold\",\n   \"luxury\",\n   \"quiet\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"idea\": \"Show the thing, bigger than seems reasonable. One photographed object fills the first screen, scaled until the viewport crops it, with the text small and tucked beside or behind it. The crop is the idea: a record whose edge leaves the top-right corner, a bottle whose shoulder runs off the bottom, a chair seen so close you read its grain. Being that close reads as confidence in the object. Everything else on the page serves it: details as tight close-ups, facts as short lines, one way to buy.\",\n  \"composition\": \"First screen: the object occupies 55–75% of the viewport and breaks at least one edge. It sits on a flat field (ground colour or one bold colour), never in a box. The headline is short and either very large and partly hidden behind the object (10–13vw, the object overlapping two or three letters) or small (28–36px) in the opposite corner with a one-line description. No navigation bar beyond a wordmark and one action. Following sections: a row of three or four close-up details at different crop ratios (not equal tiles), a single wide photograph of the object in use, a plain list of facts set large (materials, size, price) aligned to one edge, then the purchase action. The object returns once at the end from a different angle.\",\n  \"typography\": \"Either very large and structural or very small and precise; pick one for the headline and hold it. Facts are set in the text face at 22–28px, not in a table.\",\n  \"typeClasses\": [\n   \"grotesk-light\",\n   \"grotesk-tight\",\n   \"extended-heavy\",\n   \"serif-light-large\"\n  ],\n  \"colour\": \"A flat field chosen to make the object's own colour sing (its complement, or a tone darker than its shadow side). One field for the whole page, or a second for the facts section.\",\n  \"paletteTags\": [\n   \"single-field\",\n   \"light-neutral\",\n   \"pastel-fields\",\n   \"dark-neutral\"\n  ],\n  \"imagery\": \"Use the product's own photographs if they exist. Otherwise use a still-life from the dealt set as a stand-in and say so. Prefer images with a plain background; use `mix-blend-mode: multiply` on light fields so a white studio background disappears into the page colour.\",\n  \"photoTreatment\": \"Scale the main image well past its container (`width: 120–160%`) and let `overflow: hidden` on the section do the cropping.\",\n  \"sectionTags\": [\n   \"object-led\",\n   \"photo-led\",\n   \"colour-field\"\n  ],\n  \"motion\": \"shutter-image\",\n  \"richness\": \"The object's surface at close range, and the tension of the crop.\",\n  \"pitfalls\": \"A small centred product shot with space all round is a catalogue thumbnail, not this direction. If the image has a busy background it cannot sit on a field; crop tighter or change image. Keep text off the object's focal area.\",\n  \"seenIn\": [\n   \"opl-when-you-wish-upon-a-starboy\",\n   \"opl-plastic\",\n   \"opl-archiv\",\n   \"aww-moto-finance\",\n   \"aww-the-watch\",\n   \"opl-aevion\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"specimen-catalogue\",\n  \"name\": \"The specimen catalogue\",\n  \"sectors\": [\n   \"ecommerce\",\n   \"physical-product\",\n   \"restaurant\",\n   \"fashion\",\n   \"culture\",\n   \"education\",\n   \"health\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"playful\",\n   \"warm\",\n   \"editorial\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"idea\": \"Present what is on offer the way a field guide presents birds: each item alone on a flat colour, same scale, same angle, named plainly. A bakery's pastries become specimens and the specimens become the menu. A furniture maker's chairs each get their own colour tile. The format flatters ordinary objects because it treats each as worth looking at, and it replaces both the feature grid and the product-card grid with something that has a point of view.\",\n  \"composition\": \"Hero: a left-aligned statement of what this is (5–7vw, upper-left) beside or above a tight cluster of four to seven specimen tiles of different sizes arranged as a loose mosaic that runs off the right edge. Each tile is a flat colour square or 4:5 rectangle with one photograph centred on it, no border, 8–12px gaps. The main section is the catalogue itself: a grid of tiles in which each item has its name and one fact set beneath the tile in the text face, aligned left to the tile edge. Tile colours rotate through three or four fields from the palette. One tile in every six or seven is double size. Supporting sections (about, how to order) are plain text on the ground colour, kept short.\",\n  \"typography\": \"Friendly and plain. Item names at 18–22px in medium weight, facts beneath in the soft ink. One big statement in the hero; no other display type.\",\n  \"typeClasses\": [\n   \"grotesk-tight\",\n   \"serif-text\",\n   \"slab\",\n   \"rounded-friendly\"\n  ],\n  \"colour\": \"The tiles are the colour: three or four flat fields from the palette, repeated in a steady rotation. Ground stays neutral.\",\n  \"paletteTags\": [\n   \"pastel-fields\",\n   \"flat-loud\",\n   \"light-neutral\"\n  ],\n  \"imagery\": \"Photographs of single items on plain backgrounds, all cropped to sit at the same apparent size within their tile. On light tiles, `mix-blend-mode: multiply` removes white studio backgrounds. If the subject's own item photographs are missing, use the dealt set and say so.\",\n  \"sectionTags\": [\n   \"object-led\",\n   \"colour-field\",\n   \"photo-led\"\n  ],\n  \"motion\": \"drag-row\",\n  \"richness\": \"Rhythm of colour tiles and the pleasure of comparing like with like.\",\n  \"pitfalls\": \"It needs at least six items that can be shown as objects; with three it is a feature row. Keep labels outside the tiles. No shadows under the objects, no hover lift.\",\n  \"seenIn\": [\n   \"aww-noho\",\n   \"opl-madie\",\n   \"opl-humanoid-index\",\n   \"opl-smallbits\",\n   \"aww-butter\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"borrowed-category\",\n  \"name\": \"Dressed as something else\",\n  \"sectors\": [\n   \"finance\",\n   \"saas\",\n   \"consumer-app\",\n   \"physical-product\",\n   \"health\",\n   \"dev-tool\",\n   \"ai-product\",\n   \"education\",\n   \"nonprofit\",\n   \"real-estate\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"bold\",\n   \"playful\",\n   \"luxury\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Art-direct the subject as if it belonged to a different, more vivid category. A money app is sold like a streetwear drop. An industrial roaster is presented like a design object. Drilling hardware gets the calm of a watch brand. A parcel-locker service becomes a fairground of stickers. Choose the borrowed category by asking what feeling the audience is missing from this kind of product (swagger, calm, glamour, play) and which category owns that feeling. Then take its manners completely: its type, its pacing, its way of photographing things. The contrast between dull subject and vivid dress is what people remember.\",\n  \"composition\": \"Depends on the borrowed category, so decide it explicitly and write it in your notes. Fashion drop: one shouted condensed headline across the full width, a single cropped image under it, then product facts as a blunt list. Watch or perfume: a centred object on a dark field, a small serif name, very few words, long vertical pauses. Poster or zine: flat colour blocks, heavy type, tilted cut-out images. Museum: one item per screen on a plinth-like band of colour with a short label beside it. Whichever you choose, the page structure stays simple (four to six sections) and every section uses the borrowed manners, including pricing and the footer.\",\n  \"typography\": \"The borrowed category's type, fully committed: condensed and loud, or refined and small. No halfway.\",\n  \"typeClasses\": [\n   \"condensed-heavy\",\n   \"serif-display\",\n   \"extended-heavy\",\n   \"heavy-black\"\n  ],\n  \"colour\": \"The borrowed category's palette, which will be unlike the subject's sector norm. That mismatch is intended.\",\n  \"paletteTags\": [\n   \"flat-loud\",\n   \"two-tone\",\n   \"dark-neutral\",\n   \"single-field\"\n  ],\n  \"imagery\": \"Photograph the subject the way the borrowed category would be photographed. With the dealt set, choose images for attitude, not literal relevance, and crop them hard.\",\n  \"sectionTags\": [\n   \"poster\",\n   \"type-led\",\n   \"photo-led\",\n   \"colour-field\"\n  ],\n  \"motion\": \"edge-marquee\",\n  \"richness\": \"Attitude. The page has a recognisable voice from another world, applied to a subject nobody expected it for.\",\n  \"pitfalls\": \"Name the borrowed category in one word before you start, or the result is merely loud. The content must still be clear: what it is, what it costs, how to get it. Avoid borrowing from 'tech startup', which is the default you are escaping.\",\n  \"seenIn\": [\n   \"opl-uglycash\",\n   \"aww-coffeetech-r\",\n   \"aww-sstr-friction-reduction\",\n   \"opl-locker-land\",\n   \"aww-moto-finance\",\n   \"aww-vero-new-york\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"contact-sheet\",\n  \"name\": \"The contact sheet\",\n  \"sectors\": [\n   \"personal-portfolio\",\n   \"studio-portfolio\",\n   \"agency\",\n   \"fashion\",\n   \"culture\",\n   \"architecture\",\n   \"music\",\n   \"ecommerce\"\n  ],\n  \"tones\": [\n   \"quiet\",\n   \"technical\",\n   \"editorial\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Show everything at once, small, in order. The work is laid out like a photographer's contact sheet or an archive drawer: dozens of small frames in strict rows, with all text set at one small size. Nothing is featured, which is the point: the volume and consistency of the body of work is the statement, and the visitor does the choosing. It suits people and studios whose strength is range and output.\",\n  \"composition\": \"The name, or one sentence about the work, sits at display size (6–9vw) across the top of the first screen, and the sheet begins directly under it, still inside the first screen. The first screen opens with three or four short blocks of small text across the top on a 12-column grid (who, what, where to reach them), all at 14–16px, and immediately below, the sheet begins: rows of thumbnails at a fixed height (90–140px) with their natural widths, 6–10px gaps, each project forming a run of four to eight frames preceded by its title in the same small text. The sheet fills the whole page width edge to edge with 16–20px margins. Hovering a run dims the others and shows that project's one-line description in a fixed position. A single enlarged frame may interrupt the sheet once per screen at four times the size.\",\n  \"typography\": \"One face. The name at display size on the first screen; everything else at one text size and one small size; hierarchy below the name comes from position and from a single brighter ink for titles.\",\n  \"typeClasses\": [\n   \"grotesk-light\",\n   \"grotesk-tight\"\n  ],\n  \"colour\": \"Black or white ground, so the thumbnails are the only colour.\",\n  \"paletteTags\": [\n   \"dark-neutral\",\n   \"light-neutral\"\n  ],\n  \"imagery\": \"Many images: at least 24 frames to make a sheet. They can be project photographs from the dealt set cropped to mixed ratios, or page captures of the work. Square corners, no captions on the frames.\",\n  \"sectionTags\": [\n   \"dense\",\n   \"photo-led\",\n   \"quiet\"\n  ],\n  \"motion\": \"index-preview\",\n  \"richness\": \"Density and order. The mass of small images forms a texture; the strict rows keep it calm.\",\n  \"pitfalls\": \"With fewer than about 20 images it looks unfinished; choose another direction. Do not add a big headline above the sheet. On a phone the frames become two per row at a fixed height and each run scrolls sideways. Rows that run past the right edge read as clipped in screenshots and to most visitors: wrap the frames onto the next line, or end each row inside the grid.\",\n  \"seenIn\": [\n   \"aww-gil-huybrecht\",\n   \"opl-smallbits\",\n   \"opl-gunes-atakan-peksen\",\n   \"opl-proooof\",\n   \"aww-oimachi\"\n  ],\n  \"allow\": [],\n  \"needsPictures\": true\n },\n {\n  \"id\": \"editorial-report\",\n  \"name\": \"The printed annual\",\n  \"sectors\": [\n   \"culture\",\n   \"nonprofit\",\n   \"education\",\n   \"finance\",\n   \"saas\",\n   \"ai-product\",\n   \"health\",\n   \"agency\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"editorial\",\n   \"bold\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Lay the page out like a well-designed printed report or magazine feature: a masthead image, a tight oversized title, text held to a strict column line, and colour used in solid blocks the way a two-colour print job would. It gives weight and authority to subjects that are really about content: findings, a manifesto, a programme, a serious product. The reader should feel that someone edited this.\",\n  \"composition\": \"A fixed vertical axis at about 42% of the viewport width organises everything: headings begin on it, body columns hang from it, and the 0–42% zone holds small side notes, figures or stays empty. Masthead: a wide image band (photographic mosaic or a single crop) across the top 45% of the first screen; below it the title at 7–9vw starting on the axis, with a two-sentence standfirst at 20–24px. Sections alternate between text pages (title on the axis, body in one or two columns of 34–40ch to its right) and full-bleed colour pages carrying one large figure, quotation or image mosaic. Mosaics are gutterless: photographs and flat colour tiles butted together in a 4- or 6-cell grid. Page numbers, running heads and other print furniture are left out.\",\n  \"typography\": \"A tight heavy grotesk or a sharp serif for titles; an excellent text face for reading at 18–20px with leading near 1.5. Headings in sentence case, tracked tight.\",\n  \"typeClasses\": [\n   \"grotesk-tight\",\n   \"serif-display\",\n   \"serif-text\"\n  ],\n  \"colour\": \"Paper, ink and two or three solid block colours. A colour page is a whole section in one flat colour.\",\n  \"paletteTags\": [\n   \"flat-loud\",\n   \"two-tone\",\n   \"mono-accent\"\n  ],\n  \"imagery\": \"Photographs used as blocks in mosaics alongside flat colour tiles; mixed subjects are fine if cropped tight and converted to one treatment.\",\n  \"photoTreatment\": \"Give all photographs in a mosaic one treatment: greyscale via `filter: grayscale(1) contrast(1.05)`, or all full colour. Do not mix.\",\n  \"sectionTags\": [\n   \"type-led\",\n   \"colour-field\",\n   \"dense\",\n   \"poster\"\n  ],\n  \"motion\": \"masked-headline\",\n  \"richness\": \"The column line, the mosaics and whole pages of colour give structure and variety without ornaments.\",\n  \"pitfalls\": \"The axis must be exact and reused everywhere or it reads as random indentation. Keep paragraphs to a real reading measure. On a phone the axis collapses to the left margin and side notes move inline above their paragraph.\",\n  \"seenIn\": [\n   \"aww-ai-in-design-report-2026\",\n   \"opl-applied-imagination\",\n   \"opl-the-queue\",\n   \"opl-artem-taradash\",\n   \"opl-belgrade-architecture\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"loud-flat-poster\",\n  \"name\": \"Loud and flat\",\n  \"sectors\": [\n   \"agency\",\n   \"consumer-app\",\n   \"music\",\n   \"event\",\n   \"education\",\n   \"nonprofit\",\n   \"physical-product\",\n   \"saas\",\n   \"culture\"\n  ],\n  \"tones\": [\n   \"bold\",\n   \"playful\"\n  ],\n  \"needs\": [],\n  \"idea\": \"A page with the directness of a street poster: flat saturated colour, the heaviest type you can find, short blunt statements, and photographs cut out and stuck on. It is for subjects with a voice. Write the page as things a person would actually say out loud, and let the design say them at full volume. The craft is in the control beneath the noise: a strict grid, two or three colours, and exact alignment keep it from becoming a mess.\",\n  \"composition\": \"Hero: a statement of three to six words in ultra-heavy type at 11–15vw, filling the width, lines stacked tight (leading 0.85), flush left with 20–28px margins, on a flat saturated ground. One cut-out or hard-cropped photograph overlaps the type from the right or bottom, tilted 3–6 degrees. A single chunky button in the contrasting flat colour. Sections are solid panels in alternating palette colours: one is a row of short statements each on its own panel of unequal width; one is a single photograph bleeding off two edges with a caption block set over a solid colour bar; one is a large plain list. Panels meet edge to edge. Corners are square or use one large radius (28–40px) consistently.\",\n  \"typography\": \"The heaviest weight available, set tight, mostly lowercase or mostly uppercase (choose one). Body text is a plain grotesk at 18–20px.\",\n  \"typeClasses\": [\n   \"heavy-black\",\n   \"condensed-heavy\",\n   \"extended-heavy\",\n   \"rounded-friendly\"\n  ],\n  \"colour\": \"Three or four flat colours at full strength including black or white. Each panel is one colour; text on it is one other.\",\n  \"paletteTags\": [\n   \"flat-loud\"\n  ],\n  \"imagery\": \"Photographs with attitude, cropped hard or cut to a simple shape with `clip-path` (circle, arch, blunt polygon), slightly rotated, overlapping the type. Two or three on the page.\",\n  \"sectionTags\": [\n   \"poster\",\n   \"colour-field\",\n   \"type-led\"\n  ],\n  \"motion\": \"edge-marquee\",\n  \"richness\": \"Colour mass, type mass, and overlap.\",\n  \"pitfalls\": \"Headlines still obey the two-line rule: at 13vw that means very few words, which is correct for this voice. No outlines, no offset shadows, no sticker confetti. Rotation is for two or three images only, never for text blocks.\",\n  \"seenIn\": [\n   \"aww-warm-fuzzy\",\n   \"aww-aardvark-book-club\",\n   \"opl-uglycash\",\n   \"opl-depo-budget-app\",\n   \"aww-trevor-noah\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"split-stage\",\n  \"name\": \"The split stage\",\n  \"sectors\": [\n   \"restaurant\",\n   \"hospitality\",\n   \"personal-portfolio\",\n   \"physical-product\",\n   \"fashion\",\n   \"real-estate\",\n   \"health\",\n   \"culture\",\n   \"ecommerce\",\n   \"saas\",\n   \"consumer-app\"\n  ],\n  \"tones\": [\n   \"warm\",\n   \"quiet\",\n   \"editorial\"\n  ],\n  \"needs\": [],\n  \"idea\": \"Half the screen never moves. One side is a fixed photograph (or object, or product view) that stays in place for the whole visit; the other side is a calm scrolling column with everything you need to read. The fixed half keeps the feeling present while the reader gets on with the facts, like sitting in the room while reading the menu. As sections pass, the fixed image may quietly change to the one that matches.\",\n  \"composition\": \"Desktop: a two-column page, 50/50 or 45/55. One column is `position: sticky; top: 0; height: 100svh` and holds a single photograph filling it edge to edge, or the object centred on a flat field. The other column scrolls and holds all content in a single narrow measure (max 46ch) with comfortable padding (48–72px): name and one-line description first, then sections separated by generous space, then contact and footer. Headings in the scrolling column are modest (32–44px). The column grounds differ: photograph on one side, flat paper colour on the other, meeting at a clean vertical edge. On a phone the fixed half becomes a 60svh image at the top that stays sticky behind the first section, then releases.\",\n  \"typography\": \"A text-first setting: a readable serif or a calm sans at 17–19px, with one display size for the name. Left-aligned throughout.\",\n  \"typeClasses\": [\n   \"serif-text\",\n   \"serif-display\",\n   \"grotesk-light\",\n   \"slab\"\n  ],\n  \"colour\": \"The paper colour of the reading column is chosen against the photograph: a tone taken from its shadows or its lightest area. One ink, optionally one accent ink for links and the action.\",\n  \"paletteTags\": [\n   \"two-tone\",\n   \"earth\",\n   \"light-neutral\",\n   \"photographic-neutral\"\n  ],\n  \"imagery\": \"One excellent portrait-orientation photograph for the fixed half, plus three or four more that crossfade in as their sections arrive. Small inline photographs in the reading column are optional and should be few.\",\n  \"sectionTags\": [\n   \"quiet\",\n   \"photo-led\",\n   \"type-led\"\n  ],\n  \"motion\": \"slow-crossfade\",\n  \"richness\": \"A full-height photograph always in view, against a quiet, well-set column of text.\",\n  \"pitfalls\": \"The reading column must be genuinely well typeset, since it is half the page. Do not put cards or grids in it. Check that the fixed image crops well at short viewport heights. In blind tests the commonest complaint was monotony: several screens of the same split with only the text changing. Change what the reading half holds from section to section (a list, a large figure, a table, a full-colour panel, a drawing) and let at least one section break the split and run full width.\",\n  \"seenIn\": [\n   \"opl-le-petit-bleu\",\n   \"opl-rafael-derolez-2026\",\n   \"opl-flowjam-2\",\n   \"opl-devonshire\"\n  ],\n  \"allow\": []\n },\n {\n  \"id\": \"dense-tiles\",\n  \"name\": \"The well-kept board\",\n  \"sectors\": [\n   \"agency\",\n   \"studio-portfolio\",\n   \"saas\",\n   \"dev-tool\",\n   \"ai-product\",\n   \"culture\",\n   \"music\",\n   \"other\"\n  ],\n  \"tones\": [\n   \"technical\",\n   \"bold\"\n  ],\n  \"needs\": [],\n  \"idea\": \"The whole page is a board of tiles fitted edge to edge with narrow gaps, like a tidy desk seen from above. Each tile is one thing: the name, a statement, a photograph, a number, a link, a short list. There is no hero and no sequence of bands; the page is one continuous composition that the eye roams. It suits subjects with many small true things to show (a studio with work, writing, clients and news; a product with several distinct capabilities) and it replaces the gen\n\n<!-- [TRUNCATED AT 50KB] -->\n\n<!-- File: skills/taste-skill/library/heroes.json (Tokens: ~13107 | Category: anthropic-skill) -->\n[\n {\n  \"id\": \"name-under-photograph\",\n  \"name\": \"Name under a photograph\",\n  \"archetype\": \"giant-wordmark\",\n  \"directions\": [\n   \"name-as-monument\",\n   \"place-carries-it\",\n   \"dark-room\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A full-bleed photograph fills the top 58% of the 1440×900 viewport, touching the top, left and right edges, `object-fit: cover`, with its focal point in the upper two-thirds. The lower 42% is a flat ground colour that butts against the photograph with no gap. The name runs across this band on one line, spanning all 12 columns between 24px margins, at clamp(120px, 19vw, 300px), tracking -0.05em, line-height 0.85, its baseline 28px above the bottom edge so descenders nearly touch it. Fit the size to the length of the name so it never wraps. In the strip of ground between photograph and name, 24px under the photograph's edge, sits one row at 17px: the supporting sentence on columns 1–5 at the left margin, and the single action as a small solid rectangular button flush to the right margin. Navigation is four text links at 15px laid over the photograph's top-right corner, 24px in, with a neutral scrim behind that row only if the image is light there. No logo is repeated: the name is the logo. Nothing else is on the screen.\",\n  \"mobile\": \"The photograph takes the top 50svh at full width, re-cropped around its focal point. The name sits under it at 23vw on one line; a name longer than seven characters breaks onto two lines at 21vw, line-height 0.85, and fills the band down to a 16px bottom margin. The supporting sentence at 16px and the action button stack above the name on the left margin. The links collapse to one 'Menu' word over the photograph, top-right.\",\n  \"headline\": \"The name itself on one line, up to about 12 characters at 19vw (drop towards 13vw for longer names), and at most two lines on a phone.\",\n  \"motion\": \"scaling-wordmark\",\n  \"seenIn\": [\n   \"aww-house-of-honey-1\",\n   \"opl-kereliott\",\n   \"aww-lxl-creative\"\n  ]\n },\n {\n  \"id\": \"stacked-name-two-inks\",\n  \"name\": \"Stacked name, two inks\",\n  \"archetype\": \"type-poster\",\n  \"directions\": [\n   \"name-as-monument\",\n   \"colour-chapters\",\n   \"type-only-statement\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One saturated flat field covers the whole 1440×900 viewport and there is no image. The name is broken into two lines and set flush left from a 40px margin at clamp(110px, 15vw, 230px), heavy weight, tracking -0.04em, line-height 0.82 so the lines almost touch. The block starts 14% down and fills the top 58% of the screen; the longer line reaches at least column 11. Line one is set in the light ink and line two in the dark ink, so the break reads as a change of voice: split a two-word name between the lines, or break one long name with a hyphen at a syllable. The top edge carries only small text at 15px, 24px in: a monogram top-left, and two or three text links plus the single action as an underlined link top-right. The supporting sentence, 18px in the light ink and max 30ch, is right-aligned in the bottom-right corner on columns 9–12, its last line 40px above the bottom edge. The bottom-left corner stays empty. The next section begins as a different flat field exactly at the fold.\",\n  \"mobile\": \"The field fills 100svh. The name keeps its two lines and two inks at 21vw, flush left at a 16px margin, starting 18% down; a long name hyphenates rather than dropping below 18vw. The supporting sentence moves to the bottom-left at 16px across the full width, with the action as an underlined link beneath it, 24px above the bottom edge. The top-right links reduce to one word.\",\n  \"headline\": \"The name on exactly two lines, one per ink, each line up to about 8 characters at 15vw on desktop and 21vw on a phone.\",\n  \"motion\": \"masked-headline\",\n  \"seenIn\": [\n   \"opl-marina-rachello\",\n   \"opl-anidachi\"\n  ]\n },\n {\n  \"id\": \"photograph-for-a-letter\",\n  \"name\": \"Photograph for a letter\",\n  \"archetype\": \"giant-wordmark\",\n  \"directions\": [\n   \"name-as-monument\",\n   \"sentence-as-layout\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A flat white or pale ground, about 85% empty. The name sits on one line at the exact vertical centre, bold, at clamp(96px, 10.5vw, 168px), tracking -0.04em, spanning 78–88% of the width with equal side margins. One photograph is set into the line as if it were a glyph. Either it fills the word space between first and last name (a landscape frame one x-height tall and about 1.6em wide, resting on the baseline), or it replaces one round letter of a short name (a square frame exactly one cap-height tall). Build the line as an inline-flex row with `align-items: baseline` and size the frame in em so it scales with the type; square corners, `object-fit: cover`. Navigation is small and pushed to the edges: a 15px wordmark or monogram top-left at a 24px margin and up to five text links at 14px spread evenly across the right half of the top edge. Along the bottom edge, on the same margin: one supporting sentence at 16px starting at column 6, and the single action as an underlined text link flush right.\",\n  \"mobile\": \"The name stacks on two centred lines at 19vw with line-height 0.9. The photograph leaves the line and becomes a 3:2 frame at full width minus 16px margins between the two lines, so the screen reads word, picture, word. A single short name keeps the square frame inline at cap height instead. The supporting sentence and action sit under the block at 16px; the links collapse to one word top-right.\",\n  \"headline\": \"The name on one line with a photograph in its word space or in place of one letter, up to about 16 characters at 10.5vw, splitting into two lines on a phone.\",\n  \"motion\": \"shutter-image\",\n  \"seenIn\": [\n   \"aww-paul-kalkbrenner\",\n   \"opl-nia-creative\"\n  ]\n },\n {\n  \"id\": \"name-split-to-corners\",\n  \"name\": \"Name split to corners\",\n  \"archetype\": \"pinned-stage\",\n  \"directions\": [\n   \"pinned-poster\",\n   \"name-as-monument\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"The name is cut into two halves that stay pinned to opposite corners while the page passes between them. A layer with `position: sticky; top: 0; height: 100svh` and `pointer-events: none` holds both: the first word top-left, 28px from the top and left edges; the second word bottom-right, 28px from the bottom and right edges. Both are set at clamp(72px, 9vw, 140px), line-height 0.85, in white with `mix-blend-mode: difference` so they read on every panel beneath. On the first screen the stage between them is a paper-white panel on columns 1–9 and one full-height photograph on columns 10–12 touching the top, right and bottom edges. The supporting sentence, 20px and max 34ch, starts at column 3 at 44% of the height; the single action is a text link with an arrow directly under it. Three text links are stacked at 15px along the right edge of the white panel at mid-height. The rest of the panel is empty. Later panels, full-height photographs and text panels of different widths, scroll under the pinned halves for three to five viewports; then the layer releases into ordinary sections.\",\n  \"mobile\": \"Both halves stay pinned: the first word top-left and the second bottom-right, each at 15vw with 16px margins. Between them every panel is a full-width photograph 56svh tall followed by its sentence at 17px. On the first screen the photograph crosses the middle band with the supporting sentence and the action link beneath it. The stacked links collapse to one word at the top-right corner.\",\n  \"headline\": \"The name in two halves (two words, or one word cut at a syllable), each up to about 9 characters at 9vw, one per corner, with no other headline.\",\n  \"motion\": \"pinned-story\",\n  \"seenIn\": [\n   \"aww-normal-is-boring\",\n   \"aww-the-state-of-the-gallery\",\n   \"aww-milledollars\"\n  ]\n },\n {\n  \"id\": \"pinned-title-over-portraits\",\n  \"name\": \"Pinned title over portraits\",\n  \"archetype\": \"pinned-stage\",\n  \"directions\": [\n   \"pinned-poster\",\n   \"name-as-monument\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A pale flat ground. The title runs on one line of extra-bold uppercase at clamp(90px, 10vw, 160px), centred, spanning about 82% of the width, its cap line 120px from the top. It lives in a sticky layer (`position: sticky; top: 0; height: 100svh`) stacked above the images and set in one saturated ink that reads on both ground and photograph. Beneath it a single portrait photograph, 2:3, sits centred on columns 5–8 (about 37% of the width) and runs from 90px below the top edge down to the bottom edge, so the title crosses its upper quarter and the middle letters sit on the image. The wordmark sits top-left at 24px in 15px bold; one 'Menu' word sits top-right. Bottom-left on columns 1–3: the supporting sentence as a narrow column at 16px bold, max 26ch, its last line 32px above the bottom edge. Bottom-right: the single action as a solid rectangular button. As the page scrolls, further portraits of identical ratio and position replace the first, five to eight in all, each bringing its own flat ground colour sampled from the photograph, before the layer releases.\",\n  \"mobile\": \"The title stays pinned at the top at 17vw on one line, or two lines at 15vw if longer than ten characters. Each portrait becomes full width minus 16px margins at 2:3 and starts behind the lower half of the title. The supporting sentence follows the first portrait at 16px. The action button is fixed to the bottom-right corner, 16px in. The wordmark shrinks to a monogram top-left.\",\n  \"headline\": \"The title of the series, or the name: one uppercase line of up to about 14 characters at 10vw, two short lines on a phone.\",\n  \"motion\": \"pinned-story\",\n  \"seenIn\": [\n   \"opl-city-of-angels\",\n   \"aww-glitch-grit\"\n  ]\n },\n {\n  \"id\": \"sentence-with-photo-strip\",\n  \"name\": \"Sentence with a photo strip\",\n  \"archetype\": \"inline-media-sentence\",\n  \"directions\": [\n   \"sentence-as-layout\",\n   \"place-carries-it\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A warm flat ground with no navigation bar. One sentence of four or five words runs as a single line of condensed capitals at clamp(120px, 13vw, 200px), sitting on the vertical centre and reaching edge to edge inside 28px margins. Where one word of the sentence would be, a strip of photograph takes its place: a frame exactly one cap-height tall (set in em) and 45–50% of the viewport wide, ratio near 5:1, corners radiused 14px, `object-fit: cover`. Build the line as a flex row with `align-items: baseline` and give the strip `flex: 1` so words and picture always fill the width. The photograph shows the thing the sentence names: a wide view of the place, taken from above or along a horizon, so it survives the letterbox crop. The top third of the screen is empty apart from a 15px wordmark top-left and two text links top-right. About 150px under the sentence the single action sits centred as a small solid button. One supporting sentence at 22px, max 44ch, is centred 48px above the bottom edge.\",\n  \"mobile\": \"The sentence breaks into two lines at 21vw with the strip between them: the first words, then the photograph as a 2:1 frame at full width minus 16px margins with the same 14px corners, then the remaining words. The block is centred vertically. The action button sits 32px under the last line and the supporting sentence under that at 16px. The top links collapse to one word.\",\n  \"headline\": \"A sentence of four or five short words, about 14 characters of type in total, whose missing word is the photograph.\",\n  \"motion\": \"shutter-image\",\n  \"seenIn\": [\n   \"aww-colonia-zacamil\"\n  ]\n },\n {\n  \"id\": \"sentence-split-by-frame\",\n  \"name\": \"Sentence split by a frame\",\n  \"archetype\": \"inline-media-sentence\",\n  \"directions\": [\n   \"sentence-as-layout\",\n   \"pinned-poster\",\n   \"product-performs\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A white or pale ground. One short sentence is broken in two and pushed to the edges: the first half flush to the 32px left margin, the second half flush to the right margin, both on the vertical centre line at clamp(40px, 3.6vw, 60px), medium weight. Between them, dead centre on columns 5–8, sits one media frame: 35% of the viewport wide, 16:9, corners 4px, holding a photograph or a working fragment of the product. The frame belongs to a vertical reel: the bottom 60px of the previous frame shows at the top edge of the viewport and the top 60px of the next at the bottom edge, same width, 24px gaps, so the centre column reads as a strip passing through the sentence. The stage is sticky; the reel advances three or four steps while the two halves of the sentence hold their place. Wordmark top-left; three text links and the single action as a small solid button top-right, all at 15px. Bottom-left on columns 1–4: one supporting sentence at 18px, its last line 32px above the bottom edge. The other corners stay empty.\",\n  \"mobile\": \"The halves stack: the first half of the sentence at 9vw flush left under the wordmark, then the frame at full width minus 16px margins and 4:3, then the second half flush right at 9vw. The neighbouring frames show as 28px slivers above and below. The supporting sentence and the action button follow at 16px. The links collapse to one word.\",\n  \"headline\": \"One sentence of four to six words split into two halves of up to about 14 characters each; the frame between them shows what it is about.\",\n  \"motion\": \"pinned-story\",\n  \"seenIn\": [\n   \"aww-made-with-gsap-1\",\n   \"aww-artem-shcherbakov\"\n  ]\n },\n {\n  \"id\": \"headline-across-two-fields\",\n  \"name\": \"Headline across two fields\",\n  \"archetype\": \"colour-field\",\n  \"directions\": [\n   \"colour-chapters\",\n   \"sentence-as-layout\",\n   \"type-only-statement\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"The viewport is two flat fields meeting at exactly half height: paper above, one saturated colour below, with a hard edge and nothing drawn on it. A two-line headline in black-weight capitals at clamp(96px, 9.5vw, 150px), line-height 0.86, is centred across the seam and spans about 70% of the width, so line one stands on the upper field and line two is cut through its upper third by the seam. The type changes ink where it crosses: above the seam it takes the accent ink, below it a deep ink two steps darker than the lower field, as if submerged. Build it as two stacked copies of the same headline, one per ink, the first clipped with `clip-path: inset(0 0 50% 0)` and the second with `inset(50% 0 0 0)`. Wordmark top-left at 28px; up to four text links and the single action, a solid rectangular button, top-right. One supporting sentence at 20px in the paper colour is centred on the lower field, 56px above the bottom edge. The lower field continues for 30svh past the fold before the next colour begins.\",\n  \"mobile\": \"The same two fields with the seam at 46svh. The headline stays on two lines at 15vw, centred, still cut by the seam and still changing ink. Wordmark top-left and the action button top-right; the links drop into one menu word beside it. The supporting sentence sits on the lower field at 16px, centred, max 28ch, with 40px beneath it.\",\n  \"headline\": \"A statement of two to four words on two lines, up to about 10 characters per line, whose meaning the rising field acts out.\",\n  \"motion\": \"colour-on-scroll\",\n  \"seenIn\": [\n   \"opl-juggle\"\n  ]\n },\n {\n  \"id\": \"swatch-column-beside-view\",\n  \"name\": \"Swatch column beside the view\",\n  \"archetype\": \"split\",\n  \"directions\": [\n   \"colour-chapters\",\n   \"place-carries-it\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A 10px frame of paper colour surrounds the screen. Columns 1–10 are one photograph panel, full height inside the frame, corners radiused 12px, `object-fit: cover`: a wide, calm view with a low horizon and a great deal of sky. The headline is centred in the panel's upper third on two lines of light-weight serif at clamp(72px, 8.6vw, 132px), white, with a neutral scrim behind that band only if the sky is pale. The wordmark sits top-left inside the panel, 28px in. The single action, a white rectangular button, sits bottom-centre, 36px above the panel's lower edge; one supporting sentence at 18px sits bottom-left on columns 1–4, level with it. Columns 11–12 are both the navigation and a preview of the page: a full-height stack of five flat colour blocks of equal height, butted together with no gaps, each holding one text link at 16px in its top-left corner with 20px padding. The five colours are sampled from the photograph, ordered light to dark, and each is the ground colour of the section its link scrolls to. There is no other navigation.\",\n  \"mobile\": \"The photograph panel takes the top 64svh inside an 8px frame, with the headline at 12vw on two lines in its upper third and the action button at its bottom-centre. The swatch column becomes five full-width bars, each 52px tall with its link at 15px, stacked directly under the panel; the first three show above the fold. The supporting sentence moves into the first section.\",\n  \"headline\": \"A two-line statement of three to five words, up to about 14 characters per line at 8.6vw, set over the sky.\",\n  \"motion\": \"colour-on-scroll\",\n  \"seenIn\": [\n   \"aww-seasats\"\n  ]\n },\n {\n  \"id\": \"film-title-on-bottom-edge\",\n  \"name\": \"Film title, bottom edge\",\n  \"archetype\": \"bottom-anchored-type\",\n  \"directions\": [\n   \"place-carries-it\",\n   \"name-as-monument\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One photograph fills the viewport at 100vw by 100svh, `object-fit: cover`, with its subject in the upper two-thirds and a calmer, darker zone along the bottom. The name is one condensed uppercase word, or a short name in a high-contrast serif, set at clamp(150px, 17.5vw, 290px) and sized to span the full width between 32px margins. It is centred and anchored so its baseline sits 34px above the bottom edge, covering roughly the lowest quarter of the frame. A soft neutral dark scrim lies under that bottom band only, about 40% of the height; the rest of the image is untouched. Directly above the name's left end, on the same margin, sits the supporting sentence at 16px on two short lines. Directly above its right end, right-aligned, sits the single action as a small paper-coloured rectangular button. The top edge carries a small emblem or wordmark at the left margin and up to five text links at 15px grouped at the right, all in white. The central half of the screen belongs to the view.\",\n  \"mobile\": \"The photograph is re-cropped to portrait with `object-position` on its subject and fills 100svh. The name stays on the bottom edge at 22vw on one line, or two lines at 20vw beyond eight characters, 20px above the edge. The supporting sentence sits above the name's left end at 15px. The action button moves to the top-right corner and the links collapse to a menu word beside the emblem.\",\n  \"headline\": \"The name of the place: one word of up to about 12 characters at 17.5vw, or two words stacked on a phone.\",\n  \"motion\": \"slow-crossfade\",\n  \"seenIn\": [\n   \"aww-white-desert\",\n   \"opl-eagles-nest\"\n  ]\n },\n {\n  \"id\": \"small-name-open-sky\",\n  \"name\": \"Small name, open sky\",\n  \"archetype\": \"fullbleed-media\",\n  \"directions\": [\n   \"place-carries-it\",\n   \"uneven-photographs\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A single photograph fills the viewport edge to edge with no frame: choose one whose upper 45% is sky, wall or water with nothing in it and whose subject sits low and off-centre. All type is white and stays out of that empty zone. Top-left at a 24px margin, the name is stacked on two or three lines at 14px, like a letterhead. Top-right, three or four text links run in one line at 14px separated by commas, the current one marked by a 2px underline. Bottom-left, 32px from the left and bottom edges, the name repeats as the only larger type: two tight lines at clamp(44px, 4.2vw, 64px), line-height 1.0, regular weight, on columns 1–5. On the same baseline at the bottom-right margin sits the single action as an underlined text link with an arrow, and above it one supporting sentence at 15px, right-aligned, max 32ch. If a lower corner is too bright for white type, darken that corner alone with a neutral scrim. The page below opens on plain paper with one narrow paragraph and wide empty margins.\",\n  \"mobile\": \"The photograph is cropped to portrait around its subject and fills 100svh, its upper half still empty. The small stacked name stays top-left at 13px and the links collapse to one word top-right. The larger name sits bottom-left at 9.5vw on two lines, 20px in. The supporting sentence and the underlined action stack beneath it at 15px, left-aligned, 24px above the bottom edge.\",\n  \"headline\": \"The name set small on two lines of up to about 16 characters each at 4.2vw; the photograph does the work of a headline.\",\n  \"motion\": \"slow-crossfade\",\n  \"seenIn\": [\n   \"aww-kononenko-architectural-bureau\",\n   \"aww-julien-calot\",\n   \"aww-depo-luxe\"\n  ]\n },\n {\n  \"id\": \"invitation-card-cropped\",\n  \"name\": \"Invitation card, cropped\",\n  \"archetype\": \"artefact\",\n  \"directions\": [\n   \"page-is-the-object\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A flat field of one soft colour fills the viewport. Centred on it is a single portrait card in paper colour, 5:7, on columns 4–9, its top edge 190px down and its lower third cut off by the bottom of the viewport, so the page visibly continues as the rest of the card. The card is a filled shape with scalloped inner corners, made with `clip-path` or with four corner circles in the field colour, and no outline. Inside, with 56px padding, everything is centred and symmetrical like letterpress stationery. The two names, or the title, are set in a large italic serif at clamp(56px, 5.6vw, 88px) on two lines, staggered so line one sits left of centre and line two right. Between and beneath them, date, time and place appear as short lines at 15px in sentence case, separated by space and by one solid 10px diamond. The top row sits on the field above the card at 28px margins: a small monogram top-left, three text links centred, and the single action, a solid rectangular button in the ink colour, top-right.\",\n  \"mobile\": \"The card becomes full width minus 12px margins, starts 96px down and is still cropped by the bottom edge, with its scalloped top corners kept. The names stay on two lines at 12vw, centred without the stagger, and the details follow at 15px. The monogram sits top-left and the action button top-right on the field; the three links move onto the card's lower part, below the fold.\",\n  \"headline\": \"The two names or the title on two lines, up to about 12 characters per line, set as they would be printed on the card.\",\n  \"motion\": \"curtain-footer\",\n  \"seenIn\": [\n   \"opl-sarah-matt-wedding\"\n  ]\n },\n {\n  \"id\": \"card-over-dim-room\",\n  \"name\": \"Card over a dim room\",\n  \"archetype\": \"artefact\",\n  \"directions\": [\n   \"page-is-the-object\",\n   \"pinned-poster\",\n   \"dark-room\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A full-bleed, low-key photograph of the room fills the viewport, darkened with `filter: brightness(0.7)` so it reads as atmosphere. Centred over it is one square-cornered panel in a flat warm tone taken from the photograph: columns 4–10, about 55% of the width and 62% of the height, a filled programme card with 32px padding. Along its top edge the three words of the title are spread to the left, centre and right in bold condensed capitals at clamp(28px, 2.5vw, 38px); that line is the headline. Under it sit two left-aligned blocks in the same face and size, line-height 1.0: the facts (date, time, place) as three short lines, then one supporting sentence held to 30ch. Along the card's bottom edge: a credit at left in 14px, the single action as a solid rectangular button in the centre, one text link at right. There is no navigation outside the card. The card is `position: sticky`: as the page scrolls it shrinks with `transform: scale` toward the bottom-left corner and stays there as a ticket-sized stub while photographs of differing sizes pass on a flat ground.\",\n  \"mobile\": \"The photograph fills 100svh and the card sits centred at full width minus 16px margins, 70svh tall. The title words stack as a two-line heading at 9vw at the card's top-left. The facts and the supporting sentence follow at 5.2vw in the condensed face. The action button spans the card's bottom edge. On scroll the card shrinks to a 120px stub pinned bottom-left.\",\n  \"headline\": \"The event or venue name, three words at most and up to about 8 characters each, spread across the card's top edge; two lines on a phone.\",\n  \"motion\": \"pinned-story\",\n  \"seenIn\": [\n   \"opl-the-deep-end\"\n  ]\n },\n {\n  \"id\": \"tabbed-folder-stack\",\n  \"name\": \"Tabbed folder stack\",\n  \"archetype\": \"artefact\",\n  \"directions\": [\n   \"page-is-the-object\",\n   \"one-motif\",\n   \"colour-chapters\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A dark flat ground. A slim top row at 24px holds the wordmark dead centre and one text link far right at 15px. The headline is one centred line of heavy condensed capitals at clamp(96px, 10vw, 160px), spanning about 70% of the width, its cap line 110px from the top. Under it one supporting sentence in a serif at 20px, centred, max 46ch. From 51% of the height down the screen is a stack of five file folders: flat colour bands 86% of the viewport wide, centred, each offset 64px below the one behind so only a strip of the back four shows. Every folder has one trapezoid tab rising 40px from its top edge, cut with `clip-path: polygon()`, at its own horizontal position and in its own colour, holding one section name at 18px. The front folder is open and runs off the bottom edge; it carries the single action as a solid button at its top-left with 32px padding. Each folder links to its section and lends that section its ground colour. The tab shape returns as the button's top corners.\",\n  \"mobile\": \"The headline sits 96px down at 17vw on one line, or two at 15vw, centred, with the supporting sentence at 16px beneath. The folder stack starts at 48svh at full width: bands offset 52px, tabs 32px tall with names at 15px, staggered left, centre and right. The front folder runs off the bottom with the action button at full width inside it.\",\n  \"headline\": \"The name or a two-word statement on one line of up to about 12 characters at 10vw; two lines allowed on a phone.\",\n  \"motion\": \"index-preview\",\n  \"seenIn\": [\n   \"aww-mosbys-files\",\n   \"opl-medium-rare\"\n  ]\n },\n {\n  \"id\": \"striped-card-beside-room\",\n  \"name\": \"Striped card beside the room\",\n  \"archetype\": \"split\",\n  \"directions\": [\n   \"one-motif\",\n   \"page-is-the-object\",\n   \"split-stage\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"The viewport is split 50/50 with a 12px gap and 12px outer margins. The right half is one full-height photograph of the room, corners radiused 16px, `position: sticky` so it stays in view while the left half scrolls. The left half is a printed card: a flat paper-colour panel with the same 16px radius, and the subject's stripe (from its awning, label or ribbon) as the only ornament. Across the card's top runs a band 56px tall made of alternating bars of the single ink colour and paper, each bar 28px wide, built as a flex row of filled blocks. The same stripe returns as an 8px band above the footer and inside the button on hover. Under the band, centred: the wordmark about 300px wide, then a two-line headline in a light serif at clamp(40px, 3.6vw, 56px) in the ink colour, one supporting sentence at 17px held to 36ch, and the single action as a solid rectangular button. Three text links sit in one centred row at 15px, 28px above the card's bottom edge. One ink on paper; the photograph supplies every other colour.\",\n  \"mobile\": \"The photograph comes first at full width inside 12px margins, 48svh tall, with the 16px radius. The card follows and overlaps the photograph's bottom edge by 24px using a negative margin. Its striped band is 40px tall; below it the wordmark at 56% width, the headline at 8vw on two lines, the sentence and the button, all centred. The links wrap into the card's foot.\",\n  \"headline\": \"A warm two-line welcome of three to six words, up to about 18 characters per line at 3.6vw.\",\n  \"motion\": \"slow-crossfade\",\n  \"seenIn\": [\n   \"opl-le-petit-bleu\",\n   \"opl-zara-webb\"\n  ]\n },\n {\n  \"id\": \"giant-cropped-shape\",\n  \"name\": \"Giant cropped shape\",\n  \"archetype\": \"colour-field\",\n  \"directions\": [\n   \"one-motif\",\n   \"colour-chapters\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A plain ground with one flat shape at enormous scale. The shape is the simplest geometry found in the subject (a circle, a ring segment, a chamfered block, an arch), drawn in CSS or as a single inline SVG path and filled with the accent colour. It is about 120vh across and enters from the right, centred near 78% of the width and 55% of the height, so the top, right and bottom edges of the viewport crop it and its left boundary reaches column 7. If the subject has a true pair (two accounts, two modes), a second shape in a second flat colour overlaps the first by a quarter with `mix-blend-mode: multiply`. The headline sits on the bare ground on columns 1–6, vertically centred, flush left at 8% from the left edge: two lines at clamp(64px, 6.4vw, 100px), heavy weight, tracking -0.03em. Beneath it comes one supporting sentence at 19px, then the single action as a solid button cut to the same shape. A bold wordmark sits top-left at 32px; up to three text links sit top-right in the ground colour.\",\n  \"mobile\": \"The shape moves to the bottom: 130vw across, centred horizontally, its top at 56svh, cropped by the left, right and bottom edges. The headline sits above it at 11.5vw on two lines at a 16px margin, starting 15% down, with the sentence at 16px and the motif-shaped button beneath. Wordmark top-left; the links collapse to one word top-right.\",\n  \"headline\": \"Two lines of two or three words each, up to about 12 characters per line at 6.4vw.\",\n  \"motion\": \"shutter-image\",\n  \"seenIn\": [\n   \"opl-tara\",\n   \"opl-superlocal-2026\",\n   \"aww-sstr-friction-reduction\"\n  ]\n },\n {\n  \"id\": \"fragment-on-shaped-stage\",\n  \"name\": \"Fragment on a shaped stage\",\n  \"archetype\": \"split\",\n  \"directions\": [\n   \"product-performs\",\n   \"one-motif\",\n   \"colour-chapters\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A neutral ground. The headline occupies the upper-left third: two lines at clamp(52px, 5.2vw, 80px), medium weight, flush left on columns 1–6 at a 40px margin, starting 150px down. One supporting sentence at 18px, max 40ch, follows, then the single action as a small rectangular button. The rest of the screen belongs to one flat stage in a saturated colour: it spans columns 5–12, begins 42% down, and bleeds off the right and bottom edges. Its top-left corner is cut with the product's own shape using `clip-path` (a notch, a chamfer or a tab two columns wide), the only decoration on the page. On the stage, 56px in from its left and top edges, sits the main fragment of the interface at true size with labels at 13–15px, built in HTML and working: one panel or control about 620px wide, cropped by the bottom edge, never a whole window and never inside a browser or laptop frame. Mark its root with data-ui. Navigation is a plain row at 28px from the top: wordmark left and four text links right at 15px. Nothing overlaps the headline.\",\n  \"mobile\": \"The headline sits under the wordmark at 10vw on two lines, followed by the sentence at 16px and the button. The stage comes next at full width, bleeding off both sides and the bottom, its corner cut kept at 72px wide. The fragment sits 16px inside it at true size; if it is wider than the screen the right edge crops it rather than scaling it down.\",\n  \"headline\": \"A plain statement of what the product does in three to six words, two lines of up to about 16 characters each at 5.2vw.\",\n  \"motion\": \"shutter-image\",\n  \"seenIn\": [\n   \"opl-typewave\",\n   \"opl-vessa\",\n   \"opl-uni\"\n  ]\n },\n {\n  \"id\": \"control-reads-the-page\",\n  \"name\": \"Control that reads the page\",\n  \"archetype\": \"split\",\n  \"directions\": [\n   \"product-performs\",\n   \"quiet-instrument\",\n   \"dark-room\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A near-black or deep neutral ground split into two halves by tone alone: the right half is one step lighter than the left, and they meet at a clean vertical edge at 50%. Left half: a small logo mark top-left at a 40px margin, then two-thirds of empty ground, then everything else anchored bottom-left, 40px from the edges: a one-line headline at clamp(26px, 2.1vw, 32px) in medium weight, one supporting sentence at 17px in the softer ink held to 44ch, and the single action as a light rectangular button. Right half: one fragment of the product, centred, about 450px square, built in HTML and working. It is the product's defining control (a loupe, a picker, a dial, a field) and it acts on the page itself: it reads the real background colour, the real headline size or the pointer position and prints that value in its own readout at 13px. Mark its root with data-ui so the product's own radii and borders apply inside it. There is no navigation bar; one text link sits top-right at 15px.\",\n  \"mobile\": \"The halves stack as two tones. The fragment comes first: 78vw square, centred in the lighter block, which is 58svh tall, still live and reading the page under the visitor's finger. The darker block below holds the headline at 6.4vw on up to two lines, the sentence at 16px and the button, left-aligned at 20px. The logo mark sits top-left over the first block.\",\n  \"headline\": \"One plain line at 26–32px naming what the tool is, up to about 32 characters, wrapping to two lines on a phone.\",\n  \"motion\": \"masked-headline\",\n  \"seenIn\": [\n   \"opl-dabbit\"\n  ]\n },\n {\n  \"id\": \"controls-on-the-sentence\",\n  \"name\": \"Controls on the sentence\",\n  \"archetype\": \"type-poster\",\n  \"directions\": [\n   \"product-performs\",\n   \"sentence-as-layout\",\n   \"type-only-statement\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A dark flat ground with no logo bar: a 14px wordmark top-left and the single action as an underlined text link top-right, both 28px in. The headline is a two-line sentence, centred, at clamp(96px, 9vw, 150px), line-height 1.0, occupying the middle 64% of the width and sitting slightly above the midline. It is set in a variable font and it is the demonstration. Three small control chips from the product sit on top of the sentence, each about 300 by 80px with the product's true radius, a text label and a numeric readout: one above the first line near its left end, one overlapping the start of the second line, and a two-state switch at the lower right. They are tilted 2 to 4 degrees and filled solid, one step lighter than the ground. Each one works: dragging the first changes the headline's weight through `font-variation-settings`, the second changes its letter-spacing, the third toggles uppercase. Mark each chip's root with data-ui. One supporting sentence at 17px, max 40ch, is centred 72px under the headline. The bottom third of the screen stays empty.\",\n  \"mobile\": \"The sentence stays on two lines at 13.5vw, centred at 38% of the height. The three chips shrink to 200 by 60px and move off the letters: one above the sentence and two side by side beneath it, untilted and still live. The supporting sentence follows at 16px. The wordmark stays top-left and the action link top-right.\",\n  \"headline\": \"A two-line sentence of three to five words, up to about 11 characters per line at 9vw, that still reads when its weight and spacing change.\",\n  \"motion\": \"masked-headline\",\n  \"seenIn\": [\n   \"opl-dialkit\"\n  ]\n },\n {\n  \"id\": \"column-on-one-line\",\n  \"name\": \"Column on one line\",\n  \"archetype\": \"quiet-column\",\n  \"directions\": [\n   \"quiet-instrument\",\n   \"product-performs\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A warm off-white page that is more than 80% empty. Everything hangs on one vertical alignment 27% in from the left edge, the start of column 4; nothing is centred and nothing sits to its left. A small logo mark sits on that alignment 56px from the top. About 220px lower the column begins, only 380px wide: a two-line headline at 27px in medium weight, line-height 1.25; one supporting sentence at 15px in the softer ink, line-height 1.5; then, 28px below, the single action as a near-black rectangular button with 4px corners and one text link with an arrow beside it. A sign-in text link sits alone in the top-right corner at 14px; there is no navigation bar. At the bottom edge the first demonstration peeks in on the same alignment: a flat panel one step darker than the page, 368px wide, its top 90px visible, holding two real rows of the product's interface at true size with a visible pointer. Mark the panel's root with data-ui. The right half of the screen is blank on purpose, and nothing spans the full width until the footer.\",\n  \"mobile\": \"The alignment becomes the 24px left margin. The logo mark sits 32px from the top and the column starts at 30% of the height: headline at 24px on two lines, the sentence at 15px, then button and text link side by side. The demonstration panel spans the width between the margins and shows its top 120px above the fold. The sign-in link stays top-right.\",\n  \"headline\": \"A dry two-line statement at 27px, up to about 30 characters per line; it never grows larger at any width.\",\n  \"motion\": \"slow-crossfade\",\n  \"seenIn\": [\n   \"opl-rows\",\n   \"opl-lovably\"\n  ]\n },\n {\n  \"id\": \"single-object-on-plinth\",\n  \"name\": \"Single object on a plinth\",\n  \"archetype\": \"object-centre\",\n  \"directions\": [\n   \"quiet-instrument\",\n   \"hero-object\",\n   \"specimen-catalogue\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"blueprint\": \"An off-white screen that is about 80% empty and does not need to scroll. One photographed object stands dead centre: a studio shot on a plain background, shown 440px tall (about half the viewport height) whatever its width, with `mix-blend-mode: multiply` so its backdrop disappears into the page. It rests on a plinth, a rounded square 520px across filled one step lighter than the page and centred behind it, with no border. The wordmark sits top-left at a 56px margin in a heavy serif or grotesk, about 400px wide (28% of the viewport) and 80px tall; it is the only large type. Opposite it, top-right on the same margin and aligned to the wordmark's top, sits the one supporting sentence at 15px, right-aligned, max 36ch. Centred 40px under the plinth is the single action: a compact email field or button 240px wide with 8px corners. Further objects replace the first in the same position by crossfade, each scaled to the same visual mass. There is no navigation. Nothing else touches the edges, and the object never grows beyond half the viewport height.\",\n  \"mobile\": \"The wordmark sits top-left at 44vw wide with 20px margins and the supporting sentence drops beneath it at 14px. The plinth is 78vw square, centred at 54% of the height, with the object 44svh tall on it. The action sits 32px under the plinth, 40px in from each side. The screen stays mostly empty and the objects swap in place.\",\n  \"headline\": \"None beyond the name: the wordmark top-left, up to about 10 characters, is the only large type and the object is the statement.\",\n  \"motion\": \"slow-crossfade\",\n  \"seenIn\": [\n   \"opl-archiv\",\n   \"opl-humanoid-index\"\n  ]\n },\n {\n  \"id\": \"object-crops-three-edges\",\n  \"name\": \"Object cropped by three edges\",\n  \"archetype\": \"object-centre\",\n  \"directions\": [\n   \"hero-object\",\n   \"loud-flat-poster\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"blueprint\": \"A flat off-white or single bold colour field with no navigation bar: only a small wordmark top-right at 24px and the single action fixed bottom-right as a solid rectangular button. The left 60% of the screen is one object photographed on a plain background and scaled far past its container. Set the image to about 150% of the hero's height, rotate it 10 to 20 degrees and position it so the top, left and bottom edges of the viewport all crop it and only its right-hand third is fully inside; use `overflow: hidden` on the section and `mix-blend-mode: multiply` if the field is light. The headline fills the right half: two stacked lines of very bold lowercase at clamp(120px, 13vw, 210px), right-aligned 16px from the right edge, tracking -0.05em, line-height 0.86, vertically centred. It sits behind the object in the stacking order, so the object's right-hand contour tucks over the first one or two letters of each line. One supporting sentence at 18px, max 28ch, is right-aligned under the headline on columns 9–12. Nothing else is on the screen: no second image, no list.\",\n  \"mobile\": \"The object moves to the top: the image is 150vw wide, rotated, cropped by the top, left and right edges, and occupies the upper 52svh. The headline sits below it at 19vw on two lines, right-aligned at a 12px margin, its first line overlapped by the object's lower contour. The supporting sentence follows at 16px, right-aligned. The action button stays fixed bottom-right.\",\n  \"headline\": \"Two lines of one or two short words each, up to about 8 characters per line at 13vw, partly tucked behind the object.\",\n  \"motion\": \"shutter-image\",\n  \"seenIn\": [\n   \"opl-when-you-wish-upon-a-starboy\"\n  ]\n },\n {\n  \"id\": \"object-splits-the-headline\",\n  \"name\": \"Object splits the headline\",\n  \"archetype\": \"object-centre\",\n  \"directions\": [\n   \"hero-object\",\n   \"sentence-as-layout\",\n   \"dark-room\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"blueprint\": \"One deep, flat ground colour. The object, a low-key studio photograph whose background matches the ground, stands at dead centre, scaled to 66% of the viewport height and tilted about 8 degrees, with its base cropped by the bottom edge. The headline is split around it: line one is centred across the object's upper fifth and line two across its lower fifth, both at clamp(64px, 5.8vw, 92px), regular weight, spanning columns 2–11, so the object fills the gap where a paragraph would normally sit. The type lies above the object in the stacking order in the light ink, so every letter stays readable where it crosses. At the object's mid-height two small text blocks at 14px face each other: the supporting sentence far left on columns 1–2, and two short facts (size, price) far right on columns 11–12, right-aligned, each 32px from its edge. Wordmark top-left; three text links top-centre; the single action top-right as a small light rectangular tab, the only light solid on the screen. The lower corners stay dark and empty.\",\n  \"mobile\": \"The object is 54svh tall, centred, its base cropped by the bottom edge. Line one of the headline crosses its top at 11vw and line two its lower third at 11vw, both centred inside 16px margins. The side text blocks merge into one 15px sentence under the navigation. Wordmark top-left and the action tab top-right; the links collapse to one word.\",\n  \"headline\": \"A two-line statement of four to six words, up to about 16 characters per line at 5.8vw, with the object standing between the lines.\",\n  \"motion\": \"slow-crossfade\",\n  \"seenIn\": [\n   \"aww-zeroz-brand-site\",\n   \"aww-moto-finance\"\n  ]\n },\n {\n  \"id\": \"object-on-the-seam\",\n  \"name\": \"Object on the seam\",\n  \"archetype\": \"object-centre\",\n  \"directions\": [\n   \"hero-object\",\n   \"quiet-instrument\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"blueprint\": \"A white or very pale page organised by one change of tone. A square-cornered panel one step darker than the page (a flat pale blue-grey or warm grey) fills the top 44% of the viewport inside 12px margins; the page colour runs below it. The object, photographed on a plain background and blended with `mix-blend-mode: multiply`, straddles the seam between the two tones: it is about 62% of the viewport wide, starts at column 6 and runs off the right edge, with its upper half over the panel and its lower half over the page. Type is small and exact. The headline is two lines at 24px in medium weight, far left on columns 1–3 at a 32px margin, its first baseline resting exactly on the seam; the second line is set in the softer ink. One supporting sentence at 15px, max 34ch, sits 120px lower on the same margin with the single action as a small rectangular button under it. A plain top row inside the panel at 14px: wordmark left, three text links centred, one text link right.\",\n  \"mobile\": \"The tonal panel takes the top 46svh. The object is 120vw wide, centred on the seam and cropped by the right edge. The headline sits just under the seam at 22px on two lines at a 20px margin, with the sentence at 15px beneath and then the button. The wordmark sits top-left inside the panel; the links collapse to one word top-right.\",\n  \"headline\": \"Two short sentences at 24px, one per line and up to about 28 characters each, the second in the softer ink.\",\n  \"motion\": \"shutter-image\",\n  \"seenIn\": [\n   \"opl-aevion\"\n  ]\n },\n {\n  \"id\": \"statement-beside-specimen-mosaic\",\n  \"name\": \"Statement beside specimen mosaic\",\n  \"archetype\": \"mosaic\",\n  \"directions\": [\n   \"specimen-catalogue\",\n   \"split-stage\",\n   \"uneven-photographs\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"blueprint\": \"The viewport is split 50/50 by tone alone: the left half is the page ground, the right half a field one step darker, meeting at a clean vertical edge with no line. Left half: the wordmark at 22px sits top-left on a 32px margin; under it the statement at clamp(44px, 4.4vw, 68px), bold, tracking -0.04em, leading 1.0, top-left aligned and filling the upper 40% of the half. The lower part of this side stays empty except for one supporting sentence at 18px pinned bottom-left and the single action as a solid rectangle beside it. Right half: a loose mosaic of seven specimen tiles on a 4-column, 3-row grid with 14px gaps. Each tile is a flat palette colour at 3:4 holding one cut-out item, centred, object-fit: contain, mix-blend-mode: multiply. Five cells are left empty so the tiles stagger; one tile spans two columns and two rows; the rightmost column is cropped by the viewport edge. Two text links sit top-right over the darker field. The right half may be position: sticky while the left scrolls.\",\n  \"mobile\": \"The split becomes a stack. The statement comes first at 10.5vw on two lines inside 20px margins, the supporting sentence under it at 16px, then the action. Below, the darker field runs full width and the mosaic becomes two columns of tiles, the right column started 48px lower than the left; five tiles show and the last row is cropped by the bottom of the screen. Navigation is the wordmark and one link.\",\n  \"headline\": \"A 3-5 word statement of what is on offer, at most 28 characters so it holds two lines at 10.5vw on a phone.\",\n  \"motion\": \"shutter-image\",\n  \"seenIn\": [\n   \"aww-noho\"\n  ]\n },\n {\n  \"id\": \"specimen-wall-docked-panel\",\n  \"name\": \"Specimen wall, docked panel\",\n  \"archetype\": \"tiles\",\n  \"directions\": [\n   \"specimen-catalogue\",\n   \"dense-tiles\",\n   \"contact-sheet\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"blueprint\": \"There is no header and no display headline: the whole viewport is a wall of specimens. Square tiles of about 112px (7.8vw) with 8px gaps fill the screen edge to edge in eight rows; alternate rows shift half a tile sideways so the wall reads as brickwork, and tiles at every edge are cropped by the viewport (overflow: hidden on the section). Each tile is a flat fill, rotating through three palette colours, holding one cut-out item at 60% of the tile, centred, with mix-blend-mode: multiply on light fills. A solid panel in the ink colour, 800px wide (columns 4-9) and about 170px tall with square corners, is docked at the bottom centre, 24px above the bottom edge, covering the tiles behind it. Inside, on 28px padding: the sentence that says what this is at 24px semibold on the left across two lines, the single action as a filled rectangle in the paper colour on the right, and beneath them a row holding the wordmark and four text links at 15px. Nothing else overlays the wall.\",\n  \"mobile\": \"Tiles become 22vw squares with 6px gaps, four and a half per row, still offset as brickwork and cropped at both sides. The panel turns into a full-width block fixed to the bottom of the first screen, about a third of its height: the sentence at 6vw on two lines, the action full width beneath it, the wordmark and links in one wrapped row at 14px. The wall fills everything above.\",\n  \"headline\": \"No display line: one plain sentence of up to 56 characters inside the panel names what the items are.\",\n  \"motion\": \"index-preview\",\n  \"seenIn\": [\n   \"opl-smallbits\",\n   \"opl-beige-force\"\n  ]\n },\n {\n  \"id\": \"single-specimen-name-list\",\n  \"name\": \"Single specimen with name list\",\n  \"archetype\": \"object-centre\",\n  \"directions\": [\n   \"specimen-catalogue\",\n   \"borrowed-category\",\n   \"hero-object\"\n  ],\n  \"needs\": [\n   \"product-photo\"\n  ],\n  \"blueprint\": \"Borrowed from a museum plinth. A calm light ground with roughly 70% left empty. The wordmark is set large for a logo, about 28% of the viewport wide (clamp(64px, 6vw, 92px), heavy serif or grotesk), top-left on a 56px margin; one sentence of description at 15px sits top-right on the same margin, its first line aligned to the top of the wordmark. Dead centre stands one specimen: a flat tile in a palette colour, 400px wide and 460px tall (columns 5-8) with a 16px radius, holding a single cut-out item at about 80% of the tile height, object-fit: contain. Left of the tile, in columns 2-4, a vertical list of item names is right-aligned towards it: the selected name in full ink at 20px, the names above and below stepping down in size and opacity (18, 16, 14px; 60, 35, 15%). Choosing a name swaps the item and the tile colour. Below the tile, centred: the item's one-line fact at 14px, then the single action, a filled rectangle 240px wide. Three text links sit bottom-left at 14px.\",\n  \"mobile\": \"The wordmark sits top-left at 11vw with the description sentence beneath it at 15px. The tile takes the full width inside 20px margins at 4:5, starting at 30% of the height. The name list becomes one horizontal row under the tile that scrolls sideways with scroll-snap, the selected name centred in full ink at 18px. The action sits full width at the bottom of the screen; the links move to the footer.\",\n  \"headline\": \"The name itself as an oversized wordma\n\n<!-- [TRUNCATED AT 50KB] -->\n\n<!-- File: skills/taste-skill/library/motions.json (Tokens: ~2110 | Category: anthropic-skill) -->\n[\n {\n  \"id\": \"masked-headline\",\n  \"name\": \"Masked headline\",\n  \"description\": \"On load, each line of the headline rises from behind its own baseline, about 900ms with a strong ease-out, the second line 110ms after the first; the supporting sentence and the action then fade up together. Nothing else on the page performs. Because headlines are two lines at most, you author the line breaks and wrap each line yourself. Recipe: 'Masked line reveal' in references/motion.md.\"\n },\n {\n  \"id\": \"shutter-image\",\n  \"name\": \"Shutter image\",\n  \"description\": \"The one hero or showcase image opens from an edge with a clip-path over about 1.1 seconds while the picture inside settles from 1.12 scale to rest. Use it once, on the image that matters most; later images simply are there. Recipe: 'Image shutter' in references/motion.md.\"\n },\n {\n  \"id\": \"scaling-wordmark\",\n  \"name\": \"Scaling wordmark\",\n  \"description\": \"The giant name responds to the scroll: as the first screen leaves, the wordmark scales down a few percent (or grows from 0.94 to 1 as the footer arrives) on a scroll-linked timeline, so the monument feels heavy. Travel stays under 8%. Static fallback where scroll timelines are unsupported. Recipe: 'Scroll-linked progress' in references/motion.md, animating `scale`.\"\n },\n {\n  \"id\": \"pinned-story\",\n  \"name\": \"Pinned story\",\n  \"description\": \"One element holds its place with `position: sticky` (a title, a frame, a product fragment) while the items that belong to it scroll past or swap inside it. The page's ordinary scrolling does the work; nothing is hijacked. Hold it for about one screen per step and three screens at most, two held stages per page at most, with a line of text on every held screen. Recipe: 'Pinned story' in references/motion.md.\"\n },\n {\n  \"id\": \"index-preview\",\n  \"name\": \"Index with preview\",\n  \"description\": \"Rows of text are the navigation through the work; pointing at a row brings up its image in one fixed frame and dims the other rows. On touch screens each row shows its image inline instead. Fast and exact (about 240ms crossfade), no lag behind the pointer. Recipe: 'Index with preview, anchored to the row' in references/motion.md.\"\n },\n {\n  \"id\": \"curtain-footer\",\n  \"name\": \"Curtain footer\",\n  \"description\": \"The page content slides up like a sheet to uncover the footer waiting beneath it, so the last screen is revealed rather than scrolled to. Build with a sticky footer at the bottom and a main element with its own background and a higher stacking order. No JavaScript.\"\n },\n {\n  \"id\": \"slow-crossfade\",\n  \"name\": \"Slow crossfade\",\n  \"description\": \"The principal photograph quietly changes: three or four images of the same framing crossfade over about 1.6 seconds, holding five to six seconds each, or the fixed image changes when its matching section arrives. It should feel like light shifting in a room. Pause when the tab is hidden; under reduced motion show only the first image.\"\n },\n {\n  \"id\": \"edge-marquee\",\n  \"name\": \"Edge-to-edge marquee\",\n  \"description\": \"One line of very large type travels sideways across the full width at a slow constant speed, as a band between two sections or as the closing statement. Linear timing, duplicated content for a seamless loop, paused on hover and under reduced motion. One marquee per page, carrying real words (the name, the claim), never a list of buzzwords.\"\n },\n {\n  \"id\": \"drag-row\",\n  \"name\": \"Drag row\",\n  \"description\": \"A row of large items wider than the screen that the visitor pulls sideways: native horizontal scrolling with scroll snapping, the first item aligned to the page margin and the last allowed to run off the edge so the row visibly continues. No carousel library, no arrows, no dots.\"\n },\n {\n  \"id\": \"colour-on-scroll\",\n  \"name\": \"Colour by chapter\",\n  \"description\": \"Each chapter is its own full-bleed field of one palette colour, so the ground changes exactly at section edges as you scroll, never as a global recolouring of the screen. The only movement: the fixed header (or the one pinned element) takes the ink of the chapter beneath it, switching with a 300ms colour transition as each edge passes under it. Do not drive the page background from an observer: in blind tests a page recoloured mid-section, with a paragraph sitting on two colours, read as broken twice.\"\n },\n {\n  \"id\": \"stillness\",\n  \"name\": \"Stillness\",\n  \"description\": \"No showpiece. The page is simply there, instantly, and the discipline is the statement. Motion is limited to exact feedback: a 140ms press on the button, a 180ms colour change on links, focus rings that appear without delay. Do not add a load animation or scroll reveals to this direction.\"\n },\n {\n  \"id\": \"opening-window\",\n  \"name\": \"Opening window\",\n  \"description\": \"A type screen hands over to the one great photograph: the picture first shows as a window about 45% of the width in the middle of a held stage and opens to full-bleed over about one screen of scroll, while the image inside settles from 1.15 scale. Scroll-linked and linear, so the reader sets the pace; it is fully open after three quarters of the hold and rests a moment before the page moves on. Use it once, for the picture that carries the subject. Where scroll timelines are unsupported, or under reduced motion, the picture is simply a full-bleed screen. Recipe: 'Opening window' in references/motion.md.\"\n },\n {\n  \"id\": \"ink-fill\",\n  \"name\": \"Ink-fill statement\",\n  \"description\": \"One statement of three to five lines at 32px or more starts at 45% ink and fills to full ink line by line as it rises from three quarters of the way down the screen to just past half way, so the reading pace follows the scroll. Every word is readable before it fills; the fill only sets the rhythm. Once per page, never on body copy, never on a headline the visitor needs at once. Full ink without scroll timelines or under reduced motion. Recipe: 'Ink fill' in references/motion.md.\"\n },\n {\n  \"id\": \"sheet-over\",\n  \"name\": \"Sheet over a held picture\",\n  \"description\": \"A full-bleed photograph holds its place for one screen and the next chapter, an opaque sheet in the page ground carrying its heading at the top edge, slides up over it like a page being turned. The chapter change is read, not just seen, and nothing is hijacked: the photograph is a 100svh figure with position: sticky; top: 0, followed by a section with its own background and a higher stacking order. Hold for one screen at most, use it at one or two chapter changes, and give each held photograph a caption so the held screen carries a line of text.\"\n },\n {\n  \"id\": \"sideways-gallery\",\n  \"name\": \"Sideways gallery\",\n  \"description\": \"A short set of pictures (eight or fewer: rooms, kitchens, pieces) moves sideways while the vertical scroll holds the stage, one pixel of scroll for one pixel of travel, and the hold ends the moment the last picture reaches the margin. Only on wide screens with motion allowed and only when the row is under three screens long; phones, reduced motion and longer rows get the native drag row with snapping. Focusing a link scrolls its picture into view, and the only copy of a call to action never sits inside the moving row. Recipe: 'Sideways gallery' in references/motion.md.\"\n },\n {\n  \"id\": \"pushed-line\",\n  \"name\": \"Pushed line\",\n  \"description\": \"One line of very large type, the name or the claim, is pushed sideways by the scroll rather than by a clock: it travels from 12% right to 12% left of its place while it crosses the screen, linear and locked to the scrollbar, and reads whole at the middle of its run. One per page, never across running text, and the words must never be cropped at the moment the line sits in the middle of the screen. Build with animation-timeline: view() on the line and a translateX keyframe; static where scroll timelines are unsupported and under reduced motion.\"\n },\n {\n  \"id\": \"rolling-figures\",\n  \"name\": \"Rolling figures\",\n  \"description\": \"For a page whose case is a handful of numbers (a report, a fund, a practice with a founding year): three or four figures at display size roll each digit up to its value once as they come into view, about 1.1 seconds on a strong ease-out, the columns 70ms apart. Tabular figures, the real number kept in the text for screen readers and search, never in running text and never for a value that changes after load. Set at its value under reduced motion. Recipe: 'Rolling figures' in references/motion.md.\"\n },\n {\n  \"id\": \"carried-picture\",\n  \"name\": \"Carried picture\",\n  \"description\": \"Between the index and a case page, the picture the visitor clicked travels into place as the new page's hero while the old page fades out in 200ms and the new one rises in, all within 480ms, using the browser's own cross-document view transitions with no library and no full-screen curtain. Give the card picture and the hero the same view-transition-name; each name appears once per page. Browsers without view transitions simply navigate; reduced motion turns it off. Recipe: 'Page to page' in references/motion.md.\"\n }\n]\n\n<!-- File: skills/taste-skill/library/palettes.json (Tokens: ~12140 | Category: anthropic-skill) -->\n[\n {\n  \"id\": \"white-link-blue\",\n  \"name\": \"Sheet and biro\",\n  \"tags\": [\n   \"light-neutral\",\n   \"mono-accent\"\n  ],\n  \"bg\": \"#ffffff\",\n  \"surface\": \"#f4f4f4\",\n  \"ink\": \"#111111\",\n  \"muted\": \"#6b6b6b\",\n  \"accent\": \"#1a4be0\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#111111\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"White holds the whole page with black type, one grey for secondary lines and a pale grey step for tiles and inputs; the footer may invert to black. Blue is the colour of text links and the one button, and nothing else is tinted.\",\n  \"seenIn\": [\n   \"opl-shawn-golden\",\n   \"opl-lovably\",\n   \"aww-bleibtgleich26\"\n  ]\n },\n {\n  \"id\": \"cool-white-slate\",\n  \"name\": \"Frost and slate\",\n  \"tags\": [\n   \"light-neutral\"\n  ],\n  \"bg\": \"#f7f9fa\",\n  \"surface\": \"#ecf0f2\",\n  \"ink\": \"#1f3038\",\n  \"muted\": \"#5d6b72\",\n  \"accent\": \"#0d7480\",\n  \"accentInk\": \"#ffffff\",\n  \"note\": \"Cool white and one paler blue-grey step hold everything, with type in dark slate instead of black. Teal appears once per screen at most, as the primary button or one small detail beside the product photograph.\",\n  \"seenIn\": [\n   \"opl-aevion\",\n   \"aww-cominvi\"\n  ]\n },\n {\n  \"id\": \"rose-grey-green\",\n  \"name\": \"Rose grey, green\",\n  \"tags\": [\n   \"light-neutral\"\n  ],\n  \"bg\": \"#ebe5e3\",\n  \"surface\": \"#e1dad7\",\n  \"ink\": \"#2b2622\",\n  \"muted\": \"#6a615d\",\n  \"accent\": \"#0f7d45\",\n  \"accentInk\": \"#ffffff\",\n  \"note\": \"A single rosy grey covers the page from top to bottom with brown-black text and grey secondary lines; images are kept greyscale. Green appears only on the current-page link and on one button in the footer.\",\n  \"seenIn\": [\n   \"opl-the-queue\"\n  ]\n },\n {\n  \"id\": \"paper-grey-brass\",\n  \"name\": \"Newsprint and brass\",\n  \"tags\": [\n   \"light-neutral\"\n  ],\n  \"bg\": \"#e8e8e3\",\n  \"surface\": \"#dcdcd6\",\n  \"ink\": \"#181715\",\n  \"muted\": \"#63625c\",\n  \"accent\": \"#bfb21a\",\n  \"accentInk\": \"#181715\",\n  \"fields\": [\n   {\n    \"bg\": \"#181715\",\n    \"ink\": \"#e8e8e3\"\n   }\n  ],\n  \"note\": \"Warm paper grey with near-black type holds the upper page, then whole sections flip to near-black with paper-grey type; no section is tinted. Brass yellow marks one small detail per screen, such as the button or a single word.\",\n  \"seenIn\": [\n   \"aww-monolog\"\n  ]\n },\n {\n  \"id\": \"stone-blueprint\",\n  \"name\": \"Stone and blueprint\",\n  \"tags\": [\n   \"light-neutral\"\n  ],\n  \"bg\": \"#dfdedb\",\n  \"surface\": \"#d3d2ce\",\n  \"ink\": \"#26251e\",\n  \"muted\": \"#5f5d55\",\n  \"accent\": \"#2456d6\",\n  \"accentInk\": \"#ffffff\",\n  \"note\": \"Stone paper carries the whole page with near-black and grey text. One image at a time is printed in the accent blue as its only ink, and the same blue fills the single button.\",\n  \"seenIn\": [\n   \"opl-compile\"\n  ]\n },\n {\n  \"id\": \"white-navy-tab\",\n  \"name\": \"Navy on white\",\n  \"tags\": [\n   \"light-neutral\",\n   \"photographic-neutral\"\n  ],\n  \"bg\": \"#ffffff\",\n  \"surface\": \"#f4f4f2\",\n  \"ink\": \"#1f2b4d\",\n  \"muted\": \"#6a7186\",\n  \"accent\": \"#f7941d\",\n  \"accentInk\": \"#1f2b4d\",\n  \"fields\": [\n   {\n    \"bg\": \"#05070a\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#e3e1dc\",\n    \"ink\": \"#1f2b4d\"\n   }\n  ],\n  \"note\": \"Pure white pages with navy type sit between full-bleed photographs, opening on near-black and closing on a warm grey footer. Tangerine is one small tab or button, never larger than a thumbnail.\",\n  \"seenIn\": [\n   \"aww-white-desert\",\n   \"aww-realevate\"\n  ]\n },\n {\n  \"id\": \"three-stones\",\n  \"name\": \"Three stones\",\n  \"tags\": [\n   \"light-neutral\",\n   \"photographic-neutral\"\n  ],\n  \"bg\": \"#eeecea\",\n  \"surface\": \"#e4e1dd\",\n  \"ink\": \"#333231\",\n  \"muted\": \"#6b6763\",\n  \"accent\": \"#5c6b54\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#cdc3b6\",\n    \"ink\": \"#333231\"\n   }\n  ],\n  \"note\": \"Three close stone tones share the interface: the lightest for the page, the middle one for panels, the darkest for a single band, all with charcoal type. Saturated colour is left to the photographs and their backdrops; the grey-green fills the button only.\",\n  \"seenIn\": [\n   \"aww-noho\",\n   \"aww-vero-new-york\"\n  ]\n },\n {\n  \"id\": \"putty-black-teal\",\n  \"name\": \"Putty and black\",\n  \"tags\": [\n   \"light-neutral\",\n   \"photographic-neutral\"\n  ],\n  \"bg\": \"#dedad3\",\n  \"surface\": \"#d3cec6\",\n  \"ink\": \"#0a0a0a\",\n  \"muted\": \"#5c5852\",\n  \"accent\": \"#256f82\",\n  \"accentInk\": \"#ffffff\",\n  \"note\": \"Warm putty covers the page and pure black handles all type and the main shapes. The only tint in the interface is teal, used for the one button or a single marker placed near the photographs.\",\n  \"seenIn\": [\n   \"aww-colonia-zacamil\",\n   \"opl-archiv\"\n  ]\n },\n {\n  \"id\": \"moss-sand\",\n  \"name\": \"Sand and moss\",\n  \"tags\": [\n   \"light-neutral\",\n   \"earth\"\n  ],\n  \"bg\": \"#ddd6c6\",\n  \"surface\": \"#d2cab8\",\n  \"ink\": \"#2a2a26\",\n  \"muted\": \"#59574e\",\n  \"accent\": \"#4f6238\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#3f5a2a\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"Sand grey holds the page with charcoal type, and one deep leaf-green band may close it. Moss green is reserved for buttons; brighter greens and blues arrive only through photographs.\",\n  \"seenIn\": [\n   \"opl-vestris\",\n   \"aww-izanami\"\n  ]\n },\n {\n  \"id\": \"green-mat-chocolate\",\n  \"name\": \"Bone, green, chocolate\",\n  \"tags\": [\n   \"light-neutral\",\n   \"earth\"\n  ],\n  \"bg\": \"#e5e1d8\",\n  \"surface\": \"#dad5ca\",\n  \"ink\": \"#2a1d17\",\n  \"muted\": \"#6b5b51\",\n  \"accent\": \"#456f3a\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#456f3a\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"Bone ground with chocolate-brown text takes most of the page. The green is spent on one large flat block, about a third of a screen, and on the button; all other colour comes from photographs.\",\n  \"seenIn\": [\n   \"opl-davesocozy\",\n   \"opl-mat\"\n  ]\n },\n {\n  \"id\": \"lunar-grey-bronze\",\n  \"name\": \"Lunar and bronze\",\n  \"tags\": [\n   \"dark-neutral\"\n  ],\n  \"bg\": \"#111111\",\n  \"surface\": \"#1c1c1c\",\n  \"ink\": \"#f2f2f2\",\n  \"muted\": \"#8f8f8f\",\n  \"accent\": \"#a08672\",\n  \"accentInk\": \"#111111\",\n  \"note\": \"Soft black holds the page with panels one step lighter, white text and grey secondary lines, so photographs supply all the colour. Muted bronze goes on small markers and the one button only.\",\n  \"seenIn\": [\n   \"aww-21-hrs-on-the-moon\",\n   \"opl-dialkit\",\n   \"opl-lorenzo-bocchi-photography\"\n  ]\n },\n {\n  \"id\": \"blue-black-cornflower\",\n  \"name\": \"Night and cornflower\",\n  \"tags\": [\n   \"dark-neutral\"\n  ],\n  \"bg\": \"#0a0d14\",\n  \"surface\": \"#131824\",\n  \"ink\": \"#e9edf3\",\n  \"muted\": \"#8891a1\",\n  \"accent\": \"#5a9bfc\",\n  \"accentInk\": \"#0a0d14\",\n  \"note\": \"Blue-black ground and slate panels with silver-white text fill the page; no section changes colour. Cornflower blue marks the buttons and at most one word in a heading.\",\n  \"seenIn\": [\n   \"opl-viewport-2\",\n   \"aww-moto-finance\",\n   \"opl-rafael-derolez-2026\"\n  ]\n },\n {\n  \"id\": \"green-black-bone\",\n  \"name\": \"Green-black and bone\",\n  \"tags\": [\n   \"dark-neutral\",\n   \"earth\"\n  ],\n  \"bg\": \"#161c1a\",\n  \"surface\": \"#1f2725\",\n  \"ink\": \"#e3e2da\",\n  \"muted\": \"#8e948d\",\n  \"accent\": \"#9fc7b8\",\n  \"accentInk\": \"#161c1a\",\n  \"note\": \"Bone type on green-black from top to bottom, with panels and drawn details barely lighter than the ground so photographs supply the colour. Pale jade is for the booking or contact button alone.\",\n  \"seenIn\": [\n   \"opl-kereliott\",\n   \"aww-lama-lama-2\"\n  ]\n },\n {\n  \"id\": \"black-crimson\",\n  \"name\": \"Black and crimson\",\n  \"tags\": [\n   \"dark-neutral\",\n   \"mono-accent\"\n  ],\n  \"bg\": \"#0a0a0a\",\n  \"surface\": \"#151515\",\n  \"ink\": \"#efefef\",\n  \"muted\": \"#8c8c8c\",\n  \"accent\": \"#b11226\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#efefef\",\n    \"ink\": \"#0a0a0a\"\n   }\n  ],\n  \"note\": \"Black with off-white text and mid-grey texture takes nearly the whole page, and the last sections may invert to off-white with black type. Deep crimson is scattered sparingly: a few characters in a heading, a slider fill, the one button.\",\n  \"seenIn\": [\n   \"opl-textmode-overlay\"\n  ]\n },\n {\n  \"id\": \"forest-pale-lime\",\n  \"name\": \"Forest and lime\",\n  \"tags\": [\n   \"dark-neutral\",\n   \"earth\"\n  ],\n  \"bg\": \"#0f1f10\",\n  \"surface\": \"#162a17\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#9aa39a\",\n  \"accent\": \"#c6f19d\",\n  \"accentInk\": \"#0f1f10\",\n  \"fields\": [\n   {\n    \"bg\": \"#000000\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#ffffff\",\n    \"ink\": \"#0f1f10\"\n   }\n  ],\n  \"note\": \"Forest green, black and white sections alternate, with forest green holding the most; photographs stay in moss greens and stone browns. Pale lime sits on small squares only, such as arrow buttons and the closing wordmark.\",\n  \"seenIn\": [\n   \"aww-alethia\"\n  ]\n },\n {\n  \"id\": \"charcoal-room-sage\",\n  \"name\": \"Charcoal and sage\",\n  \"tags\": [\n   \"dark-neutral\",\n   \"photographic-neutral\"\n  ],\n  \"bg\": \"#1c1c1c\",\n  \"surface\": \"#262626\",\n  \"ink\": \"#f1f1ef\",\n  \"muted\": \"#9a9b96\",\n  \"accent\": \"#8fa68e\",\n  \"accentInk\": \"#1c1c1c\",\n  \"fields\": [\n   {\n    \"bg\": \"#c8c5ba\",\n    \"ink\": \"#1c1c1c\"\n   }\n  ],\n  \"note\": \"Charcoal holds the page with off-white text, and one section may flip to a pale concrete tone with dark text. Colour comes from the photographs; grey sage is used for the single button and the active state of a control.\",\n  \"seenIn\": [\n   \"opl-transport\",\n   \"opl-amanda-guo-design\"\n  ]\n },\n {\n  \"id\": \"warm-black-gold\",\n  \"name\": \"Warm black, gold\",\n  \"tags\": [\n   \"dark-neutral\",\n   \"photographic-neutral\"\n  ],\n  \"bg\": \"#0c0a08\",\n  \"surface\": \"#181512\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#8f8a84\",\n  \"accent\": \"#c9a45a\",\n  \"accentInk\": \"#0c0a08\",\n  \"note\": \"Warm near-black fills the page and photographs sit bright against it, with pure white small type; panels warm to a brown-black. Gold is for one text link or small button per screen, never a field.\",\n  \"seenIn\": [\n   \"aww-cipher\",\n   \"opl-hebbia\"\n  ]\n },\n {\n  \"id\": \"graphite-safety-orange\",\n  \"name\": \"Graphite and orange\",\n  \"tags\": [\n   \"mono-accent\",\n   \"dark-neutral\"\n  ],\n  \"bg\": \"#18191b\",\n  \"surface\": \"#222427\",\n  \"ink\": \"#eff0f1\",\n  \"muted\": \"#9c9ea3\",\n  \"accent\": \"#ff4a1f\",\n  \"accentInk\": \"#18191b\",\n  \"fields\": [\n   {\n    \"bg\": \"#eff0f1\",\n    \"ink\": \"#18191b\"\n   }\n  ],\n  \"note\": \"Graphite and cool light-grey sections alternate, graphite taking about two thirds, and photographs are desaturated so nothing competes. Safety orange marks the buttons, one thick solid bar across the top of the page and the highlighted item in a list or chart.\",\n  \"seenIn\": [\n   \"aww-sstr-friction-reduction\",\n   \"aww-boc-studio\",\n   \"aww-dragonfly-redux\"\n  ]\n },\n {\n  \"id\": \"soot-pale-lime\",\n  \"name\": \"Soot and lime\",\n  \"tags\": [\n   \"mono-accent\",\n   \"dark-neutral\"\n  ],\n  \"bg\": \"#0f0f0f\",\n  \"surface\": \"#1a1a1a\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#8f8f8f\",\n  \"accent\": \"#dafa9c\",\n  \"accentInk\": \"#0f0f0f\",\n  \"fields\": [\n   {\n    \"bg\": \"#ffffff\",\n    \"ink\": \"#0f0f0f\"\n   },\n   {\n    \"bg\": \"#dafa9c\",\n    \"ink\": \"#0f0f0f\"\n   }\n  ],\n  \"note\": \"A soot-black opening and close bracket white middle sections, all in black, white and grey. Pale lime is the single action colour: every button, and at most one headline set in it on the dark ground.\",\n  \"seenIn\": [\n   \"opl-builders-table\",\n   \"aww-made-with-gsap-1\",\n   \"aww-hilden-kaira\"\n  ]\n },\n {\n  \"id\": \"plum-black-pink\",\n  \"name\": \"Plum-black and pink\",\n  \"tags\": [\n   \"mono-accent\",\n   \"dark-neutral\"\n  ],\n  \"bg\": \"#0d060b\",\n  \"surface\": \"#1b0e17\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#9a8f97\",\n  \"accent\": \"#ff488b\",\n  \"accentInk\": \"#0d060b\",\n  \"fields\": [\n   {\n    \"bg\": \"#470c35\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#ffffff\",\n    \"ink\": \"#101421\"\n   }\n  ],\n  \"note\": \"Near-black and plum at the top and bottom bracket a white middle with navy-black text. Hot pink is reserved for primary buttons, bars in charts and map markers; it never fills a section.\",\n  \"seenIn\": [\n   \"aww-cerebrium\"\n  ]\n },\n {\n  \"id\": \"white-signal-red\",\n  \"name\": \"Signal red, white\",\n  \"tags\": [\n   \"mono-accent\"\n  ],\n  \"bg\": \"#ffffff\",\n  \"surface\": \"#f2f2f2\",\n  \"ink\": \"#0a0a0a\",\n  \"muted\": \"#6b6b6b\",\n  \"accent\": \"#d92b21\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#000000\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"White ground, black text and paper grey for filled panels, with one full black band allowed. Signal red is the only colour in the interface: one word in a headline, a few solid blocks, or the button.\",\n  \"seenIn\": [\n   \"opl-rsquad\",\n   \"aww-serotoninn\",\n   \"opl-estacion-venenta\"\n  ]\n },\n {\n  \"id\": \"white-mint-tiles\",\n  \"name\": \"Greys and mint\",\n  \"tags\": [\n   \"mono-accent\"\n  ],\n  \"bg\": \"#ffffff\",\n  \"surface\": \"#f3f3f3\",\n  \"ink\": \"#232323\",\n  \"muted\": \"#6e6e6e\",\n  \"accent\": \"#a1ffcb\",\n  \"accentInk\": \"#232323\",\n  \"fields\": [\n   {\n    \"bg\": \"#a1ffcb\",\n    \"ink\": \"#232323\"\n   },\n   {\n    \"bg\": \"#232323\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"White, near-black and two greys fill a board of flat tiles. Mint floods a few whole tiles (one statement, one figure, the closing call to action) and appears nowhere else.\",\n  \"seenIn\": [\n   \"aww-aspen-search\"\n  ]\n },\n {\n  \"id\": \"cool-grey-cobalt\",\n  \"name\": \"Cool grey, cobalt\",\n  \"tags\": [\n   \"mono-accent\"\n  ],\n  \"bg\": \"#eef0f3\",\n  \"surface\": \"#e2e5ea\",\n  \"ink\": \"#0b0c0e\",\n  \"muted\": \"#5d6470\",\n  \"accent\": \"#1f2de6\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#1f2de6\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"Cool pale grey holds the page with near-black type and nothing else tinted. Cobalt starts as the button and one highlighted sentence, takes one whole section as a flat field with white text, then returns as a single button block.\",\n  \"seenIn\": [\n   \"opl-vessa\",\n   \"opl-specia1ne\",\n   \"opl-brikkenco\"\n  ]\n },\n {\n  \"id\": \"offwhite-bottle-yellow\",\n  \"name\": \"Bottle ink, yellow\",\n  \"tags\": [\n   \"mono-accent\"\n  ],\n  \"bg\": \"#f7f7f7\",\n  \"surface\": \"#ebebeb\",\n  \"ink\": \"#0d2a1c\",\n  \"muted\": \"#5f6b64\",\n  \"accent\": \"#f6e016\",\n  \"accentInk\": \"#0d2a1c\",\n  \"fields\": [\n   {\n    \"bg\": \"#f6e016\",\n    \"ink\": \"#0d2a1c\"\n   }\n  ],\n  \"note\": \"Off-white ground with all type in a near-black bottle green instead of black. Yellow is the only saturated note: the button or one small object on most screens, and one later section that turns fully yellow.\",\n  \"seenIn\": [\n   \"aww-leo-parpeix-portfolio-2026\",\n   \"opl-wild-as\"\n  ]\n },\n {\n  \"id\": \"teal-on-paper\",\n  \"name\": \"Teal on paper\",\n  \"tags\": [\n   \"two-tone\"\n  ],\n  \"bg\": \"#f7f9f8\",\n  \"surface\": \"#ebf0ee\",\n  \"ink\": \"#06525c\",\n  \"muted\": \"#2f737d\",\n  \"accent\": \"#06525c\",\n  \"accentInk\": \"#f7f9f8\",\n  \"fields\": [\n   {\n    \"bg\": \"#06525c\",\n    \"ink\": \"#f7f9f8\"\n   }\n  ],\n  \"note\": \"Cool white paper and a single teal used for every word, shape and button, with no black anywhere. The accent is that same teal filled solid, for the button and for one inverted band with paper-coloured type.\",\n  \"seenIn\": [\n   \"opl-le-petit-bleu\"\n  ]\n },\n {\n  \"id\": \"navy-pink\",\n  \"name\": \"Navy and pink\",\n  \"tags\": [\n   \"two-tone\",\n   \"single-field\"\n  ],\n  \"bg\": \"#1a2039\",\n  \"surface\": \"#212846\",\n  \"ink\": \"#f9a3c0\",\n  \"muted\": \"#b9879c\",\n  \"accent\": \"#f9a3c0\",\n  \"accentInk\": \"#1a2039\",\n  \"note\": \"One navy field runs the entire page. Pink does everything else, from the name and headings to body text, and fills one solid button.\",\n  \"seenIn\": [\n   \"aww-trevor-noah\"\n  ]\n },\n {\n  \"id\": \"blush-aubergine\",\n  \"name\": \"Blush and aubergine\",\n  \"tags\": [\n   \"two-tone\"\n  ],\n  \"bg\": \"#edccbe\",\n  \"surface\": \"#e8c2b2\",\n  \"ink\": \"#351a2b\",\n  \"muted\": \"#6c4857\",\n  \"accent\": \"#351a2b\",\n  \"accentInk\": \"#edccbe\",\n  \"fields\": [\n   {\n    \"bg\": \"#351a2b\",\n    \"ink\": \"#edccbe\"\n   }\n  ],\n  \"note\": \"Blush pink and dark aubergine alternate as full fields and serve as each other's text colour, in roughly equal shares. There is no third colour: the button is a solid block of whichever of the two is not the ground.\",\n  \"seenIn\": [\n   \"aww-house-of-honey-1\",\n   \"opl-sarah-matt-wedding\"\n  ]\n },\n {\n  \"id\": \"cobalt-on-sand\",\n  \"name\": \"Cobalt on sand\",\n  \"tags\": [\n   \"two-tone\"\n  ],\n  \"bg\": \"#e6dbc7\",\n  \"surface\": \"#ddd0b9\",\n  \"ink\": \"#062b8a\",\n  \"muted\": \"#3a5aa8\",\n  \"accent\": \"#062b8a\",\n  \"accentInk\": \"#e6dbc7\",\n  \"note\": \"Sand paper and one cobalt do everything: text, drawings and solid shapes are all the same blue. The button is a cobalt block with sand-coloured type, and no black or second hue is used.\",\n  \"seenIn\": [\n   \"aww-illoca\"\n  ]\n },\n {\n  \"id\": \"oxblood-grey\",\n  \"name\": \"Oxblood and grey\",\n  \"tags\": [\n   \"two-tone\"\n  ],\n  \"bg\": \"#e2e2e2\",\n  \"surface\": \"#d6d6d6\",\n  \"ink\": \"#7d0c14\",\n  \"muted\": \"#7a4a4e\",\n  \"accent\": \"#7d0c14\",\n  \"accentInk\": \"#e2e2e2\",\n  \"fields\": [\n   {\n    \"bg\": \"#7d0c14\",\n    \"ink\": \"#e2e2e2\"\n   }\n  ],\n  \"note\": \"Deep red text on grey paper holds most of the page, then pale grey text on a solid red field takes one long section and the footer. Photographs are desaturated so nothing breaks the pair, and the button is a solid red block.\",\n  \"seenIn\": [\n   \"opl-belgrade-architecture\"\n  ]\n },\n {\n  \"id\": \"olive-on-bone\",\n  \"name\": \"Olive on bone\",\n  \"tags\": [\n   \"two-tone\",\n   \"earth\"\n  ],\n  \"bg\": \"#ecebe7\",\n  \"surface\": \"#e1dfd9\",\n  \"ink\": \"#38450f\",\n  \"muted\": \"#5d683a\",\n  \"accent\": \"#38450f\",\n  \"accentInk\": \"#ecebe7\",\n  \"fields\": [\n   {\n    \"bg\": \"#38450f\",\n    \"ink\": \"#ecebe7\"\n   }\n  ],\n  \"note\": \"A bone page with every word, large or small, in one olive green; the footer inverts to a solid olive field with bone text. Photography supplies all other colour, and the button is the same olive, filled.\",\n  \"seenIn\": [\n   \"aww-tengile-malamala-collection\"\n  ]\n },\n {\n  \"id\": \"burgundy-bubblegum\",\n  \"name\": \"Burgundy and bubblegum\",\n  \"tags\": [\n   \"two-tone\"\n  ],\n  \"bg\": \"#3d0012\",\n  \"surface\": \"#4d0519\",\n  \"ink\": \"#ff99d3\",\n  \"muted\": \"#c77aa0\",\n  \"accent\": \"#ff99d3\",\n  \"accentInk\": \"#3d0012\",\n  \"note\": \"Deep burgundy is the ground for the whole page and bubblegum pink sets every word on it. The button and the active state of a control are solid pink with burgundy type; product photographs supply any other colour.\",\n  \"seenIn\": [\n   \"opl-madie\"\n  ]\n },\n {\n  \"id\": \"bottle-green-gold\",\n  \"name\": \"Bottle green, gold\",\n  \"tags\": [\n   \"two-tone\",\n   \"earth\"\n  ],\n  \"bg\": \"#133621\",\n  \"surface\": \"#1a4429\",\n  \"ink\": \"#f4d96c\",\n  \"muted\": \"#b3a55e\",\n  \"accent\": \"#f4d96c\",\n  \"accentInk\": \"#133621\",\n  \"note\": \"Bottle green covers the page and warm gold sets all the type, with panels one step lighter than the ground. The button is solid gold with green text, and photographs are kept dark and warm so the pair is not disturbed.\",\n  \"seenIn\": [\n   \"aww-lacoste-ace-breaker\"\n  ]\n },\n {\n  \"id\": \"cobalt-field\",\n  \"name\": \"Cobalt field\",\n  \"tags\": [\n   \"single-field\"\n  ],\n  \"bg\": \"#0034eb\",\n  \"surface\": \"#002fd6\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#c5d0ff\",\n  \"accent\": \"#e9e34a\",\n  \"accentInk\": \"#111111\",\n  \"note\": \"One electric cobalt fills everything, with white and pale-blue type; photographs are tinted into blue monotone or kept as small thumbnails. A single yellow dot or button is the only other colour on the page.\",\n  \"seenIn\": [\n   \"opl-george-wood\",\n   \"aww-studio-k95-3\"\n  ]\n },\n {\n  \"id\": \"mustard-field\",\n  \"name\": \"Mustard and black\",\n  \"tags\": [\n   \"single-field\"\n  ],\n  \"bg\": \"#e1ac10\",\n  \"surface\": \"#cd9d0f\",\n  \"ink\": \"#0b0b0b\",\n  \"muted\": \"#4d3d0a\",\n  \"accent\": \"#24338f\",\n  \"accentInk\": \"#ffffff\",\n  \"note\": \"One warm mustard field for the whole page with black ink only. Royal blue is the single interruption, kept to a sliver along one edge or one small button.\",\n  \"seenIn\": [\n   \"opl-beige-force\"\n  ]\n },\n {\n  \"id\": \"carmine-field\",\n  \"name\": \"Carmine field\",\n  \"tags\": [\n   \"single-field\"\n  ],\n  \"bg\": \"#9c1220\",\n  \"surface\": \"#8a101c\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#f0b9bd\",\n  \"accent\": \"#ffd9dc\",\n  \"accentInk\": \"#9c1220\",\n  \"fields\": [\n   {\n    \"bg\": \"#2a2a2a\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"A deep red field bookends or fills the page, with white type and pale pink secondary lines; work shown in between sits on flat charcoal so it keeps its own colours. The button is a pale pink block with red type.\",\n  \"seenIn\": [\n   \"opl-marina-rachello\",\n   \"opl-belgrade-architecture\"\n  ]\n },\n {\n  \"id\": \"pink-field-lime\",\n  \"name\": \"Bubblegum and lime\",\n  \"tags\": [\n   \"single-field\"\n  ],\n  \"bg\": \"#ff87ab\",\n  \"surface\": \"#ff739d\",\n  \"ink\": \"#0a0a0a\",\n  \"muted\": \"#6b1f3a\",\n  \"accent\": \"#def915\",\n  \"accentInk\": \"#0a0a0a\",\n  \"fields\": [\n   {\n    \"bg\": \"#0a0a0a\",\n    \"ink\": \"#ff87ab\"\n   }\n  ],\n  \"note\": \"A flat bubblegum pink field with black type from top to bottom. Fluorescent lime is the action colour only: the menu button, one highlighter swipe behind a word and the main button.\",\n  \"seenIn\": [\n   \"opl-nodeck\",\n   \"aww-decathlon-yestalgia\"\n  ]\n },\n {\n  \"id\": \"sky-field-navy\",\n  \"name\": \"Sky and navy\",\n  \"tags\": [\n   \"single-field\"\n  ],\n  \"bg\": \"#6bb4ee\",\n  \"surface\": \"#7dbdf0\",\n  \"ink\": \"#0e1822\",\n  \"muted\": \"#1b3d5c\",\n  \"accent\": \"#ff5a1f\",\n  \"accentInk\": \"#0e1822\",\n  \"fields\": [\n   {\n    \"bg\": \"#ffffff\",\n    \"ink\": \"#0e1822\"\n   },\n   {\n    \"bg\": \"#0e1822\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"Sky blue sits behind everything, white cards lie on top of it, and navy handles all text and the footer. Orange is for buttons and one highlighted word, so orange against blue is the single clash on the page.\",\n  \"seenIn\": [\n   \"opl-ohhmydesign\",\n   \"opl-anidachi\"\n  ]\n },\n {\n  \"id\": \"orange-field-black\",\n  \"name\": \"Orange and black\",\n  \"tags\": [\n   \"single-field\",\n   \"two-tone\"\n  ],\n  \"bg\": \"#ff7a1f\",\n  \"surface\": \"#ff8633\",\n  \"ink\": \"#050f16\",\n  \"muted\": \"#5a2306\",\n  \"accent\": \"#050f16\",\n  \"accentInk\": \"#ff7a1f\",\n  \"fields\": [\n   {\n    \"bg\": \"#ffffff\",\n    \"ink\": \"#050f16\"\n   }\n  ],\n  \"note\": \"Hot orange is the page: one flat field with blue-black type, flipping at a hard horizontal seam to a white section when the content needs a rest. The button is a solid block of the same blue-black with orange text, and every other colour comes from the objects shown.\",\n  \"seenIn\": [\n   \"opl-postaway\",\n   \"opl-the-new-industrials\"\n  ]\n },\n {\n  \"id\": \"tobacco-olive\",\n  \"name\": \"Tobacco and olive\",\n  \"tags\": [\n   \"single-field\",\n   \"earth\"\n  ],\n  \"bg\": \"#472913\",\n  \"surface\": \"#55321a\",\n  \"ink\": \"#e4e0cf\",\n  \"muted\": \"#b39f84\",\n  \"accent\": \"#525e1b\",\n  \"accentInk\": \"#e4e0cf\",\n  \"fields\": [\n   {\n    \"bg\": \"#c79a3e\",\n    \"ink\": \"#2b170a\"\n   },\n   {\n    \"bg\": \"#525e1b\",\n    \"ink\": \"#e4e0cf\"\n   }\n  ],\n  \"note\": \"Tobacco brown fills the page with bone type, and photographs stay in browns and ochre. One olive block holds the main text or the button, and a single ochre band may break the brown once.\",\n  \"seenIn\": [\n   \"aww-the-tuscan-journey-begins\"\n  ]\n },\n {\n  \"id\": \"poster-chapters\",\n  \"name\": \"Poster chapters\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#e6e0d2\",\n  \"surface\": \"#dcd5c5\",\n  \"ink\": \"#1a1a1a\",\n  \"muted\": \"#5f5b52\",\n  \"accent\": \"#18bc42\",\n  \"accentInk\": \"#1a1a1a\",\n  \"fields\": [\n   {\n    \"bg\": \"#ed4b44\",\n    \"ink\": \"#0f0f0f\"\n   },\n   {\n    \"bg\": \"#1a1a1a\",\n    \"ink\": \"#e6e0d2\"\n   },\n   {\n    \"bg\": \"#18bc42\",\n    \"ink\": \"#1a1a1a\"\n   },\n   {\n    \"bg\": \"#f2c21a\",\n    \"ink\": \"#1a1a1a\"\n   },\n   {\n    \"bg\": \"#e6e0d2\",\n    \"ink\": \"#1a1a1a\"\n   }\n  ],\n  \"note\": \"Each chapter takes one flat field in turn (coral red, near-black, bone, green, yellow) with black or bone type and no tints between them. Green doubles as the accent for the one button when the ground is bone or black.\",\n  \"seenIn\": [\n   \"aww-pp-neue-montreal\"\n  ]\n },\n {\n  \"id\": \"blue-red-black\",\n  \"name\": \"Blue, red, black\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#ffffff\",\n  \"surface\": \"#f3f3f3\",\n  \"ink\": \"#0a0a0a\",\n  \"muted\": \"#6b6b6b\",\n  \"accent\": \"#2436ff\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#2436ff\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#ff3b1f\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#0a0a0a\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#050a5c\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"Three flat poster colours each own whole sections: electric blue, red-orange and black, with white for the areas that show the product. No tints sit between them, and blue is the button colour on white.\",\n  \"seenIn\": [\n   \"opl-juggle\"\n  ]\n },\n {\n  \"id\": \"charcoal-primaries\",\n  \"name\": \"Charcoal and primaries\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#191919\",\n  \"surface\": \"#242424\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#9a9a9a\",\n  \"accent\": \"#0c7866\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#d71e1e\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#1e4bd7\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#0c7866\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#ffe927\",\n    \"ink\": \"#111111\"\n   }\n  ],\n  \"note\": \"A charcoal ground holds flat poster primaries assigned to whole panels: red, blue, teal green and yellow, each placed against a different one. Type is white, or black on yellow; teal green is the button colour on charcoal.\",\n  \"seenIn\": [\n   \"aww-mosbys-files\"\n  ]\n },\n {\n  \"id\": \"ultramarine-yellow\",\n  \"name\": \"Ultramarine and yellow\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#1423b8\",\n  \"surface\": \"#1220a6\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#b4bcf0\",\n  \"accent\": \"#1fc27a\",\n  \"accentInk\": \"#0a0a0a\",\n  \"fields\": [\n   {\n    \"bg\": \"#1423b8\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#000000\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#f7dd47\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#e9479f\",\n    \"ink\": \"#000000\"\n   }\n  ],\n  \"note\": \"Each section is one flat field in sequence: ultramarine, black, yellow, then ultramarine again, with white type on blue and black, and black type on yellow. Green is the only small accent and never grows larger than a button.\",\n  \"seenIn\": [\n   \"aww-warm-fuzzy\",\n   \"aww-px-push\"\n  ]\n },\n {\n  \"id\": \"candy-chapters\",\n  \"name\": \"Candy chapters\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#ffd249\",\n  \"surface\": \"#f5c63c\",\n  \"ink\": \"#0a0a0a\",\n  \"muted\": \"#5e4a0a\",\n  \"accent\": \"#f53fd6\",\n  \"accentInk\": \"#0a0a0a\",\n  \"fields\": [\n   {\n    \"bg\": \"#ffd249\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#ffffff\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#ffc4ef\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#a4f6f8\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#f9a21f\",\n    \"ink\": \"#0a0a0a\"\n   }\n  ],\n  \"note\": \"Each section owns one flat candy colour: yellow first, then white, pink, cyan and orange, with all type in black. Magenta is kept for buttons alone.\",\n  \"seenIn\": [\n   \"aww-aardvark-book-club\"\n  ]\n },\n {\n  \"id\": \"orange-sky-lime\",\n  \"name\": \"Orange, sky, lime\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#ff8126\",\n  \"surface\": \"#ff8d3a\",\n  \"ink\": \"#111111\",\n  \"muted\": \"#5c2a05\",\n  \"accent\": \"#de194b\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#ff8126\",\n    \"ink\": \"#111111\"\n   },\n   {\n    \"bg\": \"#4db3ff\",\n    \"ink\": \"#111111\"\n   },\n   {\n    \"bg\": \"#c5f53d\",\n    \"ink\": \"#111111\"\n   },\n   {\n    \"bg\": \"#161615\",\n    \"ink\": \"#f2f2f2\"\n   }\n  ],\n  \"note\": \"The page ground changes as you read: orange first, then sky blue, then acid lime at the end, with one near-black band between; type stays black on all three colours. Crimson is one small button per field.\",\n  \"seenIn\": [\n   \"opl-the-new-industrials\",\n   \"opl-anidachi\"\n  ]\n },\n {\n  \"id\": \"post-red-mustard\",\n  \"name\": \"Post red, mustard\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#e2dccf\",\n  \"surface\": \"#d7d0c1\",\n  \"ink\": \"#2a1110\",\n  \"muted\": \"#6b524c\",\n  \"accent\": \"#4a6f84\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#dc1928\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#952625\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#e0a912\",\n    \"ink\": \"#2a1110\"\n   },\n   {\n    \"bg\": \"#4a6f84\",\n    \"ink\": \"#ffffff\"\n   },\n   {\n    \"bg\": \"#e2dccf\",\n    \"ink\": \"#2a1110\"\n   }\n  ],\n  \"note\": \"Post red and bone alternate as full section fields, with red holding the opening and the close. Mustard, slate blue and maroon are kept for whole card frames, and slate blue also fills the one button.\",\n  \"seenIn\": [\n   \"opl-locker-land\"\n  ]\n },\n {\n  \"id\": \"mint-orange-grey\",\n  \"name\": \"Grey, mint, orange\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#ffffff\",\n  \"surface\": \"#f5f5f5\",\n  \"ink\": \"#000000\",\n  \"muted\": \"#666666\",\n  \"accent\": \"#a7ff9c\",\n  \"accentInk\": \"#000000\",\n  \"fields\": [\n   {\n    \"bg\": \"#c5c5c5\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#a7ff9c\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#ff6831\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#000000\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"Black on white to start, then whole sections flood with flat mid-grey, acid mint and orange in turn. Photographs inside a flooded section are shown in black-and-white, and mint is also the button colour on white and black.\",\n  \"seenIn\": [\n   \"aww-paul-kalkbrenner\"\n  ]\n },\n {\n  \"id\": \"report-blocks\",\n  \"name\": \"Report blocks\",\n  \"tags\": [\n   \"flat-loud\"\n  ],\n  \"bg\": \"#ffffff\",\n  \"surface\": \"#f6f6f6\",\n  \"ink\": \"#000000\",\n  \"muted\": \"#5f5f5f\",\n  \"accent\": \"#fe7141\",\n  \"accentInk\": \"#000000\",\n  \"fields\": [\n   {\n    \"bg\": \"#fe7141\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#d1ddd3\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#f0ff1c\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#000000\",\n    \"ink\": \"#f4f4f4\"\n   }\n  ],\n  \"note\": \"A white base with flat blocks of orange, sage, acid yellow and black assigned to whole modules: figure tiles, quote panels and chapter bands. Text is black on every colour and off-white on black, and orange is also the button colour.\",\n  \"seenIn\": [\n   \"aww-ai-in-design-report-2026\"\n  ]\n },\n {\n  \"id\": \"card-pastels\",\n  \"name\": \"Card pastels\",\n  \"tags\": [\n   \"pastel-fields\"\n  ],\n  \"bg\": \"#f7f7f5\",\n  \"surface\": \"#ebebe8\",\n  \"ink\": \"#000000\",\n  \"muted\": \"#666662\",\n  \"accent\": \"#d0106f\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#97aaf6\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#bbf697\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#fed878\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#6ef8fb\",\n    \"ink\": \"#000000\"\n   }\n  ],\n  \"note\": \"Neutral paper ground and black type, with each card or tile given its own flat pastel (periwinkle, lime, amber or cyan), never two alike side by side. Magenta is reserved for the logo, the email address and text links.\",\n  \"seenIn\": [\n   \"opl-medium-rare\"\n  ]\n },\n {\n  \"id\": \"mint-pink-accounts\",\n  \"name\": \"Mint and pink\",\n  \"tags\": [\n   \"pastel-fields\"\n  ],\n  \"bg\": \"#f8f8f8\",\n  \"surface\": \"#eeeeee\",\n  \"ink\": \"#0a0a0a\",\n  \"muted\": \"#6a6a6a\",\n  \"accent\": \"#1f6b3a\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#c3edce\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#f8c7c9\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#ffffff\",\n    \"ink\": \"#0a0a0a\"\n   }\n  ],\n  \"note\": \"Near-white base with black type; mint and pink are the only two colours and each stands for one side of the product. They first appear as small circles, then as full-screen section fields, and deep green is used only for the button.\",\n  \"seenIn\": [\n   \"opl-tara\"\n  ]\n },\n {\n  \"id\": \"swap-pastels\",\n  \"name\": \"Swapping pastels\",\n  \"tags\": [\n   \"pastel-fields\"\n  ],\n  \"bg\": \"#c3cbe5\",\n  \"surface\": \"#d0d6eb\",\n  \"ink\": \"#141414\",\n  \"muted\": \"#4a5068\",\n  \"accent\": \"#0f5257\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#c3cbe5\",\n    \"ink\": \"#141414\"\n   },\n   {\n    \"bg\": \"#efd3da\",\n    \"ink\": \"#141414\"\n   },\n   {\n    \"bg\": \"#e6dccd\",\n    \"ink\": \"#141414\"\n   },\n   {\n    \"bg\": \"#cfd3cb\",\n    \"ink\": \"#141414\"\n   },\n   {\n    \"bg\": \"#f9cdbd\",\n    \"ink\": \"#141414\"\n   }\n  ],\n  \"note\": \"One flat pastel is the whole background and it swaps per project or chapter: periwinkle, pink, sand, sage, peach. Type and one solid box stay near-black on all five, and dark teal is only for the button.\",\n  \"seenIn\": [\n   \"opl-belen-jones\"\n  ]\n },\n {\n  \"id\": \"blush-sage-slate\",\n  \"name\": \"Blush, sage, slate\",\n  \"tags\": [\n   \"pastel-fields\",\n   \"earth\"\n  ],\n  \"bg\": \"#a6b3bc\",\n  \"surface\": \"#b2bdc5\",\n  \"ink\": \"#1c1c1c\",\n  \"muted\": \"#38424a\",\n  \"accent\": \"#2c3620\",\n  \"accentInk\": \"#e3e2da\",\n  \"fields\": [\n   {\n    \"bg\": \"#a6b3bc\",\n    \"ink\": \"#1c1c1c\"\n   },\n   {\n    \"bg\": \"#b7c8be\",\n    \"ink\": \"#1c1c1c\"\n   },\n   {\n    \"bg\": \"#d6c4b8\",\n    \"ink\": \"#1c1c1c\"\n   },\n   {\n    \"bg\": \"#2c3620\",\n    \"ink\": \"#e3e2da\"\n   }\n  ],\n  \"note\": \"Slate blue-grey, sage and blush share the page as soft flat blocks, one per chapter or menu tile, with dark type; one deep olive block anchors the close with pale type. Olive is also the button colour, and photographs of sea and sky do the rest.\",\n  \"seenIn\": [\n   \"aww-seasats\",\n   \"opl-nia-creative\"\n  ]\n },\n {\n  \"id\": \"candy-on-black\",\n  \"name\": \"Candy on black\",\n  \"tags\": [\n   \"pastel-fields\"\n  ],\n  \"bg\": \"#000000\",\n  \"surface\": \"#0d0d0d\",\n  \"ink\": \"#ffffff\",\n  \"muted\": \"#999999\",\n  \"accent\": \"#93f1f7\",\n  \"accentInk\": \"#000000\",\n  \"fields\": [\n   {\n    \"bg\": \"#9ae187\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#93f1f7\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#f3ea7a\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#fbb65c\",\n    \"ink\": \"#000000\"\n   },\n   {\n    \"bg\": \"#b9c8ff\",\n    \"ink\": \"#000000\"\n   }\n  ],\n  \"note\": \"Black ground and dark photographs take nearly all of the surface. The only flat colour is a solid block behind each title, which takes a new candy pastel per project (mint, cyan, lemon, orange, cornflower); cyan is the default for the button.\",\n  \"seenIn\": [\n   \"aww-glitch-grit\"\n  ]\n },\n {\n  \"id\": \"sky-sand\",\n  \"name\": \"Sky and sand\",\n  \"tags\": [\n   \"pastel-fields\"\n  ],\n  \"bg\": \"#cbe4f2\",\n  \"surface\": \"#bcdcee\",\n  \"ink\": \"#0a0a0a\",\n  \"muted\": \"#44606e\",\n  \"accent\": \"#b0298f\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#cbe4f2\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#f1e3b5\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#ffc013\",\n    \"ink\": \"#0a0a0a\"\n   },\n   {\n    \"bg\": \"#0a0a0a\",\n    \"ink\": \"#f2f2f2\"\n   }\n  ],\n  \"note\": \"Sky blue and sand yellow are the constant ground, each holding whole sections, with black text throughout. Saturated colour arrives only as small solid objects, and magenta is kept for the contact card and its button.\",\n  \"seenIn\": [\n   \"opl-applied-imagination\"\n  ]\n },\n {\n  \"id\": \"studio-grey\",\n  \"name\": \"Studio grey\",\n  \"tags\": [\n   \"photographic-neutral\"\n  ],\n  \"bg\": \"#a8a8aa\",\n  \"surface\": \"#b4b4b6\",\n  \"ink\": \"#0e0e0e\",\n  \"muted\": \"#3a3a3c\",\n  \"accent\": \"#1f5c49\",\n  \"accentInk\": \"#ffffff\",\n  \"fields\": [\n   {\n    \"bg\": \"#1b1b1c\",\n    \"ink\": \"#ffffff\"\n   }\n  ],\n  \"note\": \"One mid grey serves as both page and studio backdrop, so the photographed object seems to stand on the page itself; type is black and one black band comes late. Colour comes only from the product, and racing green is for the single button.\",\n  \"seenIn\": [\n   \"aww-longbow\",\n   \"aww-l-i-s-a\"\n  ]\n },\n {\n  \"id\": \"walnut-tan\",\n  \"name\": \"Walnut and tan\",\n  \"tags\": [\n   \"photographic-neutral\",\n   \"earth\"\n  ],\n  \"bg\": \"#2b2216\",\n  \"surface\": \"#382d1e\",\n  \"ink\": \"#e4e2da\",\n  \"muted\": \"#a39a8b\",\n  \"accent\": \"#bda38b\",\n  \"accentInk\": \"#2b2216\",\n  \"fields\": [\n   {\n    \"bg\": \"#bda38b\",\n    \"ink\": \"#1c150d\"\n   }\n  ],\n  \"note\": \"Dark walnut holds the opening and the close with bone type, and the middle of the page may turn to flat tan around honey-lit photographs. There is no bright accent: tan is the fill for the one button on walnut.\",\n  \"seenIn\": [\n   \"opl-the-deep-end\"\n  ]\n }\n]\n\n<!-- File: skills/taste-skill/library/photos.json (Tokens: ~16442 | Category: anthropic-skill) -->\n{\n \"source\": \"Lorem Picsum (https://picsum.photos): photographs from Unsplash, used under the Unsplash licence\",\n \"url\": \"https://picsum.photos/id/{id}/{width}/{height}\",\n \"sets\": {\n  \"fog-and-quiet\": {\n   \"title\": \"Fog and quiet\",\n   \"note\": \"misty, muted, minimal landscapes and empty horizons; calm areas for text\",\n   \"sectors\": [\n    \"hospitality\",\n    \"health\",\n    \"fashion\",\n    \"agency\",\n    \"studio-portfolio\",\n    \"personal-portfolio\",\n    \"saas\",\n    \"ai-product\",\n    \"finance\",\n    \"architecture\",\n    \"real-estate\",\n    \"other\",\n    \"nonprofit\",\n    \"culture\"\n   ],\n   \"keywords\": [\n    \"fog\",\n    \"mist\",\n    \"quiet\",\n    \"calm\",\n    \"minimal\",\n    \"silence\",\n    \"retreat\",\n    \"wellness\",\n    \"spa\",\n    \"meditation\",\n    \"slow\"\n   ],\n   \"primary\": [\n    \"health\"\n   ],\n   \"photos\": [\n    {\n     \"id\": 70,\n     \"alt\": \"Road lined with tall trees fading into thick fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"centre\",\n     \"quality\": 5,\n     \"ratio\": 1.51,\n     \"by\": \"Dorothy Lin\",\n     \"page\": \"https://unsplash.com/photos/OokBLPrkCNk\"\n    },\n    {\n     \"id\": 172,\n     \"alt\": \"Stone jetty stretching into still water and dense grey fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"warm grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.51,\n     \"by\": \"Aleksi Tappura\",\n     \"page\": \"https://unsplash.com/photos/TQeX8khR54I\"\n    },\n    {\n     \"id\": 194,\n     \"alt\": \"Wooden deck and a single rock disappearing into thick fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"cool grey\",\n      \"weathered brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.51,\n     \"by\": \"Aleksi Tappura\",\n     \"page\": \"https://unsplash.com/photos/hVOv8me9ue8\"\n    },\n    {\n     \"id\": 228,\n     \"alt\": \"Single round hay bale in a field under dense fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey green\",\n      \"golden tan\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.33,\n     \"by\": \"Michal Kubicek\",\n     \"page\": \"https://unsplash.com/photos/0AbVUUorULU\"\n    },\n    {\n     \"id\": 255,\n     \"alt\": \"Gravel path leading to a cluster of bare trees on a hill\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"olive green\",\n      \"pale grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Jon Ottosson\",\n     \"page\": \"https://unsplash.com/photos/Xg1e5bR_bL4\"\n    },\n    {\n     \"id\": 266,\n     \"alt\": \"Three ships on a distant horizon across a calm blue sea\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"pale blue\",\n      \"deep blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"all\",\n     \"quality\": 5,\n     \"ratio\": 1.78,\n     \"by\": \"John Maravelakis\",\n     \"page\": \"https://unsplash.com/photos/Vosp2wlY3Bs\"\n    },\n    {\n     \"id\": 269,\n     \"alt\": \"Gulls perched on a concrete wall beside a pale still sea\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"pale blue\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Jill Heyer\",\n     \"page\": \"https://unsplash.com/photos/bbV7QzDUJus\"\n    },\n    {\n     \"id\": 279,\n     \"alt\": \"Still misty water fading into a soft pink-grey sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"dusty pink\",\n      \"slate grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"all\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Taylor Leopold\",\n     \"page\": \"https://unsplash.com/photos/OHS0yA7OkrQ\"\n    },\n    {\n     \"id\": 302,\n     \"alt\": \"Lone marker post standing in still water wrapped in fog\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"all\",\n     \"quality\": 5,\n     \"ratio\": 1.6,\n     \"by\": \"Billy Lam\",\n     \"page\": \"https://unsplash.com/photos/O3rmGgNYLKo\"\n    },\n    {\n     \"id\": 353,\n     \"alt\": \"Low cloud drifting over dark green forested hills\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"deep green\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.78,\n     \"by\": \"Forrest Cavale\",\n     \"page\": \"https://unsplash.com/photos/qfmd9bu7IgA\"\n    },\n    {\n     \"id\": 465,\n     \"alt\": \"Dark rocky peak emerging from thick white cloud\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"charcoal\",\n      \"pale grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 5,\n     \"ratio\": 1.51,\n     \"by\": \"Paula Vermeulen\",\n     \"page\": \"https://unsplash.com/photos/_f2m3mEkaaU\"\n    },\n    {\n     \"id\": 510,\n     \"alt\": \"Small red-roofed church below a mountain under a blank white sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"olive brown\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.33,\n     \"by\": \"Jeff Sheldon\",\n     \"page\": \"https://unsplash.com/photos/4IPe3tnBKK0\"\n    },\n    {\n     \"id\": 544,\n     \"alt\": \"Layered hill ridges fading into warm beige mist\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"beige\",\n      \"warm brown\",\n      \"cream\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Francesco Gallarotti\",\n     \"page\": \"https://unsplash.com/photos/-HkuuUSY1pE\"\n    },\n    {\n     \"id\": 552,\n     \"alt\": \"Tiny sailboat on a calm sea with distant hills, black and white\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"white\",\n      \"black\"\n     ],\n     \"mono\": true,\n     \"calm\": \"all\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Hugo Kerr\",\n     \"page\": \"https://unsplash.com/photos/Ke96snCJ1m0\"\n    },\n    {\n     \"id\": 594,\n     \"alt\": \"Small boathouse at the end of a jetty on dark water at night\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"black\",\n      \"deep purple\",\n      \"warm white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Aurélien bellanger\",\n     \"page\": \"https://unsplash.com/photos/uoSEDUu8F-I\"\n    },\n    {\n     \"id\": 634,\n     \"alt\": \"Pine forest dissolving into fog beneath a pale pink sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"dark green\",\n      \"pale pink\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Jay Mantri\",\n     \"page\": \"https://unsplash.com/photos/TFyi0QOx08c\"\n    },\n    {\n     \"id\": 813,\n     \"alt\": \"Still blue lake with a faint distant shoreline in haze\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"slate blue\",\n      \"powder blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"all\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Roger Burkhard\",\n     \"page\": \"https://unsplash.com/photos/rlX9J28Pd9g\"\n    },\n    {\n     \"id\": 842,\n     \"alt\": \"Wooden steps with railings descending into pale pink fog\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"blush pink\",\n      \"pale grey\",\n      \"slate\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 0.75,\n     \"by\": \"Joe Beck\",\n     \"page\": \"https://unsplash.com/photos/NbUokuw0BQI\"\n    },\n    {\n     \"id\": 922,\n     \"alt\": \"Dark treeline dissolving upward into pale fog, black and white\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"charcoal\",\n      \"grey\",\n      \"white\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.8,\n     \"by\": \"Patrick Hendry\",\n     \"page\": \"https://unsplash.com/photos/37ZuGYD3JOk\"\n    },\n    {\n     \"id\": 926,\n     \"alt\": \"Lone figure standing on a hilltop in thick beige fog\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"warm beige\",\n      \"olive grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.78,\n     \"by\": \"Harman Abiwardani\",\n     \"page\": \"https://unsplash.com/photos/mU_aX6JBYmg\"\n    },\n    {\n     \"id\": 941,\n     \"alt\": \"Small island on a pale, glassy sea beneath soft clouds\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale blue\",\n      \"soft white\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Ivan Slade\",\n     \"page\": \"https://unsplash.com/photos/RdyMe8KQAV0\"\n    },\n    {\n     \"id\": 989,\n     \"alt\": \"Low cloud covering a forested lakeshore under a pale sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"dark teal\",\n      \"soft blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Paul Jarvis\",\n     \"page\": \"https://unsplash.com/photos/eBDdgbM5dSo\"\n    },\n    {\n     \"id\": 994,\n     \"alt\": \"Silky long-exposure sea beneath a blue and orange sunset sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"soft blue\",\n      \"peach\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"all\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Jonathan Bean\",\n     \"page\": \"https://unsplash.com/photos/ywnnwzcdR5o\"\n    },\n    {\n     \"id\": 11,\n     \"alt\": \"Misty river winding through a grassy valley between forested slopes\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"pale green\",\n      \"grey green\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Paul Jarvis\",\n     \"page\": \"https://unsplash.com/photos/Cm7oKel-X2Q\"\n    },\n    {\n     \"id\": 93,\n     \"alt\": \"Marshland with scattered pine trees under a soft pastel sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"moss green\",\n      \"pale blue\",\n      \"soft pink\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Caroline Sada\",\n     \"page\": \"https://unsplash.com/photos/r1XwWjI4PyE\"\n    },\n    {\n     \"id\": 130,\n     \"alt\": \"Single seagull gliding over a grey sea beneath pale clouds\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"white\"\n     ],\n     \"mono\": true,\n     \"calm\": \"all\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Ryan Jacques\",\n     \"page\": \"https://unsplash.com/photos/ywiAen4L4qA\"\n    },\n    {\n     \"id\": 131,\n     \"alt\": \"Tiny figure on a pier under a vast pale yellow sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale yellow\",\n      \"sand beige\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.48,\n     \"by\": \"Charlie Foster\",\n     \"page\": \"https://unsplash.com/photos/yPaskTQiNjA\"\n    },\n    {\n     \"id\": 135,\n     \"alt\": \"Dark choppy sea fading into dense blue-grey fog\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"indigo\",\n      \"slate blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.33,\n     \"by\": \"Yuriy Khimanin\",\n     \"page\": \"https://unsplash.com/photos/o4H20aIIAt8\"\n    },\n    {\n     \"id\": 213,\n     \"alt\": \"Soft orange sunset sky above a calm misty sea\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"peach orange\",\n      \"slate blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"all\",\n     \"quality\": 4,\n     \"ratio\": 1.51,\n     \"by\": \"Kelly Sikkema\",\n     \"page\": \"https://unsplash.com/photos/X7dy114KWs4\"\n    },\n    {\n     \"id\": 227,\n     \"alt\": \"Railway tracks curving into a misty forest of bare trees\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"dark teal\",\n      \"grey green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"centre\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Andrea Boldizsar\",\n     \"page\": \"https://unsplash.com/photos/1iP1dozVO8I\"\n    },\n    {\n     \"id\": 264,\n     \"alt\": \"Wooden post standing among stones beside still misty water\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"warm beige\",\n      \"grey\",\n      \"tan\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Jon Phillips\",\n     \"page\": \"https://unsplash.com/photos/XsPM2CBTTpI\"\n    },\n    {\n     \"id\": 282,\n     \"alt\": \"Wooden railing overlooking a pine forest covered by low fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"muted brown\",\n      \"dark green\",\n      \"warm grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Taylor Leopold\",\n     \"page\": \"https://unsplash.com/photos/9dw0xLlxw1s\"\n    },\n    {\n     \"id\": 291,\n     \"alt\": \"Two figures standing in a misty blue field at dusk\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"deep blue\",\n      \"muted rust\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Caleb George\",\n     \"page\": \"https://unsplash.com/photos/zdjOYZeJj3w\"\n    },\n    {\n     \"id\": 300,\n     \"alt\": \"Hay bales scattered across a pale field under white sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"light grey\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Pavel Voinov\",\n     \"page\": \"https://unsplash.com/photos/2f_CnEeZsVg\"\n    },\n    {\n     \"id\": 313,\n     \"alt\": \"Distant clump of trees in a foggy field at dusk\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"dusty mauve\",\n      \"slate blue\",\n      \"dark olive\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Sonja Langford\",\n     \"page\": \"https://unsplash.com/photos/4xYgBTYC2-Q\"\n    },\n    {\n     \"id\": 385,\n     \"alt\": \"Calm sea stretching to a thin glowing horizon at dusk\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"slate blue\",\n      \"teal\",\n      \"soft orange\"\n     ],\n     \"mono\": false,\n     \"calm\": \"all\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Griffin Keller\",\n     \"page\": \"https://unsplash.com/photos/7oS_26cb1Wo\"\n    },\n    {\n     \"id\": 406,\n     \"alt\": \"Low clouds drifting across steep forested mountain slopes\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"white\",\n      \"dark green\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.51,\n     \"by\": \"Roland Batke-Mutschler\",\n     \"page\": \"https://unsplash.com/photos/SmhN4FejPFs\"\n    },\n    {\n     \"id\": 443,\n     \"alt\": \"Mist and cloud hanging over dark pine-covered mountains\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"dark green\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Tim Mossholder\",\n     \"page\": \"https://unsplash.com/photos/p3kpqGBRPok\"\n    },\n    {\n     \"id\": 457,\n     \"alt\": \"Faint ships on a pale foggy sea with almost no horizon\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"pale grey\"\n     ],\n     \"mono\": true,\n     \"calm\": \"all\",\n     \"quality\": 4,\n     \"ratio\": 1.77,\n     \"by\": \"Volkan Olmez\",\n     \"page\": \"https://unsplash.com/photos/ccPpd02Spe0\"\n    },\n    {\n     \"id\": 467,\n     \"alt\": \"Dark sea fading into white fog in black and white\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"white\",\n      \"grey\",\n      \"charcoal\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Taylor Leopold\",\n     \"page\": \"https://unsplash.com/photos/COE-CIGj8VA\"\n    },\n    {\n     \"id\": 472,\n     \"alt\": \"Small wooded island wrapped in fog on a dark lake\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"dark green\",\n      \"grey\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Dustin Scarpitti\",\n     \"page\": \"https://unsplash.com/photos/gR_zHJqbtzo\"\n    },\n    {\n     \"id\": 481,\n     \"alt\": \"Still lake at dusk with mist and dark conifers along the shore\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"teal grey\",\n      \"slate\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Dustin Scarpitti\",\n     \"page\": \"https://unsplash.com/photos/RdF3apSExR0\"\n    },\n    {\n     \"id\": 722,\n     \"alt\": \"Tree silhouettes in thick golden fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"ochre\",\n      \"olive brown\",\n      \"pale gold\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 0.67,\n     \"by\": \"Sebastian Kostrubala\",\n     \"page\": \"https://unsplash.com/photos/4yDg-dDX9uM\"\n    },\n    {\n     \"id\": 727,\n     \"alt\": \"Sandy mound with dark shrubs beneath a blank foggy sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"ochre\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.33,\n     \"by\": \"Devan Freeman\",\n     \"page\": \"https://unsplash.com/photos/HrUbyeQvL_w\"\n    },\n    {\n     \"id\": 731,\n     \"alt\": \"Grassy rocky mountain ridge emerging from thick grey mist\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"mist grey\",\n      \"olive green\",\n      \"dark brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.33,\n     \"by\": \"Rob Bye\",\n     \"page\": \"https://unsplash.com/photos/61XW8CMNX6A\"\n    },\n    {\n     \"id\": 807,\n     \"alt\": \"Lone tree on a grassy slope disappearing into thick fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"moss green\",\n      \"mist grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.78,\n     \"by\": \"Tiago Aguiar\",\n     \"page\": \"https://unsplash.com/photos/FtVQIQ9rDFI\"\n    },\n    {\n     \"id\": 886,\n     \"alt\": \"Flat grassy field vanishing into pale yellow fog\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"straw yellow\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.33,\n     \"by\": \"Glen Carrie\",\n     \"page\": \"https://unsplash.com/photos/p62O--o1x-U\"\n    },\n    {\n     \"id\": 925,\n     \"alt\": \"Conifer trees fading into dense grey fog on a hillside\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"mist grey\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"right\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Patrick Fore\",\n     \"page\": \"https://unsplash.com/photos/vpAKO21abME\"\n    },\n    {\n     \"id\": 965,\n     \"alt\": \"Long bridge disappearing into thick grey fog\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"mist grey\",\n      \"slate\",\n      \"pale green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Liane Metzler\",\n     \"page\": \"https://unsplash.com/photos/c5uShPcKLAE\"\n    },\n    {\n     \"id\": 966,\n     \"alt\": \"Forested mountainside sloping diagonally beneath white fog\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"olive green\",\n      \"brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Alberto Restifo\",\n     \"page\": \"https://unsplash.com/photos/kKrfPaKgE1c\"\n    },\n    {\n     \"id\": 991,\n     \"alt\": \"Hazy sun above layered dark hills in sepia tones\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"sepia\",\n      \"dark brown\",\n      \"pale gold\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Fritz Bielmeier\",\n     \"page\": \"https://unsplash.com/photos/ooJi3CJQRa8\"\n    },\n    {\n     \"id\": 1028,\n     \"alt\": \"Bare dead trees standing in dry ground under sepia haze\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"sepia\",\n      \"tan\",\n      \"dark brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Dikaseva\",\n     \"page\": \"https://unsplash.com/photos/zvf7cZ0PC20\"\n    }\n   ]\n  },\n  \"coast\": {\n   \"title\": \"Coast\",\n   \"note\": \"sea, shoreline, cliffs, piers and beaches\",\n   \"sectors\": [\n    \"hospitality\",\n    \"health\",\n    \"real-estate\",\n    \"restaurant\",\n    \"event\",\n    \"fashion\",\n    \"other\"\n   ],\n   \"keywords\": [\n    \"coast\",\n    \"sea\",\n    \"ocean\",\n    \"beach\",\n    \"surf\",\n    \"island\",\n    \"harbour\",\n    \"harbor\",\n    \"seaside\",\n    \"sail\",\n    \"boat\",\n    \"fish\",\n    \"marine\",\n    \"cliff\",\n    \"guesthouse\",\n    \"shore\",\n    \"bay\",\n    \"atlantic\",\n    \"lookout\"\n   ],\n   \"primary\": [\n    \"hospitality\"\n   ],\n   \"photos\": [\n    {\n     \"id\": 77,\n     \"alt\": \"Wooden jetty leading to a small pavilion over calm sea\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"warm tan\",\n      \"pale teal\",\n      \"soft grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.48,\n     \"by\": \"May Pamintuan\",\n     \"page\": \"https://unsplash.com/photos/j9nfqTi5T5o\"\n    },\n    {\n     \"id\": 626,\n     \"alt\": \"Red and white lighthouse in turquoise sea below a chalk cliff\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"turquoise\",\n      \"white\",\n      \"grass green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Nick Diamantidis\",\n     \"page\": \"https://unsplash.com/photos/jkPKQWK1sKU\"\n    },\n    {\n     \"id\": 640,\n     \"alt\": \"Aerial view of turquoise surf breaking onto golden sand\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"sand\",\n      \"turquoise\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Sarah Bürvenich\",\n     \"page\": \"https://unsplash.com/photos/vigsqYux_-8\"\n    },\n    {\n     \"id\": 641,\n     \"alt\": \"Empty lifeguard chair on a beach at pastel dusk\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"peach\",\n      \"slate blue\",\n      \"dusty teal\"\n     ],\n     \"mono\": false,\n     \"calm\": \"right\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Fré Sonneveld\",\n     \"page\": \"https://unsplash.com/photos/2qLT_Rq-2tk\"\n    },\n    {\n     \"id\": 853,\n     \"alt\": \"Lone rock in a calm blue sea beneath a pastel sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"sea blue\",\n      \"peach\",\n      \"pale pink\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.51,\n     \"by\": \"Stephen Radford\",\n     \"page\": \"https://unsplash.com/photos/674bDNKmnIk\"\n    },\n    {\n     \"id\": 1049,\n     \"alt\": \"Rock island reflected on a wet beach under a pale sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"soft white\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.25,\n     \"by\": \"Rosan Harmens\",\n     \"page\": \"https://unsplash.com/photos/Sd8O2SgKDJA\"\n    },\n    {\n     \"id\": 1052,\n     \"alt\": \"Black sea stacks off a dark beach with white surf under a pale sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"black\",\n      \"white\",\n      \"pale grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Annie Spratt\",\n     \"page\": \"https://unsplash.com/photos/x8R2oSWZRSE\"\n    },\n    {\n     \"id\": 12,\n     \"alt\": \"Dark rocks on a sandy beach with calm sea and islands\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"sand beige\",\n      \"dark brown\",\n      \"pale grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Paul Jarvis\",\n     \"page\": \"https://unsplash.com/photos/I_9ILwtsl_k\"\n    },\n    {\n     \"id\": 14,\n     \"alt\": \"Rocky shoreline meeting a calm pale sea under hazy sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"pale blue\",\n      \"warm brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Paul Jarvis\",\n     \"page\": \"https://unsplash.com/photos/IQ1kOQTJrOQ\"\n    },\n    {\n     \"id\": 16,\n     \"alt\": \"Blue sea and distant islands seen over a rocky driftwood shore\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"sky blue\",\n      \"deep blue\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Paul Jarvis\",\n     \"page\": \"https://unsplash.com/photos/gkT4FfgHO5o\"\n    },\n    {\n     \"id\": 27,\n     \"alt\": \"Person standing on a rocky shore watching misty waves at sunset\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"warm orange\",\n      \"brown\",\n      \"pale gold\"\n     ],\n     \"mono\": false,\n     \"calm\": \"right\",\n     \"quality\": 4,\n     \"ratio\": 1.78,\n     \"by\": \"Yoni Kaplan-Nadel\",\n     \"page\": \"https://unsplash.com/photos/iJnZwLBOB1I\"\n    },\n    {\n     \"id\": 47,\n     \"alt\": \"Long wooden pier over misty surf in black and white\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"light grey\",\n      \"charcoal\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Christopher Sardegna\",\n     \"page\": \"https://unsplash.com/photos/uDUiRS8YroY\"\n    },\n    {\n     \"id\": 68,\n     \"alt\": \"Curving pier with a railing, lamp post and weather vane\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"light grey\",\n      \"charcoal\"\n     ],\n     \"mono\": true,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Cristian Moscoso\",\n     \"page\": \"https://unsplash.com/photos/2SfRAWkinpU\"\n    },\n    {\n     \"id\": 108,\n     \"alt\": \"Palm trees silhouetted against a bright washed-out sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"soft pink\",\n      \"dark brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Florian Klauer\",\n     \"page\": \"https://unsplash.com/photos/t1mqA3V3-7g\"\n    },\n    {\n     \"id\": 144,\n     \"alt\": \"Pavilion at the end of a pier over waves, monochrome\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"black\",\n      \"white\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.78,\n     \"by\": \"Mouly Kumar\",\n     \"page\": \"https://unsplash.com/photos/TuOiIpkIea8\"\n    },\n    {\n     \"id\": 154,\n     \"alt\": \"Hazy beach at dusk with distant walkers and soft surf\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"dusty pink\",\n      \"muted purple\",\n      \"pale blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Christopher Sardegna\",\n     \"page\": \"https://unsplash.com/photos/x_jTtMOOMd4\"\n    },\n    {\n     \"id\": 162,\n     \"alt\": \"Aerial view of a coastline with turquoise sea and patchwork fields\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"turquoise\",\n      \"sand brown\",\n      \"deep blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Dillon McIntosh\",\n     \"page\": \"https://unsplash.com/photos/SlGVAKyP20U\"\n    },\n    {\n     \"id\": 179,\n     \"alt\": \"Waves breaking around dark rocks on a misty shoreline\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"slate grey\",\n      \"white\",\n      \"warm brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Angelina Odemchuk\",\n     \"page\": \"https://unsplash.com/photos/lp0IFw6YqZg\"\n    },\n    {\n     \"id\": 215,\n     \"alt\": \"Wide empty sandy beach with palm trees and blue sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale sand\",\n      \"sky blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 4,\n     \"ratio\": 1.33,\n     \"by\": \"Paula Borowska\",\n     \"page\": \"https://unsplash.com/photos/04paG2PxKGs\"\n    },\n    {\n     \"id\": 218,\n     \"alt\": \"Calm turquoise bay between two limestone cliffs under storm clouds\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"turquoise\",\n      \"slate grey\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"centre\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Monika Majkowska\",\n     \"page\": \"https://unsplash.com/photos/Nq8LdWC7HnM\"\n    },\n    {\n     \"id\": 268,\n     \"alt\": \"White lifeguard chair standing in dune grass under overcast sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"straw yellow\",\n      \"green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.52,\n     \"by\": \"davide ragusa\",\n     \"page\": \"https://unsplash.com/photos/vc3ZOCf5BN8\"\n    },\n    {\n     \"id\": 317,\n     \"alt\": \"Long wooden pier with railings reaching toward a pastel horizon\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"weathered brown\",\n      \"pale peach\",\n      \"soft blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.78,\n     \"by\": \"Paula Borowska\",\n     \"page\": \"https://unsplash.com/photos/cKYgt4K0g5w\"\n    },\n    {\n     \"id\": 323,\n     \"alt\": \"Steep green headlands dropping into a deep blue bay\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"deep blue\",\n      \"olive green\",\n      \"tan\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Paweł Wojciechowski\",\n     \"page\": \"https://unsplash.com/photos/QYAojSRu82c\"\n    },\n    {\n     \"id\": 347,\n     \"alt\": \"Dune grass bending in wind beneath a wide white sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"straw gold\",\n      \"grey blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Alex Talmon\",\n     \"page\": \"https://unsplash.com/photos/umq-jgTjr28\"\n    },\n    {\n     \"id\": 356,\n     \"alt\": \"Lone surfer walking along a misty beach in black and white\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"charcoal\",\n      \"silver grey\",\n      \"white\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.33,\n     \"by\": \"Daniel Ruswick\",\n     \"page\": \"https://unsplash.com/photos/fqtOAqbbnJg\"\n    },\n    {\n     \"id\": 372,\n     \"alt\": \"Lifeguard tower on an empty sandy beach under a hazy sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale blue\",\n      \"sand\",\n      \"soft grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Gabriel Santiago\",\n     \"page\": \"https://unsplash.com/photos/KWkMiUIxcD0\"\n    },\n    {\n     \"id\": 374,\n     \"alt\": \"Coastline with green headlands, a curving beach and turquoise sea\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"turquoise\",\n      \"deep green\",\n      \"sky blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Ma. Alejandra\",\n     \"page\": \"https://unsplash.com/photos/TDahcrcPhhA\"\n    },\n    {\n     \"id\": 404,\n     \"alt\": \"Waves breaking in white foam around a rugged brown rock\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey blue\",\n      \"white\",\n      \"rust brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Cole Patrick\",\n     \"page\": \"https://unsplash.com/photos/H28ODcp4EUk\"\n    },\n    {\n     \"id\": 440,\n     \"alt\": \"Rugged coastal headlands in soft backlit haze at sunset\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"pale gold\",\n      \"warm brown\",\n      \"cream\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Artur Pokusin\",\n     \"page\": \"https://unsplash.com/photos/0nv-h04oPhM\"\n    },\n    {\n     \"id\": 483,\n     \"alt\": \"Dark sea cliffs and rocks with white surf breaking below\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"charcoal\",\n      \"teal\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.78,\n     \"by\": \"Paulo Simões Mendes\",\n     \"page\": \"https://unsplash.com/photos/hrcRtexM7M0\"\n    },\n    {\n     \"id\": 485,\n     \"alt\": \"White chalk cliffs above a curved beach in sea mist\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"turquoise\",\n      \"sand\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.51,\n     \"by\": \"David Marcu\",\n     \"page\": \"https://unsplash.com/photos/DNXWtB33WWE\"\n    },\n    {\n     \"id\": 574,\n     \"alt\": \"Grassy cliff and black sand beach with sea stacks offshore\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"green\",\n      \"charcoal\",\n      \"pale blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"right\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Julien Lavallée\",\n     \"page\": \"https://unsplash.com/photos/lVtlz3JRV6o\"\n    },\n    {\n     \"id\": 606,\n     \"alt\": \"Wooden boardwalk winding through grassy dunes toward the sea\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale grey\",\n      \"sage green\",\n      \"sand\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Aleksandra Boguslawska\",\n     \"page\": \"https://unsplash.com/photos/MS7KD9Ti7FQ\"\n    },\n    {\n     \"id\": 614,\n     \"alt\": \"Aerial view of white surf washing over a dark rocky shore\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"charcoal\",\n      \"white\",\n      \"dark brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Josefa Holland-Merten\",\n     \"page\": \"https://unsplash.com/photos/GnP5Kfg5ebU\"\n    },\n    {\n     \"id\": 732,\n     \"alt\": \"Dark rocky shoreline beside a calm sea under a pale cloudy sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"pale blue\",\n      \"soft grey\",\n      \"charcoal\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Dominik Schröder\",\n     \"page\": \"https://unsplash.com/photos/ivieBAESVWM\"\n    },\n    {\n     \"id\": 851,\n     \"alt\": \"Aerial view of turquoise sea meeting a curved reddish coastline\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"turquoise\",\n      \"teal\",\n      \"rust brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.66,\n     \"by\": \"Tiago Aguiar\",\n     \"page\": \"https://unsplash.com/photos/uXzNVOZT5no\"\n    },\n    {\n     \"id\": 969,\n     \"alt\": \"Wet rocky shore with sea stacks under a bright sky, black and white\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"black\",\n      \"grey\",\n      \"silver\"\n     ],\n     \"mono\": true,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Lee Miller\",\n     \"page\": \"https://unsplash.com/photos/_rsGm7nob3w\"\n    },\n    {\n     \"id\": 997,\n     \"alt\": \"Aerial view of a forested headland beside deep blue sea\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"deep blue\",\n      \"forest green\",\n      \"yellow green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 0.68,\n     \"by\": \"Mickey O'neil\",\n     \"page\": \"https://unsplash.com/photos/GSzD6vGIWKM\"\n    },\n    {\n     \"id\": 1055,\n     \"alt\": \"Wide wet sand flat with a distant shoreline under a pale sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"warm brown\",\n      \"sand\",\n      \"off-white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Neil Thomas\",\n     \"page\": \"https://unsplash.com/photos/12rzbJhQ89E\"\n    }\n   ]\n  },\n  \"mountain\": {\n   \"title\": \"Mountain\",\n   \"note\": \"peaks, alpine valleys, snow and rock\",\n   \"sectors\": [\n    \"hospitality\",\n    \"health\",\n    \"event\",\n    \"physical-product\",\n    \"nonprofit\",\n    \"other\",\n    \"education\"\n   ],\n   \"keywords\": [\n    \"mountain\",\n    \"alpine\",\n    \"peak\",\n    \"summit\",\n    \"hike\",\n    \"hiking\",\n    \"climb\",\n    \"outdoor\",\n    \"lodge\",\n    \"chalet\",\n    \"trail\",\n    \"expedition\"\n   ],\n   \"photos\": [\n    {\n     \"id\": 235,\n     \"alt\": \"Snow-covered peak rising above dark forested slopes and a lake\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"slate blue\",\n      \"white\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Paul E. Harrer\",\n     \"page\": \"https://unsplash.com/photos/TI-B-TNYJMU\"\n    },\n    {\n     \"id\": 260,\n     \"alt\": \"Snowy mountain peak framed by dark pine trees in mist\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"pale grey\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"centre\",\n     \"quality\": 5,\n     \"ratio\": 0.67,\n     \"by\": \"Sylwia Bartyzel\",\n     \"page\": \"https://unsplash.com/photos/OdAqbedkfiA\"\n    },\n    {\n     \"id\": 830,\n     \"alt\": \"Layered blue mountain ridges receding into haze\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"cobalt blue\",\n      \"pale blue\",\n      \"navy\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Luca Zanon\",\n     \"page\": \"https://unsplash.com/photos/X0OoHrPvgXE\"\n    },\n    {\n     \"id\": 906,\n     \"alt\": \"Sunlit snowy pyramid peak against a clear blue sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"sky blue\",\n      \"white\",\n      \"dark slate\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.33,\n     \"by\": \"Andras Toth\",\n     \"page\": \"https://unsplash.com/photos/E9CrQou9K0Y\"\n    },\n    {\n     \"id\": 931,\n     \"alt\": \"Layered mountain slopes fading into blue haze\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"steel blue\",\n      \"pale blue\",\n      \"dark teal\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.51,\n     \"by\": \"Paul Earle\",\n     \"page\": \"https://unsplash.com/photos/xJ2tjuUHD9M\"\n    },\n    {\n     \"id\": 1018,\n     \"alt\": \"Green cliffs and a winding road under low mist\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"moss green\",\n      \"mist grey\",\n      \"dark brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 5,\n     \"ratio\": 1.33,\n     \"by\": \"Andrew Ridley\",\n     \"page\": \"https://unsplash.com/photos/Kt5hRENuotI\"\n    },\n    {\n     \"id\": 29,\n     \"alt\": \"Rocky ridges and snow-covered peaks in a high mountain range\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"slate grey\",\n      \"white\",\n      \"blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Go Wild\",\n     \"page\": \"https://unsplash.com/photos/V0yAek6BgGk\"\n    },\n    {\n     \"id\": 66,\n     \"alt\": \"Lone mountain peak beyond open grassland under heavy grey cloud\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"olive green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.33,\n     \"by\": \"Nicholas Swanson\",\n     \"page\": \"https://unsplash.com/photos/agnhLQWqr1Q\"\n    },\n    {\n     \"id\": 121,\n     \"alt\": \"Hazy mountain gorge with steep slopes in black and white\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"black\",\n      \"white\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Radio Pink\",\n     \"page\": \"https://unsplash.com/photos/p-bkdO43shE\"\n    },\n    {\n     \"id\": 166,\n     \"alt\": \"Moody valley with a river, dark hills and a foreground boulder\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"charcoal\",\n      \"grey\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.78,\n     \"by\": \"Romain Briaux\",\n     \"page\": \"https://unsplash.com/photos/yD3PXDV7Sjc\"\n    },\n    {\n     \"id\": 296,\n     \"alt\": \"Snow-capped mountain range beneath a deep blue sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"deep blue\",\n      \"white\",\n      \"dark brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Greg Shield\",\n     \"page\": \"https://unsplash.com/photos/Du30R57aCyM\"\n    },\n    {\n     \"id\": 327,\n     \"alt\": \"Snow-covered mountain range under a clear teal sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"teal\",\n      \"white\",\n      \"rust brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Ryan Schroeder\",\n     \"page\": \"https://unsplash.com/photos/Gg7uKdHFb_c\"\n    },\n    {\n     \"id\": 368,\n     \"alt\": \"Sheer granite cliffs above a hazy valley in warm evening light\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"peach\",\n      \"warm grey\",\n      \"slate\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Tyssul Patel\",\n     \"page\": \"https://unsplash.com/photos/o-zOatT4kQw\"\n    },\n    {\n     \"id\": 377,\n     \"alt\": \"Snow-capped mountain range under a dark blue evening sky\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"navy\",\n      \"slate blue\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Martin Staněk\",\n     \"page\": \"https://unsplash.com/photos/8WClaa1CmZ0\"\n    },\n    {\n     \"id\": 393,\n     \"alt\": \"Green mountain streaked with snow rising above a dark gravel plain\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"moss green\",\n      \"charcoal\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Alex Talmon\",\n     \"page\": \"https://unsplash.com/photos/UFskvng2OMU\"\n    },\n    {\n     \"id\": 426,\n     \"alt\": \"Layered blue mountains and a hazy valley under streaked clouds\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"slate blue\",\n      \"teal\",\n      \"pale grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Ales Krivec\",\n     \"page\": \"https://unsplash.com/photos/01ZeHnK3F_4\"\n    },\n    {\n     \"id\": 450,\n     \"alt\": \"Turquoise lake in a forested valley between snow-dusted mountains\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"turquoise\",\n      \"slate grey\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.51,\n     \"by\": \"Tanvi Malik\",\n     \"page\": \"https://unsplash.com/photos/OeC1wIsKNpk\"\n    },\n    {\n     \"id\": 523,\n     \"alt\": \"Volcanic crater rising from a hazy plain beneath a teal sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"teal\",\n      \"tan\",\n      \"brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 2.21,\n     \"by\": \"Harman Abiwardani\",\n     \"page\": \"https://unsplash.com/photos/WLUHO9A_xik\"\n    },\n    {\n     \"id\": 538,\n     \"alt\": \"Bird soaring above snowy mountain ridges in black and white\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"grey\",\n      \"white\",\n      \"black\"\n     ],\n     \"mono\": true,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.51,\n     \"by\": \"Julia Revitt\",\n     \"page\": \"https://unsplash.com/photos/yypv2Tu-mxU\"\n    },\n    {\n     \"id\": 565,\n     \"alt\": \"Snowy peak veiled in cloud with birds crossing a white sky\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"pale grey\",\n      \"dark brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"René Reichelt\",\n     \"page\": \"https://unsplash.com/photos/HzaT5l4Fzqc\"\n    },\n    {\n     \"id\": 591,\n     \"alt\": \"Jagged rock pinnacle rising through swirling white cloud\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"grey\",\n      \"tan\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 0.75,\n     \"by\": \"Billy Onjea\",\n     \"page\": \"https://unsplash.com/photos/_qGq1Z2Bk6c\"\n    },\n    {\n     \"id\": 684,\n     \"alt\": \"Jagged snow-covered peaks under a dark blue sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"navy\",\n      \"white\",\n      \"slate blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.78,\n     \"by\": \"Lee Roylland\",\n     \"page\": \"https://unsplash.com/photos/dfZbts6B4yw\"\n    },\n    {\n     \"id\": 735,\n     \"alt\": \"Steep dark cliffs with fog drifting through the gap between them\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"charcoal\",\n      \"mist grey\",\n      \"deep green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"centre\",\n     \"quality\": 4,\n     \"ratio\": 0.62,\n     \"by\": \"wyman H\",\n     \"page\": \"https://unsplash.com/photos/ZQeRH1XD4Tc\"\n    },\n    {\n     \"id\": 809,\n     \"alt\": \"Rocky mountain peak breaking through thick white clouds\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"slate grey\",\n      \"blue grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Namphuong Van\",\n     \"page\": \"https://unsplash.com/photos/sP4UZnpSiN4\"\n    },\n    {\n     \"id\": 814,\n     \"alt\": \"Jagged rocky peaks under a soft pink and violet dusk sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"dusty violet\",\n      \"soft pink\",\n      \"slate grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.53,\n     \"by\": \"Ales Krivec\",\n     \"page\": \"https://unsplash.com/photos/duoMdMm3aY0\"\n    },\n    {\n     \"id\": 827,\n     \"alt\": \"Conical mountain silhouette above a still lake under a starry dusk sky\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"indigo\",\n      \"dusky violet\",\n      \"navy\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 0.67,\n     \"by\": \"kazuend\",\n     \"page\": \"https://unsplash.com/photos/2KXEb_8G5vo\"\n    },\n    {\n     \"id\": 866,\n     \"alt\": \"Snowy mountain peak behind a snow slope under pink-tinted clouds\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"dusky blue\",\n      \"soft pink\",\n      \"white\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Samuel Zeller\",\n     \"page\": \"https://unsplash.com/photos/9RqA6tnT0gA\"\n    },\n    {\n     \"id\": 873,\n     \"alt\": \"Turquoise lake between steep rocky mountains with distant snow\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"teal\",\n      \"slate grey\",\n      \"pale cream\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 0.67,\n     \"by\": \"Daniel Roe\",\n     \"page\": \"https://unsplash.com/photos/lpjb_UMOyx8\"\n    },\n    {\n     \"id\": 918,\n     \"alt\": \"Rocky peak wrapped in sunlit cloud above a forested valley\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"warm gold\",\n      \"dark green\",\n      \"grey brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.51,\n     \"by\": \"David Marcu\",\n     \"page\": \"https://unsplash.com/photos/CaQ_KITtnVY\"\n    },\n    {\n     \"id\": 929,\n     \"alt\": \"Green cliff face rising out of dense white mist\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"moss green\",\n      \"grey\"\n     ],\n     \"mono\": false,\n     \"calm\": \"left\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Tiago Muraro\",\n     \"page\": \"https://unsplash.com/photos/1kEHpwZdmtc\"\n    }\n   ]\n  },\n  \"forest\": {\n   \"title\": \"Forest\",\n   \"note\": \"woodland, paths between trees, moss and filtered light\",\n   \"sectors\": [\n    \"hospitality\",\n    \"health\",\n    \"nonprofit\",\n    \"education\",\n    \"physical-product\",\n    \"other\"\n   ],\n   \"keywords\": [\n    \"forest\",\n    \"wood\",\n    \"tree\",\n    \"cabin\",\n    \"nature\",\n    \"green\",\n    \"organic\",\n    \"sustainable\",\n    \"timber\",\n    \"garden\"\n   ],\n   \"photos\": [\n    {\n     \"id\": 229,\n     \"alt\": \"Path through tall pine trees fading into blue-grey fog\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"blue grey\",\n      \"dark green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 5,\n     \"ratio\": 1.5,\n     \"by\": \"Orlova Maria\",\n     \"page\": \"https://unsplash.com/photos/7FLh300YONc\"\n    },\n    {\n     \"id\": 10,\n     \"alt\": \"Dense evergreen forest with a blue lake and distant hills beyond\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"deep green\",\n      \"teal blue\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Paul Jarvis\",\n     \"page\": \"https://unsplash.com/photos/6J--NXulQCs\"\n    },\n    {\n     \"id\": 190,\n     \"alt\": \"Path winding between rows of tall pine trunks\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"dark brown\",\n      \"moss green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"James Forbes\",\n     \"page\": \"https://unsplash.com/photos/jrzvClypPq8\"\n    },\n    {\n     \"id\": 216,\n     \"alt\": \"Narrow dirt trail through mossy green woodland\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"moss green\",\n      \"brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Paul Jarvis\",\n     \"page\": \"https://unsplash.com/photos/9702xTENR-M\"\n    },\n    {\n     \"id\": 243,\n     \"alt\": \"Autumn larch forest on a foggy hillside with a footpath\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"rust brown\",\n      \"pale grey\",\n      \"olive green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Orlova Maria\",\n     \"page\": \"https://unsplash.com/photos/DYW1s0AfLwo\"\n    },\n    {\n     \"id\": 423,\n     \"alt\": \"Snow-laden fir trees fading into pale winter fog\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"pale blue\",\n      \"grey green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"centre\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Gabriel Santiago\",\n     \"page\": \"https://unsplash.com/photos/pTgTMVxQE_k\"\n    },\n    {\n     \"id\": 476,\n     \"alt\": \"Sunlight bursting between tall redwood trunks in a shaded forest\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"dark brown\",\n      \"deep green\",\n      \"gold\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Mr. Marco\",\n     \"page\": \"https://unsplash.com/photos/QP1dUyQ8WsI\"\n    },\n    {\n     \"id\": 498,\n     \"alt\": \"Upward view of towering redwood trunks converging toward the canopy\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"green\",\n      \"reddish brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Kim Daniel\",\n     \"page\": \"https://unsplash.com/photos/JsqAqevX6lg\"\n    },\n    {\n     \"id\": 559,\n     \"alt\": \"Snow-covered lane lined with bare frosted trees\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"white\",\n      \"grey brown\"\n     ],\n     \"mono\": false,\n     \"calm\": \"bottom\",\n     \"quality\": 4,\n     \"ratio\": 1.51,\n     \"by\": \"Ali Inay\",\n     \"page\": \"https://unsplash.com/photos/yNaGxHqjOuw\"\n    },\n    {\n     \"id\": 600,\n     \"alt\": \"Sunbeams streaming through tall conifers in a dark forest\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"dark green\",\n      \"pale gold\",\n      \"black\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Dustin Scarpitti\",\n     \"page\": \"https://unsplash.com/photos/eWBseWsTEpA\"\n    },\n    {\n     \"id\": 704,\n     \"alt\": \"Upward view of tall bamboo stems converging in a green canopy\",\n     \"tone\": \"dark\",\n     \"colours\": [\n      \"dark green\",\n      \"green\",\n      \"black\"\n     ],\n     \"mono\": false,\n     \"calm\": \"none\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Ståle Grut\",\n     \"page\": \"https://unsplash.com/photos/NUgw97CVdAk\"\n    },\n    {\n     \"id\": 730,\n     \"alt\": \"Snow-dusted conifer forest fading into pale winter fog\",\n     \"tone\": \"light\",\n     \"colours\": [\n      \"frost white\",\n      \"pale grey\",\n      \"slate green\"\n     ],\n     \"mono\": false,\n     \"calm\": \"top\",\n     \"quality\": 4,\n     \"ratio\": 1.5,\n     \"by\": \"Ryan Pohanic\",\n     \"page\": \"https://unsplash.com/photos/W3V2tQAZxPA\"\n    },\n    {\n     \"id\": 805,\n     \"alt\": \"Band of dark conifer forest between a meadow and a blank white sky\",\n     \"tone\": \"mid\",\n     \"colours\": [\n      \"white\",\n      \"dark green\",\n      \"olive brown\"\n     ],\n     \"mono\": false,\n     \"calm\"\n\n<!-- [TRUNCATED AT 50KB] -->\n\n<!-- File: skills/taste-skill/library/sections.json (Tokens: ~13651 | Category: anthropic-skill) -->\n[\n {\n  \"id\": \"features-capabilities-at-poster-scale\",\n  \"role\": \"features\",\n  \"name\": \"Capabilities at poster scale\",\n  \"shape\": \"list\",\n  \"tags\": [\n   \"type-led\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"type-only-statement\",\n   \"hero-object\",\n   \"loud-flat-poster\",\n   \"borrowed-category\",\n   \"colour-chapters\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"No images. The heading, two to four words, is the first line of the list itself, set at the same size as the items but in the soft ink, so no separate title sits above. Five to eight capability names follow, one per line, at clamp(40px, 5.2vw, 84px), medium to heavy weight, leading 1.0, tight tracking, flush left on the page margin across columns 1–8 of 12. Each name's one-sentence description is set at 16–18px in columns 9–12, its first baseline aligned with the name's baseline (CSS grid, align-items: first baseline). Rows are separated by 0.35em of space and nothing else. On hover one row keeps full ink while the others fall to 35% opacity. Leave 18–22vh of empty ground above and below; nothing else shares the section.\",\n  \"mobile\": \"Names drop to 11vw and stay one per line; a name that will not fit breaks onto a second line with a hanging indent. Each description sits directly under its name at 16px, indented one margin width, with 28px before the next name. The soft-ink heading line stays as the first row. All rows at full ink.\",\n  \"seenIn\": [\n   \"aww-cominvi\",\n   \"aww-cerebrium\",\n   \"opl-specia1ne\"\n  ]\n },\n {\n  \"id\": \"features-pinned-heading-passing-rows\",\n  \"role\": \"features\",\n  \"name\": \"Pinned heading, passing rows\",\n  \"shape\": \"pinned\",\n  \"tags\": [\n   \"colour-field\",\n   \"type-led\"\n  ],\n  \"directions\": [\n   \"pinned-poster\",\n   \"loud-flat-poster\",\n   \"colour-chapters\",\n   \"split-stage\",\n   \"editorial-report\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One flat saturated field, full-bleed, as tall as its content. Columns 1–5: the heading, two or three words, at clamp(56px, 6.6vw, 104px) in the heaviest weight, position: sticky; top: 32px, so it holds while the right side travels. Columns 7–12: four to six capability blocks stacked with 120px between them. Each block is a title at 28px bold, then a two-part row: a portrait photograph at 3:4, 180–220px wide with square corners, and beside it, top-aligned, a plain list of four to six short lines at 18px with 14px between lines. Photographs alternate between the left and the right of their list, so the column does not read as a ladder. One ink colour, chosen for contrast on the field. The heading releases when the bottom of the last block reaches it.\",\n  \"mobile\": \"The heading becomes a sticky bar at the top of the section: one line at 9vw on the field colour with 12px padding, holding while blocks pass under it. Each block stacks its title, a full-width 4:3 photograph, then the list at 17px. 72px between blocks.\",\n  \"seenIn\": [\n   \"opl-protip-marketing\",\n   \"aww-cerebrium\",\n   \"aww-sharplink\"\n  ]\n },\n {\n  \"id\": \"features-one-scene-stepping-statements\",\n  \"role\": \"features\",\n  \"name\": \"One scene, stepping statements\",\n  \"shape\": \"full-bleed\",\n  \"tags\": [\n   \"photo-led\"\n  ],\n  \"directions\": [\n   \"place-carries-it\",\n   \"pinned-poster\",\n   \"dark-room\",\n   \"hero-object\",\n   \"uneven-photographs\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A wrapper 350–450vh tall holds a sticky full-bleed photograph (100vw by 100svh) with a calm, symmetrical subject and a clear upper third; a neutral dark scrim covers only that upper third. At top centre, five or six short statements of two to five words are stacked at 18–20px with 10px between them; the first of them is the section's heading. One statement is at full white and the rest at 45% opacity; the active line steps down the stack as the reader scrolls (IntersectionObserver on invisible 70vh markers). For each statement, two small photographs with square corners, 160–240px wide and of different ratios, fade in left and right of the centre line at different heights, then leave when the next pair arrives. No other text. A low-key image on a deep ground works equally well.\",\n  \"mobile\": \"The photograph stays sticky at 100svh, cropped to its centre. The statement stack moves to the bottom third over a scrim, at 17px, left-aligned on the margin. Each statement brings one small photograph only, 44vw wide, placed in the top-right corner with a 16px margin.\",\n  \"seenIn\": [\n   \"aww-seasats\",\n   \"opl-eagles-nest\"\n  ]\n },\n {\n  \"id\": \"features-stacking-colour-sheets\",\n  \"role\": \"features\",\n  \"name\": \"Stacking colour sheets\",\n  \"shape\": \"stack\",\n  \"tags\": [\n   \"colour-field\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"colour-chapters\",\n   \"page-is-the-object\",\n   \"pinned-poster\",\n   \"loud-flat-poster\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Three to five capabilities, each a full-width flat colour sheet about 86svh tall with only its top corners rounded at 28px. Every sheet is position: sticky, with top offsets rising by 72px from one sheet to the next, so each new sheet slides up over the last and leaves the previous sheet's title band showing, like tabbed folders in a drawer. Inside a sheet: the capability name top-left at clamp(28px, 3vw, 44px), sitting within that 72px band; a paragraph of up to 40ch at 18px bottom-left; and in columns 7–12 one photograph filling the sheet from below the band to the bottom edge, square corners, no inset. Sheet colours follow the palette in a fixed order, with ink chosen per sheet. The heading, two to four words at clamp(40px, 5vw, 80px), sits on the ground above the stack with 48px beneath and scrolls away normally.\",\n  \"mobile\": \"Sheets stay sticky but the offset shrinks to 52px and the name drops to 22px so it fits the visible band. Inside each sheet the photograph comes first at 4:3 and full width, then the paragraph at 17px with 20px padding. Sheets are as tall as their content, 70svh at least.\",\n  \"seenIn\": [\n   \"aww-hilden-kaira\",\n   \"opl-nia-creative\",\n   \"opl-april-leihuanani-evangelista\",\n   \"aww-mosbys-files\"\n  ]\n },\n {\n  \"id\": \"features-mosaic-of-unlike-tiles\",\n  \"role\": \"features\",\n  \"name\": \"Mosaic of unlike tiles\",\n  \"shape\": \"mosaic\",\n  \"tags\": [\n   \"dense\",\n   \"colour-field\"\n  ],\n  \"directions\": [\n   \"dense-tiles\",\n   \"editorial-report\",\n   \"colour-chapters\",\n   \"specimen-catalogue\",\n   \"loud-flat-poster\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A 12-column grid with 8px gaps and rows of 96px, filled with no empty cells and no outlines. Six to eight filled tiles in four sizes only: 6×5, 6×3, 3×3 and 3×2 (columns × rows). The rule that keeps it from being a card grid: no two neighbouring tiles hold the same kind of thing. One tile is the heading alone, two to four words at 4vw, top-left. One is a photograph covering its tile. One is a single figure at 6vw with a caption. One is a short list of four lines at 20px. The others are a single sentence each at 28–32px. Text sits top-left with 24px padding; tiles holding one sentence leave their lower half empty. Tile fills: the ground one tone darker, two palette colours, and photographs. One corner radius everywhere, either 0 or 8px.\",\n  \"mobile\": \"Two columns with 6px gaps. The heading tile and the photograph tile span both columns; sentence tiles span both at their natural height; the figure and list tiles sit side by side as a pair of squares. Order: heading, photograph, pair, sentence, sentence.\",\n  \"seenIn\": [\n   \"opl-sand-studio\",\n   \"opl-builders-table\",\n   \"aww-cominvi\",\n   \"opl-uglycash\"\n  ]\n },\n {\n  \"id\": \"features-statement-cell-dark-rows\",\n  \"role\": \"features\",\n  \"name\": \"Statement cell, dark rows\",\n  \"shape\": \"split\",\n  \"tags\": [\n   \"type-led\",\n   \"dense\"\n  ],\n  \"directions\": [\n   \"dense-tiles\",\n   \"editorial-report\",\n   \"type-only-statement\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Two halves butted together, each 50vw wide and at least 90svh tall, with no gap. Left half, in a pale tone: the heading in three short lines at clamp(36px, 4.2vw, 68px), its middle line pushed flush right while the first and third stay flush left (text-align set per line), so the block zigzags inside the cell. A two-sentence paragraph of 30ch sits at the bottom-left and the single action at the bottom-right on the same baseline. Right half, in the darkest tone: four or five rows of equal height filling it, told apart by alternating two near-black tones, not by lines. Each row is a three-part grid: a title at 28px (5 parts), a short paragraph at 16px (4 parts) and a plain list of three terms at 15px (3 parts), all top-aligned with 28px padding. No images anywhere in the section.\",\n  \"mobile\": \"The halves stack. The light cell comes first at 70svh with the zigzag heading at 10vw and the paragraph at its foot. The dark rows follow at full width; each row stacks its title and paragraph, and its three terms run inline as one sentence separated by commas. Rows keep the alternating tones.\",\n  \"seenIn\": [\n   \"aww-aspen-search\"\n  ]\n },\n {\n  \"id\": \"features-staggered-fragment-cells\",\n  \"role\": \"features\",\n  \"name\": \"Staggered fragment cells\",\n  \"shape\": \"grid\",\n  \"tags\": [\n   \"ui-led\",\n   \"dense\"\n  ],\n  \"directions\": [\n   \"product-performs\",\n   \"dense-tiles\",\n   \"quiet-instrument\"\n  ],\n  \"needs\": [\n   \"product-ui\"\n  ],\n  \"blueprint\": \"A three-column grid of six filled cells with 8px gaps, each cell 420–460px tall and filled one tone off the ground, no outlines. Every cell has two parts: a text part (a title at 17px medium and three lines at 15px in the soft ink, 24px padding) and a real fragment of the interface at true size (a control, a menu, a table slice, a swatch strip) docked flush against the opposite edge of the cell and cropped by it. The stagger is the idea: across the first row cells run text-top, fragment-top, text-top; the second row runs the reverse, so fragments form a checkerboard. Fragments differ in shape and size on purpose. The heading, two to four words at 32–40px, sits left-aligned above the grid with 56px beneath it and no supporting line.\",\n  \"mobile\": \"One column of cells at their natural height with 6px gaps. Every cell runs text first, fragment second, but fragments alternate between docking to the left edge and the right edge, and they are allowed to run off the side of the cell at true size instead of shrinking.\",\n  \"seenIn\": [\n   \"opl-dabbit\",\n   \"opl-woblo\"\n  ]\n },\n {\n  \"id\": \"features-small-proof-beside-text\",\n  \"role\": \"features\",\n  \"name\": \"Small proof beside text\",\n  \"shape\": \"list\",\n  \"tags\": [\n   \"quiet\",\n   \"ui-led\"\n  ],\n  \"directions\": [\n   \"quiet-instrument\",\n   \"product-performs\",\n   \"split-stage\",\n   \"name-as-monument\",\n   \"contact-sheet\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One narrow module repeated four to six times down the page, never alternating sides. Each module is 640px wide at most and starts on the page's text margin (at about 22% of the viewport on an understated page). Left part: a flat panel 360px wide and 120 to 200px tall, one tone off the ground, radius 8px, holding one small exact demonstration: a cropped interface fragment at true size, or a tightly cropped photograph covering the panel. Right part, 20px away and top-aligned: a heading of one or two lines at 18px medium and two short paragraphs at 15px in the soft ink, in a column 250px wide. Panel heights vary with their content; text always hangs from the panel's top edge. 96–120px of empty ground between modules. The section heading is 24–28px, on the same left edge, 64px above the first module. In a column under 600px the text moves beneath its panel.\",\n  \"mobile\": \"Each module stacks: the panel at full width and natural height, then heading and paragraphs 16px below on the same left edge, at 17px and 15px. 64px between modules. Panels keep their true-size contents and crop from the right instead of scaling down.\",\n  \"seenIn\": [\n   \"opl-rows\"\n  ]\n },\n {\n  \"id\": \"features-comparison-set-as-text\",\n  \"role\": \"features\",\n  \"name\": \"Comparison set as text\",\n  \"shape\": \"table\",\n  \"tags\": [\n   \"type-led\",\n   \"quiet\"\n  ],\n  \"directions\": [\n   \"type-only-statement\",\n   \"editorial-report\",\n   \"product-performs\",\n   \"quiet-instrument\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A comparison table with no lines and no tick marks. A CSS grid: capability names in columns 1–5 of 12 at 22–24px medium, then three answer columns of equal width (plans, methods, or this against the usual way). Every cell answers in words at 17px: 'Yes, unlimited', 'Up to five', 'Not yet', never a symbol. Seven to ten rows, each 64–72px tall, with every other row on a ground one tone darker so the eye tracks across; rows touch. The column that matters is one filled block in the accent or ink colour running the full height of the table behind its cells and rising 24px above the first row, with its text reversed. Column names sit in the top row at 17px bold. The heading, two to four words at 40–48px, hangs top-left above column 1 with 48px beneath.\",\n  \"mobile\": \"The table turns on its side: one block per capability. The name at 20px bold, then three lines beneath, each giving a column name and its answer at 16px; the featured column's line is set on the filled colour at full width. Blocks alternate the two ground tones.\",\n  \"seenIn\": [\n   \"aww-pp-neue-montreal\"\n  ]\n },\n {\n  \"id\": \"features-one-size-name-columns\",\n  \"role\": \"features\",\n  \"name\": \"One-size name columns\",\n  \"shape\": \"index\",\n  \"tags\": [\n   \"quiet\",\n   \"type-led\",\n   \"dense\"\n  ],\n  \"directions\": [\n   \"contact-sheet\",\n   \"quiet-instrument\",\n   \"name-as-monument\",\n   \"dark-room\",\n   \"uneven-photographs\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Pure text at one size. Three columns start on columns 1, 4 and 7 of the 12-column grid, leaving columns 10–12 empty on purpose. Each column opens with a group name in full ink and continues with a tight stack of six to ten capability names in the soft ink, all at 16–17px, regular weight, line-height 1.25, no bullets and no symbols; one blank line separates group name from stack. Hovering a name brings it to full ink and shows a one-line description in a fixed spot: the top of the empty columns 10–12, at the same size. The heading is no larger than 28px; two or three words, alone on column 1, 96px above the columns. Give the section 20vh of empty ground above and below, so the smallness reads as decided. Works on light or deep grounds.\",\n  \"mobile\": \"Columns stack with 40px between groups; text rises to 18px with line-height 1.4 for touch. Group names stay in full ink. Hover descriptions are dropped; each group ends instead with one sentence in the soft ink that sums it up. The heading is 24px, 48px above.\",\n  \"seenIn\": [\n   \"aww-revelatio-studio\",\n   \"aww-pp-neue-montreal\",\n   \"aww-lama-lama-2\"\n  ]\n },\n {\n  \"id\": \"features-specimens-on-colour-tiles\",\n  \"role\": \"features\",\n  \"name\": \"Specimens on colour tiles\",\n  \"shape\": \"grid\",\n  \"tags\": [\n   \"object-led\",\n   \"colour-field\"\n  ],\n  \"directions\": [\n   \"specimen-catalogue\",\n   \"hero-object\",\n   \"one-motif\",\n   \"colour-chapters\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Each capability is represented by one object photographed alone and shown on a flat colour tile. Columns 1–3 hold the heading (two to four words at 40–52px), top-aligned, with a 30ch sentence beneath and nothing else down the rest of that column. Columns 4–12 hold a grid of five or six tiles in two rows with 10px gaps: tiles are 4:5 except one, which is double width at 8:5 and placed second in the first row. Tile colours rotate through three palette fields. Each photograph is centred at about 70% of its tile's height; on light tiles use mix-blend-mode: multiply so a white studio background disappears. Under each tile, outside it and aligned to its left edge: the capability name at 20px medium and one fact at 16px in the soft ink. No text on the tiles and no hover lift.\",\n  \"mobile\": \"The heading and its sentence sit on top at full width. Tiles become a two-column grid with 8px gaps; the double tile spans both columns at 8:5 and comes first. Names shrink to 17px and facts to 15px, still under each tile.\",\n  \"seenIn\": [\n   \"aww-noho\",\n   \"aww-coffeetech-r\",\n   \"opl-when-you-wish-upon-a-starboy\"\n  ]\n },\n {\n  \"id\": \"features-statements-on-colour-fields\",\n  \"role\": \"features\",\n  \"name\": \"Statements on colour fields\",\n  \"shape\": \"statement\",\n  \"tags\": [\n   \"colour-field\",\n   \"poster\",\n   \"type-led\"\n  ],\n  \"directions\": [\n   \"colour-chapters\",\n   \"loud-flat-poster\",\n   \"type-only-statement\",\n   \"sentence-as-layout\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Three or four full-bleed flat colour fields, each 72–80svh tall, butted together with no gap. Each field holds one benefit and is almost empty. The benefit is a phrase of two to four words at clamp(56px, 9vw, 150px), heavy, leading 0.9, on two lines at most, hugging the bottom-left corner with 28px margins. Its explanation is three lines at 17–18px, 30ch wide, placed near the top at column 8, so the eye travels the diagonal from small text to big phrase. On alternate fields the arrangement mirrors: phrase bottom-right and right-aligned, paragraph top-left at column 2. Text on each field is ink or paper, whichever contrasts more. There is no separate section heading: the first field's phrase is the heading. Nothing else appears on the fields: no images, shapes or buttons.\",\n  \"mobile\": \"Fields are 64svh tall. The paragraph sits top-left at 16px across 80% of the width; the phrase sits bottom-left at 13vw on two lines. Mirroring is dropped; alternate fields right-align the paragraph only, keeping the phrase on the left margin.\",\n  \"seenIn\": [\n   \"opl-anidachi\",\n   \"aww-px-push\"\n  ]\n },\n {\n  \"id\": \"features-rows-with-margin-photographs\",\n  \"role\": \"features\",\n  \"name\": \"Rows with margin photographs\",\n  \"shape\": \"list\",\n  \"tags\": [\n   \"type-led\",\n   \"photo-led\"\n  ],\n  \"directions\": [\n   \"editorial-report\",\n   \"uneven-photographs\",\n   \"place-carries-it\",\n   \"sentence-as-layout\",\n   \"colour-chapters\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Everything hangs from one vertical axis at column 5, about 35% of the width. First the heading: a statement of up to five words at clamp(40px, 5vw, 80px) starting on the axis, vertically centred in an otherwise empty 70svh of ground. Then four or five benefit rows, each starting on the same axis: a title at clamp(28px, 3vw, 48px) and under it a paragraph of 34ch at 17px. Columns 1–4 stay empty. At the right margin each row carries one photograph, top-aligned with its title and deliberately unequal: 240px wide at 4:5 in one row, 320px at 3:2 in the next, 180px square after that. Rows are separated by 96–120px of space, not lines. On a saturated field, set all type in one pale ink and leave the photographs ungraded.\",\n  \"mobile\": \"The axis collapses to the left margin. The statement sits at 9vw in 50svh of empty ground. Each row stacks its title at 26px, the paragraph, then its photograph at alternating widths: 100%, 70% flush right, 55% flush left. 64px between rows.\",\n  \"seenIn\": [\n   \"aww-px-push\"\n  ]\n },\n {\n  \"id\": \"features-paragraph-with-picture-words\",\n  \"role\": \"features\",\n  \"name\": \"Paragraph with picture words\",\n  \"shape\": \"statement\",\n  \"tags\": [\n   \"type-led\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"sentence-as-layout\",\n   \"one-motif\",\n   \"product-performs\",\n   \"editorial-report\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One paragraph does the work of a feature grid. Three or four sentences, 35–50 words in total, set at clamp(30px, 3.6vw, 60px), leading 1.18, medium weight, across columns 1–11, left-aligned. Each sentence names one capability, and directly after that capability's key noun sits an inline slot: an inline-block frame 1em tall and 1.9em wide, radius 0.18em, dropped 0.12em below the baseline, holding a tight photograph crop (object-fit: cover) or a real interface control at readable size. Four slots at most, never two on one line. The nouns keep the weight and colour of the rest; the slots are the only emphasis. Mark it up as a paragraph and give the section a visually hidden heading of two or three words; nothing visible sits above. 72px lower, starting at column 7, one supporting sentence at 18px and the action.\",\n  \"mobile\": \"The paragraph drops to 7vw with leading 1.22 and fills the width. Slots stay inline at 1em tall but narrow to 1.5em wide. If a slot lands alone at the start of a line, let it; do not shrink the type. The supporting sentence and the action follow at full width.\",\n  \"seenIn\": [\n   \"aww-monolog\",\n   \"opl-uncle-rudy\",\n   \"aww-cominvi\",\n   \"opl-midnight-2\"\n  ]\n },\n {\n  \"id\": \"features-capabilities-as-a-menu\",\n  \"role\": \"features\",\n  \"name\": \"Capabilities as a menu\",\n  \"shape\": \"table\",\n  \"tags\": [\n   \"object-led\",\n   \"type-led\"\n  ],\n  \"directions\": [\n   \"page-is-the-object\",\n   \"split-stage\",\n   \"borrowed-category\",\n   \"type-only-statement\",\n   \"quiet-instrument\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"The capabilities are set as a printed menu or price list. One paper-coloured sheet, 520–600px wide and taller than it is wide, sits on a contrasting flat ground, centred or starting at column 2; its top and bottom edges are cut into shallow scallops or a zigzag with clip-path, its sides straight. On it, centred at the top, the heading: two or three words at 44–56px, then 40px of space. Below, items in two or three groups; each group opens with its name at 20px bold. Each item is a row: the name at 19px on the left, a short value on the right (a price, a time, a quantity, 'included'), and between them a leader of round 4px dots (border-bottom: 4px dotted, sitting on the baseline). A description at 15px in the soft ink sits under the name, at most 34ch. 18px between items, 44px between groups.\",\n  \"mobile\": \"The sheet fills the width minus 12px margins and keeps its cut top and bottom edges. Names stay left and values right on one line with the dot leader between; descriptions wrap beneath at 15px. Group names drop to 18px. Padding inside the sheet is 20px.\",\n  \"seenIn\": [\n   \"opl-the-content-architecture\",\n   \"aww-pensatori-irrazionali\"\n  ]\n },\n {\n  \"id\": \"features-shape-marked-small-points\",\n  \"role\": \"features\",\n  \"name\": \"Shape-marked small points\",\n  \"shape\": \"split\",\n  \"tags\": [\n   \"object-led\",\n   \"quiet\"\n  ],\n  \"directions\": [\n   \"one-motif\",\n   \"hero-object\",\n   \"product-performs\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"For the many minor points that do not deserve a row each. Columns 1–5: one photograph inside a single large shape taken from the subject's own geometry (a circle, an arch, a chamfered block), made with clip-path or border-radius, about 78svh tall and pushed 12% past the section's left edge so the viewport crops it. Columns 7–12: the heading, two to four words at 40–48px, then 56px lower a grid of eight to twelve points in three columns with 40px column gaps and 44px row gaps, no cells and no fills. Each point is a title at 17px medium preceded by the same shape drawn at cap height (0.7em, flat fill, inline SVG or a styled span), then two lines at 15px in the soft ink. The small shapes take a different palette colour per column, which is the only colour on the right side.\",\n  \"mobile\": \"The shaped photograph comes first, 82vw wide, cropped by the left edge and no taller than 60svh. The heading follows at 30px. Points become one column with 28px between them; the small shape hangs in the margin to the left of each title, so titles and text share one edge.\",\n  \"seenIn\": [\n   \"opl-dabbit\",\n   \"aww-sstr-friction-reduction\"\n  ]\n },\n {\n  \"id\": \"showcase-two-giant-words-compared\",\n  \"role\": \"showcase\",\n  \"name\": \"Two giant words compared\",\n  \"shape\": \"statement\",\n  \"tags\": [\n   \"type-led\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"type-only-statement\",\n   \"editorial-report\",\n   \"loud-flat-poster\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"No photographs: the thing shown is a pair of words, characters or figures that make the point by comparison (before and after, input and output, ours and the usual). At the top of the section, on one row: the heading, two to four words at 28–36px, at the left margin, and a paragraph of up to 60 words at 17px starting at column 7. Then 12vh of space. Below, two specimens side by side, one starting on column 1 and one on column 7, each set at clamp(180px, 34vw, 520px) with leading 0.8, so each fills about half the viewport's width. The section has a fixed height and overflow: hidden, so its bottom edge cuts both specimens at roughly 60% of their height. One short caption at 16px sits above the top-left of each specimen, naming it. Both specimens share one ink; the difference is in the letterforms or values, not in colour.\",\n  \"mobile\": \"Heading first, then the paragraph, at full width. The two specimens stack, each at 62vw type size in its own 38svh box with overflow hidden so the lower part is cut. Captions sit above each box at 15px. The second box takes the inverse colours of the first.\",\n  \"seenIn\": [\n   \"aww-pp-neue-montreal\"\n  ]\n },\n {\n  \"id\": \"showcase-two-objects-two-fields\",\n  \"role\": \"showcase\",\n  \"name\": \"Two objects, two fields\",\n  \"shape\": \"split\",\n  \"tags\": [\n   \"object-led\",\n   \"colour-field\"\n  ],\n  \"directions\": [\n   \"specimen-catalogue\",\n   \"hero-object\",\n   \"colour-chapters\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Two panels side by side, each 50vw wide and 92svh tall, in two different flat tones from the palette, meeting on a clean vertical edge with no gap. Each panel is dominated by one cut-out object photograph scaled to 130–150% of the panel's width and positioned so the panel's top edge crops it: the reader sees the lower two-thirds of the object, very close. On light panels use mix-blend-mode: multiply to lose a white studio background. Along the bottom of each panel, 28px in from the edges, one row: the name at 20px medium and a price or fact at 17px on the left; on the right, two small rectangular actions, one filled with ink and one with paper. Nothing sits in the middle of a panel. The heading, two to four words at 32–40px, is set at the top-left of the first panel only, in the empty corner beside the object.\",\n  \"mobile\": \"Panels stack, each 78svh tall, the object scaled to 150% of the width and cut by the top and right edges. The bottom row becomes two lines: name and fact, then the two actions side by side at full width. The heading sits top-left on the first panel at 26px.\",\n  \"seenIn\": [\n   \"aww-noho\"\n  ]\n },\n {\n  \"id\": \"showcase-object-in-front-of-type\",\n  \"role\": \"showcase\",\n  \"name\": \"Object in front of type\",\n  \"shape\": \"statement\",\n  \"tags\": [\n   \"object-led\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"hero-object\",\n   \"borrowed-category\",\n   \"loud-flat-poster\",\n   \"sentence-as-layout\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Type and object share one space instead of sitting side by side. Three or four lines of display type, one or two words each, are stacked flush left at clamp(72px, 9vw, 150px) with leading 0.88, starting on the left margin and allowed to leave the right edge (white-space: nowrap; overflow: hidden on the section). The lines step through tones of one ink: one at 45%, one at full strength, the rest at 18%. The object photograph, a cut-out or a studio shot blended with multiply, is absolutely positioned over the upper right of the stack at 40–46vw wide, rotated no more than 6 degrees and above the type in the stacking order, so it hides parts of three or four letters. Under the stack, in columns 8–12, a two-paragraph block at 20px gives the facts. The full-strength line is the heading; nothing sits above it.\",\n  \"mobile\": \"Type drops to 15vw and still runs off the right edge. The object sits at 78vw wide, overlapping the last two lines from below instead of from the right, and is cropped by the right edge. The facts block follows at full width and 17px.\",\n  \"seenIn\": [\n   \"aww-the-watch\",\n   \"opl-aevion\",\n   \"aww-coffeetech-r\"\n  ]\n },\n {\n  \"id\": \"showcase-band-of-unequal-panels\",\n  \"role\": \"showcase\",\n  \"name\": \"Band of unequal panels\",\n  \"shape\": \"strip\",\n  \"tags\": [\n   \"photo-led\"\n  ],\n  \"directions\": [\n   \"place-carries-it\",\n   \"uneven-photographs\",\n   \"name-as-monument\",\n   \"editorial-report\",\n   \"dark-room\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A modest heading, then one wide band of pictures. The heading, two to four words at 36–44px, starts at column 3, left of centre, with 64px beneath it. The band spans the full viewport width edge to edge and is 68svh tall: four photographs standing side by side with no gaps and deliberately unequal widths, a flex row with flex-grow values of 5, 2, 3 and 2. Each panel is cropped with object-fit: cover to a tall slice, so the band reads as one folded view. The first panel carries a two-line title at 28px in paper colour at its top-left, 24px in, over a neutral scrim that covers only that corner. Hovering a panel raises its flex-grow to 6 over 500ms while the others give way; without hover the widths simply stay. One caption line at 16px sits under the band at the left margin.\",\n  \"mobile\": \"The heading sits on the margin at 28px. The band becomes a two-by-two block with no gaps, 84svh tall in total: the first row split 64/36 and the second 36/64, so the slices stay unequal. The title stays on the first panel. No hover behaviour.\",\n  \"seenIn\": [\n   \"aww-white-desert\",\n   \"aww-tengile-malamala-collection\"\n  ]\n },\n {\n  \"id\": \"showcase-close-up-with-column-card\",\n  \"role\": \"showcase\",\n  \"name\": \"Close-up with column card\",\n  \"shape\": \"full-bleed\",\n  \"tags\": [\n   \"photo-led\",\n   \"object-led\"\n  ],\n  \"directions\": [\n   \"hero-object\",\n   \"place-carries-it\",\n   \"dark-room\",\n   \"borrowed-category\",\n   \"pinned-poster\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A full-bleed close-up photograph, 100vw by 100svh, with nothing over most of it. A four-column grid lies on top. One solid card in the ink colour, exactly one grid column wide (about 22vw) and 52svh tall, sits in the second column, vertically centred. Inside it, centred: the item's name at 30–36px, a variant line at 17px, the price or key fact at 17px, a small 3:2 photograph of the whole object (the card shows the whole, the background shows the detail), and at the foot a square-cornered action filling the card's width. The card is opaque, radius 0–6px, with no blur. When the section presents two or three items, each gets its own full-bleed frame and its card moves one column to the right each time, so position carries the sequence. The first card's name is the section heading.\",\n  \"mobile\": \"The photograph fills 100svh, cropped to its most detailed area. The card becomes a full-width block docked to the bottom, 46svh tall, left-aligned inside with 20px padding; the small whole-object photograph sits to the right of the name at 96px wide.\",\n  \"seenIn\": [\n   \"aww-longbow\"\n  ]\n },\n {\n  \"id\": \"showcase-live-demo-with-controls\",\n  \"role\": \"showcase\",\n  \"name\": \"Live demo with controls\",\n  \"shape\": \"split\",\n  \"tags\": [\n   \"ui-led\",\n   \"quiet\"\n  ],\n  \"directions\": [\n   \"product-performs\",\n   \"quiet-instrument\",\n   \"dense-tiles\"\n  ],\n  \"needs\": [\n   \"product-ui\"\n  ],\n  \"blueprint\": \"One filled panel, 680–760px wide and about 640px tall, radius 12px, in a tone clearly darker or lighter than the ground, placed on the text column's left edge or centred, with at least 15vh of empty ground above and below. The panel is split 62/38 into two flat areas that differ by one tone. Left area: the product doing its job on real content at true size. Right area: a narrow column of working controls, six to nine stacked rows 44px tall, each with a name at 14px on the left and a slider, toggle or value on the right; changing one changes the demonstration at once. A text link sits in the panel's bottom-left corner. The heading, two to four words at 24–32px, sits above the panel on its left edge with one sentence at 16px; under the panel, one line of start instruction.\",\n  \"mobile\": \"The panel fills the width. The demonstration takes the top at 4:3; the controls follow beneath as full-width rows 52px tall, only the four most telling ones, with a text link that reveals the rest. Heading and sentence sit above at 24px and 16px.\",\n  \"seenIn\": [\n   \"opl-dialkit\",\n   \"opl-textmode-overlay\"\n  ]\n },\n {\n  \"id\": \"showcase-one-frame-three-distances\",\n  \"role\": \"showcase\",\n  \"name\": \"One frame, three distances\",\n  \"shape\": \"pinned\",\n  \"tags\": [\n   \"photo-led\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"pinned-poster\",\n   \"hero-object\",\n   \"dark-room\",\n   \"sentence-as-layout\",\n   \"place-carries-it\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A wrapper 300vh tall holds a sticky stage of 100svh. On the stage one frame is centred: 30vw wide at 4:5, square corners, overflow hidden. Inside it the same photograph is shown at three distances as the reader scrolls: the whole subject, then scaled to 180% toward one detail, then to 320% on a second detail (transform: scale with a transform-origin per stage, 700ms ease, switched by IntersectionObserver on three invisible markers). The sentence is delivered in halves: its first two or three words sit above the frame at clamp(56px, 8vw, 130px), centred; the last words arrive below the frame at the second stage, overlapping the frame's bottom edge by 0.3em. At the third stage one caption of 28ch at 17px appears to the right of the frame, top-aligned. The two halves together are the heading and stay within two lines.\",\n  \"mobile\": \"The frame grows to 70vw at 4:5 and stays sticky at centre. The first half of the sentence sits above it at 13vw, the second half below it at the same size. The third-stage caption appears under the sentence at 16px, centred.\",\n  \"seenIn\": [\n   \"aww-vero-new-york\",\n   \"aww-illoca\",\n   \"opl-screentune\"\n  ]\n },\n {\n  \"id\": \"showcase-one-image-across-tiles\",\n  \"role\": \"showcase\",\n  \"name\": \"One image across tiles\",\n  \"shape\": \"mosaic\",\n  \"tags\": [\n   \"photo-led\",\n   \"dense\"\n  ],\n  \"directions\": [\n   \"dense-tiles\",\n   \"contact-sheet\",\n   \"editorial-report\",\n   \"colour-chapters\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One photograph is cut across a board of tiles. A grid of six columns and four rows with 8px gaps spans the full width between 12px margins; every tile is square (aspect-ratio: 1). Each tile shows its own piece of the same image: set the photograph as every tile's background at background-size: 600% 400% and step background-position by column and row, so the picture reads whole through the gaps. Five of the twenty-four tiles are swapped for flat colour tiles from the palette, never two adjacent: one holds the heading (two to four words at 2.6vw, top-left, 16px padding), three hold one fact each at 18px, one holds the action. On hover a tile's piece scales to 108% inside its own clip. Choose a photograph with one clear subject, so the board is legible at a glance.\",\n  \"mobile\": \"Three columns by six rows with 6px gaps, the photograph re-cut at background-size 300% 600% from a portrait crop. Four colour tiles only; the heading tile spans two columns in the top row with the heading at 6vw. Facts drop to 15px.\",\n  \"seenIn\": [\n   \"aww-produx-design\",\n   \"aww-ai-in-design-report-2026\"\n  ]\n },\n {\n  \"id\": \"showcase-frame-run-one-lifted\",\n  \"role\": \"showcase\",\n  \"name\": \"Frame run, one lifted\",\n  \"shape\": \"strip\",\n  \"tags\": [\n   \"photo-led\",\n   \"quiet\"\n  ],\n  \"directions\": [\n   \"contact-sheet\",\n   \"uneven-photographs\",\n   \"specimen-catalogue\",\n   \"quiet-instrument\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Columns 1–3 are a nearly empty column: the heading (two to four words at 24–28px) at the top, a link under it, and one or two short notes at 15px much further down, each level with the frame it describes. Columns 4–12 hold a run of six to eight frames of the same subject at one fixed height of 30vh, with natural widths and 6px gaps: the whole view, a tight crop of the same thing, a detail, the reverse side. The run is allowed to leave the right edge. One frame is lifted out of the row: shown at 2.2 times the row height with its bottom aligned to the row's bottom (flex row, align-items: end), so it stands above the others. Under each frame, at 15px: a name on the left and a single fact on the right. Square corners, no captions on the images.\",\n  \"mobile\": \"The heading and link sit on top. The lifted frame comes first at full width. The rest of the run scrolls sideways beneath it at a fixed height of 34vw with 4px gaps and scroll-snap, bleeding off the right edge. Notes are listed under the run at 15px.\",\n  \"seenIn\": [\n   \"aww-serotoninn\",\n   \"aww-butter\",\n   \"aww-no-art\"\n  ]\n },\n {\n  \"id\": \"showcase-output-slips-along-the-edge\",\n  \"role\": \"showcase\",\n  \"name\": \"Output slips along the edge\",\n  \"shape\": \"full-bleed\",\n  \"tags\": [\n   \"photo-led\",\n   \"object-led\"\n  ],\n  \"directions\": [\n   \"page-is-the-object\",\n   \"borrowed-category\",\n   \"place-carries-it\",\n   \"loud-flat-poster\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"For subjects whose result is a piece of text or paper: a receipt, a note, a ticket, a written line. A full-bleed photograph, 100vw by 96svh, sets the scene. In the upper centre, left-aligned in a column starting at 18% of the width, two short paragraphs in paper colour at 28–32px, the first opening with the heading's two to four words; a neutral scrim sits behind that column only. Along the bottom, six paper-coloured slips stand side by side across the full width with 12px gaps, each a filled rectangle of a different height (between 26 and 44svh), their lower ends cut off by the section's bottom edge. Two or three of the slips, not all, are tilted by 1–2 degrees. Each slip carries a sample of real output in the text face at 15px: a bold first line, a divider made of typed characters, then four to eight lines.\",\n  \"mobile\": \"The photograph is 100svh. The paragraphs sit in the top third at 22px. Only three slips show, each 30vw wide, standing along the bottom at different heights, and the row scrolls sideways to reveal the rest. Slip text stays at 14px; do not scale it down.\",\n  \"seenIn\": [\n   \"opl-poetry-camera\"\n  ]\n },\n {\n  \"id\": \"showcase-object-on-a-disc\",\n  \"role\": \"showcase\",\n  \"name\": \"Object on a disc\",\n  \"shape\": \"index\",\n  \"tags\": [\n   \"object-led\",\n   \"colour-field\"\n  ],\n  \"directions\": [\n   \"one-motif\",\n   \"specimen-catalogue\",\n   \"hero-object\",\n   \"colour-chapters\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One section about a viewport tall on a plain ground. A flat filled disc 64vh across, in one palette colour, sits with its centre at 58% of the width; swap the disc for the subject's own shape if it has one. A cut-out object photograph stands in front of it, centred on it, about 78% of the disc's height and breaking the disc's outline at the top. Bottom-left, starting on the margin and ending level with the disc's lower edge: a vertical list of four to six item names at clamp(28px, 2.9vw, 44px), leading 1.15. The selected name is in full ink and the rest at 25%; choosing a name swaps the object (300ms crossfade) and the disc's colour. The heading, two to four words at the same size as the names but in the soft ink, is the first line of that list. One fact about the selected item sits at the disc's right edge at 17px.\",\n  \"mobile\": \"The disc comes first, 86vw across and centred, with the object in front. The names follow as a single sideways-scrolling line at 26px with 24px gaps, the selected one in full ink. The fact sits under the names at 16px.\",\n  \"seenIn\": [\n   \"aww-cominvi\",\n   \"opl-tara\"\n  ]\n },\n {\n  \"id\": \"showcase-square-plate-spare-text\",\n  \"role\": \"showcase\",\n  \"name\": \"Square plate, spare text\",\n  \"shape\": \"split\",\n  \"tags\": [\n   \"colour-field\",\n   \"photo-led\"\n  ],\n  \"directions\": [\n   \"split-stage\",\n   \"page-is-the-object\",\n   \"colour-chapters\",\n   \"editorial-report\",\n   \"one-motif\",\n   \"name-as-monument\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"One flat field split 50/50, at least 88svh tall. Left half: a single square photograph filling the half's width minus 40px margins, vertically centred, square corners. A large simple shape may be laid over it to turn the photograph into the object it stands for: a ring 86% of its width with a 6px stroke and a small solid dot at the centre makes a record; a notch cut by clip-path makes a ticket stub. Right half, a flex column with space-between: at the top a row of three plain text tabs at 18px (editions, years, variants), the active one in full ink and the others at 40%; in the middle the title, two to four words at 32–40px bold, with a 34ch description 48px below; along the bottom two filled rectangular cells side by side, each half the column wide and 72px tall, acting as the two actions, one in ink and one a tone off the field.\",\n  \"mobile\": \"The square photograph comes first at full width with 16px margins. The tabs sit under it as one row at 17px. Then the title at 28px, the description, and the two action cells stacked, each full width and 60px tall.\",\n  \"seenIn\": [\n   \"aww-paul-kalkbrenner\"\n  ]\n },\n {\n  \"id\": \"how-it-works-lines-that-step-across\",\n  \"role\": \"how-it-works\",\n  \"name\": \"Lines that step across\",\n  \"shape\": \"statement\",\n  \"tags\": [\n   \"type-led\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"type-only-statement\",\n   \"sentence-as-layout\",\n   \"loud-flat-poster\",\n   \"editorial-report\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"The sequence is written, not counted. Four lines of display type, one stage per line, each a complete short clause that begins with its order word: 'First you send it.' 'Then we take it apart.' 'You choose one.' 'It ships on Friday.' Set at clamp(36px, 4.6vw, 76px), leading 1.0, one line each. The first line starts on column 1 and each following line starts two columns further right (grid-column-start 1, 3, 5, 7), so the block descends as a staircase and the eye follows the diagonal. Under each line, on that line's own left edge and 12px below, a sentence of up to 34ch at 17px in the soft ink. 56px between stages. The last line may take the accent colour as the single emphasis. The first line serves as the heading; there is no title above. Leave the columns to the left of the final stage empty.\",\n  \"mobile\": \"Lines drop to 8.4vw and may wrap onto a second line. The staircase becomes a smaller indent of 6vw per stage, so the fourth line starts 18vw in. Each sentence sits under its line at 16px on the same indent. 40px between stages.\",\n  \"seenIn\": [\n   \"opl-rendez-vous-franceclat\"\n  ]\n },\n {\n  \"id\": \"how-it-works-photographs-down-a-diagonal\",\n  \"role\": \"how-it-works\",\n  \"name\": \"Photographs down a diagonal\",\n  \"shape\": \"stack\",\n  \"tags\": [\n   \"photo-led\",\n   \"quiet\"\n  ],\n  \"directions\": [\n   \"uneven-photographs\",\n   \"place-carries-it\",\n   \"dark-room\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"Three stages, three photographs of different sizes placed along a falling diagonal on the 12-column grid. Stage one: a 3:4 portrait in columns 1–4. Stage two: a 1:1 square in columns 6–8, its top edge 220px lower than the first photograph's top. Stage three: a 16:10 landscape in columns 8–12, starting 180px below the bottom of the second. Each stage's text sits in the gap the stagger leaves: a paragraph of up to 36ch at 17px, top-aligned with its photograph and placed in the columns to its right (to its left for the third). Each paragraph opens with a bold run-in phrase that carries the order: 'On the first day', 'A week later', 'By the end'. Square corners; no arrows or connecting marks. The heading, two to four words at clamp(36px, 4vw, 64px) in a light weight, sits alone in columns 7–12 at the very top, level with the first photograph's top edge.\",\n  \"mobile\": \"The diagonal becomes alternating widths: the first photograph at 100%, the second at 62% flush right, the third at 78% flush left. Each paragraph follows its photograph on that photograph's left edge at 16px. 56px between stages. The heading sits above at 30px.\",\n  \"seenIn\": [\n   \"opl-fynza\",\n   \"opl-the-queue\"\n  ]\n },\n {\n  \"id\": \"how-it-works-drag-row-of-moments\",\n  \"role\": \"how-it-works\",\n  \"name\": \"Drag row of moments\",\n  \"shape\": \"carousel\",\n  \"tags\": [\n   \"photo-led\"\n  ],\n  \"directions\": [\n   \"contact-sheet\",\n   \"place-carries-it\",\n   \"uneven-photographs\",\n   \"page-is-the-object\",\n   \"dark-room\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A story told left to right. Top row: the heading, two to four words at 28–36px, at the left margin; at the right margin two solid square buttons, 48px each, for back and forward. Directly beneath, a solid bar 6px tall spans the full width in a soft tone, with a full-ink segment showing how far the row has been scrolled. Then the row itself: six to nine columns, each 280px wide with 32px gaps, in a horizontally scrolling flex container with scroll-snap that bleeds off both viewport edges. Every column reads top to bottom: a one-line caption at 18px bold that carries the order in words ('We met', 'Two winters on', 'The move'), three lines at 15px in the soft ink, then 80–140px of empty space that varies per column, then a 4:5 portrait photograph. Because the spaces vary, the photographs' top edges rise and fall along the row.\",\n  \"mobile\": \"Columns are 72vw wide with 16px gaps, so the next one always shows at the right edge. The buttons are dropped; the 6px progress bar stays under the heading. The empty space inside columns shrinks to 32–64px but still varies from column to column.\",\n  \"seenIn\": [\n   \"opl-sarah-matt-wedding\",\n   \"aww-no-art\"\n  ]\n },\n {\n  \"id\": \"how-it-works-pinned-fragment-changing-state\",\n  \"role\": \"how-it-works\",\n  \"name\": \"Pinned fragment, changing state\",\n  \"shape\": \"pinned\",\n  \"tags\": [\n   \"ui-led\",\n   \"quiet\"\n  ],\n  \"directions\": [\n   \"product-performs\",\n   \"quiet-instrument\",\n   \"split-stage\",\n   \"pinned-poster\"\n  ],\n  \"needs\": [\n   \"product-ui\"\n  ],\n  \"blueprint\": \"Two columns. Right, columns 7–12: a stage that is position: sticky; top: 14vh, holding one fragment of the real interface at true size on a single flat stage colour, about 520px square. Left, columns 1–5: three statements, each in its own block 80vh tall, so one is in view at a time. A statement is a two-line sentence at 28–32px that begins with its order word ('Paste a link.', 'Then pick the parts you want.', 'Share it when it looks right.') plus one supporting line at 16px. The statement nearest the viewport's centre is in full ink; the others sit at 30%. As each statement becomes active the fragment changes to the matching state: an empty field, a filled list with two rows selected, a finished result with its confirmation. Build the states in HTML and switch a class; do not swap screenshots. The heading, two to four words at 24–28px, sits above the first statement.\",\n  \"mobile\": \"The stage is sticky at the top, 46svh tall, the fragment fitted by cropping to its active region, not by shrinking its text. Statements scroll beneath it in blocks 60svh tall at 22px. The stage releases after the third statement.\",\n  \"seenIn\": [\n   \"opl-juggle\",\n   \"aww-cerebrium\",\n   \"opl-vessa\"\n  ]\n },\n {\n  \"id\": \"how-it-works-itinerary-on-a-slip\",\n  \"role\": \"how-it-works\",\n  \"name\": \"Itinerary on a slip\",\n  \"shape\": \"table\",\n  \"tags\": [\n   \"object-led\",\n   \"type-led\"\n  ],\n  \"directions\": [\n   \"page-is-the-object\",\n   \"type-only-statement\",\n   \"split-stage\",\n   \"quiet-instrument\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"The process is printed as an itinerary or receipt. One paper-coloured slip 420–480px wide stands on a contrasting flat ground at columns 7–11; its bottom edge is a zigzag cut with clip-path and its top edge is straight. The heading, two to four words at clamp(40px, 4.4vw, 68px), sits in columns 1–5 with a 30ch paragraph, top-aligned with the slip. On the slip, in the text face at 16px with tabular figures: stages grouped under time headings that carry the order ('Monday', 'Midweek', 'Friday'), each heading in bold with 28px above it. Under a heading, two to four rows; each row has what happens on the left, a duration or time on the right, and a leader of round 4px dots between. The final row is inverted, paper-coloured text on a full-width ink bar 44px tall, and states the result: what the reader holds at the end and the total time.\",\n  \"mobile\": \"The heading and paragraph come first. The slip follows at full width minus 16px margins, keeping its zigzag bottom edge. Rows keep left text, dots and right value on one line; long descriptions wrap under the left text. The inverted final row stays full width.\",\n  \"seenIn\": [\n   \"opl-the-content-architecture\",\n   \"opl-lennys-newsletter-product-pass\"\n  ]\n },\n {\n  \"id\": \"how-it-works-accordion-of-tinted-panels\",\n  \"role\": \"how-it-works\",\n  \"name\": \"Accordion of tinted panels\",\n  \"shape\": \"strip\",\n  \"tags\": [\n   \"colour-field\",\n   \"poster\"\n  ],\n  \"directions\": [\n   \"colour-chapters\",\n   \"one-motif\",\n   \"loud-flat-poster\",\n   \"dense-tiles\",\n   \"borrowed-category\"\n  ],\n  \"needs\": [],\n  \"blueprint\": \"A two-column introduction, then one horizontal accordion. Introduction: the heading, two to four words at clamp(36px, 4vw, 60px), in columns 1–5; one paragraph at 18px in columns 7–11. 64px below, a flex row across columns 1–12, 520px tall, of four to six panels with no gaps. The open stage is a panel taking about 58% of the width; the rest are vertical slivers sharing what remains. Order is carried by colour: the first stage is the darkest tone of one hue and each later stage is a lighter flat tint of it, so the row reads dark to light from left to right. A sliver shows only its stage name, rotated 90 degrees and reading upward, at 20px bold, anchored to its bottom-left. The open panel shows the name at 40px top-left, a 36ch paragraph at 18px bottom-left and, optionally, one photograph in its right half. Clicking a sliver opens it (flex-basis transition, 450ms).\",\n  \"mobile\": \"The accordion turns vertical: stages stack at full width as bars 64px tall in the same dark-to-light order, names set horizontally at 18px. The open stage expands to its content height with the paragraph at 17px. The first stage is open by default.\",\n  \"seenIn\": [\n   \"aww-white-desert\"\n  ]\n },\n {\n  \"id\": \"how-it-works-tiles-that-grow\",\n  \"role\": \"how-it-\n\n<!-- [TRUNCATED AT 50KB] -->\n\n<!-- File: skills/taste-skill/library/sites.json (Tokens: ~12426 | Category: anthropic-skill) -->\n[\n {\n  \"id\": \"aww-pp-neue-montreal\",\n  \"name\": \"PP Neue Montreal\",\n  \"url\": \"https://neuemontreal.com/\",\n  \"source\": \"Awwwards Site of the Day\",\n  \"kind\": \"other\",\n  \"score\": 8.6,\n  \"idea\": \"A typeface specimen dressed as a vintage city travel guide: the font named after Montreal is sold through guidebook titling, postcards and old tourist footage.\",\n  \"mood\": [\n   \"bold\",\n   \"playful\",\n   \"retro-modernist\",\n   \"typographic\",\n   \"confident\"\n  ],\n  \"archetype\": \"giant-wordmark\",\n  \"hero\": \"Grainy coral-red field. Top row: a monogram in a pale pill at left, a pale-grey pill nav with seven links centred, a black pill button at right. Below at the left margin, a two-line white bold title at about 4.5vw; opposite it, a ring of repeated monograms set around a circle like a stamp. Three full-width black hairlines cut the field into bands: a two-line intro sentence at ~1.6vw sits in the second, and the typeface name fills the third in black bold at ~17vw, two lines, tight leading, 60% of the width. A 4:3 clip of 1960s street footage is inset bottom-right, 29% wide, bottom-aligned with the name.\",\n  \"type\": \"PP Neue Montreal only: Bold for display with -0.01em tracking and leading near 0.9, Text Regular 16px for body and lists. Sizes leap from 16px to 144px headings to a ~240px name; one section enlarges a single lowercase letter to viewport height.\",\n  \"colour\": \"#ed4b44 #1a1a1a #f0e7d4 #18bc42 #b5b5b5 #f2c21a — Each chapter takes a flat field (coral red, near-black, cream, green) with black or cream type; one headline colours every word differently. Warm, print-poster feel with visible grain.\",\n  \"imagery\": \"Archive 1960s city footage, saturated vintage postcards, a handwritten postcard back, and rotated specimen posters and stamp sheets scattered around a headline. All square-cornered and inset, never full-bleed.\",\n  \"layout\": \"24px side margins and full-width hairlines marking bands. Content is left-anchored in three or four columns split by vertical hairlines; chapters alternate between tabular lists, a scattered collage, a centred statement and a giant glyph comparison. A pill nav stays pinned.\",\n  \"sections\": [\n   {\n    \"role\": \"intro\",\n    \"description\": \"Near-black screen split by a vertical hairline at about 75% width. Left: a three-line small heading at the top margin, then a five-line bold oblique headline at ~6vw in which each line is indented further right like a staircase and each word takes its own colour (green, cream, grey, yellow, blue, orange). Right narrow column: two stacked postcards, one saturated photo card and one cream handwritten card with a stamp. A tiny section label sits bottom-left.\"\n   },\n   {\n    \"role\": \"other\",\n    \"description\": \"A dark band of pure tabular type. A body paragraph occupies column one; weight names stack as tight single-line lists in two further columns divided by vertical hairlines. Below, a small label over a full-width rule introduces a two-column timeline: years stacked at the left margin, release notes stacked from the centre line behind a short vertical rule. One text size, leading near 1.0, no decoration at all.\"\n   },\n   {\n    \"role\": \"gallery\",\n    \"description\": \"Dark full-viewport stage with a three-line cream headline at ~4vw placed dead centre. Around it eight or nine specimen artefacts (a stamp sheet, a green poster with a blue numeral, a grey flag chart, a rainbow ticket grid, concentric colour squares) are each rotated 10 to 30 degrees and arranged on a loose ring, several cropped by the viewport edge, as if tossed on a table.\"\n   },\n   {\n    \"role\": \"showcase\",\n    \"description\": \"Cream field. A caption row at the top: a two-line label at the left margin and a five-line paragraph starting at about 55% width. Then a full-width rule carrying a tiny label at each end naming the two cuts. Below it, two black lowercase letters, each roughly half the viewport wide and cropped by the bottom edge, one from each cut, so the reader compares shapes at poster scale.\"\n   }\n  ],\n  \"steal\": [\n   \"Give a product page a borrowed genre (here a tourist guidebook) and let that genre dictate titles, imagery and chapter names.\",\n   \"Cut a flat colour hero into bands with full-width hairlines and set the name at ~17vw in the bottom band beside a small inset film clip.\",\n   \"Scatter rotated print artefacts on a loose ring around a centred headline and let several crop off the viewport.\"\n  ],\n  \"media\": \"The hero is a red printed cover with paper grain; the real media is small, a 418x316 looping 1960s street clip at the bottom right (about 10% of the viewport) beside a wordmark filling about 60% of the width. Later: a postcard pair in the right half of a split, rotated ephemera orbiting a centred statement, full-bleed photo panels that slide up over the previous chapter, a spine accordion, and a full-bleed vintage photograph overscanned 72px each side; square corners, one video.\",\n  \"motion\": \"Black, then a turning seal of logo letters, then the cover by 4.5s; four hero groups rise 25px and fade over 400ms cubic-bezier(0.44,0,0.56,1) at 200ms steps, settling at about 5.5s though the page loaded in 2.5s. Lenis drives a chain of sticky full-screen chapters: ephemera fly off as a photo panel slides up, a headline steps through weights of the variable cut on scroll, and a single glyph rotates and zooms for about 5 screens; about 390 appear fades run over 400ms on a spring-shaped linear() curve, with no reduced-motion rule.\"\n },\n {\n  \"id\": \"aww-seasats\",\n  \"name\": \"Seasats\",\n  \"url\": \"https://www.seasats.com/\",\n  \"source\": \"Awwwards Site of the Day\",\n  \"kind\": \"physical-product\",\n  \"score\": 8.4,\n  \"idea\": \"Calm, dusk-lit seascapes sell autonomous boats as serene instruments, and the navigation is a column of stacked colour swatches taken from that sea-and-sand palette.\",\n  \"mood\": [\n   \"serene\",\n   \"cinematic\",\n   \"engineered\",\n   \"assured\"\n  ],\n  \"archetype\": \"fullbleed-media-overlay\",\n  \"hero\": \"A 10px white frame surrounds everything. The left 84% is one rounded media panel: a dusk scene of a low, solar-decked vessel centred on mirror-flat water, with two larger hulls cropped by the panel's left and right edges. The headline is centred in the panel's upper third, two lines of white light-weight flared serif at 124px (8.6vw). A wordmark in custom wide techno lettering sits top-left; a white rounded button with mono caps and a dark-green square arrow sits bottom-centre. The right 14% is the menu: a full-height column of stacked flat colour blocks (blush, sage, then four darkening olives), each holding left-aligned 15px links, sub-items numbered 01 to 04.\",\n  \"type\": \"seasonMix, a low-contrast serif-sans hybrid, light weight, sentence case, near-zero tracking, at 124px for the headline and about 40px for statements; seasonSans 16px for body and menu; supplyMono uppercase at 9 to 12px for buttons, tags and footer data.\",\n  \"colour\": \"#a6b3bc #232323 #b7c8be #d6c4b8 #2c3620 #e2832a — Slate blues and lilac greys from the seascapes dominate; the menu adds blush, sage and olive blocks; the footer flips to a burnt-orange and rust scene. Text stays white.\",\n  \"imagery\": \"Photoreal rendered footage of autonomous boats on glassy water at dusk: symmetrical, low horizon, lots of sky, full-bleed after the hero. Small square-cornered inset stills with mono tag labels float over the scene.\",\n  \"layout\": \"Mostly full-viewport scenes with one centred text block each, at top or bottom, and the wordmark fixed top-left. Only the hero uses the framed panel-plus-menu split. A thin vertical progress line runs down the right edge.\",\n  \"sections\": [\n   {\n    \"role\": \"features\",\n    \"description\": \"A pinned full-bleed scene shot from the boat's deck: the hull forms a dark symmetrical wedge rising from the bottom edge to a mast at centre, horizon at one-third. At top-centre six short statements are stacked, centred, at 16px; one is white and the others half opacity, and the highlight steps down the list on scroll. For each, small photo cards (150 to 220px wide, square corners, mono tag on the top edge) appear left and right of the mast.\"\n   },\n   {\n    \"role\": \"intro\",\n    \"description\": \"A full-bleed aerial view of dark teal water with several small vessels scattered across the lower half and a faint horizon near the top. A single two-line statement in the light serif at about 40px sits centred near the bottom edge. Nothing else is on screen except the wordmark top-left and the thin progress line at right.\"\n   },\n   {\n    \"role\": \"footer\",\n    \"description\": \"Colour inverts to a burnt-orange haze over rust-red terrain, with black silhouettes of hulls and a keel hanging from the top edge as if seen from below the surface. Mid-height: mono readouts at left reporting distance scrolled in metres and scroll speed in knots with a one-line quip; a link list at 16px in the centre; mono contact details at right. The wordmark fills the full width at the bottom, white, about 130px tall.\"\n   }\n  ],\n  \"steal\": [\n   \"Build the menu as a full-height column of stacked flat colour blocks sampled from the imagery, grouping links by block colour instead of by rules or headings.\",\n   \"List every claim at once, centred and dimmed, and move a single full-opacity highlight through the list on scroll while supporting images appear around a fixed subject.\",\n   \"Give the footer its own opposite-temperature scene and a live readout of how far and how fast the visitor scrolled, in the product's own units.\"\n  ],\n  \"media\": \"A dusk render of the vessel on still water, as a still, a 3s muted loop and a canvas layered together, fills an inset card at about 84% of the width beside a colour-band nav panel and goes full bleed once scrolled. Then a scroll-scrubbed frame sequence on a sticky stage with labelled photo cards floating at depth, small video thumbnails that grow into full-bleed chapter loops, a WebGL globe rising as a half-sphere from the bottom edge, and sticky product renders that turn with the scroll; 18 images, 6 videos, 8px corners on the hero frame and cards.\",\n  \"motion\": \"The preloader wordmark's seven letters slide up out of their masks at 50ms steps, the framed hero arrives at 1.2s and the title fades in softly, settling after about 5s, and smooth scroll then runs 34 sticky elements with no pins: the flythrough is a scrubbed image sequence, a fixed background layer changes the ground per chapter, and the nav collapses to a slim right-edge rail. Title characters rise on cubic-bezier(.215,.61,.355,1) (the house ease, 17 uses) with durations that shorten by 12ms per character, so the end of a word catches up with its start.\"\n },\n {\n  \"id\": \"aww-ai-in-design-report-2026\",\n  \"name\": \"Ai in Design Report 2026\",\n  \"url\": \"https://stateofaidesign.com/\",\n  \"source\": \"Awwwards Site of the Day\",\n  \"kind\": \"other\",\n  \"score\": 8.4,\n  \"idea\": \"A research report laid out like a colour-blocked print annual: a thermal-blurred video collage on top, an oversized tight grotesk title, and flat orange, lilac, sage and black blocks carrying stats, quotes and chapters.\",\n  \"mood\": [\n   \"editorial\",\n   \"bold\",\n   \"colour-blocked\",\n   \"assured\",\n   \"contemporary\"\n  ],\n  \"archetype\": \"editorial-masthead\",\n  \"hero\": \"The top 53% is a full-width video band: blurred, heat-map-like abstract footage in orange, lilac and sage, overlaid with four or five hard-edged rectangles of the same footage in grey or green, two tagged with tiny mono labels in white boxes. The header sits flush on top: a black logo block at far left, an orange link tab running to 40% of the width, two plain links at right. Below the band, on white: a two-line deck at about 1.4vw on a 1% left margin, and from 42% across a two-line title at 8.3vw, medium weight, tracking -0.06em. Bottom row: mono credit left, scroll cue and arrow aligned to the title column.\",\n  \"type\": \"Beausite Classic, a grotesk with some stroke contrast, in Medium for titles and Regular for text; sentence case, tracking -0.06em at display size. Geist Mono for small uppercase labels. Steps: 8.3vw title, about 5.5vw numerals, about 3vw statements, 16px body, 10px mono. Footer wordmark near 96vw.\",\n  \"colour\": \"#ffffff #000000 #fe7141 #cdabfe #d1ddd3 #f0ff1c — White base with flat blocks of orange, lilac, sage and black assigned to whole modules (stat tiles, quote panels, chapter bands), all drawn from the hero footage. Text is black, or off-white on black.\",\n  \"imagery\": \"Hero: abstract blurred video with a heat-map grade, cut into overlapping rectangles. Body: warm documentary photos and clips of people at desks in wood-lined rooms, square-cornered, butted directly against flat colour blocks with no gap.\",\n  \"layout\": \"1% margins and a recurring column line at about 42% where most headings and text begin. Open white text passages ruled by hairlines alternate with tight mosaics in which photos and colour blocks share edges. Each chapter opens with a full-width colour band.\",\n  \"sections\": [\n   {\n    \"role\": \"proof\",\n    \"description\": \"A full-width hairline, a tiny mono label at the left, then seven black partner logos evenly spaced across the full width in one row with generous padding above and below, closed by a second hairline. Immediately beneath, another mono label and a three-line statement at about 3vw, flush left and occupying only the left half, followed by a full-width photo strip.\"\n   },\n   {\n    \"role\": \"stats\",\n    \"description\": \"A mosaic with no gutters. A photo of two people at a laptop fills the left two-thirds at roughly 1:1; the right third is split into two stacked flat tiles, lilac above and sage below. Each tile carries a large numeral with a plus sign at about 5.5vw in its top-left corner and a two-line caption directly beneath; the rest of the tile is empty colour.\"\n   },\n   {\n    \"role\": \"testimonial\",\n    \"description\": \"Quote module as two abutting blocks: a black block on the left 40% holding only a small name and a mono role caption, and a sage block on the right 60% with the quotation at about 3vw, top-left aligned with empty sage beneath. Directly below, a full-width orange band opens a chapter: hairline at top, a large two-digit number with the chapter word under it at left, a two-line title and small paragraph starting at the 42% column.\"\n   },\n   {\n    \"role\": \"footer\",\n    \"description\": \"Black footer. A row of three small source counts along the top, separated by vertical hairlines, then the report name in off-white heavy type at nearly full viewport width with a trademark sign at its top-right, then the year at the same size right-aligned on a second line. Two small link columns with mono headings sit lower left beside the year; a hairline and one row of credits and partner logos close it.\"\n   }\n  ],\n  \"steal\": [\n   \"Start most headings and text at a fixed column line about 42% across, leaving the left for small decks, credits and chapter numbers.\",\n   \"Butt flat colour tiles directly against a photograph with no gutter and put one large numeral plus two caption lines in each tile's top-left corner.\",\n   \"Take the page's flat block colours from the hero footage so the abstract video and the layout read as one palette.\"\n  ],\n  \"media\": \"A video collage covers 100% of the screen at load and lifts to the top ~53% to uncover the title on white. Below, a documentary photograph two thirds wide in a sticky frame beside stacked colour stat blocks, a pinned deck of colour cards each with a 10s clip docked bottom-left, and a carousel of equal stills running off the right edge: 12 images and 6 muted videos, all square-cornered.\",\n  \"motion\": \"No preloader, but the collage re-cuts itself for about 4s before the title lands. Framer drives the sticky stacking (a 1350px photo frame and three 900px chapter cards that peel away to uncover the next); there is no split text, links change colour over .2s cubic-bezier(.44,0,.56,1), and one panel slides 610px in over 500ms cubic-bezier(0.44,0,0.37,1).\"\n },\n {\n  \"id\": \"aww-house-of-honey-1\",\n  \"name\": \"House of Honey\",\n  \"url\": \"https://www.houseofhoney.com/\",\n  \"source\": \"Awwwards Site of the Day\",\n  \"kind\": \"studio-portfolio\",\n  \"score\": 8.4,\n  \"idea\": \"A block-heavy wordmark pierced by a hairline script: the bold-against-delicate contrast is repeated at every scale, with giant pink script behind quiet serif statements.\",\n  \"mood\": [\n   \"glamorous\",\n   \"warm\",\n   \"playful\",\n   \"editorial\",\n   \"confident\"\n  ],\n  \"archetype\": \"giant-wordmark\",\n  \"hero\": \"Top 42% is a flat blush-pink band; the bottom 58% is a full-bleed photograph of a bright living room, arched window on the centre axis, butting against the band with no margin. A tiny nav row sits at the very top with 8px side margins: block logo glyph and five links left, contact link with a small square arrow box far right. The wordmark fills the width edge to edge: two words in ultra-black extended caps, about 120px cap height, dark aubergine, with a hairline script 'of' 230px tall between them, overshooting above and below. Directly beneath, two two-line serif uppercase taglines at 31px, one flush left, one flush right.\",\n  \"type\": \"Wordmark in ultra-black extended caps; statements in noeText serif, uppercase, 31–40px, tight tracking; nav and captions in neueHaasGrotesk around 14px; 'canora' hairline script for the connecting word and for cropped background words at 37vw. Three contrasting voices, each with one job.\",\n  \"colour\": \"#edccbe #331917 #0e0e0e #f26fcb #ffffff — Blush pink and dark aubergine-brown alternate as full fields and as each other's text colour. Hot pink appears only in the oversized script and a 2px divider. Photographs bring saturated colour.\",\n  \"imagery\": \"Editorial interior photography, saturated and daylight-lit. Hero is a full-bleed landscape crop; projects are portrait crops about 5:6 in a three-column grid with 4px gutters and square corners.\",\n  \"layout\": \"Edge-to-edge with 8px outer margins. Typographic sections (small centred label, serif statement, cropped giant script) alternate with a three-column image grid. Blush and brown fields swap each section; hairline link rows close blocks. The footer is a full-width logo glyph.\",\n  \"sections\": [\n   {\n    \"role\": \"intro\",\n    \"description\": \"Dark aubergine field under the hero photo, separated by a 2px hot-pink line. A small sans label centred, then a three-line centred serif uppercase statement at about 31px in blush, 45% of the width. Behind it a hot-pink script phrase set near 37vw runs off both sides and is cut by the section's bottom edge, its ascenders rising into the statement. A smaller serif line follows.\"\n   },\n   {\n    \"role\": \"other\",\n    \"description\": \"Title card before the project grid. Blush field, nearly empty screen. A small label and a one-line serif uppercase heading about 40px sit centred at 55% height. The giant pink script returns, cropped by the bottom edge so only its top half shows and running off both sides.\"\n   },\n   {\n    \"role\": \"work\",\n    \"description\": \"Three columns edge to edge with 4px gutters and 8px outer margins. Portrait photos about 500×580px, square corners. Under each: an uppercase sans title at 14px and a grey line of GPS coordinates. Two rows, then a full-width hairline row with a text link left and a small square arrow box at the far right.\"\n   },\n   {\n    \"role\": \"footer\",\n    \"description\": \"Brown field. The logo glyph is enlarged to full width and about a third of the screen: blush rectangles and quarter-circle arcs with 4px gaps, forming an abstract monogram. Below: four columns of small links, a hairline, two addresses in the first two columns, another hairline, then copyright left and a small blush button right.\"\n   }\n  ],\n  \"steal\": [\n   \"Set a wordmark edge to edge in ultra-heavy extended caps and thread a hairline script connecting word through it that overshoots the cap height both ways.\",\n   \"Use an oversized script word in one hot accent colour as a cropped background layer behind small, calm serif statements.\",\n   \"Split a tagline into two halves, flush left and flush right on the same baseline under the wordmark, instead of centring it.\"\n  ],\n  \"media\": \"The lower 58% of the fold is a full-bleed interior photograph that continues for one full viewport as a five-image crossfading slideshow with a pink progress line on its bottom edge. Below: a three-up grid of 4:5 project tiles with 8px gutters sliding over a giant script marquee, a full-bleed tinted feature photograph with its title docked bottom-left, a full-bleed photograph with an inset colour card, and one giant cropped letterform as the footer's picture, the photographs oversized to 110-170% of their frames for drift and no video anywhere.\",\n  \"motion\": \"There is no visible preloader and the page is whole at 400ms; under Lenis, blocks rise 8px and fade in over 800ms ease-out at 0-260ms staggers (39 WAAPI calls), slideshow crossfades take 600ms cubic-bezier(0.7,0,0.25,1), the oversized photographs drift, and script marquees run on CSS time (90-122s per pair). Page changes use a 1s view transition on the same curve; nothing pins, and there is one reduced-motion rule.\"\n },\n {\n  \"id\": \"aww-white-desert\",\n  \"name\": \"White Desert\",\n  \"url\": \"https://white-desert.com/\",\n  \"source\": \"Awwwards Site of the Day\",\n  \"kind\": \"hospitality\",\n  \"score\": 8.4,\n  \"idea\": \"One word, the destination, set a third of the screen tall over footage like a film title card; sheer scale stands in for remoteness.\",\n  \"mood\": [\n   \"cinematic\",\n   \"epic\",\n   \"luxurious\",\n   \"cold\",\n   \"restrained\"\n  ],\n  \"archetype\": \"bottom-anchored-type\",\n  \"hero\": \"Full-bleed video (the view from an aircraft window over an ice shelf, darkly vignetted by the window frame) fills the viewport. Faint vertical hairlines divide it into six columns. Top-left, three outlined rectangular nav buttons about 120 by 40px with 6px gaps; top-right, two more; between them a small white mountain logo over a condensed caps name. One condensed uppercase word spans almost the full width at 17.8vw, white, centred, anchored so its baseline sits about 35px above the bottom edge. At mid-height a two-line italic serif tagline at about 16px hangs on the first column line at left, and a film-play label sits between two hairlines at right.\",\n  \"type\": \"Three voices: Oswald 400 uppercase for the giant word and footer wordmark (up to 22vw); Cardinal Classic Long, a light high-contrast serif, for caps statements near 32px and italic taglines; Inter Tight 14px for nav and body. Body to display is roughly an 18x jump.\",\n  \"colour\": \"#040608 #ffffff #e9e7e1 #1f2b4d #f5821f #95979a — Footage and near-black open the page; content sections flip to pure white with navy serif type and end on a warm grey footer. One small orange tab is the only accent. Cool overall.\",\n  \"imagery\": \"Aerial and wildlife footage and stills of ice, penguins and rust-coloured rock peaks, natural cool grade, always full-bleed with square corners; trips appear as tall vertical image slices set side by side with no gaps.\",\n  \"layout\": \"A six-column grid made visible by faint full-height hairlines runs through every section. Text blocks are small and hung off column lines, often starting at column two or three, with large voids around them. Full-bleed image screens alternate with nearly empty white text screens.\",\n  \"sections\": [\n   {\n    \"role\": \"intro\",\n    \"description\": \"A white screen with the six vertical hairlines still showing. A serif caps paragraph at about 32px, navy, light weight and tight leading, occupies only columns two to four, left-aligned with its first line indented by half the measure. Above its top-left sits a small italic label ringed by a loose hand-drawn pen scribble. An orange vertical tab with rotated text is fixed to the right edge.\"\n   },\n   {\n    \"role\": \"gallery\",\n    \"description\": \"Leaving the hero, the giant word blurs and dissolves into white mist that becomes the next section's background. Later a full-viewport photograph of jagged rock peaks in snow bleeds to all four edges, with a narrow 13px paragraph from the white section above overlapping its top edge at a column line, so text and image interlock rather than stack.\"\n   },\n   {\n    \"role\": \"showcase\",\n    \"description\": \"A serif caps heading at about 40px sits left of centre with a long pencil-like scribble underline that extends well past the words on both sides. Below, a full-width band of four vertical image panels with no gaps and unequal widths, like an accordion; the first panel carries a two-line italic serif title in white at its top-left.\"\n   },\n   {\n    \"role\": \"footer\",\n    \"description\": \"Warm grey field. The top row holds a small logo, three columns of grey link lists with italic serif group headings and, at right, a stack of square-cornered off-white tiles (a video thumbnail, two half-width buttons, one full-width). Beneath, the brand name in navy condensed caps runs edge to edge at about 22vw. A final strip has award badges left, a centred italic quotation and legal links right.\"\n   }\n  ],\n  \"steal\": [\n   \"Set a single place name in condensed caps at about 18vw, centred and anchored to the bottom edge of full-bleed footage, with everything else on screen at 14-16px.\",\n   \"Leave the column grid visible as faint full-height hairlines across video, white and footer sections, and hang small text blocks off those lines.\",\n   \"Ring or underline small serif labels with a loose hand-drawn pen scribble to put one human mark into an otherwise strict layout.\"\n  ],\n  \"media\": \"An 18s muted aerial and ice-cave clip covers the whole first screen under a scrim, with the title docked along the bottom edge. Later pictures dissolve into the white page through fog-like fades, a horizontal accordion opens one trip panel at half width beside blurred slivers, vertical ice strips wipe across the previous photograph, and a long pinned track of inset cards floats on a full-bleed texture ground before a closing photo panel carrying a quotation; 20 images, one video, square corners and a high-key cold grade.\",\n  \"motion\": \"There is no entrance choreography and footage plays from the first frame; under Lenis the hero title blurs and is swallowed by a sticky fog layer growing from 390 to 900px tall, statement lines fill from grey to navy, the camps heading scrubs from 140px down to 60px, and a pinned horizontal track moves the cards at about 0.56px per scrolled pixel over an 8,328px runway. Blocks rise 20rem with opacity over 1.4s cubic-bezier(.16,1,.3,1), and hovers run .3s cubic-bezier(.5,1,.89,1).\"\n },\n {\n  \"id\": \"opl-applied-imagination\",\n  \"name\": \"Applied Imagination\",\n  \"url\": \"https://applied-imagination.gpc.consulting\",\n  \"source\": \"One Page Love\",\n  \"kind\": \"other\",\n  \"score\": 8.3,\n  \"idea\": \"An essay conceived on a flight is read as a descent: an altimeter ticks from 30,000 ft to zero while you scroll down through halftone clouds to mountains at ground level.\",\n  \"mood\": [\n   \"airy\",\n   \"witty\",\n   \"editorial\",\n   \"dreamlike\"\n  ],\n  \"archetype\": \"type-poster\",\n  \"hero\": \"A pale blue sky fading to warm cream fills the viewport, with white clouds shaded in halftone dots. A tiny serif logotype sits top-centre; no nav. The title, two centred lines of black wedge-serif at 8.9vw, occupies the middle half of the screen and about 73% of its width; a cloud layer passes in front of the second line's baseline so the feet of the letters dissolve into dots. A two-line centred deck at 24px sits beneath. A mono byline strip is centred on the bottom edge with a scroll cue bottom-right. On the left edge at mid-height, a short vertical rule carries a two-line mono altitude readout.\",\n  \"type\": \"fsKim, a sturdy wedge-serif display face, regular weight at 128px with -0.01em tracking for the title and pull quotes; gtAmerica at 24px for the deck and about 16px for essay body; gtAmericaMono uppercase around 11px with wide tracking for byline, altitude and tape labels.\",\n  \"colour\": \"#cbe4f2 #f1e3b5 #0a0a0a #ffc013 #8e2f8f #f04e23 — Sky blue melting into sand yellow is the constant ground and text is black. Saturated magenta, orange and yellow arrive only in collage objects, tape labels and the footer contact card.\",\n  \"imagery\": \"Photo-collage cut-outs (parachutes carrying a treasure chest and a burning dumpster, a pair of legs, mountains) given a coarse halftone dot screen, layered in front of and behind the type against painted clouds.\",\n  \"layout\": \"A narrow text column about 38% wide for essay passages, interrupted by full-width display pull quotes and collage objects floating at the edges. One continuous sky instead of sections, with a fixed left-edge altimeter. Nearly 23 screens, ending on a ground-level landscape.\",\n  \"sections\": [\n   {\n    \"role\": \"intro\",\n    \"description\": \"Sky background, no container. A three-line pull quote in black wedge-serif at about 7vw is centred and tightly leaded. Two cut-out parachutes hang over it: a magenta one from the top-left carrying a chest spilling coins, an orange one at lower right carrying a burning dumpster, each overlapping letterforms. Small mono labels on tilted strips of coloured tape are stuck to the objects. Words in the quote turn from grey to black as they are reached.\"\n   },\n   {\n    \"role\": \"other\",\n    \"description\": \"Running essay text in about 16px grotesk, black, in a single column roughly 38% of the viewport wide, positioned left of centre with large sky margins on both sides. Paragraphs are separated by a blank line; serif sub-statements at about 28px introduce passages. The next display quote is seen rising from below, its letters partly hidden behind cloud and blurred.\"\n   },\n   {\n    \"role\": \"contact\",\n    \"description\": \"Ground level: halftone-screened mountains in green and brown rise from both sides, and the title returns at huge scale, cropped by the top edge and tucked behind the peaks. Centred below is a square-cornered two-panel card: a cream left panel with a short form of two fields and a small orange button, and a magenta right panel with a round portrait, name and a yellow subscribe button. Yellow tape-strip credits sit on the bottom edge.\"\n   }\n  ],\n  \"steal\": [\n   \"Tie a persistent numeric readout to scroll position (altitude falling to zero) so the reader's progress becomes part of the story.\",\n   \"Layer an illustration element in front of the bottom of a giant title so the letters sink into the scene instead of sitting on top.\",\n   \"Apply one coarse halftone dot screen to every photo cut-out so collage pieces from different sources read as one illustration set.\"\n  ]\n },\n {\n  \"id\": \"opl-compile\",\n  \"name\": \"Cursor Compile\",\n  \"url\": \"https://cursor.com/compile\",\n  \"source\": \"One Page Love\",\n  \"kind\": \"event\",\n  \"score\": 8.3,\n  \"idea\": \"The event name drawn as seven looping one-line curves in seven colours, more signature than logotype, on an otherwise whisper-quiet off-white page whose images are re-rendered as rows of coloured characters.\",\n  \"mood\": [\n   \"quiet\",\n   \"hand-drawn\",\n   \"warm\",\n   \"technical\",\n   \"restrained\"\n  ],\n  \"archetype\": \"giant-wordmark\",\n  \"hero\": \"Warm off-white field with no header or navigation. Starting about 23% down, a line-drawn wordmark spans from 8% to 92% of the width and about 29% of the height: each letter is a single 2px stroke looping like a Lissajous figure, each in a different colour (orange, green, olive, lilac, black, brown, blue), overlapping its neighbours. Directly beneath, two 14px captions, one flush left in ink and one flush right in grey. After a gap of about 20% of the viewport, three equal columns sit at the bottom, each topped by a hairline: an 18px statement, a grey 14px paragraph, and an email field over a full-width near-black rectangular button.\",\n  \"type\": \"The only large lettering is the drawn wordmark. All real text is CursorGothic regular in two sizes, 18px and 14px (the largest text on the page is 1.8vw), sentence case, with hierarchy made by ink versus mid-grey rather than by size or weight.\",\n  \"colour\": \"#edece8 #26251e #f07a1f #2e9e3a #2f6bf0 #9b8ff0 — Warm paper ground with near-black and grey text. The wordmark's colours return one at a time as the single ink of each character-rendered image (lilac, teal, green, orange). Event photos are dark and warm.\",\n  \"imagery\": \"Two kinds: landmarks and speaker portraits redrawn as rows of tiny characters in one saturated colour on a tint of the same colour; and dark, warm documentary event photos. All are square-cornered rectangles in strict rows.\",\n  \"layout\": \"About 7% side margins on a three-column grid. Each section has a small two-line heading at left (title in ink, subtitle in grey), then a row or carousel of equal tiles with one-line captions beneath. Very large vertical gaps between sections; a denser photo grid near the end.\",\n  \"sections\": [\n   {\n    \"role\": \"list\",\n    \"description\": \"Tour dates as a three-column grid of 3:2 tiles. Each tile is a city landmark rendered entirely in rows of small characters in one colour on a pale tint of that colour: lilac, teal, green, orange. Under each tile, one caption line: city name in ink, date in grey straight after it, and a status word flush right. A fourth tile wraps alone to the left of a second row, leaving two columns empty.\"\n   },\n   {\n    \"role\": \"gallery\",\n    \"description\": \"Session recordings as stacked carousels. A small heading and grey subtitle, then per stage a tiny label at left with two arrow glyphs at far right and a row of 16:9 dark photo tiles, two full tiles visible and a third cropped by the margin. Each tile has a small white event tag in its bottom-left corner. Caption beneath: speaker name in ink followed by the talk title in grey on the same line.\"\n   },\n   {\n    \"role\": \"about\",\n    \"description\": \"Speaker row: one-line heading at left, arrows at right, then four near-square portrait tiles with 8px gaps, each a face drawn in horizontal rows of characters in one colour on its tint (orange, green, lilac, teal). Some tiles show only plain stripes with the face barely emerging, so portraits appear to resolve from lines as they load or on hover.\"\n   },\n   {\n    \"role\": \"cta\",\n    \"description\": \"After a three-column photo grid with mixed landscape and portrait crops and 8px gaps, the page ends on an empty off-white screen holding one centred sentence at 18px and a small dark pill button beneath it. There are no footer columns, links or legal rows.\"\n   }\n  ],\n  \"steal\": [\n   \"Draw the name as one continuous thin looping stroke per letter, each in a different colour, and let it be the only large element on the page.\",\n   \"Keep all text at two small sizes and build hierarchy from ink versus grey on the same line (name in ink, detail in grey right after it).\",\n   \"Re-render photographs as rows of tiny characters in a single saturated colour on a tint of that colour, one colour per tile.\"\n  ]\n },\n {\n  \"id\": \"opl-the-new-industrials\",\n  \"name\": \"The New Industrials\",\n  \"url\": \"https://thenewindustrials.com/\",\n  \"source\": \"One Page Love\",\n  \"kind\": \"other\",\n  \"score\": 8.3,\n  \"idea\": \"A long-read essay laid out inside a visible drafting grid, where colour fields shift as you read and 3D machine parts drift through the margins and finally assemble into the publisher's initials.\",\n  \"mood\": [\n   \"bold\",\n   \"playful\",\n   \"editorial\",\n   \"engineered\",\n   \"saturated\"\n  ],\n  \"archetype\": \"editorial-masthead\",\n  \"hero\": \"A saturated orange page framed by black hairlines 24px from each edge. Top strip: a monogram logo left, a black pill with orange monospaced title centred, a boxed year right. Under it a row of eight empty outlined cells, 62px tall, like a ruler. A cream panel then fills the remaining width and height. Inside, a WebGL scene of pastel low-poly machine parts with visible wireframes sits behind a two-line uppercase title in a tall condensed slab serif, glyphs about 210px high, spanning 83% of the width. Small monospaced uppercase credits flank it at mid-height; reading time is centred below, with two boxed share links on the bottom edge.\",\n  \"type\": \"Title in a tall condensed slab serif at roughly 14vw cap height, black, uppercase. Essay in Albra Book serif: 34px lead paragraph, 18px running text with generous leading. Supply Mono in tiny uppercase for credits and box labels; a narrow typewriter-like face for the pull quote.\",\n  \"colour\": \"#ff8126 #f1ead8 #161615 #4db3ff #c5f53d #ff5fc0 — The page background changes as you read: orange, then a gradient through lilac into sky blue, then acid lime at the end. Type and hairlines stay black; the 3D parts carry rainbow gradients.\",\n  \"imagery\": \"Real-time 3D machine components (cylinders, gears, polyhedra) in matte pastel with coloured wireframe edges and neon gradient caps; they overlap the title, float into text margins and form letters in the footer.\",\n  \"layout\": \"Black hairlines divide the whole page into cells: one wide text cell flanked by narrow empty ones, each chapter tagged with a small numbered box at its corner. The lead paragraph spans the cell, running text is indented into a narrower column, and full-width quote screens interrupt.\",\n  \"sections\": [\n   {\n    \"role\": \"intro\",\n    \"description\": \"On orange, a ruled cell with a small numbered square at its top-right corner. The opening paragraph is set in serif at about 34px, seven lines, filling the cell with 60px padding. A horizontal hairline closes the cell; the next one indents its text by about 180px and drops to 18px, with a vertical rule marking the indent. The side cells stay empty, so the grid reads as margin furniture.\"\n   },\n   {\n    \"role\": \"other\",\n    \"description\": \"Pull quote: a full-viewport interruption where the grid lines stop. The background becomes a vertical gradient from orange through dusty lilac to sky blue. Centred, five lines of a narrow, widely tracked typewriter-style face at about 48px in dark olive-brown, each letter trailing a soft red vertical smear downward like wet ink. The next cell resumes on the blue that the gradient ended on.\"\n   },\n   {\n    \"role\": \"other\",\n    \"description\": \"Body screens: a single serif column about 960px wide between two vertical hairlines, paragraphs separated by a blank line. One 3D object per screen (a grey-green polyhedron with green edges, an orange hexagonal nut) sits half outside the column, crossing the vertical rule and the page edge at a different height each time, so every screen of text has one sculptural interruption.\"\n   },\n   {\n    \"role\": \"footer\",\n    \"description\": \"Acid-lime field. The publisher's three initials are built as a sculpture from the 3D parts seen earlier, about 60% of the viewport tall and spanning nearly the full width, each letter a different assembly of pipes, gears and blocks in clashing gradients. Below, hairlines form two cells holding monospaced uppercase credits at 10px, aligned to the cells' left padding.\"\n   }\n  ],\n  \"steal\": [\n   \"Draw the layout grid as visible black hairlines, including a row of empty cells, and tag each text block with a small numbered box.\",\n   \"Change the page background colour between chapters of a long read so progress is felt as a shift of colour.\",\n   \"Let one family of 3D objects recur at three scales: behind the title, in the margins, and assembled into a monogram at the end.\"\n  ]\n },\n {\n  \"id\": \"opl-wild-as\",\n  \"name\": \"wild\",\n  \"url\": \"https://craft.wild.as\",\n  \"source\": \"One Page Love\",\n  \"kind\": \"agency\",\n  \"score\": 8.3,\n  \"idea\": \"A studio essay on craft versus AI in which everything decorative is drawn on one square-pixel grid: the hero heatmap, the icons, the diagrams, the marquee lettering and the footer equaliser.\",\n  \"mood\": [\n   \"precise\",\n   \"playful\",\n   \"technical\",\n   \"bright\",\n   \"editorial\"\n  ],\n  \"archetype\": \"editorial-masthead\",\n  \"hero\": \"White page with a barely visible graph-paper grid. The top 22% is a masthead band split by a vertical hairline at 60%: at left, a two-line uppercase headline in a light grotesk at 5.2vw, tight leading, starting 9% from the left and nearly touching the top edge; at right, a two-line uppercase tagline with words spread to justify the column, then a pixel logo and a small right-aligned description. Below, a full-bleed canvas about 45% of the viewport tall: thousands of small squares in yellow, red, lime, cobalt and navy form a heatmap that erodes into white along its lower edge. A 3vw intro paragraph begins at the fold.\",\n  \"type\": \"Sneak in one regular-to-light weight does everything: uppercase 75px headline at -0.035em, a 44px sentence-case intro, section headings near 30px, 13px body. Tiny SF Mono uppercase captions with wide tracking sit under headings. A bitmap pixel face appears once, in the closing marquee. No bold anywhere.\",\n  \"colour\": \"#ffffff #0a0a0a #f2b90f #3b55d9 #1e2340 #e8452c — White page, black type, black buttons. Colour lives only inside the pixel graphics, in a fixed set of yellow, cobalt, navy, red and lime, so every illustration looks related. No section changes background.\",\n  \"imagery\": \"Canvas-drawn square-pixel fields: a heatmap band, particle streams that tighten from scattered dots into a dense ribbon, pixel smiley faces, an equaliser strip. Client work appears once, as three plain square-cornered photo cards.\",\n  \"layout\": \"Content runs from 9% to 91% with a constant split: heading in the left third, body in the right two-thirds, a tiny mono caption under the heading. Full-bleed pixel canvases interrupt the text. A small fixed mono link sits top-right; the ending is centred.\",\n  \"sections\": [\n   {\n    \"role\": \"work\",\n    \"description\": \"Three equal cards in one row, each a 6:5 image with square corners (laptop mock-up, product photo, flat illustration) followed by a centred project name at about 20px and a centred two-line description in small text. No borders, shadows or tags; a small round black arrow button overlaps the right edge of the third image to advance the row. Large white space above and below.\"\n   },\n   {\n    \"role\": \"intro\",\n    \"description\": \"Essay rows: a two- or three-line heading at about 2.2vw in the left third with a tiny wide-tracked mono caption below it; in the right two-thirds, two short justified paragraphs at 13px. Under one row, two pixel-art faces built from black squares (a smile and a frown, about 30px) sit side by side, each over a mono label and a three-line centred caption, forming a two-column comparison.\"\n   },\n   {\n    \"role\": \"how-it-works\",\n    \"description\": \"A four-word heading on two lines and a short paragraph at the left, then a wide canvas diagram: scattered pale-blue and navy squares at the left converge into a tight horizontal ribbon in the middle and fan out again in yellow at the right, a pixel funnel. Below it four narrow columns, each with a small round dark marker, a bold one-word label and two lines of small text.\"\n   },\n   {\n    \"role\": \"cta\",\n    \"description\": \"A single line of bitmap lettering scrolls across the full width, each glyph assembled from yellow squares flecked with red, navy and lime. Centred beneath: a black button with stepped pixel corners, two short grey centred paragraphs and an email line. The page ends with a full-width strip of coloured pixel bars like an audio equaliser, a small black play button centred above it.\"\n   }\n  ],\n  \"steal\": [\n   \"Pick one drawing primitive, a square on a fixed grid, and render every non-text element with it (hero art, icons, diagrams, display lettering, footer) in one five-colour set.\",\n   \"Split a masthead band 60/40 with a vertical hairline: oversized light-weight uppercase headline at left, a word-spaced justified tagline and tiny descriptor at right.\",\n   \"Lay out long copy as rows with the heading in the left third and body in the right two-thirds, and put the tiny mono caption under each heading instead of an eyebrow above it.\"\n  ]\n },\n {\n  \"id\": \"aww-hilden-kaira\",\n  \"name\": \"Hildén & Kaira\",\n  \"url\": \"https://www.hildenkaira.fi/\",\n  \"source\": \"Awwwards Site of the Day\",\n  \"kind\": \"agency\",\n  \"score\": 8.3,\n  \"idea\": \"The agency name is cast in liquid chrome across the full width, and the same chrome becomes emoji that float through the page, tying a social-media pitch to one material.\",\n  \"mood\": [\n   \"brash\",\n   \"glossy\",\n   \"editorial\",\n   \"witty\"\n  ],\n  \"archetype\": \"giant-wordmark\",\n  \"hero\": \"Warm light-grey field. The lowercase serif wordmark, rendered as polished chrome 3D letters with a molten ampersand, runs edge to edge across the top quarter (about 220px tall, 16px side margins). A tilted portrait video roughly 180 by 220px covers two of its letters. Directly under the wordmark, four small nav links centred. Then 300px of nothing, with one chrome flame emoji floating at the far left. The headline sits in the bottom third: three centred lines of narrow display serif at 4.4vw, leading so tight that descenders touch ascenders, a two-line 15px sans sub, and two square-cornered buttons, black and pale lime.\",\n  \"type\": \"PP Editorial New 400 for headlines at 63px, -0.02em tracking and leading near 0.9; PP Neue Montreal 13px for nav, body and buttons. The jump is roughly 5:1 with nothing in between. Stat numerals use the sans at about 60px.\",\n  \"colour\": \"#eae9e6 #181818 #ecfdad #b5b5b5 #ffffff #3aa57a — Warm grey and near-black alternate by section. Pale lime is the single accent: secondary buttons, headline text on dark, stat tiles and service cards. Chrome silver recurs as a material.\",\n  \"imagery\": \"Chrome 3D-rendered lettering and emoji objects (flame, heart, dove, microphone, wink) floating free; vertical phone videos of client content shown as fanned, slightly rotated stacks with white borders. Square corners throughout.\",\n  \"layout\": \"Centred statements with large voids, alternating light and dark full-width bands. Content arrives as square-cornered slabs: a white case card on grey, lime service cards stacking over each other on black. Chrome objects break the grid at the edges.\",\n  \"sections\": [\n   {\n    \"role\": \"testimonial\",\n    \"description\": \"Full-viewport near-black band. A two-line centred serif statement in pale lime at about 4vw sits in the upper third with nothing near it. Two small testimonials are pushed to the bottom-left and bottom-right corners: five tiny stars, two lines of 11px sans, name and title, each centred in its own narrow block. The centre bottom is left empty.\"\n   },\n   {\n    \"role\": \"work\",\n    \"description\": \"Horizontal carousel of wide white slabs on the grey ground, the next slide peeking at the right edge. Left half: a two-line serif title top-left, then far below a red-dot label over a thin rule and two flat tiles side by side, a wide lime one and a narrower brushed-chrome one, each with a tiny caption and a 60px sans numeral. Right half: a grey panel with three vertical videos fanned like playing cards.\"\n   },\n   {\n    \"role\": \"features\",\n    \"description\": \"On black, a centred serif section title, then service cards that pin and stack: a lime slab about 55% wide with serif title top-left, grey serif index number top-right, a small paragraph and black button bottom-left and a vertical video inset bottom-right. White and green slabs peek out beneath it, offset downward, and the top card tilts a degree or two as it scrolls.\"\n   },\n   {\n    \"role\": \"footer\",\n    \"description\": \"A full brushed-silver gradient field. The chrome wordmark repeats at full width across the top. Bottom-left, a small serif label over two short link columns; bottom-right, two square translucent tiles each holding a chrome object (microphone, heart) with a serif label above and three tiny square social buttons below. A hairline and a legal row close it.\"\n   }\n  ],\n  \"steal\": [\n   \"Render the wordmark in one physical material and reuse that material for small floating objects, so decoration and logo are the same thing.\",\n   \"Leave a third of the hero empty between a top-edge wordmark and a bottom-third headline; the gap makes both read.\",\n   \"Set a display serif with leading under 1.0 so lines interlock, and pair it with 13px sans for everything else.\"\n  ]\n },\n {\n  \"id\": \"aww-px-push\",\n  \"name\": \"PX PUSH\",\n  \"url\": \"https://pxpush.com/\",\n  \"source\": \"Awwwards Site of the Day\",\n  \"kind\": \"agency\",\n  \"score\": 8.2,\n  \"idea\": \"A design subscription presented as a retro broadcast: the entire site is seen through a CRT screen, with a chrome logo token floating in the sky as its mascot.\",\n  \"mood\": [\n   \"retro-futurist\",\n   \"cool\",\n   \"technical\",\n   \"cinematic\",\n   \"confident\"\n  ],\n  \"archetype\": \"product-object-centre\",\n  \"hero\": \"Full-bleed photograph of deep-blue sky over a cloud bank, the whole viewport under a CRT treatment: horizontal scanlines, slight blur, dark vignette with rounded corners. Top row with 43px margins: thin techno wordmark left; three links and a start link with a green dot right, split by a vertical hairline; full-width hairline beneath. Then one marquee line at 12vw (173px) in off-white grotesk, cropped at both edges, words separated by a solid dot, closed by a second hairline. Dead centre: a chrome 3D ring token about 400px wide. Bottom-left: a 216×144px royal-blue rounded thumbnail with a two-line mono caption. Bottom-right: a four-line mono uppercase paragraph 450px wide.\",\n  \"type\": \"A semi-condensed grotesk (digest name 'SemiSqueezed') at regular weight carries the 173px marquee, 28px paragraphs and 5vw statements; an uppercase monospace at 11–17px handles tags, captions and link rows. Ten-to-one jump between display and labels; no bold anywhere.\",\n  \"colour\": \"#03049c #71737d #1a1a1a #788ca4 #d9dde6 #c8f31d — Each section is a full colour field: sky photo, mid grey, near-black, then saturated royal blue. Text is off-white or pale lavender; acid lime appears only in small thumbnails, green only as a status dot.\",\n  \"imagery\": \"Sky photograph, a chrome 3D logo token, and client work shown as phone UIs on a blue ground and a poster photographed in a street lightbox. Everything sits under the same scanline filter; tiles have small radii.\",\n  \"layout\": \"A narrow left rail (about 17% wide) carries a bullet, a mono section tag and a small pinne\n\n<!-- [TRUNCATED AT 50KB] -->\n\n<!-- File: skills/taste-skill/library/type.json (Tokens: ~16305 | Category: anthropic-skill) -->\n[\n {\n  \"id\": \"switzer-semibold\",\n  \"name\": \"Switzer\",\n  \"class\": \"grotesk-tight\",\n  \"display\": {\n   \"family\": \"Switzer\",\n   \"source\": \"fontshare\",\n   \"slug\": \"switzer\",\n   \"weights\": [\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 600 · tracking -0.04em · leading 0.95 · sentence case; charcoal rather than pure black\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=switzer@400,500,600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Switzer\",\n   \"source\": \"fontshare\",\n   \"slug\": \"switzer\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking -0.005em\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=switzer@400,500,600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Suisse Intl\",\n   \"Neue Haas Grotesk\"\n  ],\n  \"note\": \"One neo-grotesk doing everything: semibold headings pulled tight, small regular text, no capitals and no second voice. Suits software, hardware and studio pages that want to look exact and unshowy.\",\n  \"seenIn\": [\n   \"aww-noho\",\n   \"opl-vessa\",\n   \"aww-aspen-search\",\n   \"opl-rows\"\n  ],\n  \"links\": [\n   \"https://api.fontshare.com/v2/css?f[]=switzer@400,500,600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"general-sans-bold\",\n  \"name\": \"General Sans\",\n  \"class\": \"grotesk-tight\",\n  \"display\": {\n   \"family\": \"General Sans\",\n   \"source\": \"fontshare\",\n   \"slug\": \"general-sans\",\n   \"weights\": [\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 700 · tracking -0.02em · leading 0.9 · sentence case; sizes jump straight from 16px text to 10vw and larger\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=general-sans@400,500,700&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"General Sans\",\n   \"source\": \"fontshare\",\n   \"slug\": \"general-sans\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body and lists, 500 for emphasis · leading 1.45 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=general-sans@400,500,700&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"PP Neue Montreal\",\n   \"Aeonik\"\n  ],\n  \"note\": \"A grotesk with slightly geometric bowls, set bold and very large against plain 16px text with nothing in between. Suits studios, type and product launches, and finance or tech brands that lead with the name.\",\n  \"seenIn\": [\n   \"aww-pp-neue-montreal\",\n   \"aww-moto-finance\",\n   \"opl-brikkenco\",\n   \"aww-nothin\"\n  ],\n  \"links\": [\n   \"https://api.fontshare.com/v2/css?f[]=general-sans@400,500,700&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"schibsted-heavy\",\n  \"name\": \"Schibsted Grotesk\",\n  \"class\": \"grotesk-tight\",\n  \"display\": {\n   \"family\": \"Schibsted Grotesk\",\n   \"source\": \"google\",\n   \"weights\": [\n    800\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 800 · tracking -0.05em · leading 0.88 · sentence case or all lowercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Schibsted+Grotesk:wght@400;600;800&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Schibsted Grotesk\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for paragraphs, 600 for navigation and other functional text · leading 1.4 · tracking -0.01em\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Schibsted+Grotesk:wght@400;600;800&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"ABC Diatype\",\n   \"Khteka\"\n  ],\n  \"note\": \"A compact, warm grotesk set heavy with letters almost touching; small text stays in the same family at semibold. Suits music, events and culture pages where the type is the image.\",\n  \"seenIn\": [\n   \"aww-paul-kalkbrenner\",\n   \"opl-rendez-vous-franceclat\",\n   \"aww-monolog\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Schibsted+Grotesk:wght@400;600;800&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"hanken-medium\",\n  \"name\": \"Hanken Grotesk\",\n  \"class\": \"grotesk-tight\",\n  \"display\": {\n   \"family\": \"Hanken Grotesk\",\n   \"source\": \"google\",\n   \"weights\": [\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 500 · tracking -0.05em · leading 0.9 · sentence case; one statement size (about 6vw) used for every heading\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Hanken+Grotesk:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Hanken Grotesk\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.45 · tracking -0.005em\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Hanken+Grotesk:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Akzidenz Grotesk\",\n   \"LayGrotesk\"\n  ],\n  \"note\": \"Medium-weight grotesk statements at one large size against caption-size text: a two-size system with no bold. Suits portfolios, agencies and tools that speak in short declarative lines.\",\n  \"seenIn\": [\n   \"aww-bleibtgleich26\",\n   \"aww-made-with-gsap-1\",\n   \"opl-locker-land\",\n   \"opl-builders-table\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Hanken+Grotesk:wght@400;500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"bricolage-contrast\",\n  \"name\": \"Bricolage Grotesque\",\n  \"class\": \"grotesk-tight\",\n  \"display\": {\n   \"family\": \"Bricolage Grotesque\",\n   \"source\": \"google\",\n   \"weights\": [\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 600 · tracking -0.04em · leading 0.92 · sentence case; leave optical sizing on so large sizes tighten and gain contrast\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:wght@400;500;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Bricolage Grotesque\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:wght@400;500;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Beausite Classic\",\n   \"F37 Analog\"\n  ],\n  \"note\": \"A grotesk with visible stroke contrast and slightly irregular curves, so headings look drawn rather than engineered. Suits reports, consultancies and design-led software that want warmth without a serif.\",\n  \"seenIn\": [\n   \"aww-ai-in-design-report-2026\",\n   \"aww-illoca\",\n   \"opl-ohhmydesign\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:wght@400;500;600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"franklin-source\",\n  \"name\": \"Libre Franklin / Source Serif 4\",\n  \"class\": \"grotesk-tight\",\n  \"display\": {\n   \"family\": \"Libre Franklin\",\n   \"source\": \"google\",\n   \"weights\": [\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 700 · tracking -0.035em · leading 0.92 · uppercase for the title, sentence case for section headings\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Libre+Franklin:wght@700&family=Source+Serif+4:ital,wght@0,400;0,600;1,400;1,600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Source Serif 4\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    600\n   ],\n   \"italic\": true,\n   \"settings\": \"400 for body, 600 for emphasis, italic for quotations · leading 1.55 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Libre+Franklin:wght@700&family=Source+Serif+4:ital,wght@0,400;0,600;1,400;1,600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Founders Grotesk\",\n   \"Die Grotesk\",\n   \"NON Natural Grotesk\"\n  ],\n  \"note\": \"An American gothic for headings over a sober transitional serif for reading, the pairing of a newspaper front page. Suits essays, annual reports, archives and finance pages that have real paragraphs.\",\n  \"seenIn\": [\n   \"aww-dragonfly-redux\",\n   \"aww-trevor-noah\",\n   \"aww-mosbys-files\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Libre+Franklin:wght@700&family=Source+Serif+4:ital,wght@0,400;0,600;1,400;1,600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"switzer-roman\",\n  \"name\": \"Switzer\",\n  \"class\": \"grotesk-light\",\n  \"display\": {\n   \"family\": \"Switzer\",\n   \"source\": \"fontshare\",\n   \"slug\": \"switzer\",\n   \"weights\": [\n    400\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 400 · tracking -0.03em · leading 1.1 · sentence case; headings stay small (28–40px) and at most one line jumps to 5vw\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=switzer@400,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Switzer\",\n   \"source\": \"fontshare\",\n   \"slug\": \"switzer\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for everything, 500 only for names and links · leading 1.45 · tracking -0.01em; hierarchy by ink against mid-grey\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=switzer@400,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Neue Haas Grotesk 55 Roman\",\n   \"Helvetica Now\"\n  ],\n  \"note\": \"A single roman weight of a Swiss neo-grotesk at two or three modest sizes; position and grey value do the work that size and bold usually do. Suits architects, galleries, studios and any quiet page where photographs carry the scale.\",\n  \"seenIn\": [\n   \"aww-revelatio-studio\",\n   \"opl-spatial\",\n   \"aww-pensatori-irrazionali\",\n   \"opl-compile\"\n  ],\n  \"links\": [\n   \"https://api.fontshare.com/v2/css?f[]=switzer@400,500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"archivo-regular\",\n  \"name\": \"Archivo\",\n  \"class\": \"grotesk-light\",\n  \"display\": {\n   \"family\": \"Archivo\",\n   \"source\": \"google\",\n   \"weights\": [\n    400\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 400 · tracking -0.02em · leading 1.0 · sentence case; never bold, inactive items fade to grey\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Archivo:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Archivo\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 600 for buttons and short emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Archivo:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Scto Grotesk A\",\n   \"Cash Sans\"\n  ],\n  \"note\": \"A sturdy grotesque kept at regular weight even at 88px, so the page reads as composed rather than loud. Suits finance, infrastructure and research pages that need to look sober and current.\",\n  \"seenIn\": [\n   \"aww-sharplink\",\n   \"opl-plastic\",\n   \"opl-lovably\",\n   \"opl-berd\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Archivo:wght@400;600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"clash-grotesk-regular\",\n  \"name\": \"Clash Grotesk\",\n  \"class\": \"grotesk-light\",\n  \"display\": {\n   \"family\": \"Clash Grotesk\",\n   \"source\": \"fontshare\",\n   \"slug\": \"clash-grotesk\",\n   \"weights\": [\n    400\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 400 · tracking -0.03em · leading 0.95 · sentence case, or uppercase for one statement\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=clash-grotesk@400,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Clash Grotesk\",\n   \"source\": \"fontshare\",\n   \"slug\": \"clash-grotesk\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.4 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=clash-grotesk@400,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Sneak\",\n   \"ABC Monument Grotesk\"\n  ],\n  \"note\": \"A slightly narrow neo-grotesk with closed apertures, used at regular weight from marquee size down to paragraphs. Suits agencies and digital studios that want large type without heaviness.\",\n  \"seenIn\": [\n   \"aww-px-push\",\n   \"opl-wild-as\",\n   \"aww-sstr-friction-reduction\"\n  ],\n  \"links\": [\n   \"https://api.fontshare.com/v2/css?f[]=clash-grotesk@400,500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"work-sans-light\",\n  \"name\": \"Work Sans\",\n  \"class\": \"grotesk-light\",\n  \"display\": {\n   \"family\": \"Work Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    300\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 300 · tracking -0.035em · leading 1.0 · sentence case\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Work+Sans:wght@300;400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Work Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.55 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Work+Sans:wght@300;400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"ABC Favorit\",\n   \"Clarkson Light\",\n   \"PP Mori\"\n  ],\n  \"note\": \"A light grotesque with open, slightly old-fashioned shapes; large headings look airy and the text weight beneath stays easy to read. Suits AI and research products, fashion houses and calm brand sites.\",\n  \"seenIn\": [\n   \"aww-cerebrium\",\n   \"aww-squarespace-foundations\",\n   \"aww-boc-studio\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Work+Sans:wght@300;400;500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"anton-work\",\n  \"name\": \"Anton / Work Sans\",\n  \"class\": \"condensed-heavy\",\n  \"display\": {\n   \"family\": \"Anton\",\n   \"source\": \"google\",\n   \"weights\": [\n    400\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 400 (single heavy cut) · tracking -0.01em · leading 0.86 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Anton:wght@400&family=Work+Sans:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Work Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 600 for links and short emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Anton:wght@400&family=Work+Sans:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Druk\",\n   \"Thunder\",\n   \"Acme Gothic\"\n  ],\n  \"note\": \"Compressed heavy capitals stacked tight, with a neutral grotesque kept small beneath. Suits fashion drops, sport, nightlife and any page built as a poster.\",\n  \"seenIn\": [\n   \"aww-serotoninn\",\n   \"opl-juggle\",\n   \"opl-lorenzo-bocchi-photography\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Anton:wght@400&family=Work+Sans:wght@400;600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"big-shoulders-public\",\n  \"name\": \"Big Shoulders / Public Sans\",\n  \"class\": \"condensed-heavy\",\n  \"display\": {\n   \"family\": \"Big Shoulders\",\n   \"source\": \"google\",\n   \"weights\": [\n    800\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 800 · tracking -0.005em · leading 0.88 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Big+Shoulders:wght@800&family=Public+Sans:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Public Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 600 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Big+Shoulders:wght@800&family=Public+Sans:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Founders Grotesk Condensed\",\n   \"PP Neue York\",\n   \"Knockout\"\n  ],\n  \"note\": \"A tall American gothic taken from city signage, blunt and civic, over a plain public-service sans. Suits culture indexes, community projects, bars, sport clubs and local campaigns.\",\n  \"seenIn\": [\n   \"aww-mosbys-files\",\n   \"opl-the-sapphic-bar-index\",\n   \"opl-the-deep-end\",\n   \"aww-colonia-zacamil\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Big+Shoulders:wght@800&family=Public+Sans:wght@400;600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"archivo-compressed\",\n  \"name\": \"Archivo\",\n  \"class\": \"condensed-heavy\",\n  \"display\": {\n   \"family\": \"Archivo\",\n   \"source\": \"google\",\n   \"weights\": [\n    800\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 800 at font-stretch 62% (load the wdth axis and use its narrowest setting) · tracking -0.01em · leading 0.86 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Archivo:wdth,wght@62..125,100..900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Archivo\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"normal width · 400 for body, 500 for buttons and emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Archivo:wdth,wght@62..125,100..900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Helvetica Now Display Condensed\"\n  ],\n  \"note\": \"One variable family pushed to its narrowest, heaviest setting for headlines and relaxed to normal width for text, so display and body share a skeleton. Suits sportswear, campaigns and fintech pages that speak in capitals.\",\n  \"seenIn\": [\n   \"aww-decathlon-yestalgia\",\n   \"opl-uglycash\",\n   \"opl-juggle\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Archivo:wdth,wght@62..125,100..900&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"bebas-garamond\",\n  \"name\": \"Bebas Neue / EB Garamond\",\n  \"class\": \"condensed-heavy\",\n  \"display\": {\n   \"family\": \"Bebas Neue\",\n   \"source\": \"google\",\n   \"weights\": [\n    400\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 400 (single cut, capitals only) · tracking -0.02em, tightening to -0.06em above 15vw · leading 0.85 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Bebas+Neue:wght@400&family=EB+Garamond:ital,wght@0,400;0,500;1,400;1,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"EB Garamond\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": true,\n   \"settings\": \"leading 1.45 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Bebas+Neue:wght@400&family=EB+Garamond:ital,wght@0,400;0,500;1,400;1,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Founders Grotesk Condensed\",\n   \"Cardinal Classic Long\",\n   \"Signifier\"\n  ],\n  \"note\": \"Huge condensed capitals against a light old-style serif with italics: an industrial voice and a literary one, with a twenty-fold size gap between them. Suits crafted physical products, spirits, outdoor goods and hospitality.\",\n  \"seenIn\": [\n   \"aww-longbow\",\n   \"aww-white-desert\",\n   \"aww-mosbys-files\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Bebas+Neue:wght@400&family=EB+Garamond:ital,wght@0,400;0,500;1,400;1,500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"barlow-condensed\",\n  \"name\": \"Barlow Condensed / Barlow\",\n  \"class\": \"condensed-heavy\",\n  \"display\": {\n   \"family\": \"Barlow Condensed\",\n   \"source\": \"google\",\n   \"weights\": [\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 700 · tracking -0.02em · leading 0.9 · uppercase for statements, mixed case for item titles\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@700&family=Barlow:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Barlow\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@700&family=Barlow:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"FF DIN Condensed\",\n   \"Helvetica Now Display Condensed\"\n  ],\n  \"note\": \"Road-sign condensed type with squared curves, bold but not compressed into a wall, with its normal-width sibling for text. Suits logistics, motorsport, hardware and directories with many short titles.\",\n  \"seenIn\": [\n   \"aww-julien-calot\",\n   \"opl-medium-rare\",\n   \"opl-uglycash\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@700&family=Barlow:wght@400;500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"panchang-switzer\",\n  \"name\": \"Panchang / Switzer\",\n  \"class\": \"extended-heavy\",\n  \"display\": {\n   \"family\": \"Panchang\",\n   \"source\": \"fontshare\",\n   \"slug\": \"panchang\",\n   \"weights\": [\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 700 · tracking -0.02em · leading 1.0 · uppercase; four words or fewer per line because the face is very wide\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=panchang@700&display=swap\\\" rel=\\\"stylesheet\\\">\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=switzer@400,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Switzer\",\n   \"source\": \"fontshare\",\n   \"slug\": \"switzer\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=panchang@700&display=swap\\\" rel=\\\"stylesheet\\\">\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=switzer@400,500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Monument Extended\",\n   \"Owners Wide\",\n   \"Nimbus Sans Extended\"\n  ],\n  \"note\": \"A flat-sided extended grotesk in heavy capitals, wide enough that two words fill the screen, with a neutral sans kept small. Suits portfolios, real estate, travel and brand sites that want a broad, confident wordmark.\",\n  \"seenIn\": [\n   \"opl-belen-jones\",\n   \"aww-lxl-creative\",\n   \"aww-realevate\",\n   \"aww-the-tuscan-journey-begins\"\n  ],\n  \"links\": [\n   \"https://api.fontshare.com/v2/css?f[]=panchang@700&display=swap\",\n   \"https://api.fontshare.com/v2/css?f[]=switzer@400,500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"tiktok-sans-wide\",\n  \"name\": \"TikTok Sans\",\n  \"class\": \"extended-heavy\",\n  \"display\": {\n   \"family\": \"TikTok Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    800\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 800 at font-stretch 150% (load the wdth axis and use its widest setting) · tracking -0.01em · leading 1.0 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=TikTok+Sans:wdth,wght@75..150,300..900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"TikTok Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"normal width · 400 for body, 500 for emphasis · leading 1.45 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=TikTok+Sans:wdth,wght@75..150,300..900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Herokid Wide\",\n   \"At Aero\",\n   \"Wintyr\"\n  ],\n  \"note\": \"One variable grotesk stretched wide and bold for the headline and the closing statement, then returned to normal width for reading. Suits personal portfolios, apps and tech brands that want width without a second family.\",\n  \"seenIn\": [\n   \"aww-haoqi-design\",\n   \"opl-tara\",\n   \"aww-produx-design\",\n   \"opl-proooof\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=TikTok+Sans:wdth,wght@75..150,300..900&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"unbounded-onest\",\n  \"name\": \"Unbounded / Onest\",\n  \"class\": \"extended-heavy\",\n  \"display\": {\n   \"family\": \"Unbounded\",\n   \"source\": \"google\",\n   \"weights\": [\n    800\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 800 · tracking -0.03em · leading 1.0 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Unbounded:wght@800&family=Onest:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Onest\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Unbounded:wght@800&family=Onest:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"IntraNet\",\n   \"Nekst\",\n   \"Owners Wide\"\n  ],\n  \"note\": \"A wide display sans built from rounded squares, heavy and a little architectural, beside a clean text grotesk. Suits architecture indexes, watches, mobility and events that want a title with a constructed feel.\",\n  \"seenIn\": [\n   \"opl-belgrade-architecture\",\n   \"aww-the-watch\",\n   \"aww-risk\",\n   \"aww-house-of-honey-1\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Unbounded:wght@800&family=Onest:wght@400;500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"chivo-black\",\n  \"name\": \"Chivo\",\n  \"class\": \"heavy-black\",\n  \"display\": {\n   \"family\": \"Chivo\",\n   \"source\": \"google\",\n   \"weights\": [\n    900\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 900 · tracking -0.05em · leading 0.88 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Chivo:wght@400;700;900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Chivo\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for paragraphs, 700 for navigation, tags and links · leading 1.35 · tracking -0.01em\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Chivo:wght@400;700;900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Elza\",\n   \"ABC Diatype Heavy\",\n   \"Suisse Intl Black\"\n  ],\n  \"note\": \"A black grotesque in capitals with letters nearly colliding, and only two sizes on the page: enormous and small. Suits agencies, city and culture projects and musicians who want the type to land like a headline.\",\n  \"seenIn\": [\n   \"aww-glitch-grit\",\n   \"opl-city-of-angels\",\n   \"aww-warm-fuzzy\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Chivo:wght@400;700;900&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"cabinet-grotesk-black\",\n  \"name\": \"Cabinet Grotesk\",\n  \"class\": \"heavy-black\",\n  \"display\": {\n   \"family\": \"Cabinet Grotesk\",\n   \"source\": \"fontshare\",\n   \"slug\": \"cabinet-grotesk\",\n   \"weights\": [\n    800\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 800 · tracking -0.035em · leading 0.9 · lowercase or sentence case, one or two words per line\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=cabinet-grotesk@400,500,800&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Cabinet Grotesk\",\n   \"source\": \"fontshare\",\n   \"slug\": \"cabinet-grotesk\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=cabinet-grotesk@400,500,800&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Champ\",\n   \"Uncut Sans\"\n  ],\n  \"note\": \"A heavy sans with tight joins and an eccentric lowercase, friendly but loud. Suits bookshops, food, consumer subscriptions and marketing studios.\",\n  \"seenIn\": [\n   \"aww-aardvark-book-club\",\n   \"opl-protip-marketing\",\n   \"opl-rendez-vous-franceclat\"\n  ],\n  \"links\": [\n   \"https://api.fontshare.com/v2/css?f[]=cabinet-grotesk@400,500,800&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"epilogue-black\",\n  \"name\": \"Epilogue\",\n  \"class\": \"heavy-black\",\n  \"display\": {\n   \"family\": \"Epilogue\",\n   \"source\": \"google\",\n   \"weights\": [\n    900\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 900 · tracking -0.04em · leading 0.9 · sentence case or title case\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Epilogue:wght@400;500;900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Epilogue\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Epilogue:wght@400;500;900&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Die Grotesk D\",\n   \"Acme Gothic\",\n   \"FH Oscar\"\n  ],\n  \"note\": \"A broad black grotesque with a slightly uneven rhythm, at its best as a name set very large in mixed case. Suits entertainers, podcasts, consumer apps and blunt SaaS pages; emphasis comes from colour, not from a change of weight.\",\n  \"seenIn\": [\n   \"aww-trevor-noah\",\n   \"opl-juggle\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Epilogue:wght@400;500;900&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"red-hat-black\",\n  \"name\": \"Red Hat Display / Red Hat Text\",\n  \"class\": \"heavy-black\",\n  \"display\": {\n   \"family\": \"Red Hat Display\",\n   \"source\": \"google\",\n   \"weights\": [\n    900\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 900 · tracking -0.03em · leading 0.92 · uppercase; centred three-line stacks work well\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Red+Hat+Display:wght@900&family=Red+Hat+Text:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Red Hat Text\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Red+Hat+Display:wght@900&family=Red+Hat+Text:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"FH Oscar\",\n   \"Futura Bold\"\n  ],\n  \"note\": \"A geometric black with round bowls and flat terminals, cleaner and more even than a grotesque at the same weight. Suits fintech, apps and portfolios that want heavy type with a tidy, technical finish.\",\n  \"seenIn\": [\n   \"aww-risk\",\n   \"aww-leo-parpeix-portfolio-2026\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Red+Hat+Display:wght@900&family=Red+Hat+Text:wght@400;500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2.5rem, 1.2rem + 5vw, 5.5rem)\"\n  }\n },\n {\n  \"id\": \"jost-caps\",\n  \"name\": \"Jost\",\n  \"class\": \"geometric\",\n  \"display\": {\n   \"family\": \"Jost\",\n   \"source\": \"google\",\n   \"weights\": [\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 700 · tracking -0.03em · leading 0.9 · uppercase\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Jost:wght@400;500;700&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Jost\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Jost:wght@400;500;700&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Futura Std Bold\",\n   \"Futura PT\"\n  ],\n  \"note\": \"The pointed, circular geometry of the 1920s in bold capitals, with the same family at reading size. Suits space, science, museums, architecture and anything that should feel like a mid-century poster.\",\n  \"seenIn\": [\n   \"aww-21-hrs-on-the-moon\",\n   \"aww-leo-parpeix-portfolio-2026\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Jost:wght@400;500;700&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"stack-sans-light\",\n  \"name\": \"Stack Sans Headline / Stack Sans Text\",\n  \"class\": \"geometric\",\n  \"display\": {\n   \"family\": \"Stack Sans Headline\",\n   \"source\": \"google\",\n   \"weights\": [\n    300\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 300 · tracking -0.022em · leading 1.05 · sentence case; a heading may be two-tone, grey then full ink\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Stack+Sans+Headline:wght@300&family=Stack+Sans+Text:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Stack Sans Text\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Stack+Sans+Headline:wght@300&family=Stack+Sans+Text:wght@400;500&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Mluvka\",\n   \"Roobert\"\n  ],\n  \"note\": \"A geometric sans in a light weight at large size, soft and exact at once, with its text cut underneath. Suits consumer apps, utilities and developer tools that want to feel calm and modern.\",\n  \"seenIn\": [\n   \"opl-screentune\",\n   \"opl-dialkit\",\n   \"opl-typewave\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Stack+Sans+Headline:wght@300&family=Stack+Sans+Text:wght@400;500&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"albert-sans-semibold\",\n  \"name\": \"Albert Sans\",\n  \"class\": \"geometric\",\n  \"display\": {\n   \"family\": \"Albert Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 600 · tracking -0.035em · leading 1.0 · sentence case\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Albert+Sans:wght@400;500;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Albert Sans\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=Albert+Sans:wght@400;500;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"BT Steinhart\",\n   \"TT Norms Pro\",\n   \"Objektiv\"\n  ],\n  \"note\": \"A geometric grotesque with Scandinavian restraint: round letters, even colour, nothing decorative. Suits logistics, health, property and corporate sites that need to look clear and dependable.\",\n  \"seenIn\": [\n   \"aww-united-carriers\",\n   \"aww-likova\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=Albert+Sans:wght@400;500;600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"spartan-figtree\",\n  \"name\": \"League Spartan / Figtree\",\n  \"class\": \"geometric\",\n  \"display\": {\n   \"family\": \"League Spartan\",\n   \"source\": \"google\",\n   \"weights\": [\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 700 · tracking -0.04em · leading 0.88 · lowercase or sentence case\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=League+Spartan:wght@700&family=Figtree:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Figtree\",\n   \"source\": \"google\",\n   \"weights\": [\n    400,\n    600\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 600 for emphasis · leading 1.5 · tracking 0\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://fonts.googleapis.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://fonts.gstatic.com\\\" crossorigin>\\n<link href=\\\"https://fonts.googleapis.com/css2?family=League+Spartan:wght@700&family=Figtree:wght@400;600&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Degular\",\n   \"Roobert\"\n  ],\n  \"note\": \"A compact bold geometric with a low waist, punchy in short lowercase lines, over a friendly open text sans. Suits newsletters, consumer products, creators and small shops.\",\n  \"seenIn\": [\n   \"opl-lennys-newsletter-product-pass\",\n   \"opl-near\",\n   \"opl-sand-studio\",\n   \"aww-aardvark-book-club\"\n  ],\n  \"links\": [\n   \"https://fonts.googleapis.com/css2?family=League+Spartan:wght@700&family=Figtree:wght@400;600&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem)\",\n   \"step-head\": \"clamp(2rem, 1.3rem + 3.2vw, 4rem)\"\n  }\n },\n {\n  \"id\": \"pilcrow-rounded\",\n  \"name\": \"Pilcrow Rounded\",\n  \"class\": \"rounded-friendly\",\n  \"display\": {\n   \"family\": \"Pilcrow Rounded\",\n   \"source\": \"fontshare\",\n   \"slug\": \"pilcrow-rounded\",\n   \"weights\": [\n    700\n   ],\n   \"italic\": false,\n   \"settings\": \"weight 700 · tracking -0.05em · leading 0.9 · all lowercase, one or two words per line\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=pilcrow-rounded@400,500,700&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"text\": {\n   \"family\": \"Pilcrow Rounded\",\n   \"source\": \"fontshare\",\n   \"slug\": \"pilcrow-rounded\",\n   \"weights\": [\n    400,\n    500\n   ],\n   \"italic\": false,\n   \"settings\": \"400 for body, 500 for emphasis · leading 1.5 · tracking 0; lowercase throughout is fine\",\n   \"css\": \"<link rel=\\\"preconnect\\\" href=\\\"https://api.fontshare.com\\\">\\n<link rel=\\\"preconnect\\\" href=\\\"https://cdn.fontshare.com\\\" crossorigin>\\n<link href=\\\"https://api.fontshare.com/v2/css?f[]=pilcrow-rounded@400,500,700&display=swap\\\" rel=\\\"stylesheet\\\">\"\n  },\n  \"standsInFor\": [\n   \"Milling Triplex\",\n   \"Ease\"\n  ],\n  \"note\": \"A sturdy sans with fully rounded stroke ends, set bold and tight in lowercase with one small size for everything else. Suits toys, gadgets, cosmetics and other objects with soft moulded edges.\",\n  \"seenIn\": [\n   \"opl-when-you-wish-upon-a-starboy\",\n   \"opl-anidachi\",\n   \"aww-artem-shcherbakov\"\n  ],\n  \"links\": [\n   \"https://api.fontshare.com/v2/css?f[]=pilcrow-rounded@400,500,700&display=swap\"\n  ],\n  \"scale\": {\n   \"step-small\": \"clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem)\",\n   \"step-body\": \"clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)\",\n   \"step-lead\": \"clamp(1.25rem, 1.1rem + 0.7vw,\n\n<!-- [TRUNCATED AT 50KB] -->\n\n<!-- File: skills/taste-skill/README.md (Tokens: ~1270 | Category: anthropic-skill) -->\n# tasteskill v2 (`design-taste-frontend`)\n\nA design skill for coding agents, built from a study of 247 curated sites (One Page Love and Awwwards\nSites of the Day, October 2026). It gives an agent an art direction instead of letting it fall back on\nthe average landing page, holds it to a strict no-ornament house style, and makes it look at its own\nrender before calling the work done.\n\n## How it works\n\n1. **Inventory.** The agent lists what only this client has: the name and what it means, the street,\n   the numbers, the one constraint, the materials, the hours.\n2. **Draw.** `scripts/draw.mjs` deals three of 20 directions (each an idea engine seen on the\n   strongest studied sites); the agent picks the one that can carry something from the inventory, and\n   the script deals the rest: a hero composition, section compositions, a type system of real free\n   fonts, a palette, photographs, a motion, studied references, and under every blueprint a list of\n   where it disagrees with the house rules. Recent draws are remembered so projects do not repeat.\n3. **Idea and live thing.** One sentence tying the client's own material to the direction's device,\n   checked against the nearest competitor, and one thing the visitor can do on the page.\n4. **Build** from the sheet, words first, full content. When the project has no photographs of its\n   own, `scripts/assets.mjs` finds real pictures of the subject's world in open collections (its\n   street in old postcards, old maps, its materials, engravings of its trade, museum objects of its\n   kind), downloads them into the project and records their credits; the subject is drawn in code\n   only where no honest picture exists.\n5. **Gate.** `scripts/lint.mjs` (source) and `scripts/inspect.mjs` (real browser, 1440 / 768 / 390)\n   measure the house rules: headlines of two lines or fewer, no eyebrow labels, no monospace, no\n   01/02/03, no thin rules, no gradients, no resting shadows, no cream-and-terracotta, no violet, and\n   the faults blind jurors punished: no focal point, empty screens, text covered or cut, long pins,\n   sideways rows, faded text.\n6. **Look.** The inspector saves screenshots; the agent critiques them with an Awwwards-weighted\n   rubric, fixes the top three problems and repeats, at most three rounds.\n\nFive rounds of blind tests against a no-skill baseline and another design skill are recorded in\n`references/research.md` §11.\n\n## Contents\n\n```\nSKILL.md                 the run, the house rules, the laws\nreferences/              copy, type, colour, layout, imagery, motion, critique, tells, research\nscripts/draw.mjs         deal options / a direction / reprint / redraw; --alternatives, --photos, --site\nscripts/assets.mjs       search open image collections (Openverse, Wikimedia Commons, Art Institute of\n                         Chicago, the Met) and, with --video, real footage (Wikimedia Commons, Internet\n                         Archive, NASA); --get downloads with the credit, --credits prints them\nscripts/lint.mjs         static scan for banned patterns and stock phrases\nscripts/inspect.mjs      render, measure, photograph\nscripts/lib/             zero-dependency Chrome DevTools client, the in-page probe, the rules\nlibrary/                 directions (20), heroes, sections, type systems, palettes, photographs,\n                         studied sites, motions\nassets/base.css, base.js an optional neutral foundation\nevals/evals.json         six briefs for testing the skill against a no-skill baseline\n```\n\n## Requirements\n\nNode 22 or newer and an installed Chrome, Edge or Chromium for `inspect.mjs` (it drives the browser\nover the DevTools protocol with Node's built-in WebSocket; nothing is installed). `draw.mjs`,\n`lint.mjs` and `assets.mjs` run on Node 18+; `assets.mjs` needs network access and no API keys. Set\n`CHROME_PATH` if the browser is somewhere unusual.\n\n## Install\n\nCopy this folder to your skills directory, for example `~/.claude/skills/design-taste-frontend/`, or keep it in\na repository under `.claude/skills/`.\n\n## Notes\n\n- Photographs in the library are served by Lorem Picsum from Unsplash, under the Unsplash licence.\n  They are placeholders for atmosphere; replace them with the project's own pictures.\n- Pictures found with `assets.mjs` keep their own licences. By default it offers only CC0, public\n  domain, CC BY and CC BY-SA, and `--get` records the title, creator, licence and source of every\n  download in `assets/credits.json`. The page must carry the credits (`--credits` prints them).\n- `assets.mjs --video` finds short clips of the subject's world, takes a 720p-or-smaller rendition,\n  refuses files over 25 MB unless `--max-mb` is passed, and saves a poster frame with each clip; how\n  to use one on a page (muted loop, poster, stopped under reduced motion) is in\n  `references/imagery.md` §11.\n- Fonts are loaded from Google Fonts and Fontshare. Check each face's licence for your use.\n- The scores in `references/research.md` are model judgements from screenshots, not Awwwards scores.\n- The draw history lives in `~/.taste-skill/history.json` (set `TASTE_SKILL_HISTORY` to move it).\n  Delete it to reset.\n- A build takes an agent roughly 30–45 minutes and a few hundred thousand tokens with the full\n  look-and-fix loop; most of that is finding or drawing pictures when a project has no photographs.\n\n<!-- File: skills/taste-skill/references/app-screens.md (Tokens: ~13267 | Category: anthropic-skill) -->\n# App screens\n\nDashboards, admin, analytics, settings, inboxes, wallets and builders: the screens people work in.\nRead this file whole before you start one. The page run in `SKILL.md` does not apply to them.\n\nA generated dashboard is the average of every dashboard template: a dark or tinted sidebar with a\ncoloured pill on the active item, \"Welcome back\" and a waving hand, four KPI cards each with an icon\nin a tinted circle, a green \"+12.5%\" and a sparkline, a gradient area chart, a zebra table under\nuppercase headers. Nothing in it is wrong and none of it was decided.\n\nThis chapter is distilled from a study of 23 real product screens chosen by the owner: 17 products,\n17 light screens and 6 dark, all at desktop width (1440 or 1512px). Each screen was measured from its\npixels and noted for what works and what fails; the numbers below are those measurements and their\nmedians. The products are not named. What separates these screens from the generated kind, in order\nof how much it shows:\n\n1. **Colour goes on data, not chrome.** The median screen has about 3% coloured pixels; 17 of 23 stay\n   at 5% or less. 12 have no filled primary button at all.\n2. **KPIs are type, not tiles.** No screen puts an icon in a coloured circle on a KPI, and none draws a\n   sparkline on one.\n3. **Surfaces are flat.** 17 of 23 give their cards no shadow; separation is a 1px line or one tone\n   step.\n4. **There is no hero header.** 9 screens have no heading over 16px; where there is one, its median is\n   24px.\n5. **Charts carry almost no chrome.** A single series has no legend; gridlines are 3-7 faint lines or\n   none.\n6. **Navigation recedes.** The active item is a neutral grey pill or a change of text colour; a\n   coloured left bar appears once.\n7. **Tables are rules and alignment.** No zebra striping, no header bands, numbers right-aligned.\n8. **Data states are honest.** Zeros print as zeros, missing values as a grey dash, and an empty\n   section keeps its frame.\n\nTaking the template's devices away is half the job, as it is on a page. The other half is substance:\nthe product's real data, a screen that answers its one question first, and a grid whose arithmetic\ncloses.\n\n**A warning learned in testing.** In the first blind round, screens built with this chapter were\nclean, quiet and correct, and they lost to richer screens built without it. The judges' reasons were\nthe same every time, and each is now a rule below:\n\n- **The first screen was thin.** One large chart of a flat line filled it, and half the blocks the\n  brief asked for started below the fold. On a 1440×900 screen, every block the brief names shows its\n  header and its first rows (§2.2).\n- **The product was missing.** No name, no workspace, no mark: the screen could have belonged to\n  anyone. The shell names the product and the scope (§3.2).\n- **Restraint hid meaning.** A latency rise and a request rise were the same grey. Colour on a change\n  says good or bad, not up or down (§5).\n- **There was nothing to do.** No control for the job the screen exists for. The most frequent job is\n  one click from the first screen (§2.2).\n- **Rows ended ragged** and **a style's move was over-applied** (a tray around every card, an icon\n  rail where people needed labels). Keep the move to where it carries meaning.\n\nQuiet is the starting point, not the goal. A screen that a person would trust shows more of the\nproduct than a template does: its people, its objects, its numbers and the one thing to do next.\n\n**Give the product a face.** After four rounds the judges' top complaint was the same on most\nscreens: \"a well-applied kit, not a product with its own identity\" (stock Geist or Inter, a #f8f8f8\nground, white 12px cards, lime on black). The style's tokens make a screen correct; these make it\nthis product's, and choosing them is a step of the run, not a finish (§2.3):\n\n- **One face from the sheet, chosen before you build.** Each style lists two or three ways it takes a\n  face from the brief: a ground tinted from the product's world, a figure face with character, the\n  brand's hue on the main data element. Choose one, write it in your notes next to the screen's\n  question, and check that it shows on the first screenshot.\n- **The dealt typeface, really loaded.** A build that fell back to the default face landed on the\n  default look; the inspector now fails it.\n- **The product's mark and name** at the top of the shell, drawn for this product (a simple\n  monogram or symbol in the accent, from its name or its object), never a black square with a letter.\n- **One element only this product has**, built from its own things: an energy home's power flow, a\n  bakery's sell-out strip, a leave planner's cover against the minimum, the pace groups of a running\n  club as a unit chart, the couple as three lanes, a deploy's commit as the hero of the overview. The\n  sheet lists the library's signature elements whose words appear in the brief; otherwise invent one.\n  Name it in your notes next to the screen's question.\n- **The one chart hue on the main data element**: today's line, the booked bars, the current period,\n  the margin that breaks. A screen whose only hue is a delta reads as a kit, and the inspector warns\n  when a screen with charts carries no hue on its data (`no-data-hue`).\n- **Its people and objects as themselves**: each person gets a stable initial and a pale tint of their\n  own hue, with people listed next to each other at least 60 degrees apart. These tints are identity,\n  not data: they stay pale and out of the chart legends. Products show their thumbnails, cover art\n  shows the cover.\n- **Words of the trade** in labels and empty states (\"Waiting on the customer\", \"Off sick\", \"Due\n  on the 28th\"), never the generic noun of a template (\"Items\", \"Records\", \"Status\").\n\n**Calendars and timelines** (house rule, from testing; the study has none). People down the left on a\nfixed 160-220px column, grouped under a team subheader rather than repeating the team on every row;\ndays across with faint 1px day lines, weekends one tone step darker, and today marked by a 1px line\nin the one data hue with its date in ink. Bars are 20-24px tall at radius 4. One-line names sit on a\n32px pitch; a name with a subline (team, office) needs 40-44px, or the subline touches the next name.\n**Every kind of booking has its own mark**, so sickness reads apart from a holiday at a glance:\nholiday a pale fill, off sick a 1px diagonal hatch, long leave a darker grey step, working away an\noutline, a pending request a dashed outline. A style with a hue budget may add a 3px left edge in the\nhue for the kind the screen is about. Full colour is only for what needs a decision (a request that\nbreaks cover). A label sits inside its bar; a bar too short for it shows the kind's code inside and\nthe full label in its tooltip, or the label after the bar's end, never over the days before it.\nHoliday markers name their office in a multi-office product. Every swatch in the legend is the mark\nitself, scaled down, and lists only kinds on screen: `Charts.timeline(el, rows, kinds)` draws the bars\nand returns that legend from the same kinds map.\n\n## Contents\n\n1. When this applies\n2. The run for an app screen\n3. The shell\n4. The canvas and the page title\n5. KPIs\n6. Charts\n7. Tables and lists\n8. Forms and settings\n9. Type and colour\n10. Density\n11. Empty, zero, loading and error states\n12. The phone\n13. House rules for app screens\n14. Tells of generated dashboards\n\n## 1. When this applies\n\nAn app screen is worked in rather than read. This chapter covers:\n\n- dashboards and overviews: a seller's day, a project's health, a publication's growth;\n- admin and back office: members, orders, events, a catalogue;\n- analytics and reports, including a generated report with no app around it;\n- settings and billing;\n- list screens to work through: inboxes, queues, tables with filters;\n- wallets and finance homes;\n- builders and editors: flow, form and page builders, canvases;\n- the detail page of one object: an event, a deployment, a customer.\n\nA product site that shows its interface is a page; the interface fragments on it follow these rules\nfor their insides (mark each fragment's root with `data-ui`). When a request holds both, build each\nwith its own run and share one palette and one typeface.\n\nThe study is 23 desktop screens. It has no phone screens, no loading or error states, one settings\npage, no inbox and no dense operations table (the densest screen shows about 120 data points). Where a\nrule below goes past the study, it says **house rule**.\n\n## 2. The run for an app screen\n\nDo these in order. The first three steps decide whether the screen is any good.\n\n### 2.1 Inventory the data and the jobs\n\nThe page run inventories the subject's world; an app screen inventories its data. Write in your notes,\nin 8 to 12 lines:\n\n- **the objects** the screen shows (deployments, invoices, members, events, conversations) and their\n  fields, with units;\n- **realistic magnitudes**: how many objects, a typical amount, the range of a rate, how values move\n  over a day, a month, a year, and for a new account how small they really are;\n- **the people**: who opens this screen, how often (a glance once a day, or an eight-hour session),\n  on what device;\n- **the jobs**: what they do next from here (approve, reply, pay, ship, invite), and which job comes\n  up most;\n- **the product's own things**: its name and mark, the workspace or account it is scoped to, the people\n  in it (two partners, a team of six, the club's members), and the objects people recognise by sight\n  (product photographs in a shop, cover art in a media tool, a map of the route). These are what make\n  a screen belong to this product instead of to a template; plan where each one appears.\n\nThen write the data itself: a small dataset in a JSON or JS file that the screen renders from, with\nbelievable names, amounts that add up to their totals, dates in order and a unit on every figure.\nTotals are computed from the rows, never typed in separately. Small numbers stay small: the studied\nscreens show new accounts with 1, 6 or 9 of something, drawn honestly at their real size. Write the\nfigures that must agree as assertions in the data file (`console.assert(sold - cancelled === rsvps)`,\nthe bins sum to the total, the parts to the whole) and read the console: in testing, a ticket table\nthat did not reconcile with its own KPI cost a judge's trust in the whole screen. Checks that need\ncomputed values (allowance after a request, cover per day) go in the script that computes them.\n\n**Data that tells the truth** (house rules, from testing; judges checked every one of these):\n\n- **A fact shown twice is one variable.** A time window, a total or a state that appears in two cards\n  (the battery full 13:30-16:30 in the KPI label, the shaded span and the battery card) is one value in\n  the data file, and the copy and the chart annotation are both built from it. Two cards that\n  disagree by half an hour cost more trust than a missing card.\n- **Totals and deltas come from the parts as shown.** Sum the rounded pennies the screen displays,\n  never round the unrounded total separately: £21.68 + £8.34 − £3.81 is £26.21, and a screen that\n  says £26.22 is caught. A change is the difference of the two values on screen (£5.28 against\n  £5.22 is +£0.06, not +£0.07).\n- **Every relative figure names its baseline** in the same phrase: \"3 h 40 m before close\", \"45 m\n  earlier than last Sunday\", \"+5 on the usual Monday\". \"Early\", \"up\" or a bare \"+5\" next to another\n  time or figure reads as measured against that one.\n- **One name per time.** Shops close at 15:00 and the tills are cashed up at 15:12; the header and\n  the card use the same words for the same moment, and an error state rewrites the status line.\n- **If a caption has to say which bars are which, encode it in the chart instead**: a marked period in\n  a second tone with its own legend entry, a signed axis, a label on the mark.\n\n### 2.2 Name the screen's one question\n\nEvery screen answers one question first: \"Did today's sales come in?\", \"Which deploy broke?\", \"Who is\nwaiting for a reply?\", \"How much of this month's plan is left?\". Write it in one line. It decides\nthree things:\n\n- **what is biggest.** In the study the largest block is always the one that carries the screen's\n  question, whatever form it takes (a chart, a plan, a ring, a list). The same holds for figures:\n  the largest figure on the screen answers the question the title row's sentence answers. In testing,\n  an 88% sun ratio at 32px out-shouted the 24px charging window the title led with;\n- **what comes first** in the reading order;\n- **what is left out.** The studied settings page shows three usage numbers and links to the\n  analytics screen instead of drawing a chart; four screens draw no chart at all because a few\n  numbers say it.\n\nThen name the screen's **one finding**: the fact in today's data that most needs attention (\"9 no-shows\nwhile 8 people waited for a place\", \"the 23:28 deploy doubled the error rate\", \"eating out is £36 over\").\nPut it where it is read first, as the line under the title or the subline of the headline figure,\nnext to the action it drives. In testing, the finding that mattered sat in a 14px caption at the\nbottom of a card and the screen read as flat.\n\n**Do not rebuild a studied screen.** When the product is of the same kind as a screen in the study (a\nfinance home, a deploy overview), its arrangement is the trap: judges recognised the copies at once.\nTake the structure from the product's own things instead: for a couple's budget, Mia, Joint and Tom\nas three columns running through accounts, plan and bills; for a running club, the pace groups.\n\nThen list the screen's blocks as the answers to its next questions, one line each, the way the page\nrun lists claims. A block with no question is deleted. This is how you avoid the stock order of KPI\nrow, big chart, two small charts, table.\n\nThree more lines, each tested:\n\n- **Everything the brief names is on the first screen.** At 1440×900, every block the brief asks for\n  shows its header and its first rows or its figure. Size the headline block to the question (about\n  200-360px tall), cap long lists at 4-6 rows with \"View all\", and put time-sensitive blocks (bills\n  due, SLAs running out, a failed deploy) before long tables. A chart whose line is flat for most of\n  the window does not get the full width: give it two-thirds and put the next answer beside it.\n- **The most frequent job is one click away.** Name it (\"pack the orders due today\", \"reply to the\n  oldest breach\", \"redeploy the failed build\") and put its control where the answer shows: a primary\n  button in the title row, an action on the row that needs it, a \"View logs\" on the failed item. A\n  screen with no control for its main job reads as a report, not as a tool.\n- **Show the evidence beside the answer.** A judge trusts \"Error rate 0.28%\" more with its spike\n  annotated (\"peaked at 3.9% after the 23:28 deploy, reverted\") than with the number alone. One line\n  of explanation on the event that matters is worth more than a second chart.\n\n### 2.3 Choose a style\n\n```bash\nnode <skill>/scripts/draw.mjs --app --kind <kind> --brief \"<one line about the product>\" \\\n  --screens <screens> [--theme light|dark] [--keep palette,type] --options 3\n```\n\nThis deals up to three styles from `library/app.json` (fewer when only two suit the kind and the\ntheme). `draw.mjs --app --list kinds` (or `styles`, `screens` or `signatures`) prints the choices; the\nscreens are `overview`, `analytics`, `list`, `detail`, `settings`, `wallet`,\n`builder`, `inbox`, `home` and `report`. The library holds seven styles, each distilled from the\nstudied screens that share its move:\n\n| Style | Theme | For | The move |\n| --- | --- | --- | --- |\n| `achromatic-ledger` | light | money homes, reports, settings with usage | No colour in the chrome; charts in ink; one small signal where a figure changed |\n| `framed-sheet` | light | B2B analytics, developer platforms, builders | One tinted L-frame; the page on a white sheet inset 8px, no shadow |\n| `accent-ladder` | light | creator and small-business admin with plans | The full hue on small marks only; its pale tints on every area |\n| `editorial-greeting` | light | team and personal homes | The greeting as the h1 in a centred 12-column column; every figure at regular weight |\n| `pastel-consumer` | light | wallets, budgeting | Pale same-hue tiles under one large radius; quiet money polarity |\n| `true-black-flat` | dark | community, events, media | Elevation by lightness alone; colour only on data |\n| `data-terminal` | dark | markets, monitoring | Every selection is the same 1px accent line; signs, not colour, on numbers |\n\nChoose by how the product is used (long sessions or a quick look, money or media, a team or one\nperson, day or night), not by what is most familiar, and write one line on why. Then deal the sheet:\n\n```bash\nnode <skill>/scripts/draw.mjs --app <the same arguments, without --options> --style <id>\n```\n\nThe sheet gives the style's tokens and type, its shell and one pattern for each screen you named.\nKeep the style's one move intact and take every other value from the defaults in this file. Redraw\n(`--redraw style | shell | screen:<name>`) only for a reason you can state: it contradicts the brand,\nor the product is used in a way the style does not suit. With an existing brand, pass\n`--keep palette,type`, map its colours onto the roles in §9 and keep the style's colour budget.\n\n**Then choose its face, before any markup.** The sheet's \"Its face\" list gives two or three ways this\nstyle takes a face from the brief, and \"Signature elements\" lists the library's elements whose words\nappear in the brief (a power flow for an energy home, a sell-out strip for a bakery, a cover matrix\nand a kind-encoded timeline for a leave planner). Write in your notes, next to the screen's question:\nthe face you chose, the signature element (from the sheet, or your own built from the product's\nthings), and where each appears on the first screen. A style dealt to two products must not give them\nthe same face: in four rounds, the screens that skipped this step were scored as the same kit.\n\n### 2.4 Build the shell\n\nBuild the frame first, empty: the sidebar or rail, the top bar if the shell has one, the canvas with\nits gutters, the title row (§3 and §4). `<skill>/assets/app.css` is a neutral start for all of it:\ncopy it into the project and put the sheet's tokens in its `:root`. Look at it at 1440 and at 390 before any data goes in. Do the\ngrid arithmetic now and write it in a comment: the column count, the gutter, and the sum that proves\nthe cards land on the canvas edges.\n\n### 2.5 Put in the data\n\nRender every block from the dataset; draw the charts from it too, with `<skill>/assets/charts.js`\n(`Charts.line`, `Charts.bars`, `Charts.diverging`, `Charts.ring`, `Charts.barList`, `Charts.plan`,\n`Charts.bullet`, `Charts.timeline`, `Charts.matrix`, `Charts.timeStrip`; the file's header lists their\noptions) or your own SVG to the rules of §6, never a chart library's defaults and never a picture of a\nchart. The newer helpers return `{ svg, legend }`: put that legend in the card's header rather than\ndrawing your own, so each swatch is the mark it explains. Format every figure by §7.4: separators, fixed decimals per\nmetric, a sign on every change, units as smaller grey suffixes, tabular figures, right alignment in\ncolumns. Use the product's own words for labels. No placeholder data: the inspector fails lorem ipsum,\nAcme, John Doe and their kind. Proof is not invented here either: no vanity totals, no \"+12%\" on an\naccount that is a week old.\n\n### 2.6 Build the states\n\nFor every block, build its empty, zero, loading and error state (§11); for every row and control, its\nhover, selected, focus and disabled state. Look at each one in the browser. A screen that only works\nwith full data is half built.\n\n### 2.7 The check\n\n```bash\nnode <skill>/scripts/lint.mjs --app <source files or folder>\nnode <skill>/scripts/inspect.mjs --app <url or path/to/index.html>\n```\n\nA sheet dealt with `--app` switches both tools to the app rules by itself. The inspector opens the\nscreen at 1440, 768 and 390 and measures what this chapter asks for: an h1 (and reports it as the\nscreen's hero); a sidebar that folds on the phone; the canvas used to its right edge; panel shadows\nand borders; the number of corner radii; cards in one row that end apart, where a column of cards\nstacked with the gutter counts as one block (`ragged-row`); a blank band inside a card of over 40px,\nor over 64px before a new section's heading (`panel-void`); icons in tinted squares; numeric alignment and tabular figures; chart hues; colour\nshare, and a screen with charts but no hue on its data (`no-data-hue`); placeholder data; text under\n11px; and the page rules that still hold (contrast, gradients, the banned palettes, emoji). Fix every\n`FAIL`. Treat each `WARN` as wrong unless you can defend it to a designer in one sentence.\n\nThen look at the screenshots, every width, and answer these in writing. This is the critique for an\napp screen: the caps in `critique.md` for pictures, motion and the page's live element are page rules\nand do not apply here.\n\n1. Is the screen's question answered by the biggest thing on it, and is that read first? Is the\n   largest figure the one that answers the title row's sentence?\n2. Does every block share the screen's edges? Is there a dead strip on one side, a card stopping\n   short, an orphan cell, a stretched card with a blank band (a legend pinned to its foot, four rows\n   in a card kept at its neighbour's height)?\n3. Is colour only on data, on status and on the one primary action, and does the main data element\n   carry the one hue? Does the face you chose show on the first screen?\n4. Do the numbers add up, and do they line up digit for digit? List every fact that appears twice\n   and check that the copies agree; recompute each total and change from the values as displayed;\n   check that every relative figure names what it is against.\n5. Does every zero look like a zero and every missing value like a dash? Does every count badge sit\n   on a queue that needs action, with its noun clear from the label?\n6. Does every legend swatch match the mark it explains, and does any caption have to say which bars\n   are which (then encode it in the chart)? Does any label collide with a line or another label?\n7. On the phone, is the navigation folded away, and does each block still answer its question?\n\nFix the worst three, inspect again, look again. Three rounds at most. Judge the pictures: if a problem\nshows in a screenshot, it is real, whatever the code says.\n\n### 2.8 Report\n\nTell the user, briefly: the style dealt (name and seed) and any redraws with their reasons; the face\nyou chose and the signature element; each screen's one question; any check you allowed and why (for example `--allow icon-chips` for node-type\ntiles in a builder); and the sample data that must be replaced with real data, listed so it can be\nfound.\n\nApp screens have no motion floor. Motion is feedback: press, hover, focus, a menu or a sheet opening,\na row arriving. Nothing on the screen performs an entrance (house rule).\n\n## 3. The shell\n\n### 3.1 Five archetypes\n\n| Shell | In the study | What it is |\n| --- | --- | --- |\n| **Open plane** | 5 screens | A labelled sidebar on the page ground (or within 1-2% of it), separated by nothing or by one 1px hairline. No top bar: the header and the cards sit on the ground. The canvas is fluid with a 24-64px gutter, or a centred column. |\n| **Tinted frame, white sheet** | 8 screens | Sidebar and top bar share one tinted ground (#f6f6f6-#f9fbfc) with no rule between them; the page sits on a white sheet inset 8px from the window's right and bottom edges, radius 10-16 (median 16), a 1px #eaeaea-#ededed edge and no shadow. Variants: a flush L-frame, the inset sheet, and floating panels inset 8-12px with a 12px gap. |\n| **Ruled T-frame** | 4 screens | A 210-240px sidebar and a 64px top bar on one ground, divided only by 1px rules. The workspace switcher sits at the top bar's right end behind a full-height divider. Three of the four are dark. |\n| **Icon rail** | 3 screens | An unlabelled rail 50-60px wide (median 55); 15-18px icons on a 34-49px pitch; the active item marked by colour or by a 2% tint band; groups split by 20px hairlines. It saves about 180px of width. |\n| **No sidebar** | 3 screens | A 46-48px top bar over a centred 1088-1208px column with 152-212px gutters; the logo sits on the column's left edge. For reports, viewers and products with few destinations. |\n\nAll six dark screens use one ground everywhere, divided by 1px rules of #161616-#232323 or by nothing.\nNo screen in the study puts a dark or saturated sidebar against a light canvas (0 of 17).\n\n### 3.2 Sidebar\n\n- **Width.** Labelled sidebars run 210-292px; the median is 230 and most sit at 224-240. One floating\n  sidebar card appears (280px wide, 40px in from the window edge).\n- **Rows.** A 32px hit area on a 34px pitch is the mode (7 screens); the roomy versions run 40-52px on\n  a 42-60px pitch. Icons are 14-20px, median 16, outline at about 1.5px stroke on 14 of 16 screens.\n  Labels are 14px at 400 on 12 of 16, in ink or in a grey of #4b4d4f-#63666e, about 8-10px after the\n  icon, with the label column at x 36-48.\n- **Active item.** A neutral grey pill with the label unchanged, on 8 screens: radius 4-16 (median 8),\n  inset 8-14px from the sidebar's edges, a fill of about #e9e9e9-#ededed. On dark, brightness alone:\n  the label goes from #bbb to #fff (3 screens). Colour alone on the icon or label (3, all of them\n  rails or a floating card). A tinted accent fill (3). A left accent bar once in 23. The weight\n  changes on 2. Default: the grey pill on light, brightness on dark.\n- **Groups.** Sentence-case grey labels at 12-13px, never uppercase (9 screens), with 22-56px of air\n  above and 13-33px to the first item; or hairlines instead (4). Utilities such as settings and help\n  pushed to the bottom (5).\n- **Top and bottom.** The workspace or account switcher at the top of the sidebar (7 screens), at its\n  bottom (2), or in the top bar. The bottom holds a user row (8) or one upsell (8); one of those\n  upsells is a filled accent button.\n- **The product is named** (house rule, from testing). The product's mark and name sit at the top of\n  the sidebar or rail, and the scope (workspace, team, project, account) is shown as a switcher or a\n  breadcrumb. A screen whose product cannot be named from the screenshot reads as a template.\n- **Counts on nav items** (house rule, from testing). A count appears only on a queue that needs\n  action, and its noun is clear from the label: \"Requests 5\", \"Price changes 3\". A bare \"Range and\n  prices 9\" left the judge asking nine of what.\n- **Labels by default.** A labelled sidebar unless the product has five destinations or fewer and the\n  screen needs the width (a research or monitoring view); an icon rail always carries the product's\n  mark at the top, a tooltip and an accessible name on every icon. Nav items are other screens, never\n  anchors into the current page (a sidebar that scroll-spies one long page was marked down twice).\n\n### 3.3 Top bar\n\n14 of 23 screens have one; the default is none. Heights fall into two groups: 44-51px (median about\n48) on light chrome, and 64px, usually with a 1px rule. A top bar must hold something real: search,\nthe workspace switcher, or the page or object name. Search sits centred on the window at 548x32 with\na shortcut hint (2 screens), or at 457-537x36 in a no-sidebar bar. The right cluster is inset 24-46px\nfrom the edge. Two screens leave about 1070px of their top bar blank; both are flagged for it.\n\n### 3.4 Right rail and pinned columns\n\nOne screen has a right rail: a fixed 384px column in a `1fr 384px` grid with a 24px gap, starting\nlevel with the first card rather than with the title, its section headings outside the cards and 8px\nabove each. Use one only for a stable secondary stream: recent items, the details of the selected\nobject, share links. A pinned left column appears once: a 306px accounts card at the viewport height\nminus 72px, so net worth stays in view while the rest of the screen scrolls.\n\nFive screens float a button (24-56px), and one of those buttons covers the content it sits on and is\nflagged. House rule: no floating button unless it is the screen's one primary action and covers\nnothing at any width.\n\n## 4. The canvas and the page title\n\n### 4.1 Width and gutters\n\n- **Fluid** (14 screens): side padding 17-64px, median 29, with 24 and 36-40 the common values;\n  content 1120-1312px wide, median about 1204.\n- **Centred** (8 screens): 624, 864, 1088, 1100, 1152, about 1190 and 1208px; median about 1126.\n  Data pages land at 1100-1250 either way. Only two personal homes go narrow (624 and 864), and both\n  are flagged for wasting the width.\n- **Top offset**, from the canvas top to the title: 20-88px, median about 36. Tools sit at 20-36;\n  greeting homes at 50-88.\n- **One gutter.** Use one gap value horizontally and vertically. Mixed gutters (12 against 16, 20\n  against 24, 16 against 12) are flagged on 8 screens.\n\n### 4.2 One left edge, one right edge\n\nThe strongest screens run a single left edge from the header to the last row. One indents its page\nheader by the cards' 24px padding, so the title, the card titles, the numbers and the chart all start\non one line. Row rules may bleed 7-8px past the text column while the text stays on it.\n\nThe grid's arithmetic closes: 3 x 372 + 2 x 17 = 2 x 568 + 16 = 1152; 12 x 77 + 11 x 16 = 1100;\n4 x 144 + 3 x 16 = 624; a second-row card exactly as wide as the two cards above it\n(251 + 24 + 515). Write your sum down.\n\nFailures to avoid, all from the study: cards stopping 120px short of the sheet's right edge; a 0px\nright gutter against a 40px left one; a column centred on the window instead of on the area beside\nthe sidebar (204px on its left, 444px on its right); a medallion 108px off the column's axis. The\ninspector warns when the content stops well short of the right edge.\n\n**Dead space from a grid that does not fit the data** is the commonest failure in the study (10\nscreens): four KPI tiles in a three-column grid, orphaning the fourth; one card alone in a\nthree-column row beside 810px of nothing; a card stretched to its neighbour's height with 250px of\nblank under its legend. Choose the column count from the number of items, let a lone card span, and\ndo not stretch a card's frame over empty space.\n\n**Cards that share a row share a bottom edge.** In testing, rows whose cards stopped 26-190px apart\nwere marked down every time, by judges and by the inspector (`ragged-row`). Balance the row by its\ncontent first: move a list's rows so the two columns hold the same number, cap both lists at the same\ncount, or pair blocks of similar height. Two cards stacked in one column beside a tall card count as\none block: they balance when the column ends level. Only when the contents cannot balance, stack the\ntwo blocks, or let the shorter card fill the row height with its content top-aligned and the footer\naction (a \"View all\", a total) pinned to its bottom so the extra height is not a hole.\n\n**A stretched card stretches only when it has content to fill.** Only an action or a total may be\npinned to a stretched card's foot; a legend or a note stays directly under its chart. In testing, a\ncover card stretched to its neighbour with its legend pinned to the bottom left 60px of blank under\nthe last row, and a sell-out card left 45px above its links. When the content is short, let the card\nkeep its own height (`align-items: start` on the row), move its footer link into its header, or give\nthe row a block of similar height. A filtered block shrinks to its rows, or keeps a fixed number of\nrows with one sentence in the empty ones; four rows over 270px of empty card is a hole. The inspector\nwarns on a blank band of over 40px inside a card (`panel-void`).\n\n**Narrow blocks do not span the canvas.** A table of five columns or fewer, or a list of six rows or\nfewer, runs to about 760px at 1440 and pairs with the next block; stretched to 1300px it leaves\n400-600px voids between a name and its first figure.\n\n### 4.3 The title\n\n- **Every screen has one h1**; the inspector fails a screen without one. 14 screens set it in the\n  canvas at 18-48px, median and mode 24, at 600-700 (700 on 8). The rest have nothing over 16px: a\n  breadcrumb or the top bar names the page. Then the breadcrumb's last item is the h1, at 16px, and\n  the screen's name is still the first thing read.\n- **A noun, not a greeting**: \"Analytics\", \"Overview\", the project's or the object's name. 3 of 23\n  greet, and one adds an emoji, which goes. A greeting suits a personal or team home only.\n- **An optional second line**: one 14-16px grey sentence about the data or the object (the finding,\n  the period, the scope), never about the interface (\"the filters narrow every block…\", \"this page\n  shows…\" read as instructions, not a product), or a 12px line\n  naming the data's source.\n- **Right of the title**: actions only when they are real (10 screens); otherwise nothing. A freshness\n  stamp (\"Updated Jul 27, 4:09 PM\", with a refresh button) on 6.\n- **The primary action.** 12 of 23 have no filled primary button; 5 make it near-black (#1d1f20,\n  #1f2937) or inverted white on dark; 4 fill it with the brand hue. One primary per screen.\n\n### 4.4 Tabs, filters and the date range\n\n- **The date range** at page level (7 screens) or on each card (7), never both. A card that states its\n  own period puts it in its header, right-aligned, in grey.\n- **Underline tabs** (8 screens) always sit on a full-width 1px rule; the indicator is 1-4px (median\n  2), as wide as the label or running 8-11px past it.\n- **A segmented track** once: 48px, #f3f4f6, a white 36px active pill, and the date select inside its\n  right end, so tabs and range read as one row. A segmented control is as wide as its options, and full\n  width only below about 480px: three options spread across a 680px tablet card read as a progress bar.\n- **Control height** in title and filter rows: 28-40px, median 34, clustering at 32 and 36.\n- **Order**: scope on the left (the date first, then the filters), utility and refresh on the right.\n- **Compound filters** that read as a sentence (\"Date | Jun 14 - Jul 13 | Daily\"), 28px tall and 8px\n  apart, once.\n- **To the first card**: 13-64px, median 24.\n\n## 5. KPIs\n\n- **No tile of its own.** 11 of the 20 screens with headline numbers give a KPI no tile: bare text on\n  the page or on a card (5), or one container split by 1px hairlines (6). 9 use one card per KPI,\n  61-147px tall (median about 108). The default is one container split by 1px dividers into equal\n  columns. 7 screens have no KPI row at all and put each headline number in the card that explains\n  it, which is often better.\n- **Count.** 1-6 per row, median 3-4. The count matches the grid: four KPIs get four columns.\n- **Size.** Values 16-40px, median 26, mode 24. Values in their own tile run larger (median 30) than\n  in a shared strip (median 24). Nothing at 48px or over. Labels 12-16px, median 14; the value is\n  about 1.7 times the label.\n- **Weight.** An even split: 400 on 8 screens, 600 on 6, 700-800 on 6. A large number at regular\n  weight under a semibold label is the common pattern. Bold for money only.\n- **Order.** Label above the value on 14 screens; labels grey (#6b6b6b-#aaa) on 13; sentence case.\n- **Nothing else.** No icon in a coloured circle (0 of 23), no sparkline (0 of 23), no tinted tile.\n  An info icon beside the label is fine (5 screens). Units are a smaller grey suffix: \"5 mins\" at 24\n  over 14, \"2 m 24 s\", \"5 /10\".\n- **The answer figure leads.** When one figure is the screen's answer (a balance, net worth, the\n  portfolio's value), it is 30-36px and at least 1.3 times its sibling figures (those at 18-24px). In\n  testing, a 24px portfolio value beside two 24px figures left the screen without a lead. No other\n  figure on the screen is larger: the biggest number answers the title row's sentence, so a\n  secondary ratio in another card stays at the siblings' size.\n- **One figure, one place.** A figure shown in the strip is not repeated in a legend beside it, and a\n  KPI strip whose every cell names a panel below (RSVPs, then an RSVPs panel) is dropped: lead each\n  panel with its own number instead.\n- **A second job.** KPIs may be the chart's series tabs or the list's type filter (the selected card\n  takes a 1.5px border). As tabs, the selected one carries a 2px rule or the active fill and an ink\n  label; the others keep a grey label and their value in ink, at 400 against the selected one's 500.\n  A grey value reads as disabled: in testing, three shops' takings set in grey because they were tabs\n  read as secondary, though they were the brief's first ask. When the tabs are the per-entity\n  breakdown the brief asks for, grey nothing and let the rule alone mark the selection. On a phone the\n  tabs become a 2-up grid with the selected cell filled, or a row that scrolls sideways; never an\n  underline floating inside the grid (`app.css` does both).\n\n### Deltas\n\n- Optional: 9 of the 20 KPI screens show one; 11 do not.\n- 10-15px (median 14), never larger than the label. Text or a small glyph on 6 screens; a pale pill\n  on 3.\n- **The window in words**: \"vs prior 30 days\", \"in the last 90 days\", \"from 0 (last 4 weeks)\" (7 of\n  the 9).\n- **Colour only the number**, or set the whole delta in grey.\n- **Colour says good or bad, not up or down** (house rule, from testing). Every metric has a good\n  direction: latency, error rate, cost, churn and time-to-reply are better when they fall. A change\n  in the bad direction puts `--negative` on the number (or a small down-pointing glyph in that\n  colour); a change in the good direction is `--positive` or grey. A judge read a 2.5× rise in errors\n  set in the same grey as a rise in visits as hiding the screen's only bad news.\n- **Zero or undefined change is grey.** The study's commonest KPI failure is a zero or undefined change\n  shown as a signal: three identical green \"up 100%\" pills grown from zero, a \">999%\", a bold red\n  \"0.00%\", a green \"+0\". When the prior period was zero, write \"+4 (new)\"; when there is nothing to\n  compare, a short grey dash where the delta would be.\n\n## 6. Charts\n\n### 6.1 Which chart for which question\n\n| Question | Form | In the study |\n| --- | --- | --- |\n| Is it moving over time? | One line; an area only with a fill of 15% or less | 9 screens |\n| How much per period? | Columns with square corners | 3 |\n| How is it distributed? | A histogram with equal bins | 1 (its unequal bins are flagged) |\n| Who ranks? | A sorted horizontal bar list, or the row's fill as the bar in a one-figure list | 3 |\n| What share? | A thin ring, or a 100% stacked bar with 2px seams; five parts at most | 5 |\n| How far to the target? | A progress bar, both ends labelled, the fill the true ratio | 4 |\n| How much of the plan is used? | A track as long as the plan, the spent part filled, what is already committed as a lighter segment, an overrun past the track's end in the negative colour (`Charts.plan`) | house rule |\n| Has it drifted from its target? | One row per part: the current share as a bar with a 1px tick at the target (`Charts.bullet`); never two stacked bars to compare | house rule |\n| Where? | A map with a list beside it; the list carries the magnitudes | 1 |\n| Per period, and the running total? | The two side by side at equal width, with the same dates | 1 |\n| Which way did it flow, and how much? | Columns above and below one zero line on one scale, the axis signed and captioned on each side (\"Sold\" above, \"Bought\" below), a marked period in a second tone with its own legend entry (`Charts.diverging`) | house rule |\n| Who is away when? | A timeline of people by day, each kind of booking its own mark (`Charts.timeline`) | house rule |\n| Is there enough cover? | A team-by-day matrix of slack against the minimum (+2, +1, 0, −1), one hue ramping toward the negative colour, the headcount on hover (`Charts.matrix`) | house rule |\n| When in the day, against last time? | One row per item on a shared opening-to-closing axis: a 2px grey track, an ink dot for today, a hollow tick for the comparison day (`Charts.timeStrip`) | house rule |\n\nThree more, from testing:\n\n- **The pair of per-period bars and the running total is used once per screen**, and only when the\n  total crosses a line that matters (capacity, a target). Three such pairs in six charts read as one\n  pattern stamped out.\n- **A series that is flat except for one event** gets at most two-thirds of the width and about 140px of\n  height, or a range capped at about twice its reference line with the off-scale peak labelled\n  (`Charts.line({ max })`). A full-width plot that is 85% empty was the biggest block on a first\n  screen and was marked down.\n- **A forecast is not a fact**: after today the line is dashed and the end value is labelled\n  (`Charts.line({ today, endLabel })`), with the gap to the target bracketed when there is one.\n- **What the brief asks to see over time is drawn on the first screen.** KPI cells may switch the chart\n  only between metrics the brief did not name.\n\nWhen there are only a few numbers, draw no chart: four screens skip it, and the settings page links\nto the analytics screen with \"View more\".\n\n### 6.2 One question, one series\n\nOne series per chart is the norm; three is the most any screen draws. To show another metric, switch\nit with a control (a segmented control, a dropdown, the KPIs as tabs) instead of overlaying lines.\nPlots run 112-264px tall (median about 195) and 316-1136px wide (median about 570), an aspect of 1.8\nto 5.2.\n\n### 6.3 Axes and gridlines\n\n- **Gridlines** run horizontally only on 7 of the 12 cartesian charts, both ways on 3, and not at all\n  on 2. Use 3-5 (the study runs 3-7, median 4-5): 1px, solid, about #e5e5e5 on light (range\n  #cfcfd2-#f2f2f2), #2b2b2b on #111. Dashed lines are allowed in chart grids (4 screens: 3/3, 4/4,\n  3/2.5) and nowhere else on the screen.\n- **No y-axis line.** The baseline is the one heavier line (2px on two screens, 1px on one); full axes\n  on one.\n- **Y ticks**: 4-7, median 5, at 11-16px (median 12) in grey (#5f5f5f-#6c6c6c), on the left (8\n  screens) or the right (2). Round, even steps (0/5/10/15%; 0-600 by 150), the top tick above the\n  maximum, integers for counts, and zero as the baseline for bars and counts.\n- **Never without a scale.** Two screens draw no y-scale and show magnitude only on hover; both are\n  flagged. So are uneven ticks (0/3/6/10), a 0.8 tick on a count, a top tick equal to the maximum so\n  the line hits the plot's edge, and a cumulative axis that starts at 1.\n- **Axis text no larger than the data.** 15-16px ticks beside 14px values are flagged as louder than\n  the numbers.\n- **X labels**: 4-8 per chart, flat, never rotated (40 degrees is flagged), the first and last pulled\n  inside the plot, on one step all the way: a forced closing label after 14:00 on a 90-minute step\n  left a short last gap that a judge measured. Choose a step that lands on the end (hourly from 08:00\n  to 15:00) or leave the end unlabelled. Labelling only the two ends hides when things happened. Irregular dates on a\n  categorical axis are flagged: time goes on a time scale.\n\n### 6.4 Marks\n\n- **Lines** 1-3px, median 2, in straight segments. Four screens smooth their lines, and one smoothed\n  curve invents values between daily totals (flagged), so draw straight segments. No point markers,\n  except a hover dot (8px on one screen).\n- **Fill**: none on 7 of 10 time charts. At most a flat tint of about 14%, or a fade from the line to\n  transparent over 150-200px.\n- **Bars** have square corners (4 screens), or at most a 4px top radius with a square bottom on the\n  baseline. Stacked segments are split by a 1-2px seam.\n- **Colour.** One hue per chart. The accent touches only data on 8 screens, and data ink is under 3%\n  of the pixels on most. Neutral series are fine and often better: a near-black line that turns pale\n  grey after the cursor; a white line against a red one; signs instead of colour (\"+$24,000,000\").\n  But the one hue, when the style has one, goes on the screen's main data element (today's series,\n  the booked bars, the current period, the margin that breaks), not on a secondary chart or a delta:\n  in testing, an all-ink screen with no hue on any of its data read as a kit.\n  One subject keeps one hue across the screen: the same subscribers drawn pink in one chart and indigo\n  in the next is flagged. Unrelated hues on one screen (three, five) are flagged every time. Status\n  colours are for status. The inspector warns over four hues and fails over six.\n- **Legends.** None for a single series (9 charts): the title or the dropdown names it. Otherwise five\n  items at most, as a 5-8px dot with a 12-14px grey label in the card's header, or as a small table\n  (dot, name, value, change) that makes the legend carry data. Never list a series that has no data\n  (flagged). Every swatch is the mark it explains, scaled down: the legend dot is the line's colour,\n  a hatched bar's swatch is hatched. A swatch drawn separately from the mark drifted from it in testing\n  (a black outline with a red edge explaining a red outline); the helpers return the legend built from\n  the same style object as the marks.\n- **Rings** only for three to five parts of a whole that are not already listed beside them (a ring\n  redrawing the spent, due and left figures of the tile next to it was marked redundant). Never\n  labelled on the slices; the total sits in the centre or beside the ring. The\n  screens noted for their rings use thin strokes: 3-5px on a 90-154px ring, 8px on 182px. Two others\n  use 28 and 37px.\n- **Progress bars** are 4-24px tall (median 8), fully rounded, with both ends labelled (\"Skilled 200\"\n  and \"Expert 2,000\"); the fill is the true ratio, so 303 on that scale fills 22px of 392. A zero has\n  no stub (a 6px stub at zero is flagged).\n- **Tooltips** are bare text or a plain box without an arrow: label and value on one line.\n- **Annotate the event that matters.** A step or a spike more than about three times the usual change\n  gets a 1px marker and a 12px label naming its cause (\"Deploy a3f09c1\", \"Newsletter featured\");\n  reference lines (a budget, an SLO, a start time) are 1px dashed with their label at the end. In\n  testing, an unexplained jump was the first thing a judge asked about. `Charts.line`,\n  `Charts.bars` and `Charts.diverging` take `annotations` and `reference`.\n- **Labels never collide.** Annotation labels sit in rows above the plot, each beside the top of its\n  own leader line, and no leader line runs through another label; the rows are reserved only when a\n  label exists, so a chart without one has no dead band above it. The \"Now\" label of a forecast goes\n  on whichever side of its line the series does not cross. Lay labels out after the fonts load, or\n  the label set changes between loads (it did in testing). The helpers do all of this; give a label\n  that may not fit a `short` form.\n- **Use the helper, then extend it.** Draw charts with `assets/charts.js` and add what a chart needs to\n  it, rather than writing new axis code: in testing, every chart written from scratch on a phone put\n  its y labels on top of its line.\n- **Short and empty histories are drawn honestly**: a flat zero line with one spike, missing bars for\n  empty periods, no padded y-range, no \"No data\" picture. Do not give one point the screen's largest\n  plot, though: a lone dot in a full-size grid reads as barren (flagged once).\n\n## 7. Tables and lists\n\n### 7.1 Rows\n\n- Single-line data rows: 36-53px, median 45.\n- Two-line rows with media: 56-92px, median 72. The pitch is the media's height plus 24-32px\n  (48 + 24, 48 + 32, 50 + 30).\n- Key-value and legend rows inside cards: 21-32px.\n- In a two-line cell, line 2 sits about 21px below line 1 (19-23), one size smaller (12-14px) and\n  grey. Two-line labels need a 40-44px pitch at least: on a 32px pitch a subline nearly touched the\n  next row's name and the list ran together (house rule, from testing).\n- Overview lists show 2-5 rows.\n\n### 7.2 Header\n\n- 11-14px, median 12, mostly regular weight, grey, sentence case (9 of the 11 headed tables). The one\n  uppercase header in the study is flagged as louder than the data.\n- **No fill band** (0 of 11) and **no rule under it** on 8 of 11. Where there is a rule, it is the\n  strongest line in the table (#e5e7eb over #f3f4f6 row rules).\n- Header row 36-40px.\n- Numeric headers are right-aligned and flush with their values; a header that stops 15px short of\n  its column is flagged. A header over a control aligns with the control it labels (centred over a\n  column of steppers), and a delta beside a stepper gets its own narrow unlabelled column; three\n  alignments in one header row were flagged.\n- A sort glyph on the active column only.\n\n### 7.3 Dividers\n\n- **No zebra striping** (0 of 23).\n- No row dividers on about half the lists; they rely on a 61-92px pitch or on 2-8px gaps between\n  filled rows.\n- When present: 1px, 3-7% darker than the surface (#ededed-#f4f4f4 on white; #161616 on #000,\n  #1b1a1f on #131217).\n- Extent: bleeding 8-9px past the text edge; starting at the text column and skipping the media; or\n  the full inner width. Pick one per screen.\n\n### 7.4 Figures and alignment\n\n- **Numbers right-aligned**, in tabular figures or a monospace. Every left-aligned numeric column and\n  every column of proportional digits in the study is flagged (durations \"00:00:12\" and \"00:00:04\"\n  that jitter, cents that drift).\n- **Fixed decimals per metric**: money 2, percentages 1 or 2, counts none. Thousands separators\n  everywhere (\"$16,531.54\"); abbreviate only in a capacity line (\"12.7k of 20.0k\"). A sign on ever\n\n<!-- [TRUNCATED AT 50KB] -->\n\n<!-- File: skills/taste-skill/references/colour.md (Tokens: ~1720 | Category: anthropic-skill) -->\n# Colour\n\nThe direction sheet deals a palette with named roles. This file is how to apply it so the page looks\ndecided rather than tinted.\n\n## Contents\n\n1. What the study measured\n2. The roles\n3. Proportion\n4. Surfaces without lines or shadows\n5. Colour fields\n6. Dark pages\n7. Colour and photographs\n8. Contrast\n9. Banned families, and what \"warm\" means here\n\n## 1. What the study measured\n\n- 41% of the studied pages are dark, 59% light. A quarter sit on pure white; 12% on pure black.\n- Schemes, as the panel classed them: monochrome plus one accent 23%, light neutral 22%, dark neutral\n  14%, several flat colours 13%, strictly two-tone 12%, colour carried by photographs 9%, one saturated\n  field 6%.\n- Buttons are neutral (black, white, grey) on 52% of sites. A coloured button is a choice, not a\n  requirement.\n- Gradient fills appear on 22% of the top-scored sites and 52% of the weak ones; gradient text on 2%\n  against 13%.\n- One site in 246 has a terracotta primary button and none has a violet one. Those are colours of\n  generated pages, not of the gallery. Warm off-white grounds do occur (32 sites), nearly always with\n  a dark or green ink rather than an orange accent.\n- Top-scored sites change the page's field colour between sections more often (a median of two section\n  grounds against one).\n\n## 2. The roles\n\n```css\n:root {\n  --bg: …;          /* the ground: most of the surface */\n  --surface: …;     /* one tone step from the ground: filled panels, form fields, tiles */\n  --ink: …;         /* main text and the strongest marks */\n  --muted: …;       /* secondary text; still passes contrast on --bg */\n  --accent: …;      /* the one accent */\n  --accent-ink: …;  /* text on the accent */\n  /* --field-1 … --field-n and their inks, when the palette has section fields */\n}\n```\n\nUse the tokens for every colour in the build. A raw hex in a component is a second palette starting.\nDo not add greys between the roles: if you need a quieter text, it is `--muted`; if you need a quieter\nsurface, it is `--surface`.\n\n## 3. Proportion\n\nDecide the shares before colouring anything and check them in the screenshot:\n\n- **Ground:** 70–90% of the page.\n- **Ink:** text and perhaps one inverted section (ink as ground, ground as ink).\n- **Accent:** under 5% of any screen. It marks the action and at most one other recurring thing. The\n  moment it appears in five places it stops meaning \"here\".\n\nPalettes with fields (flat-loud, pastel) work differently: each section is one field at full strength\nand the proportion rule applies inside each section (field, its ink, nothing else).\n\nThe accent is not for headings, icons, bullets, borders or underlines unless the direction sheet says\nso. A headline is ink.\n\n## 4. Surfaces without lines or shadows\n\nWith rules and shadows banned, a surface is told apart from the ground by tone alone:\n\n```css\n.panel { background: var(--surface); }          /* 2–6 lightness points from --bg */\n.field { background: var(--surface); border: 0; } /* inputs: filled, with a clear focus state */\n.field:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }\n```\n\n- One step is enough. If a panel does not read, increase padding or separate with space before\n  reaching for a second tone.\n- Do not nest a panel inside a panel.\n- Images do not need a frame. If a light photograph melts into a light ground, change the crop or set\n  it on `--surface`, do not outline it.\n- A thick bar (4px or more) in ink or accent is a graphic element, allowed where the direction uses\n  it. A 1px line is not.\n\n## 5. Colour fields\n\nA section that changes the whole ground colour is the strongest colour move available, and it replaces\ndividers, cards and background decoration at once.\n\n- Fields meet edge to edge with a hard line. Nothing fades.\n- Every field has its own assigned ink from the palette. Never put `--muted` on a coloured field; use\n  the field's ink at full strength, or at 70% opacity for secondary text if it still passes contrast.\n- Neighbouring fields should differ in lightness, not only in hue, or the page vibrates.\n- Order them like chapters: open strong, rest, surprise, close dark or very light.\n- The page's meta theme colour and the navigation follow the first field.\n\n## 6. Dark pages\n\n- Put `color-scheme: dark` on the root so form controls and scrollbars follow.\n- The ground is a deep tone with a slight tint from the palette, and the ink is a soft light, not\n  `#fff` on `#000`, unless the palette deals exactly that for a stark two-tone direction.\n- Secondary text is where dark pages fail: check `--muted` against the ground (4.5:1).\n- Depth on dark comes from a lighter surface step, never from glows or coloured light.\n- Use lighter font weights than you would on a light page.\n\n## 7. Colour and photographs\n\n- When photographs carry the colour, the interface stays neutral and takes its ink from the darkest\n  tone in the imagery.\n- Do not wash a photograph with the brand colour. Either leave it alone, or commit to a real treatment\n  for every image on the page (all greyscale, or all untouched).\n- Text over a photograph needs a calm region. If there is none, move the text off the image. A neutral\n  scrim (black or the ink colour, 30–55% opacity, flat or fading over the text area only) is the one\n  gradient the inspector allows.\n- A flat field sampled from a photograph (its sky, its shadow) makes a section sit with that image.\n\n## 8. Contrast\n\n- Body text 4.5:1 or better; display type and large numerals 3:1 or better; the dealt palettes meet\n  7:1 for ink on ground.\n- `inspect.mjs` computes contrast for text on flat grounds and fails anything under 2.6:1. It cannot\n  see text over photographs: check those in the screenshots yourself.\n- Do not lower opacity on text to make it \"soft\" unless you have checked the resulting ratio.\n- Focus states and hover states increase contrast, never reduce it.\n\n## 9. Banned families, and what \"warm\" means here\n\nThe inspector fails these:\n\n- **Cream with terracotta.** A yellow-cream ground (roughly hue 22–62, light and noticeably\n  saturated) with a rust, clay or burnt-orange accent is the house look of AI assistants and of the\n  pages they generate. Either half alone is suspect; together they are unmistakable.\n- **Violet and indigo.** The first wave of generated pages was purple; it still reads that way.\n\nIf the brief wants warmth, get it from a low-chroma stone, bone or putty ground (saturation under\nabout 15%), from a deep green, brown or oxblood ink, from photographs, or from a full warm field\n(mustard, tomato red, pink) used flat and with conviction. Warmth is not beige.\n\nIf the brand itself owns one of the banned colours, it is the brand's and you keep it: use\n`--keep palette`, pass `--allow palette-purple` (or the relevant rule) to the inspector, and note it in\nthe report.\n\n<!-- File: skills/taste-skill/references/copy.md (Tokens: ~2369 | Category: anthropic-skill) -->\n# Words\n\nCopy is the first design decision. A headline that needs four lines cannot be rescued by typography,\nand a page of slogans cannot be rescued by layout. Write the page as plain text before any markup.\n\n## Contents\n\n1. Write the argument first\n2. The two-line headline (with the character budget)\n3. Headline shapes that work\n4. Supporting line, body, buttons\n5. Proof without inventing it\n6. Things that read as generated\n7. Micro-typography\n\n## 1. Write the argument first\n\nAnswer in one line each, in a scratch note:\n\n- Who is reading, and what do they already know?\n- What is this, said the way its maker would say it to a friend?\n- What single thing should the reader believe after one screen?\n- What would make them believe it (a picture of the thing, a number, a name, a demonstration)?\n- What do they do next?\n\nThen list the page as claims, one per section, each with its proof:\n\n```\n1. It is a three-legged oak stool, made to order.             → the stool, large\n2. Each seat is cut from one board, so the grain is yours.    → three close-ups\n3. It takes six weeks, and you can follow it.                 → the stages, photographed\n4. It costs 240 and is delivered by the maker.                → price, button\n```\n\nA section with no claim is filler; delete it. This is also how you escape the stock order of\nhero, logos, features, testimonial, pricing, call to action: the order of the argument is the order of\nthe page.\n\n## 2. The two-line headline\n\nA headline is a title. It is held in one glance. On the studied gallery sites the hero headline has a\nmedian of 5 words and 70% sit on one or two lines at desktop width. Every headline on your page, at\nevery viewport, fits in **two lines or fewer**. `inspect.mjs` measures this at 1440, 768 and 390 pixels\nand fails the page otherwise.\n\nThe constraint is arithmetic, so do it before you fall in love with a sentence:\n\n```\ncharacters per line ≈ line width in px ÷ (font size in px × k)\n\nk ≈ 0.40  condensed faces\nk ≈ 0.50  most grotesks and serifs at display size, tight tracking\nk ≈ 0.58  wide / extended faces, all-caps settings\n```\n\n| Where | Line width | Size | Per line | Two-line budget |\n| --- | --- | --- | --- | --- |\n| Phone 390, 20px gutters | 350px | 44px | ~16 | **~32 characters** |\n| Phone 390, 20px gutters | 350px | 34px | ~21 | ~42 characters |\n| Tablet 768 | 690px | 64px | ~22 | ~44 characters |\n| Desktop, 12-col measure | 1100px | 104px | ~21 | ~42 characters |\n| Desktop, half width | 620px | 72px | ~17 | ~34 characters |\n\nSo a hero headline of **about 32 characters or fewer** (four to six words) survives everywhere at a\nconfident size. Up to about 42 works if the phone size comes down to the mid-30s. Past that you are\nwriting a sentence; move the rest into the supporting line.\n\nControlling the break:\n\n- Give the headline a `max-width` in `ch` so it breaks where you intend, and add\n  `text-wrap: balance` so two lines come out even.\n- Where the break matters (it usually does), author it: `Stools for<br> small kitchens`. Check the\n  phone screenshot; if an authored line wraps there, hide the `<br>` under a breakpoint or shorten.\n- Never fix a long headline only by shrinking it. A timid 28px headline of nine words is worse than\n  five words at 64px.\n- Avoid a single orphan word on line two. Rebalance by cutting a word, not by nudging the width.\n\nSection headings follow the same rule and are shorter: two to five words.\n\n**A statement is not a headline.** An intro sentence or a quotation set large (the manifesto line\nafter the hero, a testimonial) is a paragraph: mark it up as `<p>` or `<blockquote>`, keep it to about\n25 words, and set it at statement size, which the inspector takes as 36px or less on desktop, 32px on\na tablet and 24px on a phone. It may then run to about three lines (four on a phone). Set larger than\nthat, or marked up as a heading, or placed as the main line of the first screen, it is a headline and\ngets two lines. In blind judging, a sentence set big over three or more lines was read as a long\nheadline every time, whatever its markup; if the words matter that much, cut them to a two-line\nheadline instead.\n\n## 3. Headline shapes that work\n\nAll seen repeatedly on the gallery sites. Pick the plainest one that is true.\n\n- **The name.** The brand or the person, set very large, with a one-line description elsewhere.\n  Strongest when the name is short and the subject is visual (studios, restaurants, hotels, people).\n- **What it is.** \"A vinyl shelf in your pocket.\" \"Furniture for small rooms.\" Category, stated with\n  one specific word.\n- **The claim.** \"Your bank won't do this.\" One sentence a competitor could not sign.\n- **The instruction.** \"Understand your money.\" Verb first, short.\n- **The place or the moment.** \"Antarctica.\" \"Lisbon, since 1984.\" For hospitality, events, travel.\n\nShapes to avoid, because they are the average of every landing page:\n\n- The mad-lib: \"The AI-powered platform for modern teams\".\n- The tricolon: \"Fast. Simple. Secure.\" or \"Plan. Build. Ship.\"\n- The correction: \"It's not just a tool, it's a workflow\". Also \"More than a …\".\n- \"X, reimagined / redefined / made simple\". \"Welcome to …\". \"Meet …\" for a product nobody has met.\n- A question the reader did not ask.\n- A headline that needs its colon: \"Ledgerly: invoicing for freelancers\". Drop the name, it is in the\n  navigation.\n- One word of the headline styled differently (italic, serif, coloured, underlined, in a pill).\n\nSentence case. No full stop unless the direction's voice uses them everywhere.\n\n## 4. Supporting line, body, buttons\n\n**Supporting line.** One sentence, at most about 22 words, that says concretely what the thing is and\nwho it is for. It is where the detail cut from the headline goes. It never repeats the headline in\nother words.\n\n**Body.** Short paragraphs of plain statements. Prefer the specific noun and the real number: \"ships\nin a week\" over \"fast delivery\"; \"38 seats\" over \"intimate\". Read every sentence and ask whether a\ndifferent company could print it unchanged; if so, sharpen it or cut it.\n\n**Buttons.** Name the action or the thing: \"Book a table\", \"See the plans\", \"Download for Mac\".\nOne to three words. The primary action keeps one name everywhere on the page. One primary button per\nscreen; a second action is a plain text link. No arrow glyph on every link and button; at most one\narrow, on the primary action, if the direction uses arrows at all.\n\n**Navigation.** The wordmark, up to five plain links, one action. Link labels are single nouns.\n\n## 5. Proof without inventing it\n\nNever invent customers, quotes from named people, press logos, user counts, ratings or benchmarks.\nInvented proof is both dishonest and a recognised tell.\n\nWhen the brief supplies no proof, use what is true by construction:\n\n- Show the thing itself, large. A real demonstration outranks any quote.\n- State how it works, specifically.\n- Use facts from the brief (price, place, year, materials, what is included).\n- If a testimonial or logo section is explicitly requested and no real ones exist, build the section\n  with plainly fictional sample content and say so in your final report so it is replaced before\n  launch. Do not put real company names or real people in it.\n\n**Sample details are different from proof, and they are expected.** Where the brief gives the shape of\nthe content but not every detail (six rooms \"from €140\", \"a short menu\", twelve speakers), write the\nfull set of plausible details: each room with a name, a bed, a view and its own rate; each dish with\nits price; each speaker with a talk title. A design can only be judged at its real density, and a page\nthat shows one rate where six rooms exist looks unfinished. List every sample detail in the report so\nthe client confirms or replaces it.\n\n## 6. Things that read as generated\n\n`lint.mjs` flags most of these.\n\n- Verbs and adjectives of the genre: unlock, unleash, supercharge, elevate, empower, streamline,\n  seamless, effortless, robust, cutting-edge, next-generation, world-class, all-in-one, blazing fast.\n- Labels pretending to be editorial: \"Field notes\", \"The details\", \"Our philosophy\", \"Quietly trusted\n  by\". A section heading can simply be \"Pricing\".\n- Furniture text: locale or time strips, \"Est. 2024\", coordinates, version stamps, \"Scroll\", \"(Scroll\n  to explore)\", fake photo credits, status lines such as \"Available for work\" with a dot, strings of\n  words separated by middle dots or slashes.\n- The em dash as a habit. One or two on a page read as writing; ten read as a model. Use a full stop.\n- Explainer captions that narrate the design: \"A clean, minimal layout for…\".\n- Step labels that duplicate numbers: \"Step 1\", \"Phase 02\".\n- Three parallel items everywhere: three features, three stats, three steps. Use the number the\n  content has.\n\n## 7. Micro-typography\n\n- Curly quotes and apostrophes (“ ” ’), a real ellipsis (…), an en dash for ranges (9–5).\n- Non-breaking space between a number and its unit, and before the last short word of a headline\n  when it would otherwise orphan (`&nbsp;`).\n- `font-variant-numeric: tabular-nums` where numbers line up in columns (prices, tables).\n- `text-wrap: balance` on headings, `text-wrap: pretty` on paragraphs.\n- No all-caps for anything longer than three words; if you set caps, add 0.02–0.06em tracking.\n- No text under 13px. No centred paragraphs longer than three lines. No justified text.\n\n<!-- File: skills/taste-skill/references/critique.md (Tokens: ~2732 | Category: anthropic-skill) -->\n# Critique — judging the render\n\n`inspect.mjs` passing means nothing banned or broken was measured. It says nothing about whether the\npage is good. This file is how you find out. Use it on the screenshots, never on the code: you wrote\nthe code, so you will read your intentions into it. The pictures only show what is there.\n\n## Contents\n\n1. How to look (fourteen passes, a few minutes)\n2. The score\n3. Caps\n4. Writing the critique\n5. What to fix first\n6. When to stop\n\n## 1. How to look\n\nOpen `desktop-fold.jpg`, then the `desktop-page-*.jpg` sheets, then `mobile-fold.jpg` and the mobile\nsheets. Make each pass on its own; do not blend them.\n\n1. **One second, then five.** Glance and look away. What did you see? There should be exactly one\n   answer: a word, an image, an object. If the answer is \"a website\", there is no focal point. Then\n   give the first screen five seconds as a stranger: can you say what this is, who it is for and\n   what to do next? If the title only makes sense after scrolling, it is not a title.\n2. **Squint.** Blur your attention until text becomes grey bars. The page should reduce to two or\n   three large masses with clear size differences. Many small similar masses means everything is\n   medium and nothing leads.\n3. **Cover the logo.** Could this first screen belong to a competitor, or to a different industry?\n   If swapping the name and the noun in the headline would produce an equally valid page, the page has\n   no idea. Go back to the direction sheet; the idea is written there. Then scroll: does the idea reach\n   the pricing, the FAQ and the footer, or does the page turn into stock blocks after the first screen?\n4. **Edges.** Follow the left edge of every text block down the page. Count the distinct x positions.\n   A composed page has two or three, reused on purpose. Six means things were placed one at a time.\n5. **Space and frame.** Are related things close and unrelated things far? Is the gap between sections\n   clearly larger than any gap inside a section? Is any region empty by accident (a hole) rather than\n   by decision (a rest)? A hole usually sits beside a short column or under a removed decoration.\n   Then look at the frame: are the left and right margins of the page the same? Does any section keep\n   its text in one half and leave the other half empty? Is there a stretch of nothing taller than half\n   a screen? Readers name these first (\"it is pushed to the left\", \"random empty space\"), before any\n   detail; in the study of 100 Sites of the Day about 1 section in 100 left half the width empty.\n6. **Type.** Is the jump from body text to headline decisive (three times or more)? Do you see more\n   than five sizes? Any headline with one orphan word on its last line? Any paragraph wider than about\n   75 characters or centred over more than three lines?\n7. **Colour.** Name the proportions: which colour holds most of the surface, which supports, where is\n   the accent? An accent that appears in ten places means nothing. One that appears on the single\n   action and one detail means \"here\".\n8. **Images.** Count the real pictures: are there at least four, and is there a moving one? A page of\n   drawings only, or of type only, looks unfinished next to one with real photographs and footage.\n   Is every image doing a job (showing the thing, setting the place, proving the claim)?\n   Do the crops share ratios? Is anything a grey box, a stretched photo, a fake screen made of bars?\n   Does the photography share one light and one grade, or is it a stock mix?\n9. **Sameness.** Write one word for each section's layout (split, list, full-bleed, grid, statement,\n   index …). The same word twice in a row, or three times on the page, is the template showing.\n10. **Phone.** Is the mobile screen a composition of its own, with its own crop and its own line\n    breaks, or the desktop page squeezed? Is the first screen still one clear thing?\n11. **Fullness.** Go through the desktop sheets screen by screen. Is each screen a composed poster, or\n    is it a narrow column of small text with dead ground either side? Is any statement held on screen\n    for three screens? An austere page is not a restrained one: if the page could be mistaken for an\n    unfinished wireframe (grey shapes, grey text, one small column), it is underbuilt. A single motif or\n    drawing blown up to fill a whole screen with nothing to read is a hole too, however bold it looks.\n12. **Substance.** Does every section the brief asked for deliver its information completely and at a\n    readable size (the full menu, each room, every speaker, the price and what it includes)? Would the\n    visitor leave knowing what they came to find out? Is the primary action a real button on the first\n    screen?\n13. **Collisions.** Is anything lying on top of a headline, a statement or a button at any scroll\n    position? Does any element run off the edge of the phone screen? A row that scrolls sideways on\n    the phone reads as cut off in a screenshot and to most visitors; wrap it unless the cut is\n    plainly deliberate (a partial card showing at the edge).\n14. **The competitor and the live thing.** Put the nearest competitor's name on the page: does the\n    idea still work? Then name the one live thing (what the visitor can do or what differs each visit).\n    If either answer is weak, that is the first problem of the round, ahead of any detail.\n\nA note from testing: in blind comparisons a richer page full of template devices beat a cleaner page\nthat was thin, every time. The house rules remove the devices; passes 11–13 are where you make sure the\npage did not lose its substance with them.\n\n## 2. The score\n\nScore like an Awwwards juror: four criteria, 1–10 each, weighted **design 40%, usability 30%,\ncreativity 20%, content 10%**.\n\n**Design (40%)** — composition, typography, colour, imagery, craft.\n- 9–10: every screen holds as a poster. Nothing could be removed or moved.\n- 8: confident and coherent; one or two soft spots a designer would notice.\n- 7: clean and professional, a clear system, little tension.\n- 6: tidy but anonymous. Reads as a kit.\n- 5 or less: weak hierarchy, accidental spacing, default type, mismatched images.\n\n**Usability (30%)** — orientation in three seconds, readable text, obvious actions, honest mobile.\n- 9–10: you know what it is, who it is for and what to do without scrolling; flawless on a phone.\n- 8: clear and comfortable; minor friction (a long section, a small target).\n- 7: works, with one real problem (weak contrast somewhere, a cramped phone layout).\n- 6 or less: you have to hunt, or something breaks.\n\n**Creativity (20%)** — an idea you can state in a sentence, carried through.\n- 9–10: a concept specific to this subject that you have not seen applied this way.\n- 8: a clear idea with one memorable move.\n- 7: a tasteful execution of a known approach.\n- 6 or less: the category default.\n\n**Content (10%)** — words and pictures that are specific, true-sounding and edited.\n- 9–10: every line could only be about this subject; imagery is the subject.\n- 7–8: clear and concrete, some generic lines.\n- 6 or less: slogans, filler, stock.\n\n`overall = 0.4·design + 0.3·usability + 0.2·creativity + 0.1·content`\n\nFor calibration: real Sites of the Day land around 7.5–8.0 overall from the jury. An honest 8.5 is\nrare. If your first score for your own work is 9, score it again as the juror who did not build it.\n\n## 3. Caps\n\nThese override the arithmetic.\n\n- Any `FAIL` still reported by `inspect.mjs`: overall cannot exceed **6.0**.\n- A headline of three or more lines at any viewport, an eyebrow label, monospace labels, 01/02/03\n  numbering, a decorative gradient, a shadow on a resting element, or a decorative hairline visible in\n  a screenshot: overall cannot exceed **6.5**, whatever else is true.\n- Pass 3 fails (the page could belong to anyone): creativity cannot exceed **6**.\n- The idea passes for the nearest competitor (pass 14): creativity cannot exceed **7**.\n- Fewer than four real pictures (photographs, archival images, footage; drawings do not count):\n  design cannot exceed **6.5**.\n- A page that barely moves (the inspector's `still-page`), or motion that is one identical fade on\n  every block: design cannot exceed **7**.\n- No live thing (pass 14): creativity cannot exceed **7.5**.\n- Any placeholder (grey box, lorem, \"Image here\"): content cannot exceed **5**.\n- Two or more desktop screens that are mostly empty ground, or a page whose running text is small and\n  grey: design cannot exceed **6.5**.\n- A section the brief asked for that is missing or reduced to a few words: content cannot exceed **6**.\n- No real button for the primary action on the first screen: usability cannot exceed **7**.\n- The five-second pass fails (no clear title saying what this is on the first screen): usability\n  cannot exceed **6**.\n- Unequal page margins, a section huddled on one side with the other half empty, or a blank stretch\n  taller than half a screen: design cannot exceed **6.5**.\n- A section of running text with no heading naming it: usability cannot exceed **7**.\n- Anything covering a headline at any scroll position: usability cannot exceed **6**.\n- A blank band where a reveal did not fire, or content clipped off-screen: usability cannot exceed **5**.\n\n## 4. Writing the critique\n\nWrite it down; do not just think it. Use exactly this shape so rounds can be compared:\n\n```\nROUND n\nSeen in one second: …\nIdea (one sentence): …\nLive thing: …\nLayout words by section: hero=… / …=… / …\nScores: design _ · usability _ · creativity _ · content _ → overall _._\nCaps applied: …\nTop three problems (most visible first), each with the screenshot it shows in and the fix:\n1. …\n2. …\n3. …\n```\n\nName problems the way a designer would to a colleague: \"the supporting paragraph starts 40px left of\nthe headline's edge\", \"the testimonial section is the third split layout in a row\", \"the phone hero\ncrops the bottle out of frame\". \"Could be more polished\" is not a finding.\n\n## 5. What to fix first\n\nFix in this order; later items cannot rescue earlier ones.\n\n1. **The idea.** If pass 3 fails, change the hero concept, not the details.\n2. **Hierarchy.** One dominant element per screen. Make the big thing bigger and the small things\n   fewer before touching anything else.\n3. **Composition.** Shared edges, section spacing, variety of layout between sections, holes.\n4. **Typography.** Scale contrast, line breaks, measure, leading.\n5. **Imagery.** Replace weak pictures, unify crops and grade.\n6. **Colour.** Proportion and accent discipline.\n7. **Detail.** States, focus, small alignments, mobile refinements.\n8. **Motion.** Last.\n\nWhen removing something leaves a gap, do not refill it with an ornament. Close the gap, enlarge what\nremains, or let a picture or a colour field take the space.\n\n## 6. When to stop\n\nRun at most three rounds: critique → fix the top three → re-inspect → critique. Stop early when a round\nfinds no problem a stranger would notice. If round three still scores under 7.5, say so plainly in\nyour report, with the remaining problems listed; do not round up.\n\n<!-- File: skills/taste-skill/references/imagery.md (Tokens: ~13134 | Category: anthropic-skill) -->\n# Imagery\n\nPictures are where generated pages most obviously give up: a grey box, an icon in a square, a fake\ndashboard, an abstract blob. This file is how to decide what the pictures are, where to find real ones,\nhow to crop and place them, and what to do when there are none.\n\n## Contents\n\n1. What the study measured\n2. Decide what imagery exists\n3. Real pictures from the open collections\n4. The dealt photographs\n5. Cropping and placing\n6. Treatment\n7. Showing software\n8. Drawing the subject\n9. Type and colour alone\n10. Markup and credits\n11. Video\n12. Where pictures and footage go\n\n## 1. What the study measured\n\n- On 60% of the studied sites one piece of media covers at least half of the first screen; on half of\n  them it covers nearly all of it. Top-scored sites: 68% and 56%. Weak sites: 48% and 39%.\n- Only 15% of heroes have no media at all, and those are deliberate typographic statements.\n- Media has square corners on 73% of sites. Where corners are rounded the usual radius is about 12px,\n  applied to every image alike.\n- Top-scored pages carry far more imagery (a median of 37 images against 5 on weak pages): the strong\n  sites show, the weak ones tell.\n- What the imagery is, by the panel's classification: a mix of kinds 32%, photography 14%, generative\n  or WebGL scenes 13%, real product interface 12%, 3D renders 11%, illustration 9%, video 6%, type only\n  3%.\n- Among the 54 sites the panel scored under 6.8, legibility (text lost over a busy image, or too\n  little contrast) was named as a weakness in 13.\n- In the October 2026 study of 91 Awwwards Sites of the Day (section 12), the median page carries 7\n  pictures (top sites 8, the lowest 2) and footage appears on 42% of sites (half of the top ones, one\n  of the 16 lowest).\n- Pictures come in whole screens: 42% of scrolled screens hold none and 19% are 90% picture or more.\n- 94% of pictures have square corners, and on a typical site two ratios hold three-quarters of them.\n\n## 2. Decide what imagery exists\n\nIn order of preference:\n\n1. **The project's own images.** Product shots, the place, the people, the work. Even ordinary\n   photographs of the real thing beat beautiful photographs of something else. Ask what exists; look in\n   the repository.\n2. **Images you can generate** with an image tool in this session. Write prompts as a photographer's\n   brief: subject, angle, light, background, crop ratio, and \"no text\". Generate the hero first and\n   make the rest match its light.\n3. **Real pictures of the subject's world from the open collections** (section 3). Archives,\n   museums and photographers have published millions of pictures anyone may use with a credit: the\n   client's city and street in old postcards, maps of its neighbourhood, its materials, its trade in\n   engravings, museum objects of its kind. Whenever an honest one exists, it beats a drawing of the\n   same thing: it is real, it has detail no drawing in a page's budget reaches, and it carries history.\n   Honest means nobody could take it for the client's own product, room, dish, person or team.\n4. **Pictures you draw in code from the subject itself** (section 8), for what no honest picture\n   exists of: the product's own objects as flat shapes, the place's tiles and windows, a map of its\n   streets, the document a tool produces, the interface of a piece of software. In testing, pages that\n   drew their subject with care beat pages that borrowed unrelated photographs every time, and beat\n   pages that showed nothing.\n5. **The photographs dealt on the direction sheet.** Real photographs of places, light, texture and\n   weather. Use them only where an honestly generic picture fits (the open sea for a house on the sea,\n   fog for a quiet retreat). They cannot stand in for a specific product, dish, room, person or\n   screen: a foggy motorway on a restaurant page reads as stock at once, and jurors notice.\n6. **Type and colour alone,** done on purpose (section 9).\n\nTell `draw.mjs` the truth with `--have`. If you have no product photographs and no image tool, do not\npass `product-photo`; the draw will avoid the directions that depend on showing the object. Pictures\nfound in the open collections are not the project's own: do not pass `photography` for them.\n\n## 3. Real pictures from the open collections\n\n`scripts/assets.mjs` searches four open sources without keys and prints, for each find, a direct image\nURL, the page it comes from, its size, its creator, its licence and a credit line:\n\n- **Openverse**: one index over Flickr, Wikimedia Commons, museums and libraries.\n- **Wikimedia Commons**: archival photographs, old maps, scans of prints and books, places as they\n  look now.\n- **The Art Institute of Chicago** and **The Metropolitan Museum of Art**: public-domain paintings,\n  prints, drawings, photographs, textiles and objects, in large scans.\n\n```bash\nnode <skill>/scripts/assets.mjs \"ghent postcard\"\nnode <skill>/scripts/assets.mjs \"fig\" --source museums --orientation portrait\nnode <skill>/scripts/assets.mjs \"basalt texture\" --min-width 2400 --source openverse,commons\nnode <skill>/scripts/assets.mjs --get commons:36649959,met:707892     # download, record the credits\nnode <skill>/scripts/assets.mjs --credits                             # footer line and report list\n```\n\nBy default it keeps only licences that allow commercial use (CC0, public domain, CC BY, CC BY-SA) and\npictures at least 1000 pixels wide, and checks that every image it prints actually loads.\n`--license pd` keeps only pictures that need no credit; `--orientation`, `--min-width` and `--limit`\nnarrow the list; `--source` picks the sources; `--json` gives the raw results. Each result has a ref\n(`commons:36649959`) that `--get` takes.\n\n**What to search for.** The inventory (SKILL.md step 1), not the category: \"bakery\" finds other\npeople's bakeries. The subject's world is specific:\n\n- **Its place:** the city, the street, the harbour, the valley, in old postcards and photographs\n  (\"ghent postcard\", \"rotterdam harbour 1920\") and as it looks today (\"gent korenmarkt\").\n- **Its maps:** the street plan, the chart of its bay, the geology of its valley (\"ghent old map\",\n  \"nautical chart lisbon\").\n- **Its materials,** close enough to read as a surface: the stone of its quay, the grain of its oak,\n  its glaze, its tiles (\"azulejo tiles\", \"basalt cobblestones\", \"oak grain\").\n- **Its trade's history:** the old tools, the craft in engravings and trade catalogues, patent\n  drawings (\"bread oven engraving\", \"potter's wheel\", \"bicycle patent drawing\").\n- **Museum objects of its kind,** with `--source museums`: a coffee set from about 1810 for a studio\n  that makes coffee sets, a woodblock print of a wave for a surf school, a porcelain plate painted\n  with figs for a fig orchard.\n- **Scientific imagery:** botanical and zoological plates (\"botanical engraving fig\"), star charts,\n  microscope photographs, satellite views of its coast, geological sections.\n\nSearch in the place's own words (azulejo, not \"blue tile\"; Korenmarkt, not \"market square\"), add a\nmedium (postcard, engraving, old map, lithograph, aerial photograph) or a decade, and try two or three\nqueries per idea. The museum sources match best on one or two words (\"fig\", \"harbour\", \"teapot\").\n\n**What makes a good find.**\n\n- It belongs to this subject's world and would not fit the nearest competitor's page.\n- It still reads at the crop the slot needs. Look at it before deciding: `--get` downloads it, then\n  open the file. A title is not a picture.\n- It is large enough: twice the width it is shown at for anything full-bleed (the script prints the\n  largest size available). A 1024-pixel Flickr photograph is a half-width picture at most.\n- It belongs to one family with the others on the page: all engravings, or all photographs from one\n  era, or all close surfaces in one light. A 1900 postcard beside a modern stock photograph beside a\n  botanical plate reads as a scrapbook.\n- No watermark, no burned-in text or logo, no frame or scanner edge you cannot crop away, and no\n  recognisable living person who could be taken for the client's staff or customers.\n\n**Use it creatively.** Found pictures are material, not decoration:\n\n- **One archival photograph as the hero,** full-bleed: the street as it was a century ago, behind the\n  name of the business that stands in it today, with the year in the caption.\n- **A museum engraving enlarged until its line becomes texture,** cropped tight and returning at\n  different scales as the page's one motif (the whole fig plate in the hero, a single leaf of it\n  beside the menu).\n- **An engraving or a map on white paper set with `mix-blend-mode: multiply` on the page's colour\n  field,** so the ink sits on the ground (section 6).\n- **The real map of the street as the contact section,** the door marked, the north and the scale\n  taken from the original.\n- **A material close-up as a whole field:** the quay's stone behind the opening hours.\n- **A run of old postcards or plates as the gallery,** one size, one treatment.\n\nTreatments stay within section 6: untouched, greyscale for the whole set, or multiply on a field.\n\n**Stay honest.**\n\n- **A found picture is never the client's own.** It may show the client's city, its materials, its\n  history, the kind of thing it makes; it may never stand in for the client's product, room, dish,\n  person, team or customers. If a visitor could take it for the client's own (a bakery counter, a\n  plate of pasta, a smiling barista, a guest room), do not use it.\n- **Caption from the source** when a caption helps: what it is and when, as the archive describes it\n  (\"Gand, unloading a steamer, 1905\"). Never write a caption that ties it to the client.\n- **Record and credit every picture.** `--get` writes the source, creator, licence and page of each\n  download to `assets/credits.json`. CC BY and CC BY-SA require a credit with the title, the creator,\n  a link to the source and a link to the licence; `--credits` prints them as one line of HTML for\n  the footer (section 10). Public-domain pictures need no credit; give one anyway.\n- **Respect the licence.** CC BY-SA: an altered version (recoloured, combined with other pictures)\n  must be shared under the same licence. Non-commercial (NC) and no-derivatives (ND) licences are out\n  for a client's site, which is why the script leaves them out unless asked. Read the `note` lines:\n  some pictures carry personality rights or a trademark, are public domain only in the United States,\n  or come with an archive's statement instead of a licence.\n- **Download, do not hotlink.** Save what you use into the project: `--get` puts it in `assets/` at\n  1920 pixels wide (pass `--width 1280` for a picture shown at half the screen, `--width 3840` for a\n  very large hero where the source has it). The page then works offline, does not break when an\n  archive moves a file, and does not load from someone else's server. Every licence the script\n  allows by default permits copying.\n- **List them in the report:** file, title, creator, licence, source page, and where the credit sits.\n  `--credits` prints that list too.\n\nIf two or three honest queries per idea find nothing that fits, draw (section 8). A drawing made for\nthe subject is better than a found picture that is merely nearby. If the script cannot reach any\nsource (no network), draw, and say so in the report. For moving pictures, the same script searches\nreal footage with `--video` (section 11).\n\n## 4. The dealt photographs\n\n- The sheet lists eight from one set so they share a subject and a light. Use three to six.\n- Each line says where the calm area is. Put text there or keep text off the image.\n- More from the same or another set: `node scripts/draw.mjs --photos list`, `--photos <set>`, or\n  `--photos \"fog coast\"` to search descriptions.\n- URLs have the form `https://picsum.photos/id/<id>/<width>/<height>`. Request the exact pixel size you\n  render at twice the CSS size for sharpness, capped around 2400 wide. Add `?grayscale` for\n  black-and-white.\n- These are photographs from Unsplash served by Lorem Picsum under the Unsplash licence. List the ids\n  you used in your report; they are meant to be replaced by the project's own pictures.\n\n## 5. Cropping and placing\n\n- **Choose a small set of ratios and stick to them:** for example 4:5 for portraits, 16:10 for\n  landscapes and 1:1 for details. Random ratios look like a stock dump.\n- **Go large.** A photograph at full width, or at half the screen and full height, has presence. Six\n  small ones in a grid have none. If the image is good, give it the room; if it is not, cut it.\n- **Crop with intent.** Use `object-fit: cover` with an `object-position` chosen per image so the\n  subject sits where the composition needs it (off-centre, on a third, against the text side).\n- **Let images touch edges.** Full-bleed, or bleeding off one side, reads as designed. An image\n  floating with equal margins on all sides reads as placed by default.\n- **Overlap sparingly and on purpose:** a headline whose last line runs over the top edge of the\n  picture, a small image overlapping a large one by a fixed 40–80px. One overlap per screen at most.\n- **Square corners** unless the direction or the one-motif shape says otherwise. If rounded, one radius\n  for every image on the page.\n- **No frames:** no borders, no shadows, no device mock-ups, no browser chrome around pictures.\n- **Captions** are one short line in the small size and soft ink under the image, left-aligned to its\n  edge. Most images need none.\n- Where each picture goes on the page, how large, and what the phone does with it: section 12.\n\n## 6. Treatment\n\nOne treatment for the whole page:\n\n- **Untouched.** The default. Pick images whose light already agrees.\n- **Greyscale.** `filter: grayscale(1) contrast(1.05)`, or `?grayscale` on the URL. Unifies a mixed\n  set instantly and suits editorial and typographic directions. Apply to every image or none.\n- **Multiply on a field.** On a light flat ground, `mix-blend-mode: multiply` makes a white studio\n  background vanish so a product sits directly on the colour.\n- **Darkened for a dark page.** `filter: brightness(0.85) contrast(1.05)` so the image edges sink into\n  the ground.\n\nNot treatments: colour washes over photographs, duotone overlays, blur, grain overlays, vignettes,\ntilted \"polaroid\" frames with shadows.\n\nFor text on a photograph, a neutral scrim covering only the text area: a solid block at 40–55% black,\nor a fade from 55% black to transparent over the lower third. Never a coloured overlay.\n\n## 7. Showing software\n\n- Build a real fragment of the interface in HTML at its true size, with believable content, instead of\n  a shrunken screenshot or a decorative mock-up. Crop to the part that makes the point: one control,\n  one row, one panel.\n- Believable means real labels, real numbers that add up, one item hovered or selected, proper\n  alignment. Grey bars standing in for text are worse than no image.\n- Put the fragment directly on the page or on one flat stage colour. No laptop, no phone frame unless\n  the product is a phone app and the frame is a plain rounded rectangle.\n- Inside a fragment the product's own interface conventions apply (its small radii, its 1px control\n  borders, a shadow on its open menu). Put the attribute `data-ui` on the fragment's root element: the\n  inspector and the linter then leave what is inside alone, and hold the page around it to the house\n  rules. `data-ui` is for cropped fragments only; wrapping a heading or a whole section in it fails.\n  Write the fragment's CSS under a `[data-ui]` selector (`[data-ui] .row { … }`) so the linter can\n  tell it apart from page styles.\n- If the user supplies real screenshots, show them large and uncropped at least once.\n\n## 8. Drawing the subject\n\nWhen nothing real can be photographed and the open collections hold no honest picture of it, draw it,\nand draw it well. Inline SVG and CSS are enough. Drawings and found pictures can share a page: the\nfound ones show the world around the client, the drawings show the client's own things.\n\n- **Draw the subject's own things,** not decoration: the stool's three legs and the grain of its seat,\n  the enamel sign over the bakery door, the hut's two windows and its stove pipe, the street plan, the\n  invoice the tool produces, the festival's stage. If you cannot name what a drawing depicts in the subject's world, it is decoration.\n- **One graphic language for the whole page:** flat filled shapes, no outlines or one consistent\n  stroke weight, the same corner and curve vocabulary everywhere, drawn in the palette's real colours\n  (fields and accent at full strength, not greys). A set of drawings that obviously belong together\n  reads as an identity; a mix of styles reads as clip art.\n- **Colour is the material.** A product sold on its finish is drawn in that finish's colours; a sea house in the\n  sea's blues and the sand; never a page of grey placeholders.\n- **Draw with three levels of detail.** Jurors called simple drawings \"basic\" every time. Give each\n  drawing big shapes that read at a glance, middle shapes that describe the thing (the handle, the\n  window frame, the step), and small details that reward a second look (the maker's mark, the house\n  number, the chipped tile, the hinge, a bird on the roof). Make light with flat tone steps (a lit face\n  and a shaded face of each volume), not gradients. A drawing that would pass as a placeholder icon at\n  full size is not finished.\n- **Draw large and let it work:** the drawing is the hero's dominant element, a full-width band, a set\n  of tiles, the footer mark. Small doodles scattered around read as filler.\n- **Let it carry the idea through the page,** the way a motif does: the same drawn object returns at\n  different scales, the tile grid becomes the opening hours, the map becomes the booking section.\n- **Honesty:** say plainly, in small text near the first drawing or in the footer, that the pictures\n  are drawn until photographs exist, if the client might otherwise be taken to be showing real\n  products. In your report, list which drawings are placeholders for photography.\n- **Not this:** gradient-shaded 3D-looking blobs, isometric clip art, generic line illustrations of\n  people at laptops, abstract floating shapes, icons in squares. Those are the generated look.\n\n## 9. Type and colour alone\n\nThis is a legitimate design, not a gap to disguise. Only 7 of the studied sites use no imagery at all,\nand they hold their own: a median panel score of 7.5 against 7.2 for the whole set.\n\n- Make the typography the image: one statement at 10–14vw, a list set at 5vw, numerals at display size.\n- Use colour at scale: a full field, an inverted section, a two-field split.\n- Use the subject's own shape as one flat motif if the direction calls for it (a circle, an arc, a\n  notch), drawn in CSS, cropped by the viewport.\n- Do not add: icons in squares, abstract gradients, dot grids, wave dividers, floating shapes, emoji,\n  generic line illustrations, or an empty box where a picture \"will go\".\n\n## 10. Markup and credits\n\nA found picture, downloaded into the project with `--get`, used as the hero:\n\n```html\n<img src=\"assets/fig-engraving.jpg\" width=\"1920\" height=\"2807\" fetchpriority=\"high\" decoding=\"async\"\n     alt=\"Hand-coloured engraving of a fig cut open, with its flowers and seeds, in black, pink and green\">\n```\n\nA dealt photograph further down the page:\n\n```html\n<img src=\"https://picsum.photos/id/626/2400/1500\" width=\"2400\" height=\"1500\"\n     alt=\"Red and white lighthouse in a turquoise sea below a chalk cliff\" loading=\"lazy\" decoding=\"async\">\n```\n\nThe credits, as `--credits` prints them, in the footer:\n\n```html\n<p class=\"credits\">Pictures: <a href=\"https://commons.wikimedia.org/wiki/File:Fig_(Ficus_carica_L.);_57_segments_of_flowers_and_fruits_at_Wellcome_V0043000.jpg\">“Fig (Ficus carica L.): 57 segments of flowers and fruits”</a>, <a href=\"https://creativecommons.org/publicdomain/mark/1.0/\">public domain</a>, via Wikimedia Commons.</p>\n```\n\n- Always `width` and `height` (or `aspect-ratio` in CSS) so nothing jumps while loading.\n- `loading=\"lazy\"` on everything except the hero image, which gets `fetchpriority=\"high\"`.\n- `alt` describes the picture in plain words. Decorative repeats get `alt=\"\"`. The script's suggested\n  alt is the archive's title; rewrite it to say what the picture shows.\n- A coloured `background-color` on the image container (the ground or surface tone) so the layout is\n  whole before the image arrives.\n- The credit line is part of the footer's design, at full contrast, with its links. Set it at the body\n  size; one step smaller only on a page with plenty of running text, because a long credit line in\n  small type can become the page's most common text size and fail the inspector's body-size check.\n  One line for all pictures; no credit captions laid over the pictures themselves. Credit only the\n  pictures the page still uses.\n- A broken image fails the inspector. Check every picture in the screenshots.\n\n## 11. Video\n\nA moving picture of the subject's world can carry a section the way a photograph does: the river at\nthe end of the street, the roaster's drum turning, a timber frame going up. `assets.mjs --video`\nsearches real footage without keys: Wikimedia Commons (every video there comes with web-sized\ntranscodes; the best source for short clips), the Internet Archive's Prelinger Archives (industrial,\neducational, city and home films from the 1920s to the 1970s, mostly public domain and mostly long)\nand NASA (the Earth from orbit, launches, aircraft, laboratories). The rest of the Internet Archive is\nleft out: anyone can upload there, and the licence claims are unchecked.\n\n```bash\nnode <skill>/scripts/assets.mjs \"coffee roasting\" --video\nnode <skill>/scripts/assets.mjs \"river\" --video --source commons,nasa --orientation landscape\nnode <skill>/scripts/assets.mjs --get commons:49769620        # the clip, a poster frame, the credit\n```\n\nIt takes a rendition of 720p or smaller (`--res` changes that), lists short clips first, prints each\nclip's length and file size, and flags anything over 25 MB or longer than a minute. `--get` refuses a\nclip over 25 MB unless you pass `--max-mb`, and saves the source's still frame beside it as the\nposter (Commons and NASA; the archive's own stills are too small). An archive film of ten minutes is\ntoo heavy as it stands: trim a few seconds from it with ffmpeg if it is installed, or choose a\nshorter clip. Licences, credits and honesty work exactly as for pictures (section 3).\n\n**Choosing a clip.**\n\n- **Short:** 5 to 20 seconds that loop without a visible jump: water, smoke, a turning drum, traffic,\n  leaves, a crowd from far away. Watch it to the end before choosing.\n- **Light:** under about 5 MB for a section and 10 MB for a hero. In the study sources are 1920×1080\n  (the commonest) or 1280×720, median length 10 s; 720p is plenty behind type. For a full-bleed hero,\n  cut a tall 720×1280 version for the phone, or set `object-position` on the subject.\n- **Clean:** no slate, title card, logo, watermark or burned-in caption. NASA and archive films often\n  open with a slate, and the source's poster frame may be that slate. No recognisable person who could\n  be taken for the client's staff or customers.\n- **Never the client's own:** a found clip of a roastery is not this roastery.\n- **Found clips: one per page, two at most.** A found clip shows the world around the client; a\n  third makes a theme of it. The project's own footage can carry more: in the study a site with\n  footage carries a median of three or four clips. Either way, **one moving picture per screen**;\n  two loops running side by side are noise.\n\n**On the page.**\n\n- Muted, looping, inline, with a poster and a fixed size, as `--get` prints it:\n  `<video autoplay muted loop playsinline preload=\"metadata\" poster=\"assets/river-poster.jpg\"\n  width=\"854\" height=\"480\" aria-hidden=\"true\"><source src=\"assets/river.webm\" type=\"video/webm\"></video>`.\n  No sound and no controls on a decorative loop. `aria-hidden` because it is decoration: whatever the\n  clip says that matters belongs in the text beside it.\n- The poster shows before the clip plays, on slow connections and under reduced motion, so it must\n  work as a picture on its own. If the source's still is a slate or a blur, take a frame from the clip\n  yourself or use a found picture.\n- In the study only 31% of clips had a poster, and the panel recorded the blank and grey boxes\n  before they played as faults. Here every clip has one.\n- Play a clip only while it is in view, and none under `prefers-reduced-motion: reduce`, where the\n  poster shows instead:\n\n  ```html\n  <script>\n    const calm = matchMedia('(prefers-reduced-motion: reduce)');\n    const clips = [...document.querySelectorAll('video[autoplay]')];\n    const inView = new Set();\n    const sync = (v) => {\n      if (calm.matches) return;\n      if (inView.has(v)) v.play().catch(() => {}); else v.pause();\n    };\n    const settle = () => {\n      for (const v of clips) {\n        if (calm.matches) { v.removeAttribute('autoplay'); v.pause(); v.load(); }\n        else if (inView.has(v)) v.play().catch(() => {});\n      }\n    };\n    const watch = new IntersectionObserver((entries) => {\n      for (const e of entries) {\n        if (e.isIntersecting) inView.add(e.target); else inView.delete(e.target);\n        sync(e.target);\n      }\n    }, { threshold: 0.2 });\n    clips.forEach((v) => watch.observe(v));\n    settle();\n    calm.addEventListener('change', settle);\n  </script>\n  ```\n\n- Crop and place it like a photograph (sections 5 and 6): `object-fit: cover`, one ratio, square\n  corners, no frame, a ground-coloured `background-color` while it loads.\n- Never under body text. On a clip put a headline, one line and one action at most, and check the\n  contrast where they sit across the whole loop, not only on the poster: footage that is dark at\n  one second can be bright at the next. If any frame drops below 4.5:1 (3:1 for 24px and up), use the\n  scrim in section 6 or move the text off the clip. Nothing lies on top of a headline or a statement.\n- It is motion: let it be the page's one moving thing, or sit in a section where nothing else moves.\n- Credit it with the pictures: `--credits` prints one footer line for both (\"Pictures and footage:\")\n  and the list for the report, with each clip's length.\n- Where footage goes (hero background, inline loop, the frame that grows, a docked card), and what\n  the study measured about it: section 12. Nothing that matters plays on hover only, and a full film\n  with sound sits behind a play button that opens a player with controls.\n\n## 12. Where pictures and footage go\n\nWhat strong pages do with their pictures, measured on the latest 100 Awwwards Sites of the Day\n(10 July to 17 October 2026, captured at 1440×900 and 390×844). 91 were usable. A panel described where\nevery picture sat and scored each site the Awwwards way, and a script measured how much of each screen\nis picture. \"Top\" means a panel score of 7.5 or more (36 sites), \"lowest\" under 7.3 (16 sites). The\nscores sit close together (6.7 to 7.9) and a single score carries about half a point of noise, so read\nthe links between a placement and the score as leanings, not laws.\n\n### How much of each screen is picture\n\n- **All or nothing.** Counting photographs, footage and picture backgrounds (not canvases), the median\n  scrolled screen in the study is 16% picture, but few screens sit near it: 42% hold no picture and\n  19% are 90% picture or more. Only 19% fall between 20% and 60%. A picture either leads its screen or\n  stays out of it.\n- **About a third, with rests.** On the 67 sites that put pictures in the page, the average screen is\n  36% picture (middle half 18–69%). Top sites sit at 30% and leave 28% of their screens with no picture\n  at all: screens of type are the rests between picture screens.\n- **The first screen.** A picture covers at least half of it on 41% of the sites and nearly all of it\n  on 32%. A full-bleed photograph or film is the whole first screen on 29%; footage is the main hero\n  picture on about a quarter.\n- **A scene is not a picture.** 66 of the 91 keep a WebGL canvas over at least 30% of the screen, so\n  counting canvases the median screen is entirely covered. On the lowest-scored sites that canvas is\n  often all there is: the five lowest usable sites (6.7 to 7.0) draw everything in it and put two\n  pictures at most in the page.\n- **Text is small in area.** The median screen is 8% text. Type is set large and sparse around the\n  pictures, not packed beside them.\n- **Off-centre.** Measured per section across the crawled sites, pictures sit to the left or right\n  939 times, centred 273 times, and full-bleed or behind text 269 times.\n- **The phone carries more picture,** not less: 19% of a phone screen at the median, and 27% of the\n  first phone screen against 17% on desktop. Full-bleed pictures re-crop to portrait and fill the\n  screen; splits put the picture first at full width.\n\n### How many\n\n- **Seven pictures per page** at the median (middle half 1–25). Top sites 8 (middle half 4–27), lowest\n  2 (0–4). The floor in SKILL.md step 6, four and usually six to twelve, is the strong half of the\n  study.\n- **Footage on 42% of sites:** on half of the top sites and half of the middle band, and on one of the\n  16 lowest. A site with footage carries a median of three or four clips.\n- **Three to five placements.** Sites that use two or fewer of the placements below average 7.31;\n  sites that use three or more average about 7.5. The median top site uses four, the median lowest\n  site one. Where the pictures go changes from section to section on a designed page.\n\n### The placements, ranked\n\n| Placement | Sites (of 91) | Top (of 36) | Lowest (of 16) | Mean score with / without |\n| --- | --- | --- | --- | --- |\n| Split: picture in a half or two-thirds | 32 | 17 | 2 | 7.50 / 7.38 |\n| Horizontal gallery | 32 | 13 | 4 | 7.44 / 7.41 |\n| Full-bleed band between sections | 31 | 14 | 3 | 7.48 / 7.40 |\n| Full-bleed picture or film as the first screen | 26 | 10 | 3 | 7.45 / 7.41 |\n| Uneven mosaic | 25 | 11 | 1 | 7.49 / 7.40 |\n| Picture held while text scrolls | 23 | 12 | 1 | 7.52 / 7.39 |\n| Footage behind text | 22 | 8 | 2 | 7.46 / 7.41 |\n| Even grid | 20 | 11 | 2 | 7.48 / 7.41 |\n| Scattered collage | 19 | 6 | 3 | 7.47 / 7.41 |\n| Panel sliding over a held picture | 19 | 8 | 2 | 7.48 / 7.41 |\n| Inset frame that grows | 17 | 7 | 1 | 7.52 / 7.40 |\n| One picture centred on a field | 14 | 5 | 3 | 7.38 / 7.43 |\n| Cut-out object on a flat field | 13 | 7 | 1 | 7.57 / 7.40 |\n| Index with hover preview | 12 | 6 | 1 | 7.49 / 7.41 |\n| 3D gallery | 12 | 4 | 4 | 7.30 / 7.44 |\n| Small card docked in a corner | 11 | 5 | 1 | 7.47 / 7.42 |\n| Picture inside or in front of display type | 11 | 7 | 1 | 7.50 / 7.41 |\n| One small picture beside a statement | 8 | 5 | 0 | 7.56 / 7.41 |\n| Small pictures between words | 6 | 4 | 0 | 7.52 / 7.42 |\n\n- Found on top pages more than their share and almost never on the lowest: the split, the picture held\n  while text scrolls, the uneven mosaic, the inset frame that grows, the cut-out on a flat field, and\n  pictures set with the type (the last three rows together: 24 sites, 16 of them top, 1 lowest).\n- The horizontal gallery is common in every band and lifts nothing. Use it where browsing is the point.\n- The 3D gallery is the one placement that goes with lower scores, and with the lowest usability in the\n  table (5.9 against 6.35 for all sites).\n\n### Each placement\n\nEach entry gives when to use it, the geometry at 1440×900, the phone version and how it fails.\n\n**Split: picture in a half or two-thirds**\n\n- *When.* A claim and the picture that proves it. The commonest way strong pages pair words and a\n  picture.\n- *Geometry.* The picture takes 42% of the width at the median (middle half 33–49%), up to two-thirds,\n  at the full height of its section: 680×850 and 720×900 are typical. 38% of these pictures are\n  portrait, mostly 4:5 or 3:4. The text starts on the 50% line (x = 720) or on the line where the\n  picture ends, top-aligned or docked low, not centred in its half. Let the picture touch the viewport\n  on its outer side: only about 30% do in the study, and the ones with margin on every side read as\n  placed by default (section 5). Alternate sides only across three or more rows.\n- *Phone.* Picture first at full width (4:5, or 4:3 for a landscape), text under it.\n- *Fails.* The same split in three sections running; a picture floating in the middle of its half; a\n  text column narrower than about 30 characters.\n\n**Full-bleed band**\n\n- *When.* One picture carries a whole screen between type screens: the place, the work, the object at\n  full size. One every three or four screens at most.\n- *Geometry.* 100% wide and one to one and a half screens tall (median 900px at 1440×900, middle half\n  890–1,170px; ratios 1.4 to 1.9). For a slow parallax the picture is oversized in its frame by 4–10%\n  (32–72px a side in the study) and travels no further than that. Text is a headline and one line, or\n  nothing, docked 32–64px in from a corner over the calm part of the picture.\n- *Phone.* A portrait re-crop that fills the screen, with `object-position` set on the subject; the\n  text moves to the bottom quarter.\n- *Fails.* 11–14px white text over a bright area; three bands with nothing between them; a band that\n  only decorates.\n\n**Picture held while text scrolls**\n\n- *When.* A list, steps or a long paragraph that all belong to one picture. If the picture changes for\n  each item, it is the index with a preview, below.\n- *Geometry.* A 100vh sticky stage inside a section two to six screens long (runways of 1,800–5,400px\n  are typical in the study). The picture holds one half (685×880 is a typical portrait), two-thirds, or\n  the whole screen with the text passing over it on a solid panel. Text rows about 150px apart, so two\n  or three are in view at once.\n- *Phone.* Release the stick: picture first, text under it. If the picture swaps per item, keep it as\n  a band in the top 40% of the screen.\n- *Fails.* Long runways where the text has faded out and the held picture is all that is left (the\n  panel recorded several empty stages on phones); body copy set on the held picture.\n\n**Inset frame that grows**\n\n- *When.* Once per page, for the film or picture the page is about, as the move from type into\n  picture.\n- *Geometry.* The frame starts centred at 35–50% of the width (549×366, 710×480 and 864×540 in the\n  study) or as a 16px inset round a full screen, and grows to the full width and height over\n  720–2,700px of scroll. Any corner radius goes to 0 as it reaches the edges. A headline sits above it\n  before it starts; nothing else on the screen moves while it grows.\n- *Phone.* Start at full width inside the 16px margins and grow to a full-bleed portrait, or skip the\n  growth.\n- *Fails.* The growth is the only thing on screen for three scrolls; a loading spinner or a blank box\n  in the first frame (give it a poster, start loading before it enters); used twice.\n\n**Uneven mosaic**\n\n- *When.* A body of work, or one place seen several ways: five to twelve pictures.\n- *Geometry.* Two columns, or rows of three on a 24-column grid. Two or three picture widths (for\n  example 32%, 48% and 65% of the width, or 5, 7 and 12 columns), neighbours offset vertically by\n  120–190px, 130–450px between rows, one or two ratios, a caption under each.\n- *Phone.* One column alternating full width and about 70% width, or two columns of 120–180px tiles\n  that keep the offsets.\n- *Fails.* Random ratios with random offsets, which read as a stock dump. Captions in 9–12px mono with\n  index numbers, the award-site habit: here the caption is one line in the text face at body size, with\n  no number.\n\n**Horizontal gallery**\n\n- *When.* A set people browse in any order: products, rooms, events, a team.\n- *Geometry.* Cards 25–35% of the width (435×326 with 20px gaps at 1440: three in full and a fourth\n  cut by the edge), or a strip at one fixed height with mixed widths (576px tall in the study), or a\n  slider whose centre slide is about 73% of the width with 170–180px of each neighbour showing. Always\n  cut by the right edge so it reads as more. A marquee of pictures moves slowly: 60–120s per loop.\n- *Phone.* One card at 75–80% of the width (290–300px of 390) with the next one showing; swipe.\n- *Fails.* Arrows and no drag or swipe; a marquee of things people need to read; a carousel holding the\n  page's one important picture.\n\n**Panel sliding over a held picture**\n\n- *When.* A change of chapter: the picture holds, and the next section rises over it.\n- *Geometry.* The picture is sticky at 100vh; the next section's ground slides up over it at full width,\n  its top edge straight or shaped from the subject (the study has the arch of a building's windows).\n  Here it is a solid panel with square corners: no rounded sheet tops, no frosted glass.\n- *Phone.* Unchanged.\n- *Fails.* Decks of five or six cards whose earlier cards linger as slivers; stacking for its own sake.\n\n**Even grid**\n\n- *When.* An archive only (layout.md §5): a shop range, the team, a menu, the full list of work.\n- *Geometry.* Two, three or four across, equal cells, 8–16px gaps, one ratio (4:5 is the commonest),\n  the caption under each picture.\n- *Phone.* Two across for products, one for work and people.\n- *Fails.* Three equal cards as \"features\". Cards with a dark gradient at the foot so the label can sit\n  on the picture, common in the study: here the label goes under the picture.\n\n**Index with hover preview**\n\n- *When.* A list of eight or more projects or clients where the names matter as much as the pictures.\n- *Geometry.* Rows on a 45–80px pitch, names at 30–60px. One picture at a time, about a third of the\n  width at 16:9 or a portrait 300–450px tall, at a fixed place (the right half from the 50% line, or\n  the centre), swapped within 0.3s. A version that needs no mouse: the names scroll across a picture\n  fixed at the centre and the picture shows whichever name is crossing it. In the study the picture\n  sits on top of the names; here nothing lies on top of large type, so the names pass in front of it.\n- *Phone.* No hover. Give each row a thumbnail about 100px wide, or use the scroll version.\n- *Fails.* Pictures that never appear on a touch screen. Rows divided by hairlines, the award-site\n  habit: here rows are separated by space, and the active row by ink or a change of ground.\n\n**One picture on a field, or one small picture beside a statement**\n\n- *When.* A pause in the page: a single portrait or object. Or a small picture that gives a statement\n  a face.\n- *Geometry.* A single centred picture at 3:4 and 75% of the viewport height, on a ground taken from\n  the picture. Or a small picture 7–26% of the width (108–374px) beside, above or between the lines\n  of a 48–136px statement, aligned to one of its lines.\n- *Phone.* The picture above the statement at 60–100% of the width.\n- *Fails.* Used as the default for every picture: a picture with equal margins on all sides reads as\n  placed by default (section 5).\n\n**Small pictures between words**\n\n- *When.* A statement about the things themselves (materials, people, products), on a screen of its\n  own.\n- *Geometry.* Two to four chips in the statement, from the cap height to three-quarters of the type\n  size tall and one to one and a half times as wide (50×46px in a 60px line; 113×75px between the two\n  words of a 150px name), all from one shoot, square corners. Give them a width and height so the lines\n  do not jump while they load.\n- *Phone.* Keep them inline at the height of the text.\n- *Fails.* More than four; chips from different shoots; a chip that carries information the words do\n  not.\n\n**Picture inside or behind display type**\n\n- *When.* The object is the subject: a product, a building, a person.\n- *Geometry.* A small picture window sits inside a block of 150–200px display type and later opens\n  into the next screen; or the object stands behind the type, showing between and around the letters;\n  or it touches the edge of the word without covering a letter. In the study the object more often\n  stands in front and covers one or two letters, or a line of type runs behind a square picture; here\n  nothing lies on top of a headline (the inspector fails large text a fifth or more hidden), so the\n  type stays in front.\n- *Phone.* Keep it, with the type at about 15vw, and check the word still reads.\n- *Fails.* An object over the letters; type displaced or glitched by the picture.\n\n**Cut-out object on a flat field**\n\n- *When.* Products and objects. The highest mean score in the table, on 7 of the 36 top sites.\n- *Geometry.* The object at 35–60% of the width on a flat ground taken from its own colours, standing\n  on the bottom edge or running off one side, with the type behind or beside it.\n- *Phone.* The object at 80–90% of the width under the headline.\n- *Fails.* A render floating in a void with no ground; a drop shadow added to a cut-out (no resting\n  shadows here; keep a contact shadow only if it was photographed).\n\n**Scattered collage**\n\n- *When.* Archives, ephemera, a festival of many small things. Sparingly: it is about as common on the\n  lowest pages as on the top ones.\n- *Geometry.* Six to sixteen pictures of 100–300px at a few sizes around a centred heading, never over\n  it.\n- *Phone.* Re-stack as overlapping pairs in one column.\n- *Fails.* Tilted prints and stickers with offset shadows, common in the study and not a treatment\n  here (section 6); pictures crossing the text.\n\n**Small card docked in a corner**\n\n- *When.* A standing pointer to the reel or to the next thing.\n- *Geometry.* About 216×144 to 240×140, 30–43px from the corner; one per page.\n- *Phone.* Drop it, or move it into the flow.\n- *Fails.* Content scrolling under it; a second one.\n\n**3D gallery**\n\n- *What.* Pictures on a ring, sphere, helix or tunnel in a WebGL scene, turned by the wheel or by\n  dragging.\n- *In the study.* 12 sites, 4 of them among the 16 lowest; mean score 7.30 against 7.44, usability 5.9\n  against 6.35.\n- *Here.* Do not build one. Show the same pictures as an index with previews or a horizontal gallery.\n\n### Footage\n\n**What the study measured.**\n\n- Footage on 38 of 91 sites (42%): 18 of the 36 top sites, 19 of the 39 in the middle, 1 of the 16\n  lowest. A site with footage carries a median of three or four clips (middle half 1–8).\n- Footage covers at least half of the first screen on about a quarter of the sites, and is full-bleed\n  on nearly all of them.\n- Clips are short: median 10s, middle half 5–14s; 61% run 10s or less and 88% 20s or less.\n- Every decorative clip is muted, loops, plays inline and has no controls. The autoplay attribute is on\n  44% of clips; the rest are started by script, mostly as they come into view.\n- Only 31% of clips have a poster (13 of the 38 sites). The rest show a blank or grey box until they\n  play, and the panel recorded those as blank first paints. Here a poster is required (section 11).\n- Sources: 1920×1080 is the commonest, then 1280×720; tall clips at 450×800 or 540×960 for phones and\n  portrait tiles. Median source width 1,080px.\n- On the page: 16:9 41%, square 19%, portrait (4:5 to 9:16) 25%, 4:3 or 3:2 12%. Corners square on 75%\n  (the rest 8px or less, or 20–32px). `object-fit: cover` on 84%, contain on 16% (product strips, letterboxed\n  films).\n\n**Where it goes.**\n\n- **Hero background:** full-bleed, cover, often oversized by 1–25% so a drift or zoom never shows an\n  edge. Either one slow take or a montage cutting every second or two.\n- **Inline, as a picture:** in splits, tiles and cards, at about a third of the width (median 33%,\n  middle half 24–45%); a third of these clips are under a quarter of the width and fewer than one in\n  ten is full width. Slow, near-still subjects (water, skin, light, a turning object) read as living\n  photographs and sit well among stills.\n- **The frame that grows** (above), for a reel.\n- **A docked card** (above): one small clip in a corner.\n- **On hover:** only two or three sites play clips on hover, all of them in an index or list. Nothing\n  that matters should play on hover only; phones have no hover.\n- **Full films:** about ten sites offer a full film behind a play button that opens a player with\n  controls. None autoplays it.\n- **Sound:** six sites offer sound behind a toggle; no clip starts with sound.\n\n**How text sits on it.**\n\n- Of about 30 sites with a full-bleed picture or film behind text on the first screen, about 14 set the\n  type straight on it and rely on the footage being graded dark where the type sits; about 10 dim it\n  (to half brightness, under a 30–40% dark layer, or with a dark fade along the bottom 180–590px);\n  about 6 keep the text off the picture, above it or on a solid card.\n- What goes on footage in the study is the name or a headline at 47–136px and one short line, docked\n  bottom-left or centred. Where body text at 11–14px went on footage or a busy photograph, the panel\n  named it as a fault, on top-scored sites too.\n- Here: one headline, one line and one action on footage at most, and never body text. Check contrast\n  where the type sits across the whole loop, not only on the poster; if any frame drops below 4.5:1\n  (3:1 for type of 24px and up), use the scrim in section 6 or a solid band.\n\n**On the phone.** Footage re-crops to a full-screen portrait (a separate tall source, or\n`object-position` on the subject); inset frames go full-bleed. One site in the study adds a 40% scrim\non the phone only, where the type covers more of the picture.\n\n### Crops and treatment\n\n- **Ratios.** Of 1,356 pictures and clips measured: 4:5 21%, 16:9 19%, 1:1 16%, 16:10 10%, 3:2 7%, 2:3\n  5%, 4:3 5%, 5:4 4%, 3:4 3%, wider than 2:1 6%, 9:16 or taller 3%. Landscape 52%, portrait 33%,\n  square 15%.\n- **Two ratios do most of the work.** On sites with four pictures or more, the two commonest ratios\n  hold 76% of the pictures. The others (five ratios in all at the median) are exceptions with a reason:\n  one tall portrait in a run of landscapes, one wide band.\n- **Square corners** on 94% of pictures; 62 of the 68 sites with pictures in the page keep at least 80%\n  of them square. Where corners are rounded, it is 5px or less on two-thirds of them, or 20–32px on\n  card interfaces, one value per site.\n- **Cover.** `object-fit: cover` on 78%, contain on 10% (a product on a tile, a letterboxed film).\n- **Untouched.** CSS filters touch pictures on only 9 sites, mostly for hover states. A handful use\n  black-and-white photography as a set; two multiply scanned paper onto the ground. Several keep the\n  interface black, white and grey and let the photographs carry all the colour.\n- **Common in the study, not treatments here** (section 6): a fixed grain layer over the whole page\n  (about a third of the sites), duotone or tinted photographs, blurred copies behind a picture as a\n  glow, tilted prints and stickers with offset shadows.\n- **Oversize only by the distance it moves.** 22 sites move pictures with the scroll, oversizing them by\n  1–25%. Oversize by the travel and no more, on one picture per screen.\n- **Resolution.** The study serves pictures at a median 1.9 times their CSS width, but 17% are served\n  smaller than they are shown and full-width pictures at a median of only 1,440px. Here: twice the CSS\n  width, capped at about 2,400px (section 4).\n\n### Text over pictures\n\n- In the study, text sits on pictures often and is checked rarely: about 28 notes record text set\n  straight on a picture with no scrim, and the faults of 16 sites include text lost over pictures: 8–14px\n  labels and body over photographs, and navigation in a difference blend or with no backing passing\n  over them.\n- Where it works, the text is display size and sits over the calm part (sky, a dark wall, the shadow\n  side), docked in a corner or along one edge. Two other forms in the study: a solid card in the\n  ground colour inset over the photograph and carrying the heading, and text on the white of a picture\n  that fades into the page.\n- Here: on a picture put only display text, one short line and one action. Body text, captions and\n  labels go beside or under it. Measure contrast at the text's own position (4.5:1, or 3:1 for 24px and\n  up). If it fails, move the text to a calmer part, put it on a solid card in the ground colour, or use\n  the scrim in section 6. A fixed navigation that passes over pictures gets a solid band, or hides\n  while scrolling down.\n\n### Rules for a generator\n\n1. **About a third of the page is picture.** Across the scrolled screens, pictures fill 30–40% of the\n   area, and at least one screen in four carries no picture (top sites: 30% and 28%).\n2. **A picture leads its screen or stays small.** A leading picture takes at least 60% of its screen;\n   an accent stays under 10% of it. Avoid screen after screen of pictures at 20–40%: in the study 42% of\n   screens are 0% and 19% are 90% or more.\n3. **Three to five placements per page,** and no two neighbouring sections with the same one. Sites\n   with two or fewer average 7.31, sites with three or more about 7.5.\n4. **Six to twelve pictures, never fewer than four.** Study median 7; top sites 4–27; lowest 2.\n5. **Two ratios for at least 75% of the pictures** (76% in the study), a third only for a deliberate\n   exception. Defaults: 4:5 for portraits, 16:9 or 3:2 for landscapes.\n6. **Square corners on every picture** (94% in the study). If the direction rounds them, one radius of\n   4px for every picture and clip.\n7. **Split pictures take 42–50% of the width, or two-thirds,** at the full height of the section and\n   touching the viewport on their outer side; the text starts on the 50% line. On the phone the\n   picture goes first, full width.\n8. **Full-bleed bands are 100% wide and 100–150vh tall,** one every three or four screens, oversized by\n   10% at most for parallax, with text only in one corn\n\n<!-- [TRUNCATED AT 50KB] -->\n\n<!-- File: skills/taste-skill/references/layout.md (Tokens: ~4556 | Category: anthropic-skill) -->\n# Layout\n\nHow the page is put together: margins, the grid, where text sits, how sections differ, navigation,\nendings and the phone. The direction sheet gives the specific compositions; this file gives the habits\nbehind them, taken from the panel's notes on the 114 studied sites that scored 7.3 or higher (counts\nbelow are hand tallies from those notes, so read them as \"about\").\n\n## Contents\n\n1. What strong pages do\n2. Margins and the grid\n3. Where text sits\n4. Empty space\n5. The frame: margins, balance and titles\n6. Sections: carry the idea, vary the arrangement\n7. Navigation\n8. Endings\n9. The phone is a second composition\n10. How pages fail\n\n## 1. What strong pages do\n\n- **Tight margins, content to the edges.** About 45 of 114 use outer margins of 32px or less; only\n  about 8 use 80px or more. The centred 1100–1300px container is the minority among strong sites and\n  the usual frame of the ones the panel called stock.\n- **Text hangs from an off-centre line.** About 22 anchor text to one fixed line that is neither the\n  centre nor the margin: a third across, 42%, the midpoint.\n- **Two or three type sizes with nothing between** (about 30): one very large with one small, or\n  everything small with the scale given to the image.\n- **One thing per screen** (about 20): one statement, one object, one project.\n- **Sections told apart by their ground.** About 20 change the whole background colour at each\n  section; about 12 alternate light and dark; about 10 never change and separate by space alone.\n- **Sections recomposed, not repeated.** About 14 rearrange every section; about 12 alternate a\n  full-bleed image screen with a near-empty type screen.\n- **The system broken once, on purpose** (about 14): one centred line on a split page, one paper card\n  on a dark page, colour held back until the last screen.\n- **Often no navigation bar** (about 45), and endings that are a designed scene rather than link\n  columns.\n- **Few words.** Median 575 on the whole study; some of the best carry under 200.\n\n## 2. Margins and the grid\n\n```css\n:root {\n  --margin: clamp(1rem, 2.2vw, 2rem);   /* 16–32px: tight, so content reaches the edges */\n  --gutter: clamp(0.75rem, 1.4vw, 1.5rem);\n}\n.wrap { padding-inline: var(--margin); }\n.grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gutter); }\n```\n\n- One pair of margins and one grid for the whole page. Every left edge is a column line.\n- Do not wrap the page in a `max-width: 1200px; margin: auto` container by reflex. Let large things\n  (type, images, colour fields) run the full width, and constrain only the measure of running text\n  (`max-width` in `ch` on the paragraph, not on the page).\n- On very wide screens cap the layout at about 1760–1920px, or let type sized in `vw` stop growing with\n  a `clamp()`.\n- Directions that call for wide margins (uneven photographs, the quiet instrument) say so on the\n  sheet; follow the sheet.\n- Never draw the grid. Column lines, crosshairs and guides are banned ornaments here even though they\n  are fashionable; the grid is felt through alignment.\n\n## 3. Where text sits\n\n- **Pick the anchor line and reuse it.** If the hero headline starts at column 5, the section\n  headings, the pricing figure and the footer links start there too. Two or three anchor lines on a\n  whole page; six means nothing was decided.\n- **Off-centre beats centred.** A heading in the left third with its paragraph in the far-right\n  column on the same baseline and nothing between; a headline in the bottom third under a deliberate\n  void; text docked in corners with the middle given to the picture.\n- **Opposite ends.** Two short texts at opposite ends of one baseline (name left, one-line description\n  right) is the commonest alternative to the centred stack.\n- **Centred is a decision.** When a strong page centres, it uses one axis with wide empty flanks and a\n  single element per screen, not a centred stack of heading, paragraph and two buttons.\n- **Rows for long copy:** heading in the left third, body in the right two-thirds, the same split for\n  every row on the page.\n- Stagger sparingly: a second line indented by a third so a two-line headline steps across the screen.\n\n## 4. Empty space\n\nEmpty space is placed, not left over. In the study of 97 Sites of the Day captured in October 2026,\nreaders judged every large empty area either a rest, which something closes, or a hole, which nothing\ncloses. Strong sites have plenty of rests. About half of them still leave at least one hole, and the\nholes are what visitors name (\"big random blank spaces\").\n\n**A void is placed when something closes it.** In the readers' notes the closer is, most often:\n\n- the picture itself (sky, ground, the object, the film) with the type docked at its edge;\n- a picture across the void: the photograph at the far side of an empty band, the full-width row\n  rising under a statement, the opposite picture in a stagger;\n- the type: a headline large enough to span the space, or two short texts at the two ends of one\n  baseline;\n- on a one-screen page, the wordmark, the navigation and one fact in the corners, like a mount around\n  a print.\n\nAbout one closer in five in the study is a hairline or grid line. That device is banned here; close the\nvoid with the picture, the type, a step in ground tone or a field of flat colour.\n\n**Where holes come from.** In order of frequency in the study:\n\n1. A gap between sections stretched too far: bands of 250–760px of plain ground.\n2. Text in one half of a section and nothing in the other.\n3. Content that arrives late: a reveal not yet fired, so the visitor scrolls onto bare ground while the\n   words fade in.\n4. A short block stretched to a full screen: a footer padded to the viewport height, a section title\n   alone on a whole screen.\n5. A pinned scene that holds almost nothing for several screens.\n6. Pictures of different heights top-aligned in a row, leaving a hole under the short one.\n\n**Rules**\n\n- Decide where the void is and name what closes it. If nothing does, it is a hole: move the section's\n  picture into it, make the main element bigger, or take the space out.\n- Keep the void clean: no stray caption, no decorative shape, no faint watermark, no grid lines.\n- Sections sit 120–240px apart on desktop, counted from the last line of one to the first line of the\n  next (the median in the study is about 230–250px), and 72–112px on a phone. A change of ground\n  colour lets the gap be a little smaller. More than about 40% of a screen of plain ground between two\n  sections is a hole.\n- The gap between sections is clearly larger than any gap inside one. Related things sit close and\n  unrelated things far; a heading has at least twice as much space above it as below.\n- No stretch of the page taller than about half a screen holds nothing at all. In the study, runs of a\n  screen or more with nothing in the page were almost always scroll distance for a pinned scene; the\n  pinned stage must then hold something at every scroll position.\n- Content is in place on the first paint. An entrance moves what is already there (see `motion.md`);\n  it never leaves a screen of bare ground while the words arrive.\n- Size a section to its content. `min-height: 100vh` belongs to a section that fills the screen, not\n  to a footer or a lone heading.\n- In a row of pictures of different heights, align the bottoms or put something under the short one,\n  or crop the row to one ratio.\n- A rest is one thing on a screen: a single line, one object, one picture or a field of colour. Once\n  per page at most. A screen of nothing is never a rest, and the inspector fails two near-empty screens.\n- When a section looks empty, the answer is almost never \"add something\". Make the main element\n  bigger, or cut the section.\n\n## 5. The frame: margins, balance and titles\n\nThe frame is what readers judge before any detail: \"no good margin\", \"everything is shifted to one\nside\", \"no clear title\", \"random unclear sections\". The inspector measures each of these. The numbers\nare from the study of 97 Sites of the Day (October 2026).\n\n**One pair of equal margins.**\n\n- The left and right margins are the same, at every width. On the studied sites with scrolling\n  sections the two sides match to a few pixels: 16 and 16, 20 and 21, 32 and 32, 140 and 137. No\n  strong page in the study was pushed to one side.\n- The usual margin is tight: median about 28px at 1440, half the sites between about 18 and 45px, a\n  few at 80px or more. Here it is 16–32px (section 2), and never under 16px at any width, on the phone\n  included. About one award site in seven sets text 8–15px from the edge; that studio habit is\n  excluded here.\n- The navigation sits on the same margins as the content. The commonest small fault in the study is a\n  header on one inset and the page on another (40px against 20px, or 34px on the left against 10px on\n  the right).\n- A bleed is deliberate and starts from the margin: a row of pictures that runs off the right edge\n  begins on the left margin; a display line that bleeds starts or ends on one. A bleed never moves the\n  margin.\n- Asymmetry belongs inside the frame: an off-centre anchor line (a third across, 42%, the centre line)\n  on symmetric margins.\n\n**Use the width the page has set up.**\n\n- In the study about one text section in a hundred leaves half the width empty. Text that sits in one\n  half is common, in roughly one site in three, but the other half then holds the section's own\n  picture (most often), a full-bleed picture behind the text, a second column, a list or a figure.\n- When the text takes one side, put the picture, the second column, the list or the large number on\n  the other. Never leave the other half to plain ground.\n- The middle counts too: a card at the left edge and a lone button at the right with the middle third\n  empty is the same hole.\n- The first screen counts too. When the sentence and the button take the left third above a name\n  docked at the foot, the upper right holds something (the picture or film, one fact, the action) or\n  the name grows up to meet them; in testing, 60% of a first screen left as plain ground under the\n  navigation read as a hole, and the inspector now warns when one empty block takes 28% of the first\n  screen or more.\n- A display line fitted to the width is fitted by measurement (a small script that sets its size from\n  the content box, or SVG text with `textLength`), never by a size guessed for one face: a name that\n  starts on the margin and runs a few pixels off the other edge reads as a mistake.\n- A centred composition has one axis, equal flanks and one thing on it, not a stack of heading,\n  paragraph and two buttons.\n\n**A title that says what this is, on the first screen.**\n\n- Asked whether a stranger could say what the page is within five seconds, readers found that 40 of\n  the 97 first screens say it in words, 42 say it only through pictures, small print or a bare name,\n  and 15 do not say it at all. The last group lost usability and content points, not design points.\n- Size alone does not do it: 66 of the 97 first screens carry a display-size line, but 26 of those are\n  a name, a slogan or a place with nothing saying what is offered.\n- The first screen has one `h1`, at display size (32px or more on desktop; on the clear first\n  screens in the study mostly 50–150px), two lines at most, that says what this is: the name with\n  what it does, the product with what it is for, the event with its date and place. If the `h1` is\n  the name, the line under it, at 18px or more, says what the thing is.\n- It is there on the first paint. About a third of the studied pages still showed a loader or nothing readable 4.5\n  seconds.\n\n**A heading on every section.**\n\n- 82% of the text sections on the studied sites open with a heading: median 57px (40–96px for the\n  middle half), about three and a half times the body size, one or two lines.\n- Headings start on the outer margin or on the page's inner anchor line (in the study about a third\n  each) and in the same place for every section. About a quarter of the headings in the study are\n  centred; centre one moment per page here.\n- Where a studied section has no heading, the usual stand-in is a small label: caps, mono or a number\n  in brackets. All three are banned here. Put the label's words in a heading in the heading face at the\n  section size (\"The rooms\", \"How it works\", \"Prices\"), set them on the anchor line, and let the first\n  sentence carry the rest.\n- A statement can open a section as its heading only when it names what the section holds.\n\n## 6. Sections: carry the idea, vary the arrangement\n\nThe most common failure in every score band is a distinctive first screen followed by stock blocks:\nicon cards, a three-up row, an accordion, a link-column footer. About 25 of the studied sites lose\npoints this way, including several above 7.5.\n\n- **The idea survives to the last pixel.** Ask of each section, pricing and FAQ included: what does\n  the page's idea do here? If the page is a menu, the prices are menu lines. If the name is a\n  monument, the footer is the name again. If the object's shape is the motif, the button and the image\n  masks carry it.\n- **No two neighbours share a layout.** Use the shape of each dealt blueprint (list, split, statement,\n  full-bleed, mosaic, table, strip, pinned …). Count them in the screenshot; a shape used three times\n  is the template showing.\n- **Alternate dense and empty, image and type, light and dark** so the scroll has rhythm.\n- **A repeated module is for archives only** (a work index, a menu, a schedule). Anywhere else,\n  repetition reads as a kit.\n- **Break the system once.** After the page has established its rule, one planned exception (a single\n  centred line, one inverted section, one image at a different scale) is what makes the rule visible.\n- **Short pages are fine.** A quarter of the studied sites are one or two screens. Do not add sections\n  to seem complete; each one must carry a claim (see `copy.md` §1).\n\n## 7. Navigation\n\n- The plain form: the wordmark at one end, three to five text links, one action, all at text size on\n  the page ground with no bar, border or background. Median link count in the study is 3.\n- It is also normal to have less: small links in the corners, a single action, or the navigation\n  folded into the content (a list of section titles that is itself the index).\n- If it stays fixed, it must never sit on top of content: check every scroll position in the\n  screenshots, especially on the phone. Floating pill bars are where the panel most often recorded a\n  nav covering text.\n- On a phone: wordmark and one action in view; the links go in a simple full-screen sheet opened by a\n  text button (\"Menu\"), or move to the footer when there are only three.\n- Navigation is small furniture, however it is drawn. On desktop it takes no more than about a tenth\n  of the first screen; on a phone it is one row. A blueprint that builds the navigation as a column of\n  colour blocks or a stack of tabs gets that treatment on desktop only, and collapses to one row on\n  the phone so the headline, the supporting sentence and the action stay in the first screen. In\n  blind tests a nav that ate the hero cost a whole point of usability.\n\n## 8. Endings\n\n- The page should end on a designed scene. In the study: the name at full width (about 18 of 114), the\n  hero repeated in inverted colours (about 12), a closing scene of its own such as the one contact\n  fact set as a headline (about 14), or simply one quiet line (about 22). Link-column footers appear\n  in the panel's notes only as criticism.\n- The full-width name is strong but already a studio habit; use it when the direction is name-led,\n  otherwise prefer the blueprint dealt for the footer.\n- Put the practical facts (address, hours, email, legal line) in the text face at a readable size, on\n  the same anchor lines as the rest of the page.\n\n## 9. The phone is a second composition\n\nDesign the 390px screen as its own page, not the desktop page squeezed. Strong sites that neglect this\nlose usability points; weak ones are often just broken.\n\n- Each blueprint on the sheet has its own phone paragraph. Build it.\n- Keep one dominant thing on the first screen. A wordmark that was 20vw wide on desktop might stack on\n  two lines at 26vw on the phone and be even stronger.\n- Re-author line breaks; re-crop images to portrait (`object-position` per breakpoint, or a different\n  crop size in the image URL); keep unevenness with alternating widths rather than making everything\n  full width.\n- Margins 16–20px. Body text 16–18px. Touch targets at least 44px high.\n- Check 390px in the inspector's screenshots for every round: sideways scroll and three-line headlines\n  usually appear here first.\n\n## 10. How pages fail\n\nFrom the panel's notes on the 54 sites scoring under 6.8 (counts out of 54):\n\n- The whole page is the category's stock template; swap the logo and it could be any competitor\n  (about 20).\n- Centred headline, pill badge, two buttons, screenshot or tile grid below (about 9).\n- A distinctive hero, then stock modules in the usual order (about 8, and about 17 more in the middle\n  band).\n- A default typeface with no character (about 13).\n- Text too small or too low in contrast (about 13); legibility lost over busy photographs (about 9).\n- An undersized headline and no focal point (about 9).\n- The page never says what the thing is, or shows no work (about 12 and 7).\n- Thin content stretched over many screens, or a single gag (about 11).\n- Gates, preloaders and entry pop-ups before any content (about 9).\n- A phone layout that is the desktop shrunk, or broken (about 8).\n- Fixed elements sitting on content; careless details such as colliding lines (about 7 and 5).\n\nAnd the faults of the best sites, which are not to be copied: body text at 9–13px (about 24 of the 90\nsites at 7.5 or more), information hidden behind the concept (about 20), the idea running out\nmid-page (about 15), text over footage with no scrim (about 12), gates and blank first paints (about\n12), floating elements colliding with content (about 11), and a first screen with no statement of what\nthis is and no action (about 9). Say what the thing is, and offer the action, on the first screen.\n\n<!-- File: skills/taste-skill/references/motion.md (Tokens: ~13222 | Category: anthropic-skill) -->\n# Motion\n\nRead this before adding any animation. The static page must already be finished and passing\n`inspect.mjs`; motion is the last pass, never a way to rescue a weak layout.\n\n## Contents\n\n1. The budget\n2. What strong pages do with motion\n3. Four questions before any animation\n4. Tokens\n5. Scroll behaviours, ranked\n6. Recipes (copy, then adapt)\n7. Signature moves\n8. Reduced motion and performance\n9. What gives generated motion away\n10. Rules for motion\n\n## 1. The budget\n\nA page that does not move reads as a mock-up; the inspector counts what moves while the page loads and\nscrolls, and fails it under eight elements. The motion layer has five parts:\n\n- **Two or three scroll scenes:** the big, scroll-driven moments award sites are remembered for (a\n  camera flying through a field of pictures, a picture that grows from a window to the whole screen,\n  type that crosses a held stage, cards that deal out and stack). The direction sheet deals them from\n  `library/scenes.json` when the library has scenes for the brief; `references/scenes.md` says how to\n  fill and fit them. They are where the page is bold; everything else stays quiet so they land.\n\n- **One signature moment:** the thing a visitor would describe an hour later: the headline that rises\n  out of a mask, the image that opens like a shutter, the wordmark that scales with the scroll. The\n  direction sheet from `draw.mjs` names one. Build that one well; it is the only move allowed to be\n  loud.\n- **Section entrances, choreographed per section:** the parts of each section arrive in reading order\n  (heading, text, picture, details), staggered 60–90ms, rising 16–32px with opacity, once. Vary the\n  manner with the content instead of stamping one preset everywhere: a list arrives row by row, a\n  picture opens from a mask or settles from a slight scale, a figure counts up once, a statement rises\n  line by line.\n- **Feedback under the hand:** buttons that give on press, links that answer the pointer, cards and\n  pictures that respond on hover, a menu that opens from where it was clicked.\n- **One moving picture:** a found clip as a muted loop with a poster frame, a slow drift or scale on\n  a large photograph, or a scroll-linked move on the hero picture.\n\nWhat is still banned: the same fade-and-slide-up with the same timing on every block, which is the most\ncited motion tell of generated pages; motion that hides content until a script runs, with no fallback;\nbounce and elastic easing; anything that animates layout properties. Uniform motion says nobody decided\nanything; choreographed motion with one protected moment says somebody did.\n\n## 2. What strong pages do with motion\n\nMeasured on the latest 99 Awwwards Sites of the Day (July to October 2026), at 1440 and 390, with\nthe transitions, tweens and scroll triggers recorded while each page loaded and was scrolled. Where\nthe gallery does something the house rules ban, the house version follows.\n\n- **The stack.** Two in three use a smooth-scroll library and three in five ship Three.js; GSAP is\n  named on 56. The quiet layer below (reveals, line rises, the ink fill) needs none of it: CSS scroll\n  timelines and view transitions do that work, though only 3 and 6 of the sites use them. The big\n  scroll scenes are built on GSAP ScrollTrigger, as on the award sites, through the shared stage in\n  `assets/scenes/` (`references/scenes.md`).\n- **Curves.** The curves that really ran are strong ease-outs: expo out (`.16,1,.3,1` and\n  `.19,1,.22,1`) ran on 14 sites, cubic out on 13, quint out on 7, and by number of transitions the\n  quint and expo outs lead every chosen curve. In-out curves are kept for wipes and things that\n  travel (cubic and quart in-out, about 15 sites each). Ease-in appears only for exits, short, before\n  a slow arrival. Colour changes use plain `ease` (46 sites). Overshoot sits in 19 stylesheets and\n  ran on 2.\n- **Durations.** Hover colour 200-300 ms; small interface moves 300-450 ms; reveals and line rises\n  600-1,000 ms; picture openings and wipes 1,100-1,600 ms. The median of everything that ran on a\n  site is 420 ms.\n- **Staggers.** 20-40 ms between characters, 75-120 ms between lines, 50-100 ms between list items.\n- **Scroll-linked motion is locked to the scrollbar.** Of the sites that scrub, 14 of 18 lock it with\n  no smoothing; the other four smooth it by 0.1-3 s. Reveals fire when the element's top is 80-95% of the way\n  down the viewport, once.\n- **How much moves.** A median of 130 elements are moved by script on a page, but they come from a\n  few gestures: one split heading is 20-60 elements. The inspector's floor (8, warning under 16) is a\n  floor, not a target.\n- **Waiting is the most common cost.** 60 of 99 open on a loading screen, 26 of them with a counter.\n  Half the usable pages were still unreadable 2.5 s after the browser said the page had loaded, a\n  third at 4.5 s. The preloaders were not covering slow pages (their documents loaded faster than the\n  rest) and the readers' design marks were the same whatever the wait; only usability fell. House\n  version: no preloader, the message readable on the first frame, the load sequence over by 1.2 s.\n- **Pins cost length.** Two in three scrolling pages hold something sticky or pinned. Those pages\n  are twice as long (a median 16.6 screens against 7.5) for fewer words per screen (27 against 46).\n  House version: at most two held stages, about one screen per step, three screens per stage.\n- **Reduced motion is mostly missing.** 35 of 99 have any `prefers-reduced-motion` rule, 16 have\n  three or more; 5 of 26 scroll-scrubbed scenes have one. Every recipe here keeps the finished state\n  as the reduced state.\n\n## 3. Four questions before any animation\n\n1. **How often will someone see it?** Once per visit (hero load, a section reveal): it can take its\n   time. Many times per visit (hover, menu, accordion): fast and small. Hundreds of times (keyboard\n   actions, typing): no animation.\n2. **What is it for?** Valid answers: it shows where something came from, it confirms an action, it\n   keeps a change from being jarring, it explains how the product works, it is the signature moment.\n   \"It looks nice\" is only valid for the signature moment.\n3. **Which easing?** Entering or leaving: ease-out, so movement starts the instant the eye arrives.\n   Moving between two places on screen: ease-in-out. Colour and opacity on hover: `ease`. Constant\n   travel (marquee, progress): `linear`. `ease-in` makes interfaces feel slow because the first frames\n   barely move; do not use it. The CSS keyword curves are weak, so use the tokens below.\n4. **How long?** Press feedback 100–160ms. Hover 150–200ms. Menus and popovers 150–250ms. Dialogs and\n   drawers 250–450ms. Section and hero reveals 500–900ms. Leaving is quicker than arriving (about 70%).\n\n## 4. Tokens\n\n```css\n:root {\n  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);        /* entrances, moving hovers, UI under 600ms */\n  --ease-expo: cubic-bezier(0.16, 1, 0.3, 1);        /* new: reveals of 800ms and longer, line rises, openings */\n  --ease-in-out: cubic-bezier(0.76, 0, 0.24, 1);     /* wipes, panels, things that travel while visible */\n  --ease-soft: cubic-bezier(0.33, 1, 0.68, 1);       /* slow scale and drift on photographs */\n  --ease-exit: cubic-bezier(0.55, 0.055, 0.675, 0.19); /* new: something leaving for good, short */\n  --t-press: 140ms;\n  --t-hover: 180ms;\n  --t-ui: 240ms;\n  --t-reveal: 800ms;\n  --t-open: 1200ms;                                  /* new: picture openings and clip wipes */\n  --stagger-line: 90ms;                              /* new */\n  --stagger-item: 70ms;                              /* new */\n}\n```\n\nHow the study bears on each:\n\n- `--ease-out` (quint out) is in 28 stylesheets with its near twin and is the single most frequent\n  chosen curve among transitions that ran. Keep it.\n- `--ease-expo` is new. Expo out (`.16,1,.3,1` and `.19,1,.22,1`) is in 28 stylesheets and ran on 14\n  sites, more than any other chosen family, and it is the curve the long reveals use: line rises,\n  picture openings, card entrances of 0.9-1.6 s. Use it for anything at `--t-reveal` or longer; it\n  replaces `--ease-out` in the masked headline and the reveal-on-scroll recipes.\n- `--ease-in-out` (quart in-out) matches its family (14 stylesheets, 7 ran). Keep it for wipes,\n  shutters, menus and page transitions.\n- `--ease-soft` (cubic out) matches the cubic-out family (21 stylesheets, 13 ran), but the study uses it\n  for interface moves of 0.3-0.8 s, where `--ease-out` already serves. Narrow it to slow scale and\n  drift on photographs.\n- `--ease-exit` is new. Ease-in is right for exactly one job: something that leaves for good (an\n  outgoing caption, a replaced slide, a closing panel), short, at about 60-70% of the matching\n  entrance. Never for anything the visitor is waiting to see.\n- Not adopted: `.4,0,.2,1` (38 stylesheets) is a framework default, and overshoot curves (19) stay\n  banned on interface elements.\n- `--t-hover` stays at 180ms. The study's colour hovers run 200-300ms; a little quicker reads as\n  more exact. A hover that moves something (a label roll, an arrow) takes `--t-ui` to 400ms.\n\n## 5. Scroll behaviours, ranked\n\n| Behaviour | Pages of 99 | What it serves | House version |\n| --- | --- | --- | --- |\n| Smooth-scroll library | 67 | A feeling of weight; makes scrubbed scenes easier to build | Optional, through `Stage.smooth()`: Lenis at lerp 0.1-0.14, off for touch and reduced motion |\n| Held (sticky or pinned) stage | 44 | One picture or object carries several claims; chapters | Yes: the scroll scenes (`references/scenes.md`), two or three per page, one to four screens each; other sticky stages three screens at most |\n| Split text | 40 | Lines and words arriving as they are read; hover rolls | Lines for headings and statements; words only for the ink fill; characters only for a heading of one to three words |\n| Colour by chapter | 34 | Tells chapters apart without padding bands | Yes, as hard cuts at section edges; the header ink follows in 300ms |\n| Scroll-scrubbed scene (camera, object, image sequence) | 26 | Explains a product by moving it | Yes, from the scene library, built on the shared stage with a finished composition for reduced motion |\n| Parallax depth | 24 | Depth in collages; pictures drifting inside oversized frames | Travel under 8% of the element, pictures held at 106-110% in their frames |\n| Marquee | 21 | Life on a static band | Existing \"Edge-to-edge marquee\": one per page, pausable |\n| Masked line or word rise | 18 | Headings that arrive like set type | Yes: \"Masked line reveal\" on load, \"Lines that rise on scroll\" below the fold |\n| Wheel drives a scene, no page scroll | 16 | Browsing one object | Not used (see 2.6) |\n| Blur-in | 15 | Soft arrival | At most 8px of blur, 600ms, gone once settled; never on body text |\n| Picture from inset frame to full-bleed | 14 | The hand-over from a type screen to the big picture | Yes: \"Opening window\", about one screen of scroll |\n| Grey-to-ink text fill | 14 | Paces one statement | Yes, once per page, starting at 45% ink: \"Ink fill\" |\n| Sheet slides over a held layer | 11 | Page-turn rhythm between chapters | Yes: new move \"Sheet over a held picture\" |\n| Scramble or decode | 11 | A \"code\" voice | Not used (see 2.6) |\n| Header ink by chapter | 10 | The fixed header stays legible | Yes, with colour by chapter |\n| Horizontal track pinned to vertical scroll | 8 | Walking through rooms or a collection | Native drag row first; pinned only when the row is under three screens long, with keyboard support: \"Sideways gallery\" |\n| Curtain footer | 8 | The page ends as a scene | Existing move |\n| Rolling digits | 6 | Figures that arrive | Yes, for pages whose case is a handful of numbers: \"Rolling figures\" |\n| Index with hover preview | 5 | Navigating work by name | Existing move, upgraded recipe |\n\nText, split by unit: characters on about 20 pages, lines on about 14, words on about 11. Character\nsplits serve short headings and button rolls; on long statements they leave fragments mid-scroll.\n\n## 6. Recipes\n\nAll recipes keep the content visible when JavaScript is off, put every hidden state inside\n`prefers-reduced-motion: no-preference`, and use the tokens above. Two notes that apply to several:\n\n- **Scroll timelines need a scroller to watch.** `animation-timeline: view()` takes the nearest scroll\n  container, and `overflow: hidden` makes one. A picture inside an `overflow: hidden` frame therefore\n  never animates. Use `overflow: clip` on frames, or name the timeline on the section\n  (`view-timeline-name: --hero`) and point the children at that name. This also applies to the\n  existing \"Scroll-linked progress\" recipe.\n- **Scroll-linked means linear.** The scroll is the easing. 14 of the 18 scrubbing sites in the study\n  lock motion to the scrollbar, which is what CSS scroll timelines do.\n\nAll recipes keep content visible when JavaScript is off or slow: the hidden state only applies under\n`html.js`, which a one-line inline script sets.\n\n```html\n<script>document.documentElement.classList.add('js')</script>\n```\n\n### Load sequence in 1.2 seconds\n\nEverything is in the HTML and painted on the first frame; the sequence only adds arrival. Nothing\nwaits for the load event, and nothing in the navigation animates.\n\n```html\n<header class=\"hero\">\n  <h1 class=\"display lines\">\n    <span class=\"line\"><span data-line style=\"--i:0\">Stools for</span></span>\n    <span class=\"line\"><span data-line style=\"--i:1\">small kitchens</span></span>\n  </h1>\n  <p class=\"lead\" data-load style=\"--d:420ms\">…</p>\n  <a class=\"button\" data-load style=\"--d:480ms\" href=\"#stools\">See the stools</a>\n  <figure class=\"hero__picture\" data-open><img src=\"stool.jpg\" alt=\"…\" fetchpriority=\"high\"></figure>\n</header>\n```\n\n```css\n.hero__picture { overflow: clip; margin: 0; }\n@media (prefers-reduced-motion: no-preference) {\n  .js .hero [data-line] { transform: translateY(105%); animation: load-line 800ms var(--ease-expo) forwards; animation-delay: calc(100ms + var(--i) * var(--stagger-line)); }\n  .js .hero [data-load] { opacity: 0; transform: translateY(12px); animation: load-rise 500ms var(--ease-out) forwards; animation-delay: var(--d); }\n  .js .hero [data-open] { clip-path: inset(0 0 100% 0); animation: load-open 1000ms var(--ease-in-out) 150ms forwards; }\n  .js .hero [data-open] img { transform: scale(1.08); animation: load-settle 1100ms var(--ease-expo) 100ms forwards; }\n}\n@keyframes load-line { to { transform: none; } }\n@keyframes load-rise { to { opacity: 1; transform: none; } }\n@keyframes load-open { to { clip-path: inset(0); } }\n@keyframes load-settle { to { transform: none; } }\n```\n\nThe timeline: the headline's lines rise from 100 to 990 ms, the picture opens from 150 to 1,150 ms,\nthe sentence and the button arrive from 420 to 980 ms. All settled by 1.2 s, four things at most.\nPreload the display font (`<link rel=\"preload\" as=\"font\" type=\"font/woff2\" crossorigin>`) so the lines\nrise in the real face, and give the picture `fetchpriority=\"high\"` and a ground colour sampled from it,\nso a slow image opens onto its own colour rather than a blank box. Study: 22 of 91 pages were readable\nat the first intro frame and 11 more by 1.2 s; the intros the readers called respectful finished in\nabout 1-1.2 s; a third of the pages were still unreadable at 4.5 s.\n\n### Masked line reveal (the classic gallery headline)\n\nEach line slides up from behind its own baseline. Because headlines are capped at two lines, you set\nthe line breaks yourself and wrap each line.\n\n```html\n<h1 class=\"lines\">\n  <span class=\"line\"><span data-line style=\"--i:0\">Stools for</span></span>\n  <span class=\"line\"><span data-line style=\"--i:1\">small kitchens</span></span>\n</h1>\n```\n\n```css\n.lines .line { display: block; overflow: hidden; padding-bottom: 0.08em; margin-bottom: -0.08em; }\n.lines [data-line] { display: block; }\n@media (prefers-reduced-motion: no-preference) {\n  .js .lines [data-line] {\n    transform: translateY(105%);\n    animation: line-up 900ms var(--ease-out) forwards;\n    animation-delay: calc(var(--i) * 110ms + 150ms);\n  }\n}\n@keyframes line-up { to { transform: none; } }\n```\n\nThe `padding-bottom` / negative margin pair stops descenders (g, y, p) being clipped by the mask.\nOn a narrow phone the two authored lines may each wrap; check the mobile screenshot, and if they do,\nauthor a shorter mobile break with a `<br class=\"only-wide\">` pattern or reduce the size.\n\n### Reveal on scroll (once)\n\nFor the two or three sections that deserve it, not for every block.\n\n```css\n@media (prefers-reduced-motion: no-preference) {\n  .js [data-reveal] { opacity: 0; transform: translateY(24px); transition: opacity 700ms var(--ease-out), transform 900ms var(--ease-out); }\n  .js [data-reveal].is-in { opacity: 1; transform: none; }\n}\n```\n\n```js\nconst io = new IntersectionObserver((entries) => {\n  for (const e of entries) if (e.isIntersecting) { e.target.classList.add('is-in'); io.unobserve(e.target); }\n}, { rootMargin: '0px 0px -12% 0px', threshold: 0.1 });\ndocument.querySelectorAll('[data-reveal]').forEach((el) => io.observe(el));\n```\n\nNever attach reveals with a scroll listener, never replay them when the element re-enters, and never\nleave anything at `opacity: 0` if the observer fails to fire (the `html.js` gate handles no-JS; the\n`unobserve` handles replays).\n\n### Image shutter\n\nAn image opens from one edge while scaling down slightly inside its frame. Gallery staple; use it for\nthe one hero or showcase image.\n\n```css\n.shutter { overflow: hidden; }\n@media (prefers-reduced-motion: no-preference) {\n  .js .shutter { clip-path: inset(0 0 100% 0); transition: clip-path 1100ms var(--ease-in-out); }\n  .js .shutter img { transform: scale(1.12); transition: transform 1500ms var(--ease-soft); }\n  .js .shutter.is-in { clip-path: inset(0); }\n  .js .shutter.is-in img { transform: none; }\n}\n```\n\n### Press and hover\n\n```css\n.button { transition: transform var(--t-press) var(--ease-out), background-color var(--t-hover) ease, color var(--t-hover) ease; }\n.button:active { transform: scale(0.97); }\n.link { text-decoration: underline; text-decoration-color: transparent; text-underline-offset: 0.2em; text-decoration-thickness: 0.07em; transition: text-decoration-color var(--t-hover) ease; }\n@media (hover: hover) and (pointer: fine) {\n  .button:hover { background-color: var(--accent-strong); }\n  .link:hover { text-decoration-color: currentColor; }\n}\n```\n\nHover styles go behind `(hover: hover)` because touch devices fire hover on tap and leave it stuck.\nHover should raise contrast, never lower it. Do not change font weight on hover (the text reflows).\nDo not lift or scale every card on hover; one consistent, small response is enough.\n\n### Scroll-linked progress without JavaScript\n\nFor a wordmark that scales as the hero leaves, an image that drifts a few percent, or a progress bar.\nWrap in `@supports` so browsers without scroll timelines get the static state.\n\n```css\n@supports (animation-timeline: view()) {\n  @media (prefers-reduced-motion: no-preference) {\n    .drift { animation: drift linear both; animation-timeline: view(); animation-range: entry 0% exit 100%; }\n    @keyframes drift { from { transform: translateY(-4%); } to { transform: translateY(4%); } }\n  }\n}\n```\n\nKeep the travel small (under 8% of the element). Large parallax makes text hard to read and looks\ndated.\n\n### Pinned story\n\nA section whose heading stays put while items pass. Use `position: sticky`; do not hijack scrolling.\n\n```css\n.story { display: grid; grid-template-columns: 5fr 7fr; gap: var(--gutter); align-items: start; }\n.story__title { position: sticky; top: 18vh; }\n@media (max-width: 800px) { .story { grid-template-columns: 1fr; } .story__title { position: static; } }\n```\n\n### Index with preview, anchored to the row\n\nRows of names; pointing at a row or tabbing to it opens one frame level with that row. The frame\nfollows the row, never the pointer.\n\n```html\n<section class=\"index\">\n  <ul class=\"index__list\">\n    <li><a class=\"index__row\" href=\"/work/harbour-house\" data-preview=\"/img/harbour-house.jpg\">\n      <span class=\"index__name\">Harbour House</span><span class=\"index__year\">2025</span>\n      <img class=\"index__thumb\" src=\"/img/harbour-house-small.jpg\" alt=\"\" loading=\"lazy\" width=\"640\" height=\"400\">\n    </a></li>\n    <!-- … -->\n  </ul>\n  <div class=\"index__frame\" aria-hidden=\"true\"><img alt=\"\"></div>\n</section>\n```\n\n```css\n.index { position: relative; }\n.index__list { list-style: none; margin: 0; padding: 0; }\n.index__row { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: 0 var(--gutter); padding-block: 0.3em; font-size: var(--step-head); color: inherit; text-decoration: none; transition: opacity var(--t-hover) ease; }\n.index__thumb { order: -1; flex-basis: 100%; width: 100%; height: auto; margin-bottom: 0.4rem; }\n.index__frame { display: none; }\n@media (hover: hover) and (pointer: fine) {\n  .index__list { max-width: 62%; }\n  .index__thumb { display: none; }\n  .index__list:has(.index__row:hover, .index__row:focus-visible) .index__row:not(:hover, :focus-visible) { opacity: 0.4; }\n  .index__frame { display: block; position: absolute; top: 0; right: var(--margin); width: 30%; aspect-ratio: 4 / 3; z-index: 1; pointer-events: none; clip-path: inset(100% 0 0 0); transition: clip-path 320ms var(--ease-out), transform 360ms var(--ease-out); }\n  .index__frame.is-open { clip-path: inset(0); }\n  .index__frame img { width: 100%; height: 100%; object-fit: cover; }\n}\n@media (prefers-reduced-motion: reduce) { .index__frame { transition: none; } }\n```\n\n```js\n(() => {\n  const root = document.querySelector('.index');\n  if (!root) return;\n  const frame = root.querySelector('.index__frame');\n  const picture = frame.querySelector('img');\n  const fine = matchMedia('(hover: hover) and (pointer: fine)');\n  let warmed = false;\n  const show = (row) => {\n    if (!fine.matches) return;\n    if (!warmed) { warmed = true; root.querySelectorAll('[data-preview]').forEach((a) => { new Image().src = a.dataset.preview; }); }\n    picture.src = row.dataset.preview;\n    const y = row.offsetTop + row.offsetHeight / 2 - frame.offsetHeight / 2;\n    const max = root.offsetHeight - frame.offsetHeight;\n    const opening = !frame.classList.contains('is-open');\n    if (opening) frame.style.transitionProperty = 'clip-path';   // open in place, do not slide in from the top\n    frame.style.transform = `translateY(${Math.min(max, Math.max(0, y))}px)`;\n    if (opening) { frame.getBoundingClientRect(); frame.style.transitionProperty = ''; }\n    frame.classList.add('is-open');\n  };\n  const hide = () => frame.classList.remove('is-open');\n  root.querySelectorAll('.index__row').forEach((row) => {\n    row.addEventListener('pointerenter', () => show(row));\n    row.addEventListener('focus', () => show(row));\n  });\n  root.addEventListener('pointerleave', hide);\n  root.addEventListener('focusout', (e) => { if (!root.contains(e.relatedTarget)) hide(); });\n})();\n```\n\nOn touch screens each row shows its own picture above the name. Study: 5 pages navigate work this way;\nframes from about 470x270 to large plates behind the list; the other rows dimmed to about 0.3 (0.4 here, the floor for dimmed text). The\nimage trails and cursor-borne previews seen elsewhere in the study are the gimmick version.\n\n### Lines that rise on scroll\n\nFor a section heading or a statement whose line breaks you do not control. Splits after the fonts\nload, reveals once, then gives the plain text back so it rewraps normally. Plain text only (no links or\nemphasis inside).\n\n```html\n<h2 class=\"head\" data-lines>Turned by hand in one small workshop</h2>\n```\n\n```css\n[data-lines] .line { display: block; overflow: clip; padding-bottom: 0.12em; margin-bottom: -0.12em; }\n[data-lines] .line > span { display: block; }\n@media (prefers-reduced-motion: no-preference) {\n  .is-split .line > span { transform: translateY(110%); }\n  .is-split.is-in .line > span { transform: none; transition: transform 900ms var(--ease-expo) calc(var(--i) * var(--stagger-line)); }\n}\n```\n\n```js\n(() => {\n  const els = [...document.querySelectorAll('[data-lines]')];\n  if (!els.length || !('IntersectionObserver' in window) || matchMedia('(prefers-reduced-motion: reduce)').matches) return;\n  const restore = (el) => { el.textContent = el.dataset.text; el.classList.remove('is-split', 'is-in'); };\n  const split = (el) => {\n    const text = el.textContent.trim().replace(/\\s+/g, ' ');\n    el.dataset.text = text;\n    el.textContent = '';\n    const words = text.split(' ').map((word) => {\n      const s = document.createElement('span');\n      s.style.display = 'inline-block';\n      s.textContent = word;\n      el.append(s, ' ');\n      return s;\n    });\n    const lines = [];                                   // group the words by the line they landed on\n    for (const w of words) {\n      const last = lines.at(-1);\n      if (last && Math.abs(last.top - w.offsetTop) < 4) last.words.push(w.textContent);\n      else lines.push({ top: w.offsetTop, words: [w.textContent] });\n    }\n    el.textContent = '';\n    lines.forEach((line, i) => {\n      const mask = document.createElement('span');\n      const inner = document.createElement('span');\n      mask.className = 'line';\n      inner.style.setProperty('--i', i);\n      inner.textContent = line.words.join(' ');\n      mask.append(inner);\n      el.append(mask, ' ');\n    });\n    el.classList.add('is-split');\n  };\n  const io = new IntersectionObserver((entries) => {\n    for (const e of entries) {\n      if (!e.isIntersecting) continue;\n      io.unobserve(e.target);\n      e.target.classList.add('is-in');\n      e.target.querySelector('.line:last-of-type > span')\n        .addEventListener('transitionend', () => restore(e.target), { once: true });\n    }\n  }, { rootMargin: '0px 0px -12% 0px' });\n  document.fonts.ready.then(() => els.forEach((el) => { split(el); io.observe(el); }));\n  let width = innerWidth;                               // a width change before the reveal: give the text back\n  addEventListener('resize', () => {\n    if (innerWidth === width) return;\n    width = innerWidth;\n    els.filter((el) => el.matches('.is-split:not(.is-in)')).forEach((el) => { io.unobserve(el); restore(el); });\n  });\n})();\n```\n\nStudy: masked rises from 100-120% below the line, 0.6-1.2 s, 75-120 ms between lines, triggered when\nthe block's top is 80-95% down the viewport. Reduced motion: the script does not run; the text is plain.\n\n### Opening window\n\nThe hand-over from a type screen to the one big picture: the picture first shows as a window in the\nmiddle of a held stage and opens to full-bleed over about one screen of scroll.\n\n```html\n<section class=\"opening\">\n  <div class=\"opening__stage\">\n    <img src=\"workshop-wide.jpg\" alt=\"The workshop at first light, benches cleared\" width=\"2400\" height=\"1500\">\n  </div>\n</section>\n```\n\n```css\n.opening__stage { height: 100svh; overflow: clip; }\n.opening__stage img { display: block; width: 100%; height: 100%; object-fit: cover; }\n@supports (animation-timeline: view()) {\n  @media (prefers-reduced-motion: no-preference) {\n    .opening { height: 200svh; view-timeline-name: --opening; --inset-y: 20%; --inset-x: 28%; }\n    .opening__stage { position: sticky; top: 0; animation: opening-window linear both; animation-timeline: --opening; animation-range: contain 0% contain 75%; }\n    .opening__stage img { animation: opening-settle linear both; animation-timeline: --opening; animation-range: contain 0% contain 75%; }\n  }\n}\n@media (max-width: 700px) { .opening { --inset-y: 18%; --inset-x: 8%; } }\n@keyframes opening-window { from { clip-path: inset(var(--inset-y) var(--inset-x)); } to { clip-path: inset(0); } }\n@keyframes opening-settle { from { transform: scale(1.15); } to { transform: none; } }\n```\n\nThe section is two screens tall; the stage is held for one, and the window is fully open after three\nquarters of it, so the full-bleed picture rests for a moment before the page moves on. Study: 14 pages;\nstart windows 38-60% of the width; runways 600-1,800 px, and the readers asked for one to two screens.\nWithout scroll timelines, and under reduced motion, the picture is a full-bleed screen.\n\n### Held picture, passing captions\n\nThe pinned story built for photographs: the picture holds on one side while short captions pass on\nthe other; the caption at the middle of the screen is lit and its picture is shown.\n\n```html\n<section class=\"steps\">\n  <figure class=\"steps__media\">\n    <div class=\"steps__pictures\">\n      <img src=\"seasoning.jpg\" alt=\"Ash boards stacked to season\" class=\"is-on\">\n      <img src=\"turning.jpg\" alt=\"A leg being turned on the lathe\">\n      <img src=\"finish.jpg\" alt=\"Oil rubbed into a finished seat\">\n    </div>\n    <figcaption class=\"steps__count\" aria-hidden=\"true\"></figcaption>\n  </figure>\n  <ol class=\"steps__list\">\n    <li class=\"steps__item\"><h3>Seasoned for a year</h3><p>…</p></li>\n    <li class=\"steps__item\"><h3>Turned by hand</h3><p>…</p></li>\n    <li class=\"steps__item\"><h3>Finished with oil</h3><p>…</p></li>\n  </ol>\n</section>\n```\n\n```css\n.steps { display: grid; grid-template-columns: 7fr 5fr; column-gap: var(--gutter); }\n.steps__media { margin: 0; align-self: start; }           /* a stretched grid item cannot stick */\n.steps__pictures img { display: block; width: 100%; height: auto; }\n.steps__list { list-style: none; margin: 0; padding: 0; }\n.steps__item { min-height: 80svh; display: flex; flex-direction: column; justify-content: center; }\n.js .steps__media { position: sticky; top: 0; height: 100svh; display: flex; flex-direction: column; justify-content: center; gap: 0.75rem; }\n.js .steps__pictures { position: relative; aspect-ratio: 4 / 5; max-height: 80svh; }\n.js .steps__pictures img { position: absolute; inset: 0; height: 100%; object-fit: cover; opacity: 0; transition: opacity 500ms ease; }\n.js .steps__pictures img.is-on { opacity: 1; }\n.js .steps__item { opacity: 0.4; transition: opacity var(--t-ui) ease; }\n.js .steps__item.is-active { opacity: 1; }\n@media (max-width: 800px) {\n  .steps { display: block; }                               /* the section, not a grid area, contains the sticky picture */\n  .js .steps__media { height: auto; z-index: 1; background: var(--bg); padding-block: 0.5rem; }\n  .js .steps__pictures { aspect-ratio: 3 / 2; max-height: 42svh; }\n  .steps__item { min-height: 60svh; }\n}\n@media (prefers-reduced-motion: reduce) { .js .steps__pictures img, .js .steps__item { transition: none; } }\n```\n\n```js\n(() => {\n  const root = document.querySelector('.steps');\n  if (!root || !('IntersectionObserver' in window)) return;\n  const items = [...root.querySelectorAll('.steps__item')];\n  const pictures = [...root.querySelectorAll('.steps__pictures img')];\n  const count = root.querySelector('.steps__count');\n  const show = (i) => {\n    items.forEach((el, k) => el.classList.toggle('is-active', k === i));\n    pictures.forEach((el, k) => el.classList.toggle('is-on', k === i));\n    if (count) count.textContent = `${i + 1} of ${items.length}`;\n  };\n  const io = new IntersectionObserver((entries) => {\n    for (const e of entries) if (e.isIntersecting) show(items.indexOf(e.target));\n  }, { rootMargin: '-45% 0px -45% 0px' });                 // a band across the middle of the screen\n  items.forEach((el) => io.observe(el));\n  show(0);\n})();\n```\n\nWithout JavaScript the pictures and captions are two plain columns. Study: inactive items at 20-40%\n(dims of 10-15% read as missing text, so the floor here is 40%), crossfades of 400-600 ms, about one\nscreen per step; the readers asked for a visible count on any held sequence of more than two steps.\nThe count is a plain sentence in the body face, not a zero-padded numeral.\n\n### Sideways gallery\n\nA row of pictures that the vertical scroll moves sideways while the stage is held, for a short\ncollection (eight items or fewer). The native drag row is the base; the pinned version is added only\non wide screens with motion allowed, and only when the row is under three screens long.\n\n```html\n<section class=\"gallery\">\n  <div class=\"gallery__stage\">\n    <h2 class=\"head\">Eight kitchens, one stool</h2>\n    <ul class=\"gallery__track\">\n      <li class=\"gallery__item\"><a href=\"/kitchens/leith\"><img src=\"leith.jpg\" alt=\"A narrow galley kitchen in Leith\" width=\"1200\" height=\"1500\"><span>Leith</span></a></li>\n      <!-- … -->\n    </ul>\n  </div>\n</section>\n```\n\n```css\n.gallery__track { display: flex; gap: var(--gutter); list-style: none; margin: 0; padding: 0 var(--margin); overflow-x: auto; scroll-snap-type: x mandatory; scroll-padding-inline: var(--margin); }\n.gallery__item { flex: 0 0 min(72vw, 28rem); scroll-snap-align: start; }\n.gallery__item img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover; }\n.gallery.is-pinned .gallery__stage { position: sticky; top: 0; height: 100svh; display: flex; flex-direction: column; justify-content: center; gap: 2rem; overflow: clip; }\n.gallery.is-pinned .gallery__track { overflow: visible; scroll-snap-type: none; }\n.gallery.is-pinned .gallery__item { flex-basis: calc(62svh * 0.8); }\n```\n\n```js\n(() => {\n  const root = document.querySelector('.gallery');\n  if (!root) return;\n  const track = root.querySelector('.gallery__track');\n  const wide = matchMedia('(min-width: 900px) and (prefers-reduced-motion: no-preference)');\n  let dx = 0, queued = false;\n  const place = () => {\n    queued = false;\n    if (!root.classList.contains('is-pinned')) return;\n    const p = Math.min(1, Math.max(0, -root.getBoundingClientRect().top / dx));\n    track.style.transform = `translate3d(${(-p * dx).toFixed(1)}px, 0, 0)`;\n  };\n  const measure = () => {\n    root.classList.add('is-pinned');                     // measure the row as it would be when pinned\n    track.style.transform = '';\n    dx = track.scrollWidth - track.clientWidth;\n    const pin = wide.matches && dx > 0 && dx < innerHeight * 3;\n    root.classList.toggle('is-pinned', pin);\n    root.style.height = pin ? `${innerHeight + dx}px` : ''; // one pixel of scroll moves the row one pixel\n    place();\n  };\n  track.addEventListener('focusin', (e) => {             // keyboard: bring the focused item into view\n    if (!root.classList.contains('is-pinned')) return;\n    const item = e.target.closest('.gallery__item');\n    const x = Math.min(dx, Math.max(0, item.offsetLeft - parseFloat(getComputedStyle(track).paddingLeft)));\n    scrollTo({ top: root.getBoundingClientRect().top + scrollY + x, behavior: 'instant' });\n  });\n  addEventListener('scroll', () => { if (!queued) { queued = true; requestAnimationFrame(place); } }, { passive: true });\n  addEventListener('resize', measure);\n  addEventListener('load', measure);\n  wide.addEventListener('change', measure);\n  measure();\n})();\n```\n\nStudy: 8 pages pinned a horizontal track; their pages ran a median 25 screens, and the readers' worst\ncases spent 9 screens on three cards and 10,000-23,000 px of wheel on one track. Here the speed is 1:1\nand the hold ends when the last picture reaches the margin. Phones, narrow windows, reduced motion and\nlong rows all get the native row with snapping, which also works with touch, trackpads and the\nkeyboard. Never put the only copy of a call to action inside the moving row.\n\n### Receding hero\n\nAs the first screen leaves, its picture sinks a little and darkens while the words lift away a little\nfaster, so the hero recedes instead of simply scrolling off.\n\n```html\n<header class=\"hero\">\n  <img class=\"hero__picture\" src=\"kitchen.jpg\" alt=\"…\" width=\"2400\" height=\"1600\" fetchpriority=\"high\">\n  <div class=\"hero__copy\"><h1 class=\"display\">…</h1><p class=\"lead\">…</p></div>\n</header>\n```\n\n```css\n.hero { position: relative; min-height: 100svh; overflow: clip; display: grid; align-items: end; view-timeline-name: --hero; }\n.hero__picture { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }\n.hero::after { content: ''; position: absolute; inset: 0; background: var(--ink); opacity: 0; pointer-events: none; }\n.hero__copy { position: relative; z-index: 1; padding: var(--margin); }\n@supports (animation-timeline: view()) {\n  @media (prefers-reduced-motion: no-preference) {\n    .hero__picture { animation: hero-sink linear both; animation-timeline: --hero; animation-range: exit 0% exit 100%; }\n    .hero::after { animation: hero-dim linear both; animation-timeline: --hero; animation-range: exit 0% exit 100%; }\n    .hero__copy { animation: hero-lift linear both; animation-timeline: --hero; animation-range: exit 0% exit 70%; }\n  }\n}\n@keyframes hero-sink { to { transform: translateY(8%) scale(1.06); } }\n@keyframes hero-dim { to { opacity: 0.35; } }\n@keyframes hero-lift { to { transform: translateY(-6%); opacity: 0; } }\n```\n\nThe `exit` range runs from the moment the hero's top meets the top of the screen until its bottom\ndoes, which for a first screen is the first screen of scroll. Study: hero pictures that sink and dim as\nthey leave, a heading scrubbed from 140 to 60 px, a title card that scales down on the phone; the\nreaders called it quiet and the page \"one sheet\". Travel stays under 8%; the overlay is a flat ink at\nup to 35%, not a gradient. Static where unsupported or reduced.\n\n\n\n\n\n### Page to page\n\nNavigation between pages of the site with the browser's own view transitions: the old page fades\nquickly, the new one rises in, and the picture the visitor clicked travels into place as the new\npage's hero. No library, no full-screen curtain.\n\n```css\n/* on every page */\n@view-transition { navigation: auto; }\n@media (prefers-reduced-motion: reduce) { @view-transition { navigation: none; } }\n::view-transition-old(root) { animation: vt-leave 200ms var(--ease-exit) both; }\n::view-transition-new(root) { animation: vt-arrive 380ms var(--ease-out) 60ms both; }\n::view-transition-group(*) { animation-duration: 480ms; animation-timing-function: var(--ease-in-out); }\n::view-transition-image-pair(*.picture) { overflow: clip; }\n::view-transition-old(*.picture), ::view-transition-new(*.picture) { height: 100%; object-fit: cover; }\n@keyframes vt-leave { to { opacity: 0; } }\n@keyframes vt-arrive { from { opacity: 0; transform: translateY(16px); } }\n```\n\n```html\n<!-- on the index: the card picture of one project -->\n<img src=\"/img/leith.jpg\" alt=\"…\" style=\"view-transition-name: kitchen-leith; view-transition-class: picture\">\n<!-- on that project's page: its hero picture -->\n<img src=\"/img/leith-wide.jpg\" alt=\"…\" style=\"view-transition-name: kitchen-leith; view-transition-class: picture\">\n```\n\nEach name may appear once per page. Browsers without cross-document view transitions simply navigate.\nStudy: 16 pages load a page-transition library and run full-screen curtains of 0.7-2.4 s; 6 use view\ntransitions. The new page should be readable within half a second.\n\n### Ink fill\n\nOne statement that fills from part-ink to full ink as it rises through the screen, line by line. It is\nreadable before it fills; the fill only sets the pace.\n\n```html\n<p class=\"statement head\" data-fill>Nine people, one workshop, no catalogue: every stool is made for the kitchen it goes to.</p>\n```\n\n```css\n[data-fill] { --fill: var(--ink); color: var(--fill); }\n@supports (animation-timeline: view()) {\n  @media (prefers-reduced-motion: no-preference) {\n    .is-filling > span { display: inline-block; color: color-mix(in oklab, var(--fill) 45%, transparent); animation: ink-fill linear both; animation-timeline: view(); animation-range: cover 20% cover 45%; }\n  }\n}\n@keyframes ink-fill { to { color: var(--fill); } }\n```\n\n```js\n(() => {\n  if (!CSS.supports('animation-timeline: view()') || matchMedia('(prefers-reduced-motion: reduce)').matches) return;\n  document.querySelectorAll('[data-fill]').forEach((el) => {\n    const words = el.textContent.trim().split(/\\s+/);\n    el.textContent = '';\n    words.forEach((word, i) => {\n      const s = document.createElement('span');\n      s.textContent = word;\n      el.append(s, i < words.length - 1 ? ' ' : '');\n    });\n    el.classList.add('is-filling');\n  });\n})();\n```\n\nEach word watches its own position, so the words of a line fill together as the line moves from three\nquarters of the way down the screen to just past half way. Set `--fill` on a dark chapter to its ink.\nStudy: 14 pages scrub a statement from grey to ink; unread words started at about 25-30% and settled\nframes still caught statements half pale, which reads as disabled text. Here: one statement per page,\nthree to five lines, 32px or larger, starting at 45% (about 3:1 against the ground, enough for large\ntext). Full ink without scroll timelines or under reduced motion.\n\n### Rolling figures\n\nFor pages whose case is a handful of numbers: each digit rolls up to its value once, the columns a\nbeat apart. The real number stays in the text for screen readers and search.\n\n```html\n<p class=\"figure\"><span class=\"display\" data-roll>1987</span> the year the first stool was sold</p>\n```\n\n```css\n.roll__digits { display: inline-flex; font-variant-numeric: tabular-nums; line-height: 1; }\n.roll__col { display: inline-block; height: 1em; overflow: clip; }\n.roll__strip { display: flex; flex-direction: column; transform: translateY(calc(var(--d) * -1em)); }\n.roll__strip > span { height: 1em; }\n@media (prefers-reduced-motion: no-preference) {\n  .roll:not(.is-in) .roll__strip { transform: none; }\n  .roll.is-in .roll__strip { transition: transform 1100ms var(--ease-expo) calc(var(--i) * var(--stagger-item)); }\n}\n```\n\n```js\n(() => {\n  const els = [...document.querySelectorAll('[data-roll]')];\n  if (!els.length) return;\n  els.forEach((el) => {\n    const value = el.textContent.trim();\n    const said = Object.assign(document.createElement('span'), { className: 'sr-only', textContent: value });\n    const shown = Object.assign(document.createElement('span'), { className: 'roll__digits' });\n    shown.setAttribute('aria-hidden', 'true');\n    let i = 0;\n    for (const ch of value) {\n      if (!/\\d/.test(ch)) { shown.append(ch); continue; }\n      const col = Object.assign(document.createElement('span'), { className: 'roll__col' });\n      const strip = Object.assign(document.createElement('span'), { className: 'roll__strip' });\n      strip.style.setProperty('--d', ch);\n      strip.style.setProperty('--i', i++);\n      for (let n = 0; n < 10; n++) strip.append(Object.assign(document.createElement('span'), { textContent: n }));\n      col.append(strip);\n      shown.append(col);\n    }\n    el.classList.add('roll');\n    el.replaceChildren(said, shown);\n  });\n  if (!('IntersectionObserver' in window)) { els.forEach((el) => el.classList.add('is-in')); return; }\n  const io = new IntersectionObserver((entries) => {\n    for (const e of entries) if (e.isIntersecting) { e.target.classList.add('is-in'); io.unobserve(e.target); }\n  }, { rootMargin: '0px 0px -15% 0px' });\n  els.forEach((el) => io.observe(el));\n})();\n```\n\nStudy: 6 pages roll digit columns (stats, a year, coordinates), about 0.9-1.1 s per column on an\nexpo-out, staggered by column. Use it for three or four figures at display size, never in running text\nand never for a value that changes after load. Reduced motion: the figure is set at its value.\n\n### Accordion\n\n```css\n.acc__panel { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 320ms var(--ease-out); }\n.acc__panel > div { overflow: hidden; }\n.acc[open] .acc__panel, .acc__item.is-open .acc__panel { grid-template-rows: 1fr; }\n```\n\nAnimating `grid-template-rows` from `0fr` to `1fr` opens to the content's real height without measuring\nit in JavaScript.\n\n### Menu or dialog\n\n```css\n.menu { transform-origin: top right; transition: opacity var(--t-ui) var(--ease-out), transform var(--t-ui) var(--ease-out); }\n.menu[hidden], .menu.is-closed { opacity: 0; transform: scale(0.97) translateY(-6px); pointer-events: none; }\n```\n\nThings open from where they were triggered (`transform-origin` at the trigger). Nothing enters from\n`scale(0)`; start at 0.95–0.98. A centred dialog is the one case that scales from its centre.\n\n## 7. Signature moves\n\nThe direction sheet names one. Each of these was seen repeatedly on the studied gallery sites.\n\n| Move | What happens | Build with |\n| --- | --- | --- |\n| Masked headline | Lines rise from behind their baselines on load | Masked line reveal recipe |\n| Shutter image | Hero or showcase image opens from an edge, settling from 1.12 scale | Image shutter recipe |\n| Scaling wordmark | A giant wordmark shrinks or grows a few percent as the hero scrolls out | Scroll-linked recipe on `scale` |\n| Pinned story | A heading holds while its items scroll past | Sticky recipe |\n| Index with preview | Text rows; the hovered row shows its image | Index with preview, anchored to the row |\n| Curtain footer | The last section is revealed from under the page as you reach the end | `position: sticky; bottom: 0` footer under a main with a background and `z-index` |\n| Slow crossfade | Hero image crossfades through 3–4 photographs, 5–6s each | Stacked images, opacity keyframes, pause when the tab is hidden |\n| Edge-to-edge marquee | One line of very large type travels sideways, slowly | Duplicate the content, `translateX(-50%)` linear loop, pause on hover and under reduced motion |\n| Drag row | A horizontally scrollable row of large images with scroll snapping | `overflow-x: auto; scroll-snap-type: x mandatory`, no library |\n| Colour by chapter | Each chapter is its own full-bleed colour field, so the ground changes at section edges; a fixed header takes the ink of the chapter beneath | Section backgrounds in CSS; `base.js` sets `--header-ink` from `data-ink`. Never recolour the whole page from an observer |\n| Opening window | A type screen hands over to the big picture: a window in the middle of a held stage opens to full-bleed over about one screen | Opening window recipe |\n| Ink-fill statement | One statement fills from 45% to full ink as it rises through the screen | Ink fill recipe |\n| Sheet over a held picture | A full-bleed photograph holds for one screen; the next chapter slides up over it as an opaque sheet | A 100svh `position: sticky; top: 0` figure followed by a section with its own background and a higher `z-index`; no script |\n| Sideways gallery | A short row of pictures moves sideways while the vertical scroll holds the stage | Sideways gallery recipe |\n| Pushed line | One line of very large type is pushed sideways by the scroll, reading whole at the middle of its run | `animation-timeline: view()` on the line, `translateX` from 12% to -12%, linear; static where unsupported |\n| Rolling figures | The few figures that make the case roll up to their values once | Rolling figures recipe |\n| Carried picture | The picture clicked in a list travels into place as the next page's hero | Page to page recipe |\n\nPick by subject. A portfolio wants the index with preview; a restaurant wants the slow crossfade; a\nproduct wants the shutter on its hero object. If the move says nothing about the subject, it is\ndecoration and the page is better without it.\n\nPick by subject, as before: the opening window for a product or a place with one great photograph; the\nsheet for chapters that each own a picture; the sideways gallery for a short set of rooms, kitchens or\npieces; the pushed line for a brand whose claim is a word; rolling figures for a report, a fund or a\npractice that leads with numbers; the carried picture for a portfolio whose index and case pages are\nboth built.\n\n## 8. Reduced motion and performance\n\n- `prefers-reduced-motion: reduce` means fewer and gentler, not none: keep opacity and colour changes,\n  drop travel, scale, parallax and autoplay. All recipes above are written inside\n  `no-preference` blocks so the reduced state is simply the finished state.\n- Animate `transform`, `opacity` and `clip-path`. Animating `width`, `height`, `top`, `left`, `margin`\n  or `padding` forces layout on every frame. `grid-template-rows` for accordions is the accepted\n  exception because it is short and rare.\n- Do not drive many children from one changing CSS variable on a parent; set the transform on the\n  element that moves.\n- `will-change` only on an element that is about to animate, removed afterwards.\n- Pause loops when off screen or when the tab is hidden.\n- No scroll hijacking and no custom cursor. They cost usability, which is 30% of an Awwwards score and\n  the line most winners score lowest on. Smoothing only through `Stage.smooth()`, which stays off for\n  touch and reduced motion.\n\n## 9. What gives generated motion away\n\n- The same fade-up on every block.\n- A dozen staggered entrances in the hero.\n- Hover lift or zoom on every card and image.\n- Bounce or elastic easing on interface elements.\n- Infinite loops that mean nothing: pulsing dots, floating shapes, shimmering text, rotating badges.\n- A reveal that never fires and leaves a blank band in the page. Run `inspect.mjs` after the motion\n  pass and look at every screenshot for missing content.\n\n### Seen in the latest Sites of the Day\n\nSeen in the study, with how often, and what the house does instead.\n\n- **Preloaders and counters (60 of 99; 26 with a counter).** Half the usable pages were unreadable\n  2.5 s after load, a third at 4.5 s; the preloaders sat mostly on pages that had already loaded, and\n  25 of the 29 that loaded in under 3 s still showed nothing readable at 4.5 s. Counters stalled,\n  outlasted the load or were tweens with nothing behind them. House: no preloader. If a scene must\n  load, the HTML first screen (headline, picture, action) is there at once and the scene fades in\n  behind it when ready.\n- **Gates (10 of 99): enter, sound, age or gesture before any content.** House: none. Sound is a\n  control on the page, off by default.\n- **Scroll hijacking (16 wheel-driven scenes, 9 of them endless, plus 14 single screens where the wheel\n  does nothing).** The visitor cannot tell where they are, how much is left or how to get out, and the\n  keyboard and screen readers get nothing. Usability 6.01 against 6.50 for pages that scroll. House:\n  native scroll; any scene is \n\n<!-- [TRUNCATED AT 50KB] -->\n\n<!-- File: skills/taste-skill/references/research.md (Tokens: ~6567 | Category: anthropic-skill) -->\n# The study\n\nEverything numeric in this skill comes from here. Cite these figures; do not round them up or invent\nothers.\n\n## Contents\n\n1. Method and its limits\n2. Scores\n3. Where the idea comes from\n4. Headlines\n5. Type\n6. Devices: what separates strong from weak, and what does not\n7. Colour and shape\n8. Imagery and page structure\n9. What the inspector says about the gallery itself\n10. The 25 highest-scored sites and their ideas\n11. How the skill was tested\n12. The October 2026 study: 100 Sites of the Day\n13. The app-screen study\n\n## 1. Method and its limits\n\n- **Sample.** 248 sites collected on 5 October 2026: 156 from One Page Love (the latest gallery pages\n  and the category listings) and 92 Awwwards Sites of the Day (the three most recent listing pages).\n  247 loaded; 246 were re-measured with the final probe.\n- **Capture.** Headless Chrome at 1440×900 and 390×844. For each site: the first viewport, five more\n  frames while scrolling with real wheel input, the mobile first viewport, and a measurement pass in\n  the page (computed styles, text geometry, colours, fonts actually loaded).\n- **Panel.** 21 model reviewers each studied about 12 sites from the screenshots and the measurements,\n  described them (idea, hero, type, colour, imagery, layout, sections) and scored them the Awwwards\n  way: design 40%, usability 30%, creativity 20%, content 10%. These are model judgements from still\n  frames, not human jurors and not the real Awwwards scores. Batches mixed both sources so each\n  reviewer saw a spread.\n- **Usable sets.** 235 sites were usable for the panel (12 showed only a preloader, an entry gate or a\n  bot wall). 202 were measurable for typography (a page with at least 25 words and a detectable\n  headline). \"Top\" below means panel score 7.5 or higher (82 measurable sites); \"weak\" means under 6.5\n  (23 measurable sites).\n- **Limits.** One capture per site on one day. Some heroes were caught mid-animation or behind a cookie\n  notice. WebGL-heavy sites are under-described by text measurements. The eyebrow detector counts any\n  small short label directly above a large heading, so it over-counts against the panel's stricter\n  reading (60% measured against 35% observed). Motion was inferred from frames, not watched. The sample\n  is whatever the two galleries had recently featured; it is fashion as much as quality.\n\n## 2. Scores\n\n| | All 235 | One Page Love (151) | Awwwards (84) |\n| --- | --- | --- | --- |\n| Median overall | 7.2 | 7.1 | 7.5 |\n| Middle half | 6.8–7.6 | | |\n| 8.0 or higher | 25 sites (11%) | | |\n| 7.5 or higher | 90 sites (38%) | | |\n| Under 6.5 | 29 sites | | |\n\nMedian by criterion: design 8, usability 7, creativity 7, content 7. Among the top 25: design 9,\nusability 7, creativity 8, content 8. Usability is the one line that does not rise with the rest: the\nbest sites are no easier to use than the average one. Do not copy their gates, preloaders, tiny text\nor hidden navigation.\n\n## 3. Where the idea comes from\n\nThe clearest pattern in the panel's notes: high scores go with a concept taken from the subject, and\nlow scores go with its absence. The weakest entries' ideas were recorded in words like \"none beyond the\nstandard dark SaaS launch formula\", \"no visual idea beyond clarity\", \"no strong idea\". The strongest\nwere sentences only that subject could own (section 10).\n\nRecurring engines among the 7.3+ sites, each the basis of a direction in the library:\n\n- **The product demonstrates itself.** A colour picker's loupe reads the page's own background; a list\n  tool is sold with tiny working lists; a photo app's page is a wall of its own output.\n- **The page is an artefact from the subject's world.** A wedding site that is the invitation; an\n  archive as tabbed folders; a coupon with a cut line; a portfolio as a contact sheet.\n- **The name is the hero.** Wordmarks as wide as the screen, a photograph set inside the name like a\n  letter, a name split to opposite corners with the page between.\n- **One motif from the subject drives everything.** A tool's octagonal section as button, mask and\n  loader; two circles for two accounts; a café's stripes.\n- **Dressed as another category.** A money app as a streetwear drop; an industrial roaster as a design\n  object; a parcel service as a fairground.\n- **The place carries it.** One full-bleed view and a name along the bottom edge.\n- **A fixed stage.** A title or object stays put while content swaps beneath it.\n- **One section, one colour.** Flat fields as chapters.\n- **Radical understatement.** A 27px headline and tiny live demonstrations, carried through completely.\n\nHero types, by the panel's classification (top sites against weak sites): full-bleed media with type\nover it 16% / 10%; giant wordmark 14% / 0%; typographic poster 13% / 7%; text beside media 10% / 3%;\n**centred statement with media below 7% / 24%**. The centred headline over a screenshot is the weak\nsites' signature layout.\n\n## 4. Headlines\n\n| Hero headline | All | Top | Weak |\n| --- | --- | --- | --- |\n| Words, median | 5 | 5 | 5 |\n| Words, middle half | 3–9 | 2–8 | 3–8 |\n| Characters, median | 32 | | |\n| One line at 1440 | 47% | | |\n| Two lines or fewer at 1440 | 70% | 71% | 83% |\n| Two lines or fewer at 390 | 57% | | |\n| Three lines or fewer at 390 | 82% | | |\n\nAwwwards heroes are shorter (median 4 words, 76% within two lines) than One Page Love's (6 words, 66%).\nSection headings have a median of 3 words. Length does not separate strong from weak; nearly everyone\nin the gallery writes short headlines. The two-line limit in this skill is a house rule that most of\nthe gallery already meets on desktop and that takes care to meet on a phone.\n\n## 5. Type\n\n| | All | Top | Weak |\n| --- | --- | --- | --- |\n| Hero size, median | 72px (5.0vw) | 6.0vw | 4.7vw |\n| Hero size, middle half | 3.0–7.6vw | 2.5–9.7vw | 2.7–6.1vw |\n| Largest text on the page, median | 6.4vw | 8.4vw | 5.0vw |\n| Largest text, upper quarter starts at | 10.4vw | 12.5vw | 6.7vw |\n| Hero on a phone, median | 40px | | |\n| Hero tracking, median (middle half) | -0.01em (-0.03 to 0) | | |\n| Hero leading, median (middle half) | 1.0 (0.95–1.1) | | |\n| Body size, median (middle half) | 16px (14–18) | | |\n| Headline ÷ body, median | 4.3 | 4.7 | 4.0 |\n| Typefaces carrying 3%+ of text | one 31%, two 45%, three 22% | | |\n| Distinct font sizes, median | 8 | | |\n\nHero weight: regular 48%, medium 18%, semibold 6%, bold or heavier 22%, light 6%. Capitals 24%.\nCentred 39% overall, 52% on weak sites. Display classes by the panel: neo-grotesk 48%, transitional\nserif 11%, geometric sans 10%, condensed 6%, extended 6%, old-style serif 4%, custom lettering 4%.\n\nStrong sites push the extremes: their biggest type is bigger and their range is wider. Weak sites\ncluster in the middle.\n\n## 6. Devices: what separates strong from weak, and what does not\n\nMeasured in the page unless marked (panel).\n\n**More common on weak sites (the data supports avoiding them):**\n\n| Device | Top | Weak |\n| --- | --- | --- |\n| Icon-topped feature cards (panel) | 1% | 28% |\n| Rows of identical cards with a small icon (measured) | 7% | 26% |\n| Pill badges (panel) | 14% | 34% |\n| Pill-shaped label above a heading (measured) | 5% | 26% |\n| Tiny uppercase letter-spaced labels, any | 16% | 57% |\n| Tiny uppercase letter-spaced labels, three or more | 6% | 43% |\n| Gradient fills (not counting scrims) | 22% | 52% |\n| Gradient text | 2% | 13% |\n| Shadows on resting elements, any | 24% | 48% |\n| Shadows, five or more | 10% | 30% |\n| Emoji in the page | 10% | 26% |\n| Eyebrow labels (panel) | 32% | 45% |\n\n**No real difference:**\n\n| Device | Top | Weak |\n| --- | --- | --- |\n| Backdrop blur anywhere | 32% | 39% |\n| Italic-serif accent word (panel) | 4% | 7% |\n| Thin rules, any | 61% | 52% |\n\n**More common on strong sites (banned here anyway, as house style):**\n\n| Device | Top | Weak |\n| --- | --- | --- |\n| Monospace labels (panel) | 44% | 24% |\n| Monospace anywhere outside code (measured) | 45% | 26% |\n| Index numbering (panel) | 38% | 21% |\n\nMonospace captions, index numbers and ruled grids are the present fashion of award sites. They are\nexcluded from this skill by the owner's choice, not by the data: they are the devices generators copy\nfirst, and a page that cannot lean on them has to find structure in space, tone and scale.\n\n## 7. Colour and shape\n\n- Dark page ground 41%; pure white 25%; pure black 12%; a warm off-white 13%.\n- Scheme (panel): monochrome plus one accent 23%, light neutral 22%, dark neutral 14%, several flat\n  colours 13%, two-tone 12%, photographic 9%, one colour field 6%.\n- Primary buttons are neutral (black, white, grey) on 52% of sites. One site in 246 has a terracotta\n  button; none has a violet one.\n- Median number of distinct section grounds: 2 on top sites, 1 on weak sites.\n- Button shape: top sites square (0–2px) 52%, fully round 23%, small radius 19%, medium (9–16px) 6%.\n  Weak sites fully round 59%, medium 24%, square 18%.\n- Media corners are square on 73% of sites; where rounded, the median radius is 12px.\n- Buttons in the first viewport: none on 55% of top sites and 39% of weak ones.\n\n## 8. Imagery and page structure\n\n- Hero media covers at least half the first viewport on 60% of sites (top 68%, weak 48%) and nearly\n  all of it on 50% (top 56%, weak 39%). No hero media: 15%.\n- Video is present on 49% of sites and a canvas element on 49% (top 62%, weak 35%).\n- Images per page, median: 24 overall, 37 on top sites, 5 on weak ones.\n- Imagery kind (panel): mixed 32%, photography 14%, generative or WebGL 13%, product interface 12%,\n  3D render 11%, illustration 9%, video 6%, type only 3%. Median panel score is lowest for\n  illustration-led (6.9) and product-interface-led (7.1) pages and highest for video and type-only\n  (7.5).\n- Page length, median: 8.7 screens and 575 words (middle half 1.6–14.4 screens, 250–956 words). A\n  quarter of the sites are a single screen or two.\n- Navigation: a median of 3 links; fixed or sticky on 66%.\n- Density (panel): airy 46%, balanced 45%, dense 9%. Alignment: centred 33%, mixed 31%, left-anchored\n  17%, modular grid 13%, free 6%.\n- Asked to describe each site's most interesting sections, the panel picked a pricing, testimonial or\n  FAQ section only 7, 12 and 9 times across 235 sites. Where strong sites have them at all, they are\n  not where the design effort goes, and they avoid the stock form.\n\n**From the panel's written notes on the 114 sites scoring 7.3 or more** (hand tallies, approximate;\n`layout.md` turns these into practice):\n\n- Outer margins of 32px or less on about 45; 80px or more on about 8. A centred 700–1300px container\n  on about 15, several of them the pages the panel called stock.\n- Text anchored to a fixed off-centre line on about 22. Text docked in corners or at opposite ends of\n  a baseline on about 25 and 15.\n- Two or three type sizes with nothing between on about 30; no note describes a graded five-step\n  scale.\n- One thing per screen on about 20. A full background colour per section on about 20; alternating\n  light and dark on about 12.\n- Every section recomposed on about 14; one planned exception to the page's own system on about 14.\n- No conventional top navigation bar on about 45; small corner links on about 22; a single link or\n  button on about 10.\n- Endings: the name at full width about 18, the hero repeated inverted about 12, a closing scene of\n  its own about 14, no footer or a single line about 22. Link-column footers are mentioned only as\n  criticism.\n- Motion (inferred from frames): autoplaying video about 50; pinned or fixed stages about 40; text\n  reveals about 30 (blur-in 10, masked line rises 8, scroll-tied word colouring 7); horizontal strips\n  about 27; marquees about 26; media swapped behind a fixed element about 15; scroll-linked scaling\n  about 12. Rare: hover effects (4 mentions), parallax (6), accordions (5), bounce or spring motion\n  (none). About 10 strong sites show little or no motion at all.\n- How weak sites fail (54 sites under 6.8): the category's stock template about 20; centred headline,\n  pill badge, two buttons and a screenshot about 9; stock modules after a distinctive hero about 8,\n  plus about 17 in the middle band; a characterless default typeface about 13; text too small or too\n  faint about 13; never saying what the thing is about 12.\n- Faults of the best sites (90 at 7.5 or more), not to be copied: text at 9–13px about 24;\n  information hidden behind the concept about 20; the idea running out mid-page about 15; text over\n  footage with no scrim about 12; gates, preloaders and blank first paints about 12.\n\n## 9. What the inspector says about the gallery itself\n\nRunning this skill's own `inspect.mjs` rules over the 202 measurable gallery sites: the median site\nhas 4 `FAIL`s and only 4% have none. The rules that fire most: headline over two lines somewhere on\nthe page 60%, eyebrow-like label 60%, thin rules 50%, monospace 37%, shadows 32%, gradients 29%, index\nnumbering 29%.\n\nSo the house style is deliberately stricter than the gallery. It is not a description of award sites;\nit is a narrower target inside what they do: their scale, their ideas, their imagery and restraint,\nwithout the ornaments that have since become a uniform.\n\n## 10. The 25 highest-scored sites and their ideas\n\nThe panel's one-sentence reading of each. Notice that every one names something only that subject\ncould own. (Several use devices this skill bans; take the idea, not the ornament.)\n\n| Site | Source | Score | Idea |\n| --- | --- | --- | --- |\n| PP Neue Montreal | Awwwards | 8.6 | A typeface specimen dressed as a vintage city travel guide: the font named after Montreal is sold through guidebook titling, postcards and old tourist footage. |\n| Seasats | Awwwards | 8.4 | Calm, dusk-lit seascapes sell autonomous boats as serene instruments, and the navigation is a column of stacked colour swatches taken from that sea-and-sand palette. |\n| AI in Design Report 2026 | Awwwards | 8.4 | A research report laid out like a colour-blocked print annual: a video collage on top, an oversized tight grotesk title, and flat orange, lilac, sage and black blocks carrying stats, quotes and chapters. |\n| House of Honey | Awwwards | 8.4 | A block-heavy wordmark pierced by a fine script: the bold-against-delicate contrast is repeated at every scale, with giant pink script behind quiet serif statements. |\n| White Desert | Awwwards | 8.4 | One word, the destination, set a third of the screen tall over footage like a film title card; sheer scale stands in for remoteness. |\n| Applied Imagination | One Page Love | 8.3 | An essay conceived on a flight is read as a descent: an altimeter ticks from 30,000 ft to zero while you scroll down through clouds to mountains at ground level. |\n| Cursor Compile | One Page Love | 8.3 | The event name drawn as seven looping one-line curves in seven colours, more signature than logotype, on an otherwise whisper-quiet off-white page. |\n| The New Industrials | One Page Love | 8.3 | A long-read essay laid out inside a drafting grid, where colour fields shift as you read and machine parts drift through the margins and finally assemble into the publisher's initials. |\n| Wild | One Page Love | 8.3 | A studio essay in which everything decorative is drawn on one square-pixel grid: the hero heatmap, the icons, the diagrams, the lettering and the footer. |\n| Hildén & Kaira | Awwwards | 8.3 | The agency name is cast in liquid chrome across the full width, and the same chrome becomes the objects that float through the page, tying the pitch to one material. |\n| PX Push | Awwwards | 8.2 | A design subscription presented as a retro broadcast: the entire site is seen through a CRT screen, with a chrome logo token as its mascot. |\n| Illoca | Awwwards | 8.2 | Software for architects sold as a drafting table: a two-colour illustrated studio on graph paper that the scroll pushes into until the drawing fills the screen. |\n| Aspen Search | Awwwards | 8.2 | The page is a tile system with no margins: the two-word name is split across cells that alternate type, dithered image, black and one mint green. |\n| Dragonfly Redux | Awwwards | 8.2 | A crypto fund presented as a terminal artefact: every picture is rendered in characters, framed by four letters of the name pinned to the viewport corners. |\n| Monolog | Awwwards | 8.2 | A studio pitch run as an asymmetric sheet: a narrow left column carries the sales talk while a wide right column stacks a very heavy headline and the proof. |\n| The Queue | One Page Love | 8.1 | An essay on queueing where the queue is the ornament: a line of drawn figures stands along the bottom of the hero and returns between chapters in changing period dress. |\n| Paul Kalkbrenner | Awwwards | 8.1 | Swiss poster typography for a techno artist: the name as one black line with a photo set inside it like a glyph, then every chapter gets its own flat colour. |\n| Vero New York | Awwwards | 8.1 | A keepsake treated like couture: a slow close-up film opens, then a white sculpture of a dress stays pinned at centre while one sentence passes over it. |\n| Depo Luxe | Awwwards | 8.1 | A film production roster shown as a full-screen reel in which every step is one film with only a title, a director and a client, set like credits at body size. |\n| Longbow | Awwwards | 8.1 | The page is built on a visible four-column construction grid, and cars, cards and a giant condensed marquee are slotted into its cells like objects on an artboard. |\n| Mosby's Files | Awwwards | 8.0 | An archive of architects presented as a physical stack of coloured index-tab file folders that you flip through. |\n| Sarah & Matt Wedding | One Page Love | 8.0 | The site is the invitation: a letterpress-style card opens the page, and its ornaments and small typographic parts become the components for everything after it. |\n| Zara Webb | One Page Love | 8.0 | A one-woman newborn-care practice presented like a hand-made keepsake: a mascot rabbit, scalloped and flower-shaped cut-outs, candid film photographs. |\n| Noho | Awwwards | 8.0 | Furniture sold through people misusing it (wearing, balancing on, hiding behind chairs on flat colour backdrops) while the interface stays quiet. |\n| Juggle | One Page Love | 8.0 | The headline literally drowns: a flat blue field rises to half height and the lines below the waterline change colour. |\n\nFull notes on any studied site: `node scripts/draw.mjs --site <id>` (ids appear on direction sheets).\n\n## 11. How the skill was tested\n\nSix client briefs (an invoicing tool, a restaurant, a designer's portfolio, a ceramic product, a\nguesthouse, a design conference), each with no photographs. For every brief a fresh agent built the\npage three ways: with no skill (baseline), with another published design skill (atelier, three briefs)\nand with this skill. Every build was photographed by `inspect.mjs` in the same way and judged blind\nby a separate agent with the juror brief (Awwwards weights, anonymous A/B/C folders, screenshots\nonly). The skill was revised after each round from the jurors' reasons and the builders' notes.\n\n| Round | Briefs | This skill | Baseline | Atelier | Wins |\n| --- | --- | --- | --- | --- | --- |\n| 1 | 4 | 6.6 | 7.7 | 6.8 | 1 of 4 |\n| 2 | 3 | 7.1 | 8.0 | | 0 of 3 |\n| 3 | 3 | 7.5 | 7.5 | | 1 of 3 |\n| 4 (unseen briefs) | 3 | 6.9 | 7.9 | 7.5 | 0 of 3 |\n| 5 (same three) | 3 | 7.7 | 7.8 | 7.2 | 2 of 3 |\n\nUnder the inspector, the final builds measured 0 FAIL each; the baselines measured 8 to 13 FAIL each\n(eyebrows, monospace labels, 01/02/03 numbering, hairlines, gradients, shadows, three-line headlines,\ntext under 13px).\n\nWhat the jurors rewarded, in the order they named it: an idea that belongs to this client and not to\nthe category (the competitor test); one live thing on the page; full content at a readable size; a\nfirst screen with one dominant element and a real button; drawings of the subject with detail. What\nthey punished: a quiet page that read as empty, a small headline, text sliding over pictures or cut\nat the top, a page recoloured mid-section, rows cut at the right edge, a large sentence over three or\nmore lines (read as a long headline whatever its markup), navigation that took over the first screen.\nEach of these is now a rule in SKILL.md or a check in the inspector.\n\nLimits: one juror per brief per round, so single scores carry about half a point of noise; the round-5\nbriefs had been seen in round 4; jurors are models, not people.\n\n## 12. The October 2026 study: 100 Sites of the Day\n\nA second study, made for v2.1, of the latest 100 Awwwards Sites of the Day (10 July to 17 October\n2026), with a different aim from the first: where the pictures and footage sit, how pages move, and\nthe frame (margins, balance, empty space, titles). About three in four of these sites were also in\nthe first study.\n\n- **Capture.** Headless Chrome at 1440×900 and 390×844 on 18 October 2026: four frames of the first\n  4.5 seconds after load, every screen while scrolling with real wheel input (one frame at rest per\n  step; the mid-step frames were cut from the top of the document instead of the viewport, so they\n  were not used), five phone screens, and a measurement pass in the page: every picture and\n  clip with its box, ratio, fit and corners; every section's content edges and pictures; blank runs;\n  the CSS that loaded (curves, durations, keyframes, breakpoints, feature counts); the animations,\n  transitions and script-driven moves that actually ran; GSAP tweens and scroll triggers where the\n  page exposed them. Nothing a site owns (code, copy, pictures) is reproduced in the skill; only\n  measurements and descriptions in our own words.\n- **Panel.** One model reader per site studied its frames and measurements, described the idea, the\n  first screen, the frame, every section, where each picture sits, the motion and what not to copy,\n  and scored it the Awwwards way. 91 of 99 captures were usable (the rest showed a gate, a bot wall or\n  a firewall page). Scores ran 6.7 to 7.9 (median 7.45); \"top\" means 7.5 or more (36 sites), \"lowest\"\n  under 7.3 (16).\n- **What it changed.** Where pictures and footage go: `imagery.md` §12. What strong pages do with\n  motion, new tokens, recipes and the gimmicks to avoid: `motion.md` §2, §4–6 and §9–10. Empty space\n  and the frame: `layout.md` §4–5. New compositions in `library/heroes.json` and `sections.json` and\n  notes on media and motion in `library/sites.json` (`draw.mjs --site <id>`).\n- **Headline numbers.** Pictures fill a median 16% of a scrolled screen, but in whole screens: 42% of\n  screens hold none and 19% are 90% picture or more. The median page carries 7 pictures (top 8,\n  lowest 2) and 42% carry footage (half of the top sites, one of the 16 lowest). 94% of pictures have\n  square corners. Strong ease-outs are the curves that ran (expo and quint out); the median of all\n  that ran on a site is 420ms. 60 of 99 open on a loading screen, and a third of the usable pages were\n  still unreadable 4.5 seconds after load, with no gain in the design marks. About 1 text section in\n  100 leaves half the width empty; the outer margins of strong pages match to a few pixels; 82% of\n  text sections open with a heading; 15 of 97 first screens never say what the thing is, and those\n  lose usability points.\n- **Limits.** One capture per site on one day; a WebGL scene can render blank in a headless browser;\n  the scroll-linked frames are partly an artefact of smooth-scroll libraries; one reader per site, so\n  single scores carry about half a point of noise.\n\n## 13. The app-screen study\n\nFor dashboards and app screens (v2.1), a separate study of 23 real product screens chosen by the\nowner (17 products, 17 light and 6 dark, at 1440–1512px): each screen measured from its pixels by a\nreader with full-resolution crops, six cross-cutting reports (shell, data and charts, tables and\nforms, visual language, taste, styles), and a synthesis into `references/app-screens.md` and\n`library/app.json` (seven styles, five shells, screen patterns). The screenshots stay private; the\nskill carries only the measurements and the rules. Blind test rounds of app screens built with and\nwithout the skill then shaped the warnings at the top of that file.\n\n<!-- File: skills/taste-skill/references/scenes.md (Tokens: ~2540 | Category: anthropic-skill) -->\n# Scroll scenes\n\nThe big moments of a page: stretches of scroll where the page stops being a column of sections and\nbecomes a scene. A camera flies through a field of pictures, a picture grows from a window to the whole\nscreen, a word buckles under the scroll, a set of photographs orbits and lands in a grid. These are what\nvisitors remember from award sites, and what a page built from tidy sections alone never has.\n\nThe scene library is taken apart from recent Awwwards Sites of the Day (October 2026: 43 sites recorded\nframe by frame while scrolling, 261 scenes described, 30 types), rebuilt from scratch in our own code,\ntested frame by frame at desktop and phone width and under reduced motion, and reviewed against the\nscenes it came from. Nothing a site owns is in them. Until `library/scenes.json` ships the draw deals\nnone; a page that needs a scene builds one on the stage (section 8), with every rule here.\n\n## Contents\n\n1. What a scene is\n2. Putting a scene on a page\n3. Filling it\n4. Fitting it to the page\n5. The phone, reduced motion, no script\n6. Checking it\n7. Rules for scenes\n8. When no scene in the library fits\n9. The catalogue\n\n## 1. What a scene is\n\nA tall section whose stage holds still while the page scrolls past it. The stage is\n`position: sticky`; the section is (hold + 1) screens tall, so the stage is held for `hold` screens;\na GSAP timeline is scrubbed from 0 to 1 by that scroll. Nothing captures the wheel: the scrollbar always\ntells the truth, the keyboard and the trackpad work as everywhere else, and the scene ends.\n\nWhat a scene is not: a fade-up, a small parallax, a sticky footer, a marquee. Those are the quiet layer\n(`references/motion.md`). A scene changes the whole screen.\n\nThe direction sheet deals two or three (section 9 of the sheet), from different families, each placed\non the section of the argument it can carry. Build them in step 6, with that section: a scene is\ncomposition, not decoration added at the end.\n\n## 2. Putting a scene on a page\n\nCopy the shared stage and the dealt scene's files into the project (`assets/scenes/stage.css`,\n`stage.js`, `<id>.css`, `<id>.js`). Each scene file's header comment lists the markup it expects and\nits options; `assets/scenes/demo/<id>.html` is a complete working page to read beside it.\n\n```html\n<head>\n  <script>document.documentElement.classList.add('js')</script>\n  <link rel=\"stylesheet\" href=\"scenes/stage.css\">\n  <link rel=\"stylesheet\" href=\"scenes/<id>.css\">\n</head>\n<body>\n  …\n  <section class=\"scene\" data-scene=\"<id>\" data-options='{\"hold\": 3}' aria-label=\"…\">\n    <div class=\"scene-stage\">\n      <!-- the markup from the scene file's header, filled with this page's content -->\n    </div>\n  </section>\n  …\n  <script src=\"https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js\"></script>\n  <script src=\"https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/ScrollTrigger.min.js\"></script>\n  <script src=\"https://cdn.jsdelivr.net/npm/lenis@1.3.26/dist/lenis.min.js\"></script>\n  <script src=\"scenes/stage.js\"></script>\n  <script src=\"scenes/<id>.js\"></script>\n  <script>Stage.smooth(); Stage.init();</script>\n</body>\n```\n\n- Load SplitText (`gsap@3.15.0/dist/SplitText.min.js`) only when a scene file says it needs it.\n- `Stage.smooth()` adds weighted wheel scrolling (Lenis at lerp 0.12). It stays off for touch and for\n  reduced motion. Leave it out on a quiet page; the scenes work either way.\n- `Stage.init()` starts every `[data-scene]` on the page. A page with two scenes loads both files.\n- The versions are pinned. Do not change them to `@latest` or an unpinned major.\n\n## 3. Filling it\n\nA scene is only as strong as what goes in it. The scene file's header and the sheet's \"Content\" line\nsay how many pictures and words it takes; these hold for all of them:\n\n- **Pictures of one family.** Same light, same grade, same kind of subject: a field of mismatched stock\n  photographs breaks the illusion of one space faster than any timing error. Real pictures of the\n  subject's world (`assets.mjs`), the project's own, or the dealt photographs, in that order\n  (`references/imagery.md`). Size each to its largest display size, set `width` and `height`.\n- **Words that read in a breath.** A held statement is 4 to 12 words; captions are one to four words in\n  the text face, sentence case. One statement on screen at a time.\n- **The scene says something about the subject.** A fly-through of the studio's work, the route a\n  shipment really takes, the four rooms of the house, the product's change of state. A scene filled\n  with unrelated pictures is a gimmick and reads as one.\n- **Real content only.** If the scene needs eight pictures of the subject and there are three, take the\n  `--redraw scenes`, never pad it with stand-ins.\n\n## 4. Fitting it to the page\n\n- The scene files read the page's tokens: `--ground`, `--ink`, `--muted`, `--accent`,\n  `--font-display`, `--font-text` (with fallbacks). Set them on `:root` from the sheet and the scene\n  takes the page's colour and type. Check the demo against your page, not the other way round.\n- Display type in a scene uses the dealt display face and the two-line headline rule; statements stay\n  at statement size.\n- Leave a quiet section between two scenes (a text section, a list, a plain picture) so each one lands.\n  Two scenes back to back read as one long ride and the second loses.\n- A scene on the first screen must be readable at progress 0: the title, the sentence and the action are\n  there on the first frame (motion rule 1), and the scene starts moving only when the visitor scrolls.\n- Give the section a heading. If the design has no visible heading in the scene, the section still\n  carries one (`aria-label` on the section and a real heading in the finished composition).\n\n## 5. The phone, reduced motion, no script\n\n- **The phone.** Each scene has a phone plan in its file: the same scene with changed numbers, a\n  simpler version, or `phone: 'rest'`, where the phone shows the finished composition. Touch scrolling\n  is never smoothed. Look at the phone sheet as carefully as the desktop one.\n- **Reduced motion and no script.** The section is an ordinary section showing the finished\n  composition: the same content, laid out to read without motion. Nothing is hidden waiting for a\n  script. The inspector's `reduced-hidden` check and the reduced sheet of `scenes.mjs` show it.\n- **A failed CDN** falls back to the finished composition too (the stage adds `.is-rest`). The\n  inspector fails a scene that rests on desktop (`scene-not-live`), so a broken script cannot pass.\n\n## 6. Checking it\n\n```bash\nnode <skill>/scripts/scenes.mjs <page>        # every scene at 0, 10 … 100%, desktop and phone, and reduced motion\nnode <skill>/scripts/inspect.mjs <page>       # the gate; with scenes on the sheet it also films the scroll\n```\n\n`scenes.mjs` writes one contact sheet per scene and width to `.taste-skill/scenes/`. Read every one.\nAt every frame ask: is there one clear thing to look at; can the statement on screen be read; is\nanything popping, blank, cut off or crossing the words; is it as bold as it should be? The inspector's\n`desktop-film-NN.jpg` shows the whole page's scroll a third of a screen at a time: check that the\nscenes and the quiet sections between them make a rhythm, and that nothing between them is empty.\n\n## 7. Rules for scenes\n\n1. **Two or three per page,** from different families, a quiet section between them. The inspector\n   warns over four (`many-scenes`) and when scenes hold more than 60% of the page (`scene-heavy`).\n2. **Each holds one to four screens:** about one screen per beat of the story; a hold with nothing new\n   to show is cut, not padded.\n3. **Native scroll only.** No wheel capture, no locking the page, no scenes that only run on a click.\n   Smoothing only through `Stage.smooth()`.\n4. **Readable at its rest points.** The statement on screen reads whole; nothing passes over text while\n   it is being read; text on a picture has a flat scrim or a calm area under it.\n5. **Inside a scene the scene's numbers apply** (motion rule 7): a picture may grow from a window to the\n   whole screen, type may cross the stage, a camera may fly through pictures. Outside scenes, the quiet\n   limits of `references/motion.md` hold.\n6. **Transform, opacity, clip-path.** Nothing that forces layout on every frame. Pictures decoded before\n   they move.\n7. **The house rules hold inside scenes:** no monospace captions, no 01/07 counters (a plain \"3 of 7\" if\n   a count is needed), no gradients (flat scrims), no shadows or glows, no hairline decoration, no\n   decorative particles, no violet.\n8. **The finished composition is designed,** not an afterthought: it is what reduced motion, a failed\n   script and some phones see.\n\n## 8. When no scene in the library fits\n\nRedraw first (`--redraw scenes`). If the brief really needs a scene the library does not have, build it\non the same stage so it inherits the guards:\n\n```js\nScenes['my-scene'] = (root, opts = {}) => Stage.scene(root, {\n  hold: opts.hold ?? 2,          // screens the stage is held for\n  scrub: opts.scrub ?? true,     // true when Lenis runs; 0.4-0.8 without it reads as weight\n  phone: 'same',                 // or 'rest', or { hold, build } for a phone plan\n  build(tl, { q, phone }) {      // positions are fractions of the scene, 0-1\n    tl.fromTo(q('.picture'), { clipPath: 'inset(30% 30% 30% 30%)' }, { clipPath: 'inset(0% 0% 0% 0%)', duration: 0.6 }, 0)\n      .to(q('.title'), { yPercent: -40, autoAlpha: 0, duration: 0.25 }, 0.7);\n  },\n});\n```\n\nand write its CSS finished composition first, then the live layout under `.scene.is-live`. Check it\nwith `scenes.mjs` like any other.\n\n## 9. The catalogue\n\n(Generated from `library/scenes.json`; the draw deals from it. `node <skill>/scripts/draw.mjs --list\nscenes` prints it.)\n\n<!-- File: skills/taste-skill/references/tells.md (Tokens: ~1805 | Category: anthropic-skill) -->\n# Tells — the dated registry\n\nA tell is a device that makes a page read as generated. Tells are not bad design in themselves; most\nbegan as good ideas on good sites. They became tells by being produced by default, everywhere, without\na reason. That is why this registry is dated, and why it never names a replacement font, colour or\ncomponent: every published \"use this instead\" list has become the next wave of tells within months.\nReplacements here are procedures (draw from the library, derive from the subject), not products.\n\n`scripts/inspect.mjs` and `scripts/lint.mjs` detect most entries. Status: **banned** means the\ninspector fails the page; **warned** means it flags it and you need a reason.\n\n## Contents\n\n1. First wave (2023–2024)\n2. Second wave (2025)\n3. Third wave (2025–2026): the \"fix\" that became the look\n4. Gallery fashion, banned as house style\n5. Structural tells\n6. Copy tells\n7. Motion tells\n8. Why removal is not enough\n\n## 1. First wave (2023–2024)\n\n| Tell | Status | Do instead |\n| --- | --- | --- |\n| Violet / indigo gradients on hero, buttons and glows | banned | The dealt palette; flat colour |\n| Gradient-filled headline text | banned | Solid ink |\n| Glass panels: backdrop blur, translucent cards | warned (2 or more) | Opaque surfaces one tone step from the ground |\n| Glowing or gradient \"Get started\" button | banned | Flat button named for its action |\n| Soft grey drop shadow under every card | banned | Tone step, or no box |\n| Three identical feature cards, each with an icon in a rounded square | banned | The dealt section blueprint |\n| Emoji as icons or bullets | banned | Words, or a real picture |\n| Centred headline, subtitle, two buttons, screenshot below | no rule; the draw avoids it | The dealt hero |\n| The same typeface on every generated page | warned (lint: default-font) | The dealt type system |\n\n## 2. Second wave (2025)\n\n| Tell | Status | Do instead |\n| --- | --- | --- |\n| Eyebrow / kicker: tiny tracked uppercase label above every heading | banned | Fold it into the heading, or delete |\n| Pill badge above the hero headline (\"New\", \"Beta\", \"Introducing\") | banned | Say it in the supporting sentence |\n| One word of the headline in italic serif, colour or underline | warned | One face, one colour |\n| Bento grid of rounded tiles as the feature section | warned as card rows | A composed section; tiles only in the dense-tiles direction, filled, strict sizes |\n| Near-black ground with one neon accent and a glow | banned via shadow, gradient | A dealt dark palette, no glow |\n| Floating rounded pill navigation with blur | warned | A plain bar |\n| Fake dashboard hero built from grey bars and donut charts | no rule; see imagery.md §7 | A real interface fragment, or no image |\n| Decorative status dot (\"Available for work\", pulsing \"live\") | lint: bounce | Remove |\n| Fade-and-rise on every section | no rule; see motion.md | One signature move |\n\n## 3. Third wave (2025–2026): the \"fix\" that became the look\n\nThe remedy published for the first two waves was \"warm it up and make it editorial\". Models adopted\nthe remedy wholesale and it is now the most recognisable generated look of all.\n\n| Tell | Status | Do instead |\n| --- | --- | --- |\n| Yellow-cream ground + terracotta / rust / clay accent | banned together; terracotta banned alone; cream warned | The dealt palette. Warmth from a low-chroma stone, a deep ink, a photograph, or a full warm field |\n| High-contrast or soft serif display as the shortcut to \"premium\" | no rule | The dealt type system, whatever class it is |\n| Oversized italic serif headline | no rule | As dealt |\n| Broadsheet cosplay: hairline rules everywhere, zero radius, dense columns | banned via hairline | Structure from space and tone |\n| \"Field notes\", \"Quietly trusted by\", \"On our desks\": performative labels | lint: copy | Plain section names |\n\n## 4. Gallery fashion, banned as house style\n\nThese are common on award sites right now. In the study they appear *more* often on the top-scored\nsites than on the weak ones (panel observations: monospace labels 44% against 24%, index numbering 38%\nagainst 21%; measured thin rules 61% against 52%). They are banned here regardless, by the owner's\ndecision: they are the first things a generator copies from the gallery, they carry no information,\nand a page built without them has to find real structure.\n\n| Tell | Status | Do instead |\n| --- | --- | --- |\n| Monospace micro-labels, mono as a \"technical\" voice, mono captions | banned | The text face; tabular figures for data |\n| Index numbering: 01 / 02 / 03, (001), \"Step 02\", numbered section markers | banned | Order by position, scale, or the words; `<ol>` when it is truly a list |\n| Thin rules: hairline dividers, ruled grids, 1px outlined boxes and tiles | banned (boxes: 3 or more) | Space, tone steps, filled shapes, a thick bar if a bar is the idea |\n| Design-tool chrome as ornament: crosshairs, crop marks, selection handles, dashed guides, rulers | banned via hairline, dashed | Remove |\n| Agency micro-meta: local time, coordinates, weather, version stamps, \"©2026 — Scroll\", middle-dot strings | lint: copy; micro-label | Remove |\n| Tiny uppercase letter-spaced captions scattered around the viewport | banned (3 or more) | Sentence case at readable size, placed with the content it describes |\n\nTiny tracked capitals are the one item in this group the data condemns as well: 16% of top sites\nagainst 57% of weak ones.\n\n## 5. Structural tells\n\n| Tell | Status | Do instead |\n| --- | --- | --- |\n| Headline as a full sentence at display size, three or four lines | banned (over two lines) | A title of about five words; the rest goes below |\n| Stock section order: hero, logos, features, testimonial, pricing, CTA | no rule; see copy.md §1 | The order of the argument |\n| Every section the same layout family | critique.md pass 9 | Different composition per section, from the sheet |\n| Everything centred | warned over 72% | Left-anchored, one centred moment |\n| One medium border radius (12–16px) on everything | none | Square or fully round, chosen once |\n| Nine nearly equal font sizes | warned over 9 | Five sizes, far apart |\n| Invented social proof: logos, quotes, star rows, \"10,000+ teams\" | copy.md §5 | Real proof, or none |\n| Text or a CSS box where a picture belongs | critique.md cap | A real picture, or a design that needs none |\n\n## 6. Copy tells\n\nFlagged by `lint.mjs`: the genre's verbs and adjectives (unlock, supercharge, seamless, elevate,\neffortless, cutting-edge, all-in-one …); the correction (\"not just X, it's Y\"); tricolon headlines;\n\"Get started\" and \"Learn more\" as labels; more than a handful of em dashes; lorem ipsum. See\n`copy.md` §6.\n\n## 7. Motion tells\n\nIdentical fade-up on every block; a dozen staggered hero entrances; hover lift on every card; bounce\neasing; infinite loops that mean nothing; reveals that fail and leave a blank band. See `motion.md` §9.\n\n## 8. Why removal is not enough\n\nA page with every tell removed and nothing put in their place is an empty page with good manners, and\nthat is a tell too (the \"avoidance aesthetic\": anyone could guess it from the category plus the list of\nthings to avoid). The tells were filling a gap where an idea should have been. The order of work in\n`SKILL.md` exists to fill that gap first: the idea from the subject, the dealt composition, real\npictures or committed type, and only then the checks.\n\n<!-- File: skills/taste-skill/references/type.md (Tokens: ~2370 | Category: anthropic-skill) -->\n# Type\n\nTypography is most of what a visitor sees and most of what makes a page look designed or assembled.\nThe direction sheet deals you a type system (faces, weights, settings). This file is how to use it.\n\n## Contents\n\n1. What the study measured\n2. The scale: few sizes, far apart\n3. Setting display type\n4. Setting text\n5. Loading the fonts properly\n6. One family or two\n7. Details that separate set type from typed text\n8. Mistakes the inspector cannot see\n\n## 1. What the study measured\n\nFrom 202 measurable sites out of the 247 studied (Chrome, 1440×900 and 390×844):\n\n| | Median | Middle half | Note |\n| --- | --- | --- | --- |\n| Hero headline size | 72px (5.0vw) | 43–109px | Top-scored sites: 6.0vw median |\n| Largest type on the page | 6.4vw | up to 10.4vw | Top-scored sites 8.4vw, weak sites 5.0vw |\n| Hero headline on a phone | 40px | 32–59px | |\n| Hero tracking | -0.01em | -0.03 to 0 | Tighter as size grows |\n| Hero leading | 1.0 | 0.95–1.1 | |\n| Body size | 16px | 14–18px | |\n| Headline ÷ body size | 4.3 | | Top-scored sites 4.7 |\n| Typefaces in real use | 2 | 31% use one, 45% two, 22% three | |\n| Hero weight | regular 48%, medium 18%, bold or heavier 22% | | Big type does not need to be bold |\n| Hero in capitals | 24% | | |\n| Hero centred | 39% | | 52% on the weak sites |\n\nTwo things to take from it. First, size contrast is the main lever and the best sites pull it harder.\nSecond, weight is not: half of the heroes are set in a regular weight. Scale and spacing make type\nconfident; bold is one option among several.\n\n## 2. The scale: few sizes, far apart\n\nThe panel described about 30 of the 114 strongest sites as using two or three type sizes with nothing\nin between, and none as using a graded five- or six-step scale. So: one display size, one text size\nand a small size carry the page; a lead size and a heading size exist for when they are needed. Five\nis the ceiling. The common failure is nine sizes that are all near each other (16, 18, 20, 24, 28,\n32…), which reads as mush. Choose steps that are clearly different:\n\n```css\n:root {\n  --step-small: clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem);   /* 13–14px  captions, legal */\n  --step-body:  clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem);    /* 17–19px  paragraphs */\n  --step-lead:  clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem);      /* 20–26px  supporting line, large body */\n  --step-head:  clamp(2rem, 1.3rem + 3.2vw, 4rem);             /* 32–64px  section headings */\n  --step-display: clamp(3rem, 1rem + 9vw, 9rem);               /* set by the hero blueprint */\n}\n```\n\n- `--step-display` belongs to the direction. A monument wordmark is 16–24vw; a quiet instrument's\n  headline is 28px. Use the size the hero blueprint gives, as a `clamp()` so it scales with the\n  viewport but is bounded on phones and very wide screens.\n- Keep the gap: the display size should be at least four times the body size on desktop, and nothing\n  should sit between `--step-lead` and `--step-head` unless the design truly needs a sixth size.\n- Resist a \"subheading\" size for every card and label. If two sizes look almost the same, make them\n  the same.\n\n## 3. Setting display type\n\nLarge type exposes spacing that is invisible at text size. Apply all of these to anything over 40px:\n\n```css\n.display {\n  font-size: var(--step-display);\n  line-height: 0.95;              /* 0.85–1.05; tighter for capitals and condensed faces */\n  letter-spacing: -0.035em;       /* -0.02 to -0.05em; use the value on the direction sheet */\n  font-kerning: normal;\n  text-wrap: balance;\n  max-width: 14ch;                /* choose the measure so lines break where you want */\n  margin: 0;\n}\n```\n\n- **Tracking scales with size.** The larger the type, the tighter it needs to be; a value right for\n  120px will choke 32px. Set tracking per step, not once for all headings.\n- **Leading below 1.0 needs checking.** Look for collisions between descenders and the ascenders or\n  accents of the next line. Two-line headlines make this easy to verify by eye.\n- **All capitals** want slightly open tracking (0 to +0.03em) even at display size, and leading around\n  0.9.\n- **Optical alignment.** Big letters with round or diagonal left edges (O, C, A, T, W) look indented.\n  Pull the headline left by about 0.04–0.06em (`margin-left: -0.05em`) so it aligns optically with the\n  text beneath it.\n- **Viewport-wide type.** For a line that must span the screen, size it in `vw` and verify at 390 and\n  1440; set `white-space: nowrap` and let the container clip rather than wrap. Calculate the size from\n  the character count: `font-size ≈ container width ÷ (characters × k)` with k from `copy.md` §2.\n- Never add a text shadow, an outline stroke, or a gradient fill to display type.\n\n## 4. Setting text\n\n```css\nbody { font-size: var(--step-body); line-height: 1.5; font-kerning: normal; text-rendering: optimizeLegibility; }\np { max-width: 62ch; text-wrap: pretty; margin: 0; }\np + p { margin-top: 0.9em; }\n.lead { font-size: var(--step-lead); line-height: 1.35; max-width: 40ch; }\nsmall, .caption { font-size: var(--step-small); line-height: 1.45; }\n```\n\n- Measure: 45–75 characters. Wider than that and the eye loses the next line; the inspector warns\n  past about 88.\n- Leading: 1.45–1.6 for body, tighter (1.3–1.4) for the larger lead size, looser for long reading.\n- Secondary text is the same face in a softer ink (`--muted`), not a lighter weight and not smaller\n  than 13px.\n- Do not centre paragraphs longer than three lines. Do not justify.\n- Light text on a dark ground looks heavier: drop one weight step or add 0.01em tracking, and raise\n  leading slightly.\n\n## 5. Loading the fonts properly\n\nThe sheet gives a `<link>` tag. Use it exactly; do not swap in a face you prefer.\n\n```html\n<link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\n<link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin>\n<link href=\"…from the direction sheet…\" rel=\"stylesheet\">\n```\n\n```css\n:root {\n  --font-display: \"Family From Sheet\", \"Helvetica Neue\", Arial, sans-serif;\n  --font-text: \"Family From Sheet\", Georgia, serif;\n}\n```\n\n- Request only the weights you use (usually two or three in total).\n- Always give a fallback stack of the same broad kind (sans for sans, serif for serif).\n- In a framework, use its font loader with the same family and weights (`next/font/google`, or a\n  self-hosted `@font-face` with `font-display: swap`). Fontshare faces load from the\n  `api.fontshare.com` stylesheet on the sheet.\n- After building, `inspect.mjs` reports the families that actually rendered. If it warns that a face\n  did not load, the screenshots show a fallback and nothing you judge from them is real. Fix the link\n  first.\n\n## 6. One family or two\n\nA third of the studied sites use a single family for everything, and it is the safest way to look\ncoherent. When the dealt system has two faces:\n\n- Give each a job and never swap them: one sets headlines, the other sets everything else.\n- Do not introduce a third face for labels, numbers or quotes.\n- Do not mix two faces inside one headline.\n- Italic is for titles of works and real emphasis inside paragraphs, never as decoration.\n\n## 7. Details that separate set type from typed text\n\n- Curly quotes and apostrophes, real dashes, a real ellipsis (see `copy.md` §7).\n- `font-variant-numeric: tabular-nums` for prices, tables, dates in columns; `oldstyle-nums` suits\n  serif body text.\n- `text-underline-offset: 0.18em; text-decoration-thickness: 0.07em` on links, so underlines clear the\n  descenders.\n- `hyphens: none` on headings. `overflow-wrap: anywhere` only on long URLs or emails.\n- A heading belongs to the text after it: space above a heading is at least twice the space below.\n- `::selection { background: var(--accent); color: var(--accent-ink); }` and a visible\n  `:focus-visible` outline in the accent, so even the browser's own states belong to the design.\n- Do not change weight on hover; the line reflows.\n\n## 8. Mistakes the inspector cannot see\n\n- A headline that passes the two-line rule but breaks badly: one orphan word on line two, or a break\n  that splits a phrase (\"Stools for small / kitchens\"). Author the break.\n- Display type so tight that letters touch, or so loose it falls apart.\n- A confident hero followed by section headings almost as large. Keep one size dominant per screen.\n- Body text set in the display face when that face was drawn for large sizes only.\n- Everything bold. If every line is emphasised, none is.\n\n<!-- File: skills/taste-skill/SKILL.md (Tokens: ~9286 | Category: anthropic-skill) -->\n---\nname: design-taste-frontend\ndescription: >-\n  tasteskill v2, the anti-slop frontend skill. Art direction for websites, distilled from a study of\n  247 curated gallery sites (One Page Love, Awwwards Sites of the Day). Deals researched directions\n  (idea, composition, type, palette, photographs, section blueprints) from a library, enforces a strict\n  no-slop house style with a real-browser inspector, and runs a look-and-fix loop on screenshots. Use\n  this whenever you build, design, redesign, restyle, polish or review a landing page, marketing site,\n  portfolio, product page, one-pager, hero or any public-facing web page, in any stack (HTML/CSS, React,\n  Next.js, Vue, Svelte, Astro, Tailwind) — also when the user says a page looks generic, templated,\n  \"AI-made\", sloppy, or asks to make it look designed, premium, award-level or less like every other\n  site. Also for app screens: dashboards, admin and analytics views, settings, inboxes and other screens\n  people work in, with their own run and rules.\n---\n\n# tasteskill v2\n\nA page built by a model usually looks like the average of every page the model has seen: a centred\nheadline over three lines, a little label above it, a row of icon cards, a soft gradient, a few thin\nrules and a monospace caption. Nothing in it is wrong and nothing in it was decided.\n\nThis skill replaces those defaults with decisions, in four ways:\n\n1. **A script deals the directions, you choose among them.** Asked to invent a look, a model picks\n   the category default every time. `scripts/draw.mjs` deals three of twenty researched directions;\n   you choose the one that carries the subject's idea, and the script then deals its type system,\n   palette, hero and section compositions from a library distilled from 247 real sites.\n2. **The idea comes from the subject.** In the study, what separated the best sites from the forgettable\n   ones was a concept taken from the thing itself, not the styling.\n3. **A house style with no ornaments,** measured in a real browser by `scripts/inspect.mjs`, so the\n   rules are checked rather than hoped for.\n4. **You look at what you made.** Screenshots at three widths, a juror's rubric, fix, look again.\n\nOne warning learned in testing. Taking the ornaments away is only half the job; a page that has lost its\nlabels, rules and cards and gained nothing in their place reads as thin, and blind jurors rightly prefer\na richer page with tells over an empty page without them. The other half is substance: type set\nlarger, whole fields of colour, real pictures of this subject's world (found or drawn), and every\nsection carrying its full content. The skill is built to give you that; do not trade it for restraint.\n\nIn the commands below `<skill>` is this skill's folder. Run them from the project's root, so the\nworking files land in `.taste-skill/` there. The scripts need Node 22+ and an installed Chrome, Edge\nor Chromium, and install nothing. `assets.mjs` also needs network access; it uses no API keys.\n\n## Page or app screen\n\nDecide first which of two kinds of work this is.\n\n- **A page** is read and scrolled: a landing page, a marketing or product site, a portfolio, an\n  event, a restaurant, a one-pager. It follows **the run** below.\n- **An app screen** is worked in: a dashboard, an admin or analytics view, settings, billing, an inbox\n  or queue to work through, a wallet, a list with filters, an editor or builder. It follows\n  **`references/app-screens.md`**: its own run, its own draw (`draw.mjs --app`), its own house rules\n  (quiet borders, small labels and repeated panels are normal there; gradients, glows, icons in tinted\n  squares, rainbow charts and invented vanity numbers are not) and `inspect.mjs --app`. Read that file\n  whole before you start; the page run below does not apply.\n\nA product site that shows its app is a page; the interface fragments on it follow the app-screen\nrules for their insides. Deal the product's app style once, in its own folder, with the page's colours\nand type kept:\n\n```bash\nnode <skill>/scripts/draw.mjs --app --kind <kind> --brief \"<the product>\" --keep palette,type --out .taste-skill/app\n```\n\nand build every fragment the page shows (the hero's live screen, a feature's crop, a chart) as a real\npiece of that app: `assets/app.css` for its panels, tables and controls, `assets/charts.js` for its\ncharts, real data that adds up, one finding stated, cropped and scaled the way the page's blueprint\ntreats a picture. A fragment that looks like a working product is the strongest picture a software page\nhas; grey bars and lorem numbers are the weakest. When a request mixes both (a landing page and the\ndashboard behind it), build each with its own run and one shared palette and typeface.\n\n## The run\n\nDo these in order. Steps 1–5 take a few minutes and decide whether the page is any good.\n\n### 1. Read the brief and the project\n\nFind out what is real: the subject, the audience, the one thing the page must get someone to do, the\nstack, any existing brand (colours, fonts, logo), and above all **what imagery truly exists**: the\nproject's own photographs or product shots, a real interface that can be shown, an image generation\ntool you can call, or nothing. Do not plan around pictures you do not have. Nothing of its own is\nrarely nothing at all: the subject's city, street, materials and history are in open archives and\nmuseums, free to use with a credit (step 6, `scripts/assets.mjs`).\n\nIf the request is vague, decide and state your reading in one line instead of asking. Ask only when a\nmissing fact blocks the work (for example, no product name).\n\nThen **inventory the subject** in your notes: eight to twelve things that belong to this client and to\nno competitor. Look for its name and what the name means; its address, door number, street and\nneighbourhood, and what that place looks like (its tiles, signs, paint colours, typefaces on its shop\nfronts, its light, its weather); the numbers in the brief (seats, rooms, minutes to the sea, the\nprice, the year); the constraint it lives with (only one batch a month, closed in winter, by\nappointment); its materials and colours; its rituals and hours (the oven lit at five, the ferry at\nseven); the printed things of its world (a timetable, a label, a ticket, a sign). This list is where\nthe idea comes from in step 4. In blind tests, the page that won each brief was built from an item on\nsuch a list (the client's name and what it means, the street it stands in, the one constraint that\nmakes it what it is), and the pages that lost had a good composition with a category idea. The list\nis also your picture search: each place, material and printed thing on it is a query for step 6.\n\n### 2. Write the argument\n\nBefore any design, list the page as claims with their proof, one line per section, the way\n`references/copy.md` §1 shows. The claims decide which sections exist and in what order. Delete any\nsection that has no claim. This is how you avoid the stock sequence of hero, logos, three features,\ntestimonial, pricing, call to action.\n\n### 3. Draw the direction\n\n```bash\nnode <skill>/scripts/draw.mjs --sector <sector> --brief \"<one line about the subject>\" \\\n  --sections <roles in the order of your argument> [--tone <tone>] [--have <assets>] [--keep palette,type] \\\n  --options 3\n```\n\nThis deals three directions and prints a short summary of each. Hold each one against your inventory:\nwhich way of composing can carry something only this client has? Choose that one, not the most\nfamiliar, and write one line in your notes on why. In testing, a single random direction that did not\nsuit the subject was the commonest cause of a weak page. Then deal the full sheet:\n\n```bash\nnode <skill>/scripts/draw.mjs <the same arguments, without --options> --direction <chosen id>\n```\n\n- `--sector`: `node <skill>/scripts/draw.mjs --list sectors`. Pick the closest.\n- `--sections`: roles from `--list roles` (features, showcase, how-it-works, testimonial, proof, stats,\n  pricing, faq, cta, footer, intro, about, work, gallery, list, contact). The hero is implied.\n- `--tone` (optional): quiet, bold, warm, technical, playful, luxury, editorial. Only pass it when the\n  brief clearly asks for one.\n- `--have`: assets that really exist, comma-separated: `photography` (the project's own photographs of\n  the place, people or work), `product-photo` (photographs of the specific product, or an image tool\n  that can make them), `product-ui` (real screenshots), `illustration`, `video`. Leave it out if you\n  have none: the draw then avoids compositions that depend on them and the sheet says how to fill\n  picture slots honestly (software shows its own interface built in HTML; a product with no photographs\n  is drawn and set among real pictures of its world, never a fake product shot). Pictures you will\n  find in the open collections are not the project's own; leave them out of `--have`.\n- `--keep palette,type`: when the brand already fixes colours or typefaces. The draw then deals only\n  the composition, and you map the brand's values onto the roles.\n\nThe command prints a **direction sheet**. It is the art direction for this build:\n\n- **Adopt it.** Do not blend it with the layout you would have made anyway. If it feels unfamiliar,\n  good: the familiar layout is the one this skill exists to prevent.\n- Redraw one slot (`--redraw hero | type | palette | photos | scenes | section:<role> | direction`) only for a\n  reason you can state: it contradicts a stated brand constraint, or needs an asset that does not\n  exist. Never redraw to get something more comfortable. Record every redraw in your report.\n- When a dealt section cannot hold the real content (it compares three plans and there is one price;\n  it wants five quotations and there are none), do not bend the content to fit. List the others with\n  `--alternatives <role>`, pick the one whose assumptions match the content, and take it with\n  `--redraw section:<role>=<id>`.\n- **Check the palette against the subject.** A dealt palette is a set of proportions (one ground, one\n  ink, one accent, fields) as much as a set of colours. If its colours fight the subject's own material\n  (candy pastels for a peat whisky, neon for a mountain hut), redraw the palette once; if the subject\n  has unmistakable colours of its own (its material, the paint of its street, the landscape outside\n  its windows), keep the dealt proportions and take the colours from the subject instead, and say so\n  in the report.\n- Reprint it any time with `node <skill>/scripts/draw.mjs --show`. In a long session, re-read it before each\n  section you build.\n\n### 4. Find the idea\n\nThe direction is a way of composing. The idea is what makes the page belong to this subject and no\nother. Write this sentence in your notes and do not start building until both blanks are filled from\nthe subject itself:\n\n> On this page, **[something that belongs to the subject]** becomes **[the device the direction calls for]**.\n\nPlaces to look for the first blank:\n\n- **Its output.** What does the thing produce? Put the real output on the page as material. (A camera\n  that prints poems delivered its copy as paper slips.)\n- **Its object or shape.** What does it physically look like, in cross-section, in silhouette?\n  Enlarge it, crop it, make it the frame or the one motif.\n- **Its name.** Can the letters hold a photograph, stack into a wall, split to two corners?\n- **Its place.** Is there one view that makes someone want to be there?\n- **Its ritual.** Is there a sequence the page can perform as it scrolls?\n- **Its artefact.** What printed thing already exists in its world: ticket, menu, label, receipt,\n  invitation, folder, manual?\n- **Its opposite.** Which other category owns the feeling this one lacks?\n\nFill the first blank from your inventory (step 1), not from the category. **The competitor test:** put\nthe nearest real competitor in the sentence (the bakery two streets away, another oak furniture maker,\nanother hut on the same mountain). If the sentence still works, the idea belongs to the category: a\nloaf of bread is every bakery; the seven doors of the street this one is named after are only this one.\n\"Clean and modern\" is not an idea. The sites the study's panel scored lowest were the ones whose idea\nwas recorded as \"none beyond the standard formula\".\n\n**One live thing.** Give the page one thing the visitor can do, or that is different for each visit,\nmade from the idea: pick a wood and see the chair in it; type your name and see it cut in the\nfoundry's letters; set the loan and read the real monthly figure; see whether the hut's stove is lit\nright now and how long until the last ferry; choose a size and see it against the room. In blind tests every winning page had one and the jurors named it first. Rules: it uses the subject's real content, it works on a phone with a thumb, it has a plain\nfallback without script, it never blocks reading, and it is one thing, not a playground. It is\nbuilt in step 6 as part of the page, not added as motion in step 9.\n\n**The scenes carry the idea too.** The scroll scenes on the sheet are devices waiting for a subject.\nDecide what each one shows from your inventory before building: the fly-through passes through this\nstudio's own title cards, the route is the road this shipment really takes, the picture that opens to\nthe whole screen is the room the guest will wake up in. A scene filled with pictures that could belong\nto anyone is a screensaver.\n\n### 5. Write the words\n\nWrite the whole page as a copy deck (plain text) before markup, following `references/copy.md`:\n\n- **Every headline fits in two lines or fewer at every width.** Do the arithmetic in copy.md §2 before\n  committing to a sentence: about 32 characters is safe everywhere at a confident size. The studied\n  gallery heroes have a median of 5 words and 32 characters.\n- One supporting sentence, directly under the headline (32–48px below it) and shown with it, never\n  docked at the foot of the first screen or held back by an animation. When the headline is a name or\n  a figure of speech, this sentence says plainly what the thing is. One primary action, named for what\n  it does, as a real button on the first screen.\n- **The first screen answers the visitor's first question in large type.** For an event: what it is,\n  when and where (the dates belong in the headline or at the second size, never only in small text).\n  For a product: what it is and what it costs or does. For a person: who and what they do. Every\n  section the visitor came for (the line-up, the menu, the rooms, the price) has its own heading and\n  its own place in the navigation.\n- **Write the full content.** Every section the brief asks for delivers its information completely:\n  the whole menu with prices, each room with its own details, every speaker and talk, the price with\n  what it includes, an answer for each real question. Thin sections are the commonest reason a clean\n  page loses to a busier one.\n- Sample details are expected where the brief leaves gaps (dish names, room names and rates, project\n  titles) so the design is seen at full density; list them in the report for the client to confirm.\n  Proof is never invented: no customers, quotes, reviews, press, logos or business statistics.\n\n### 6. Build it, still\n\nBuild the page with motion switched off in your head; a page that needs animation to look finished is\nnot finished. Order of work:\n\n1. **Tokens.** Colour and type roles from the sheet as CSS custom properties. Everything downstream\n   references tokens only. `<skill>/assets/base.css` is a neutral foundation you may start from (reset, token\n   names, fluid type steps, grid, focus and selection styles, the motion helpers); it has no look of\n   its own.\n2. **The hero, exactly as the blueprint describes it,** at desktop and at phone width. Get the big\n   thing big and the small things small before anything else exists.\n3. **Each section from its blueprint,** with this project's content. Keep the geometry, change the\n   subject. Neighbouring sections must not share a layout. **Carry the idea into every section,**\n   pricing, FAQ and footer included: the commonest failure in the study, even among good sites, is a\n   distinctive first screen followed by stock blocks.\n4. **Imagery,** in this order of preference:\n   1. the project's own;\n   2. generated, if you have an image tool;\n   3. **real pictures of the subject's world from the open collections,** whenever an honest one\n      exists. Search them with `node <skill>/scripts/assets.mjs \"<query>\"` (Openverse, Wikimedia\n      Commons, the Art Institute of Chicago and the Met; only licences that allow commercial use, by\n      default). Search the inventory, not the category: its street in old postcards, an old map of the\n      neighbourhood, its material up close, its trade in engravings, a museum object of its kind, a\n      botanical plate, a star chart. Use them large and with intent: one archival photograph as the\n      hero, an engraving enlarged into the page's motif, the real map of the street as the contact\n      section. Look at each before choosing; `--get <ref>` downloads it into `assets/` and records\n      its source and licence, and `--credits` prints the credit line for the footer. A found picture\n      shows the world around the client and is never presented as the client's own product, room,\n      dish, person or team;\n   4. **drawn in code from the subject itself,** for what no honest picture exists of (its objects,\n      its tiles, its windows, its product's interface, made as one consistent flat graphic language in\n      the palette's real colours);\n   5. the photographs dealt on the sheet, only where an honestly generic picture fits (the sea for a\n      sea house), never as a stand-in for the subject;\n   6. type and colour alone.\n\n   When the project has footage or a real picture of its own process or product, the first screen\n   shows it, large (about 40% of the screen or more). Never write a sentence on the page about where\n   the pictures come from or what they are not (\"none of these shows our bar\"): a caption says what\n   the picture is, and the credit line sits small in the footer. A portfolio whose work is invented\n   for the brief draws each piece as a finished still of that work (its title card with its own type,\n   an end frame, a poster), with real detail, never as a pictogram of the client's product.\n\n   **The floor, which the inspector checks:** at least four real pictures on the page, usually six to\n   twelve (photographs, archival images, maps, engravings, footage, raster artwork; for software, its\n   cropped interface fragments count too). SVG drawings do not count toward the floor: draw what no\n   picture exists of, and still carry real pictures. Add one moving picture wherever an honest clip\n   exists: search it with `assets.mjs --video \"<query>\"` and use it as a muted loop with a poster\n   frame. Models skip pictures and footage because finding them is work; the page fails without them.\n\n   `references/imagery.md` covers searching, licences and credits, video, drawing, crops and treatments.\n5. **The live thing** from step 4, built into the section where it proves the claim (often the hero\n   or the booking), with real content, a thumb-sized phone version and a plain fallback.\n6. **The scroll scenes,** when the sheet deals them (section 9), each with the section it carries: the page's big\n   moments, the camera that flies through the work, the picture that opens to the whole screen, the\n   word that buckles under the scroll. Copy the shared stage and the scene's files from\n   `<skill>/assets/scenes/`, fill the scene with this project's own pictures and words, and set the\n   page's tokens so it takes the page's look. A scene is composition: it decides how long the page is\n   and what each screen shows, so it is built now and seen in every look round, not added at the end.\n   `references/scenes.md` says how to put one on a page, fill it, fit it and check it;\n   `assets/scenes/demo/<id>.html` is a working example of each.\n7. **Fullness.** Look at each desktop screen as a poster: one dominant thing and the content it\n   carries. A screen that is mostly empty ground is an underbuilt section, not a rest; one deliberate\n   rest per page is the limit, and the inspector fails a page with two or more near-empty screens.\n   Running text is in the full ink at 16px or more; grey is for secondary notes.\n8. **The frame.** The page has one pair of equal outer margins at every width, and every section uses\n   the width the page has set up: when its text sits in the left half, the right half holds its\n   picture, its second column, its list or its figure, never nothing. Asymmetry lives inside the grid,\n   never in the frame: a void is placed only when something closes it on the far side. No stretch of\n   the page taller than about half a screen holds nothing at all; sections are 120–240px apart on\n   desktop. Every section the visitor came for opens with a heading that names it, and the first\n   screen carries the page's title in an `h1`. These are what readers name first when a page looks\n   wrong (\"no clear title\", \"random empty space\", \"everything is pushed to one side\"), and the\n   inspector measures each of them.\n9. **States and semantics.** Real links and buttons, visible focus, alt text, a phone layout that is\n   its own composition.\n\nRead `references/type.md`, `references/colour.md` and `references/layout.md` when you need the detail\nbehind a decision; the laws below are the short form.\n\n### 7. Gate\n\n```bash\nnode <skill>/scripts/lint.mjs <source files or folder>\nnode <skill>/scripts/inspect.mjs <url or path/to/index.html>\nnode <skill>/scripts/scenes.mjs <url or path/to/index.html>     # when the page has scroll scenes\n```\n\n`scenes.mjs` photographs every scroll scene at 0, 10 … 100% of its hold, on desktop and on a phone,\nand the reduced-motion page; with scenes on the sheet, `inspect.mjs` also films the whole scroll\n(`desktop-film-NN.jpg`). A scene that never started or rests on desktop is a `FAIL`.\n\n`lint.mjs` scans source for banned patterns and stock phrases. `inspect.mjs` opens the page in a real\nbrowser at 1440, 768 and 390 pixels, measures it (headline line counts, type sizes, fonts actually\nloaded, colours, rules, shadows, gradients, contrast, overflow, and the frame: equal margins, sections\nhuddled on one side, blank stretches, the title, untitled sections, text against the screen edge) and\nsaves screenshots to `.taste-skill/inspect/`. Fix every `FAIL`. Treat each `WARN` as wrong unless you can defend it to a\ndesigner in one sentence. Re-run until there are no `FAIL`s. Do not argue with the meter and do not\nhide things from it. The inspector serves local files over a throwaway local server; if the page must\nalso open straight from the file system, open `index.html` that way once before you finish.\n\n### 8. Look\n\nPassing the gate means nothing banned was measured. It does not mean the page is good. Open the\nscreenshots the inspector lists (every viewport, with your image viewer or Read tool) and critique them\nwith `references/critique.md`: the fourteen passes, the Awwwards-weighted score, the caps. Write the critique\ndown in its format, fix the top three problems, run the inspector again, look again. Three rounds at\nmost.\n\nJudge only the pictures. If a problem is visible in a screenshot, it is real, whatever the code says.\n\n### 9. Move\n\nNow build the motion layer. It is required, and it is more than one fade: the inspector counts the\nelements that really move while the page loads and is scrolled, and fails a page under eight (it warns\nunder sixteen). Any scroll scenes are already built (step 6); around them the layer has four parts:\n\n1. **The signature move** named on the sheet: one, done well (a dealt scene can be it).\n2. **An entrance for the parts of every section:** the heading, then the text, then the picture,\n   staggered by 60–90ms, rising 16–32px with opacity, triggered once as the section enters. Not one\n   fade for the whole block, and never content that stays hidden if the script fails.\n3. **Feedback on every control:** press, hover and focus on buttons, links, cards and the live thing.\n4. **One moving picture:** a found clip as a muted loop, a slow scale or drift on a photograph, or a\n   scroll-linked move on the hero picture.\n\nTransform and opacity only; every move has a `prefers-reduced-motion` fallback that keeps the content\nand drops the travel. A move that changes the colour or the layout of whole screens (colour by\nchapter, a pinned story) is part of the composition, so build it in step 6 and let every look round see\nit. `references/motion.md` has the tokens and tested recipes. Then run the inspector once more and check\nevery screenshot for content that failed to appear.\n\n### 10. Report\n\nDo not report until all of these are true; each one was skipped in a test run that came out badly:\n\n- `inspect.mjs` shows **0 FAIL** at 1440, 768 and 390, on the final version of the page.\n- You opened every screenshot it listed after the last change, not only the first screen.\n- With scroll scenes: `scenes.mjs` ran on the final page with no problems, and you read every sheet\n  (desktop, phone, reduced motion).\n- A stranger reading the first screen for five seconds can say what this is and what to do.\n- Every section has a heading; the margins match on both sides; no stretch of the page is empty.\n- The critique of your last round is written down in the shape of `references/critique.md` §4.\n\nTell the user, briefly: the direction dealt (name and seed) and any redraws with reasons; the idea\nsentence and the live thing; the final scores from your last critique round and what still falls short;\nevery found picture and clip with its title, creator, licence and source page (`assets.mjs --credits` prints\nthe list) and where its credit sits on the page; which bundled photographs and which drawings stand in\nfor photography (so they can be replaced); and any sample content that must be swapped before launch.\nDo not claim a check you did not run.\n\n## House rules\n\nThese hold on every build, whatever the direction. `inspect.mjs` measures them.\n\n| Rule | Instead |\n| --- | --- |\n| **Headlines: two lines or fewer, at every width.** Every `h1`–`h6`, and the main line of the first screen whatever its tag. | Cut words. Then widen the measure. Size last. |\n| **A clear title on the first screen**, in the page's one `h1`, and a heading on every section. | Say what this is: the name with what it does, the product with what it is for, the event with its date and place. |\n| **Equal outer margins; no section huddled on one side** with the other half of the screen empty. | Close every void with something on its far side: the section's picture, a second column, a list, a figure. |\n| **No blank stretches** taller than about half a screen. | The normal section gap. A deliberate rest is a placed picture or a field of colour, once per page. |\n| **Statements are paragraphs.** An intro sentence or a quotation set large is marked up as `<p>` or `<blockquote>`, stays at statement size (36px or less on desktop, 24px on a phone) and runs to about 25 words, three lines. | Larger than that it is a headline and the two-line rule applies. In blind tests jurors read a 42px sentence over four lines as a four-line headline. |\n| **No eyebrows.** No small label above a heading, no pill badge above the headline, no \"New ·\" chip. | Put the information in the heading or the first sentence, or drop it. |\n| **No monospace** outside real code blocks. | The text face. Tabular figures where numbers align. |\n| **No index numbering.** No 01 / 02 / 03, no (001), no \"Step 2\". | Order shown by position, size, or the words. A real `<ol>` if order matters. |\n| **No thin rules.** No hairline dividers, no 1px outlined boxes, no grid lines, crosshairs or crop marks. | Space. A step in background tone. A change of scale. A filled shape. |\n| **No gradients.** Not as backgrounds, not on buttons, not in text. | Flat colour, or a real photograph. A neutral scrim under text on a photo is the one exception. |\n| **No shadows on things at rest.** No glows. | A tone step between surfaces. Shadows only on what truly floats: a menu, a dialog. |\n| **No assistant palette.** No yellow-cream ground with terracotta or rust; no violet or indigo. | The dealt palette. |\n| **No tiny uppercase letter-spaced labels.** | Sentence case at a readable size. |\n| **No icon-topped feature cards, no rows of identical cards.** | The dealt section blueprint. |\n| **No glass.** No backdrop blur panels, no floating pill navigation. | A plain bar: wordmark, a few links, one action. |\n| **No emoji, no gradient blobs, no decorative shapes, no fake dashboards of grey bars.** | A real picture, a real interface fragment, or nothing. |\n| **No styled accent word** in a headline (italic, serif, coloured, underlined). | One face, one colour. The words carry the emphasis. |\n| **Two typefaces at most,** usually one. | The dealt type system. |\n\nThree places keep their own conventions and are left alone by the inspector: real code in\n`<pre>`/`<code>` (monospace is correct there), real tables and form fields (they may have lines), and\na real interface fragment whose root carries the attribute `data-ui` (the product's own borders and\nmenus; see `references/imagery.md` §7).\n\nWhy these, honestly. Some are what the study measured: among the 247 sites, those the panel scored\n7.5 or higher used icon feature cards 1% of the time against 28% for sites under 6.5, pill badges 14%\nagainst 34%, gradients 22% against 52%, shadows 24% against 48%, tiny tracked caps 16% against 57%.\nOthers are the owner's taste and go against current gallery fashion: monospace labels, index numbers\nand hairline grids are actually *more* common on award sites than on weak ones, which is exactly why\ngenerators imitate them and why they now read as costume. They are banned here without exception.\n`references/tells.md` keeps the dated registry.\n\nRemoving ornament leaves space. Never fill it with another ornament. Fill it with scale (make the main\nthing larger), with the full content, with a picture made for this subject, or with a field of flat\ncolour. Leave it empty on purpose once per page at most.\n\n## Laws of the craft\n\nShort form. Numbers are from the study unless marked as house style.\n\n**Type**\n- Two or three sizes do the visible work: one very large, one small, nothing in between. Median\n  headline-to-body ratio on the studied sites is 4.3; the best go far beyond (largest type: median\n  8.4vw on the top sites against 5.0vw on the weak ones).\n- Display type: tracking -0.02 to -0.05em, leading 0.85–1.05. Text: 16–20px, leading 1.45–1.6,\n  45–75 characters per line.\n- Five sizes on a page is the ceiling. One family is normal (a third of the studied sites); two is the\n  limit.\n- Left-aligned by default. Centre at most one moment.\n\n**Space**\n- One grid, one pair of tight margins (16–32px), used everywhere; large things run to the edges. Text\n  blocks share two or three left edges on the whole page.\n- Asymmetry inside the grid, never in the frame: the two outer margins are equal, and an off-centre\n  heading is answered by something at the far side of the grid.\n- The gap between sections is clearly larger than any gap inside one: 120–240px on desktop (the study's median is about 240).\n- Each section has a different composition from its neighbours; none is a card grid.\n\n**Colour**\n- One ground, one ink, one accent. The accent appears on the action and perhaps one other thing.\n- Running text in the full ink. A page set in soft grey reads unfinished.\n- Surfaces are separated by a small step in tone, never by a line or a shadow.\n- A section may change the whole field colour. Nothing fades into anything.\n\n**Imagery**\n- One dominant image beats six small ones. On the top-scored sites the hero media covers at least half\n  the first screen 68% of the time.\n- Same crop ratios, same treatment, square corners unless the direction says otherwise (73% of the\n  studied sites leave media square).\n- No image is better than a placeholder, an icon, or an abstract shape. A picture drawn for this\n  subject, in its colours and with care, is better than either. A real picture of its world, found\n  and credited, is better still.\n- Every found picture is downloaded into the project, credited on the page and listed in the report.\n  None is presented as the client's own.\n- Nothing ever lies on top of a headline or a statement (the inspector fails it).\n\n**Components**\n- Buttons: flat, one fill colour, either square-cornered or fully round, decided once (top sites: 52%\n  square, 23% pill; the 9–16px \"soft\" radius is the weak-site default). Most strong heroes have no\n  button at all, or one.\n- Navigation: wordmark, three to five plain links, one action. No bar chrome.\n- The footer is a designed close, not a sitemap: on most strong sites the name returns at full width.\n\n## Special cases\n\n**An existing brand or design system.** Pass `--keep palette,type`, map the brand's colours and faces\nonto the roles, and take only composition from the draw. The house rules still apply; if the brand\nitself requires a banned device (its logo sits in a gradient, its accent is violet), keep the brand\nasset, say so in the report, and pass `--allow <rule>` to the inspector for that rule only.\n\n**Redesign, restyle or review of an existing page or app screen.**\n\n1. **Record the before.** Run the project as it is and inspect it into its own folder\n   (`inspect.mjs <url> --out .taste-skill/before`, with `--app` for an app screen) and lint its\n   source. Read the code: the framework, the styling method (Tailwind v3 or v4, CSS modules,\n   styled-components, plain CSS), the components, and what must survive: routes, forms, data,\n   behaviour, the brand's own assets.\n2. **A review stops here.** Critique the before screenshots with `references/critique.md`, list the\n   findings with the inspector's measurements, and name the three changes that would move the page\n   most.\n3. **Keep the stack, the content and what works.** No framework or styling-library migration; check the\n   dependency file before adding anything. A restyle keeps the layout and takes type, colour and\n   components from a dealt direction (`--keep` whatever the brand fixes); a redesign deals a full\n   direction and rebuilds the sections from its blueprints inside the existing components. Either way\n   proceed from step 2 of the run with the page's real content.\n4. **Order of work, biggest effect for least risk:** type (faces and scale), colour (one ground, one\n   ink, one accent), the frame (margins, section rhythm, a title on the first screen and a heading on\n   every section), states (hover, focus, loading, empty, error), then the stock components (icon\n   cards, pill badges, gradient blobs, card grids) replaced by the dealt blueprints.\n5. **Prove it.** Inspect again into `.taste-skill/after`, compare before and after at every width,\n   click through every link, form and menu that worked before, and report the before and after\n   measurements side by side.\n\n**A component or a single section, not a page.** Skip the draw unless there is no direction to follow.\nMatch the surrounding design, apply the house rules and the laws, and still inspect the result.\n\n**No checkout, no form backend.** The primary button goes to the real destination when the brief names\none. Otherwise it opens an email with a written subject and body (`mailto:` with the visitor's choices\nfilled in), or, for a shop, it points at `#checkout` and the report says it must be wired before\nlaunch. Never fake a payment form.\n\n**No Chrome or Node 22.** Run `lint.mjs` (Node 18+), take screenshots with whatever browser tool you\nhave, and critique those. Say in the report that the inspector could not run.\n\n**No network.** If `assets.mjs` reaches no source, draw the pictures and say in the report that the\nopen collections could not be searched.\n\n## Files\n\n| File | Read it when |\n| --- | --- |\n| `references/app-screens.md` | Any dashboard, admin, settings or other app screen: its own run, rules, tokens and checks. |\n| `references/copy.md` | Writing the argument and the copy deck (steps 2 and 5). The two-line arithmetic. |\n| `references/type.md` | Setting type: scales, tracking, measure, loading fonts, pairing. |\n| `references/colour.md` | Applying the palette: roles, proportions, tone steps, dark pages, contrast. |\n| `references/layout.md` | Grid, margins, rhythm, section variety, navigation, footer, the phone composition. |\n| `references/imagery.md` | Choosing, finding, crediting, cropping and treating pictures; what to do with none. |\n| `references/motion.md` | Step 9. Budget, tokens, recipes, reduced motion. |\n| `references/scenes.md` | Step 6, when the sheet deals scroll scenes: putting one on a page, filling, fitting, the phone, checking, the catalogue. |\n| `references/critique.md` | Step 8. How to look, how to score, what to fix first. |\n| `references/tells.md` | The dated registry of generated-page tells and what each is replaced by. |\n| `references/research.md` | The study: method, numbers, what the best and worst sites do. Cite it, do not guess. |\n| `scripts/draw.mjs` | Deals and reprints the direction; `--photos`, `--site <id>` for more references; `--app` deals an app style instead. |\n| `scripts/assets.mjs` | Step 6: searches open collections for real pictures of the subject's world; `--get` downloads with the credit, `--credits` prints them. |\n| `scripts/lint.mjs` · `scripts/inspect.mjs` | The gate. |\n| `scripts/scenes.mjs` | The gate for scroll scenes: each scene at 0-100% of its hold, desktop, phone, reduced motion. |\n| `assets/base.css` · `assets/base.js` | An optional neutral foundation to build on. |\n| `assets/scenes/` | The scroll scenes: the shared stage (`stage.js`, `stage.css`) and, for each scene in the library, its `.js`, `.css` and a working demo page in `demo/`. |\n| `assets/app.css` · `assets/charts.js` | For app screens: a neutral shell, panels, tables and controls, and small SVG charts drawn to the app rules. |\n| `library/` | The data the draw reads: directions, heroes, sections, type systems, palettes, photographs, studied sites, motions, scroll scenes (`scenes.json`), and the app styles, shells and screen patterns (`app.json`). Do not read it whole; use the script. |\n\n<!-- File: .agents/plugins/marketplace.json (Tokens: ~119 | Category: marketplace) -->\n{\n  \"name\": \"taste-skill\",\n  \"interface\": {\n    \"displayName\": \"Taste Skill\"\n  },\n  \"plugins\": [\n    {\n      \"name\": \"taste-skill\",\n      \"source\": {\n        \"source\": \"url\",\n        \"url\": \"https://github.com/Leonxlnx/taste-skill.git\",\n        \"ref\": \"main\"\n      },\n      \"policy\": {\n        \"installation\": \"AVAILABLE\",\n        \"authentication\": \"ON_INSTALL\"\n      },\n      \"category\": \"Design\"\n    }\n  ]\n}\n\n<!-- File: .claude-plugin/marketplace.json (Tokens: ~264 | Category: marketplace) -->\n{\n  \"name\": \"taste-skill\",\n  \"description\": \"tasteskill: art direction for coding agents, for websites, product pages, dashboards and app screens, checked in a real browser.\",\n  \"owner\": {\n    \"name\": \"leonxlnx\",\n    \"email\": \"hello@tasteskill.dev\"\n  },\n  \"plugins\": [\n    {\n      \"name\": \"taste-skill\",\n      \"description\": \"tasteskill v2: art direction for websites, product pages, dashboards and app screens, with a library of researched directions, real pictures from open collections and a real-browser inspector.\",\n      \"version\": \"2.1.4\",\n      \"source\": \"./\",\n      \"skills\": [\"./skills/taste-skill\"],\n      \"author\": {\n        \"name\": \"leonxlnx\",\n        \"email\": \"hello@tasteskill.dev\"\n      },\n      \"homepage\": \"https://github.com/Leonxlnx/taste-skill\",\n      \"repository\": \"https://github.com/Leonxlnx/taste-skill\",\n      \"license\": \"MIT\",\n      \"keywords\": [\"skills\", \"frontend\", \"design\", \"taste\", \"ui\", \"dashboard\"]\n    }\n  ]\n}\n\n<!-- File: .codex-plugin/plugin.json (Tokens: ~329 | Category: plugin-manifest) -->\n{\n  \"name\": \"taste-skill\",\n  \"version\": \"2.1.4\",\n  \"description\": \"tasteskill v2: art direction for websites, product pages, dashboards and app screens, checked in a real browser.\",\n  \"author\": {\n    \"name\": \"leonxlnx\",\n    \"url\": \"https://github.com/Leonxlnx\"\n  },\n  \"homepage\": \"https://github.com/Leonxlnx/taste-skill\",\n  \"repository\": \"https://github.com/Leonxlnx/taste-skill\",\n  \"license\": \"MIT\",\n  \"keywords\": [\n    \"skills\",\n    \"frontend\",\n    \"design\",\n    \"taste\",\n    \"ui\"\n  ],\n  \"skills\": \"./skills/\",\n  \"interface\": {\n    \"displayName\": \"Taste Skill\",\n    \"shortDescription\": \"Art direction for websites, dashboards and app screens.\",\n    \"longDescription\": \"tasteskill v2 from Leonxlnx/taste-skill: researched directions, real pictures and a real-browser inspector for websites, product pages, dashboards and app screens.\",\n    \"developerName\": \"leonxlnx\",\n    \"category\": \"Design\",\n    \"capabilities\": [],\n    \"websiteURL\": \"https://github.com/Leonxlnx/taste-skill\",\n    \"defaultPrompt\": [\n      \"Design a distinctive frontend without generic AI patterns.\",\n      \"Redesign this interface while preserving its brand.\",\n      \"Build the dashboard for this product with real data and charts.\"\n    ]\n  }\n}\n</yakaai_skills>"}