# Callout guide ## The rules that make a callout graphic readable 1. Leaders never cross each other. `add-callouts.mjs` refuses to write the image if two cross. 2. Leaders cross the product as little as possible: choose the pose so features face the empty backdrop, put labels in the backdrop (above, below, or inside the headband arch), and approach each dot from outside: a line should start in open backdrop and enter the product only for the last stretch. 3. Each label sits on the same side as its target. A feature on the left of the product gets a label on the left. 4. Sort callouts top to bottom on each side in the same order as their targets, so lines fan out and do not twist. 5. A leader is at most about 35 percent of the image width. If it is longer, move the label closer. 6. Put the dot on the near edge of the feature (the edge nearest the label), on the feature itself, never on a blank bevel or a hole next to it. 7. The leader leaves the rule under (or over) the label at the point nearest the target; the rule sits on the side of the text that faces the dot, so the line never runs through words. 8. Keep labels 5 percent clear of every edge and off the product. 9. Before returning: trace each line from label to dot with your eye. No two intersect, none crosses text, each ends on its feature. ## Worked example Bad (the first sample): headphones photographed in one three-quarter pose, labels in the four corners. The "Active noise cancelling" line ran about 520 px across the headband and a cup, the cushions line crossed the headband, and two dots landed on bare bevel and a tiny hole. Good (the current sample): the headphones are turned about 25 degrees, so the left cushion and the right cup's control tab and port face the viewer. "Memory-foam cushions" is bottom left with a 210 px straight line up to the cushion's lower rim. "USB-C fast charge" (about 390 px) and "40 h battery" (about 280 px) sit below with lines that do not cross. "Active noise cancelling" sits in the empty headband arch with a 270 px vertical line down to the tab on the right cup, entering the product only for the last 110 px. The longest leader is about 24 percent of the width and every line starts in open backdrop. ## How many callouts | Count | Layout | Use when | |---|---|---| | 3 | Two on one side, one on the other, or one above and two below | A simple product with three clear wins | | 4 | Two below, one in the arch or backdrop, one beside (the sample) | The default | | 5 | Three on one side, two on the other, stagger the heights | A feature-rich product; keep labels to 3 words | | 6 | Three a side | Only if the product is large and every point is on a different part | Fewer than 3 is a caption. More than 6 is a spec sheet: split it into two graphics. ## Writing labels - 2 to 4 words, sentence case, no full stops. Lead with the number when there is one: "40 h battery". - Use only what the person supplied. A feature with no visible part (battery life, waterproofing) points at the most plausible body part and says nothing more. - One optional `detail` line (about 5 words) under a label. Leave it off unless the person gave the words. - Same grammar for all labels. ## Measuring targets Run `node scripts/add-callouts.mjs --input hero.jpg --spec callouts.json --grid --output grid.png`. It draws a cyan 10 percent grid labelled 0.1 to 0.9. Target and label positions are fractions of the full hero photo (targets) or of the output crop (labels). View grid.png, read the fraction of each feature, enter it, then render without `--grid` and check the dot is on the feature. ## Product types | Product | Pose for the hero (`--pose`) | Targets | |---|---|---| | Headphones, speakers, tech | upright, front view turned 25 degrees so one cushion face and the other cup's controls show | buttons, ports, cushions, grille | | Bottles, jars, skincare | standing upright, front facing, slight 10 degree turn | cap, label, pump, base | | Shoes | side profile, toe pointing left, floating a little | sole, upper, laces, heel | | Bags, luggage | standing three-quarter, front pocket facing | zip, strap, pocket, wheels | | Appliances, tools | three-quarter from the front, on the floor with a soft shadow | controls, lid, tank, cable | | Wearables, watches | face on, slight angle | dial, crown, strap, clasp | A long thin product (pen, knife) should fill 78 percent of the width and sit diagonal. Very dark products need a light backdrop; very pale ones a mid-grey backdrop. Tall products (bottles) work best as 4:5 with labels left and right; wide ones (shoes) as 1:1 with labels above and below. ## Brand colour and fonts Set `style.accent` to the brand hex. Keep `ink` dark (#1B1B1D) on a light backdrop; on a dark backdrop set `ink` to near white and `line` to light grey. Check the accent against the backdrop for contrast. Fonts are not embedded. The script asks for Helvetica Neue, Helvetica, Arial, Liberation Sans, DejaVu Sans, then the system sans-serif; the first installed one is used, so widths differ slightly between machines. Set `style.font` to override. If text renders oddly on a machine without any of them, install Liberation Sans or DejaVu Sans. ## Crops `style.crop` holds [left, top, width, height] as fractions of the hero for each format. The output is the crop at native pixels, so the default portrait (the whole 1600 x 2000 hero) and square ([0, 0.12, 1, 0.8], 1600 x 1600) never upscale. A tighter crop is allowed but lowers the output size (for example 0.8 wide gives 1280 px); do not go below 0.66 of the hero on either side or the result is too small. The portrait crop must stay 4:5 and the square 1:1; the script warns when it does not. ## Failure modes - Model changed the product (extra buttons, different logo): retry with "unchanged" stressed, or lower the share. - Lens flare or hot spot in the backdrop: add "even backdrop, no flare" and retry, or crop it out. - A feature you need is hidden: change `--pose` so it faces the camera. - Dot misses the feature: you measured on the wrong image. Target fractions are of the full hero, not of a crop.