@nodaro/prompts 1.7.2 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/dist/index.cjs +5453 -4271
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +1221 -63
  4. package/dist/index.d.ts +1221 -63
  5. package/dist/index.js +5366 -4273
  6. package/dist/index.js.map +1 -1
  7. package/package.json +1 -1
  8. package/src/__tests__/b7-person-pack-e2e.test.ts +37 -0
  9. package/src/__tests__/catalog-funnel-ratchet.test.ts +97 -0
  10. package/src/__tests__/catalog-packs.test.ts +130 -0
  11. package/src/__tests__/catalog-sidecar-coverage.test.ts +27 -0
  12. package/src/__tests__/catalog-terms.test.ts +162 -0
  13. package/src/__tests__/character-default-role.test.ts +3 -2
  14. package/src/__tests__/content-free-contract.test.ts +45 -0
  15. package/src/__tests__/dod-replace-pack-acceptance.test.ts +41 -0
  16. package/src/__tests__/fixtures/parameter-hint-golden.json +2959 -0
  17. package/src/__tests__/fixtures/person-sector-pack.ts +27 -0
  18. package/src/__tests__/i18n-entry-completeness.test.ts +5 -2
  19. package/src/__tests__/parameter-hint-mode.test.ts +385 -0
  20. package/src/__tests__/parameter-prompt-hint-pack-fallback.test.ts +25 -0
  21. package/src/__tests__/person-packs.test.ts +166 -0
  22. package/src/__tests__/project-all-catalogs.test.ts +26 -0
  23. package/src/__tests__/prompt-builder.test.ts +53 -0
  24. package/src/__tests__/registered-catalogs-funnel.test.ts +30 -0
  25. package/src/__tests__/registered-catalogs-guard.test.ts +11 -0
  26. package/src/__tests__/term.test.ts +104 -0
  27. package/src/__tests__/transitions.test.ts +8 -5
  28. package/src/__tests__/upstream-immutability.test.ts +23 -0
  29. package/src/action-fx.ts +67 -17
  30. package/src/aesthetic.ts +54 -6
  31. package/src/atmosphere.ts +64 -23
  32. package/src/backdrop.ts +44 -30
  33. package/src/camera-format.ts +33 -11
  34. package/src/camera-motions.ts +89 -0
  35. package/src/catalog-packs.ts +125 -0
  36. package/src/catalog-sidecar-coverage.ts +36 -0
  37. package/src/character-fx.ts +112 -39
  38. package/src/color-look.ts +44 -27
  39. package/src/composition-effects.ts +21 -7
  40. package/src/era.ts +24 -0
  41. package/src/exposure-settings.ts +76 -18
  42. package/src/framing.ts +100 -0
  43. package/src/held-prop.ts +125 -63
  44. package/src/identity-lock.ts +12 -5
  45. package/src/image-reference-doctrine.ts +55 -0
  46. package/src/index.ts +6 -0
  47. package/src/instrumentation.ts +148 -57
  48. package/src/lens.ts +31 -15
  49. package/src/lighting.ts +120 -59
  50. package/src/loop-subject.ts +27 -1
  51. package/src/materials.ts +123 -69
  52. package/src/mood.ts +123 -51
  53. package/src/music-genre.ts +171 -67
  54. package/src/music-mood.ts +85 -17
  55. package/src/parameter-prompt-hint.ts +168 -56
  56. package/src/person-packs.ts +182 -0
  57. package/src/person.ts +506 -408
  58. package/src/photo-genre.ts +37 -22
  59. package/src/photographer.ts +138 -1
  60. package/src/picker-catalogs.ts +86 -40
  61. package/src/picker-wiring.ts +1 -1
  62. package/src/pose.ts +105 -40
  63. package/src/post-process-effects.ts +51 -8
  64. package/src/prompt-builder.ts +16 -1
  65. package/src/provider-prompt-doctrine.ts +1 -2
  66. package/src/render-quality.ts +25 -7
  67. package/src/setting.ts +30 -14
  68. package/src/style-presets.ts +1 -1
  69. package/src/style.ts +33 -15
  70. package/src/styling.ts +155 -94
  71. package/src/surround-fill.ts +67 -0
  72. package/src/temporal.ts +80 -18
  73. package/src/term.ts +155 -0
  74. package/src/transitions.ts +73 -26
  75. package/src/voice-character.ts +190 -90
  76. package/src/voice-delivery.ts +83 -12
@@ -27,6 +27,8 @@
27
27
  * and the backend orchestrator.
28
28
  */
29
29
 
30
+ import { resolveTerm } from "./term.js"
31
+
30
32
  export type PhotoGenreCategory =
31
33
  | "editorial"
32
34
  | "documentary"
@@ -42,21 +44,29 @@ export interface PhotoGenre {
42
44
  readonly category: PhotoGenreCategory
43
45
  readonly description: string
44
46
  readonly promptHint: string
47
+ /**
48
+ * Compact professional term (see `term.ts`). Authored only where the
49
+ * lowercased label is not what a photographer would write in a prompt —
50
+ * UI compounds ("Campaign / Ad"), the "Signature" brand framing, and bare
51
+ * nouns that read as the SUBJECT rather than the genre ("documentary",
52
+ * "real estate", "advertising"). Elsewhere the label IS the term.
53
+ */
54
+ readonly term?: string
45
55
  }
46
56
 
47
57
  export const PHOTO_GENRES: ReadonlyArray<PhotoGenre> = [
48
58
  // -------------------- Editorial / Fashion --------------------
49
59
  { id: "fashion-editorial", label: "Fashion Editorial", category: "editorial", description: "High-fashion magazine spread", promptHint: "shot as a high-fashion magazine editorial, polished studio lighting, deliberate posing, designer wardrobe, full-bleed composition with strong color blocking and a glossy print-ready finish" },
50
60
  { id: "vogue-editorial", label: "Vogue Editorial", category: "editorial", description: "Vogue-style cover editorial", promptHint: "shot in the language of a Vogue editorial cover, dramatic single-source lighting, couture wardrobe, confident direct-camera gaze and clean negative space sized for a glossy magazine cover" },
51
- { id: "magazine-cover", label: "Magazine Cover", category: "editorial", description: "Tightly framed cover composition", promptHint: "framed as a magazine cover with a tight head-and-shoulders composition, strong eye contact with the lens, generous headroom for a masthead and a saturated punchy color grade" },
61
+ { id: "magazine-cover", label: "Magazine Cover", category: "editorial", description: "Tightly framed cover composition", term: "magazine cover photography", promptHint: "framed as a magazine cover with a tight head-and-shoulders composition, strong eye contact with the lens, generous headroom for a masthead and a saturated punchy color grade" },
52
62
  { id: "lookbook", label: "Lookbook", category: "editorial", description: "Clean lookbook outfit shot", promptHint: "shot as a brand lookbook image, full-body framing, neutral seamless backdrop, soft even studio lighting and subdued styling that lets the wardrobe read clearly" },
53
63
  { id: "ecommerce-flatlay", label: "E-commerce Flat Lay", category: "editorial", description: "Overhead product flat lay", promptHint: "composed as a top-down e-commerce flat lay with even shadowless studio lighting, a clean white surface and the subject arranged neatly within the frame for catalog use" },
54
64
  { id: "beauty-editorial", label: "Beauty Editorial", category: "editorial", description: "Macro beauty / skincare close-up", promptHint: "shot as a beauty editorial close-up, ring-lit with a soft glowing key, hyper-detailed skin texture, glossy lips, defined brows and a clean cosmetic palette" },
55
- { id: "campaign-advertising", label: "Campaign / Ad", category: "editorial", description: "Polished brand campaign image", promptHint: "shot as a polished brand campaign image, bold visual hook, strong product or wardrobe presence and an aspirational lighting setup designed to read on a billboard" },
65
+ { id: "campaign-advertising", label: "Campaign / Ad", category: "editorial", description: "Polished brand campaign image", term: "brand campaign photography", promptHint: "shot as a polished brand campaign image, bold visual hook, strong product or wardrobe presence and an aspirational lighting setup designed to read on a billboard" },
56
66
 
57
67
  // -------------------- Brand / Editorial Reference --------------------
58
- { id: "brand-vogue", label: "Vogue Signature", category: "editorial", description: "Vogue magazine editorial signature", promptHint: "shot in the signature language of a Vogue magazine editorial, clean polished beauty lighting, glossy makeup, sculpted hair and a wardrobe of polished glamour, with the controlled high-fashion sheen unique to Vogue's print pages" },
59
- { id: "brand-dior", label: "Dior Signature", category: "editorial", description: "Dior editorial — chiaroscuro and silhouette", promptHint: "shot in the signature language of a Dior editorial, dramatic chiaroscuro carving the subject from deep shadow, a sculptural couture silhouette and the brand's restrained Parisian elegance" },
68
+ { id: "brand-vogue", label: "Vogue Signature", category: "editorial", description: "Vogue magazine editorial signature", term: "vogue magazine editorial style", promptHint: "shot in the signature language of a Vogue magazine editorial, clean polished beauty lighting, glossy makeup, sculpted hair and a wardrobe of polished glamour, with the controlled high-fashion sheen unique to Vogue's print pages" },
69
+ { id: "brand-dior", label: "Dior Signature", category: "editorial", description: "Dior editorial — chiaroscuro and silhouette", term: "dior editorial style", promptHint: "shot in the signature language of a Dior editorial, dramatic chiaroscuro carving the subject from deep shadow, a sculptural couture silhouette and the brand's restrained Parisian elegance" },
60
70
  { id: "brand-jil-sander", label: "Jil Sander Minimalism", category: "editorial", description: "Jil Sander — minimalist architectural muted", promptHint: "shot in the language of a Jil Sander editorial, minimalist composition, muted ecru and stone palette, architectural wardrobe with clean unbroken lines and the brand's quiet austere mood" },
61
71
  { id: "brand-vivienne-tam", label: "Vivienne Tam Style", category: "editorial", description: "Vivienne Tam — orientalist ornate fashion", promptHint: "shot in the language of a Vivienne Tam editorial, orientalist motifs and dragon embroidery, ornate East-Asian fashion detailing and a saturated jewel-toned palette" },
62
72
  { id: "brand-jacquemus", label: "Jacquemus Style", category: "editorial", description: "Jacquemus — sun-soaked surrealist playful", promptHint: "shot in the language of a Jacquemus campaign, sun-soaked Mediterranean light, surrealist scale play with oversized hats and miniature bags, terracotta and ochre palette and a playful French Riviera mood" },
@@ -64,18 +74,18 @@ export const PHOTO_GENRES: ReadonlyArray<PhotoGenre> = [
64
74
  { id: "brand-harpers-bazaar", label: "Harper's Bazaar Style", category: "editorial", description: "Harper's Bazaar — high-fashion glossy", promptHint: "shot in the signature language of a Harper's Bazaar editorial, high-fashion glossy production, bold graphic backdrops, dramatic single-source key light and the brand's distinctively confident composition" },
65
75
 
66
76
  // -------------------- Documentary / Candid --------------------
67
- { id: "paparazzi", label: "Paparazzi", category: "documentary", description: "Flash-blown tabloid candid", promptHint: "shot as a paparazzi tabloid candid, harsh on-camera flash blowing out the highlights, slight motion blur, low candid angle, blurred crowd in the background and grainy cropped tabloid framing" },
77
+ { id: "paparazzi", label: "Paparazzi", category: "documentary", description: "Flash-blown tabloid candid", term: "paparazzi flash candid", promptHint: "shot as a paparazzi tabloid candid, harsh on-camera flash blowing out the highlights, slight motion blur, low candid angle, blurred crowd in the background and grainy cropped tabloid framing" },
68
78
  { id: "street-photography", label: "Street Photography", category: "documentary", description: "Unposed urban street frame", promptHint: "shot in a street-photography idiom, available light, mid-stride candid moment, busy city background slightly out of focus and a grainy 35mm reportage feel" },
69
- { id: "candid-journalism", label: "Candid Journalism", category: "documentary", description: "Unposed photojournalist moment", promptHint: "captured as candid photojournalism, unposed expression, naturalistic available light, slightly off-balance composition and a documentary honesty rather than glamour" },
79
+ { id: "candid-journalism", label: "Candid Journalism", category: "documentary", description: "Unposed photojournalist moment", term: "candid photojournalism", promptHint: "captured as candid photojournalism, unposed expression, naturalistic available light, slightly off-balance composition and a documentary honesty rather than glamour" },
70
80
  { id: "photojournalism", label: "Photojournalism", category: "documentary", description: "Editorial news-grade reportage", promptHint: "shot as editorial photojournalism with a 35mm reportage lens, faithful natural lighting, the subject reacting to events outside the frame and a wire-service caption-ready composition" },
71
- { id: "documentary", label: "Documentary", category: "documentary", description: "Long-form documentary portrait", promptHint: "shot in a long-form documentary portrait style, soft window light, subject lightly aware of the camera, environmental context behind them and an unhurried observational tone" },
72
- { id: "snapshot", label: "Snapshot", category: "documentary", description: "Casual amateur snapshot", promptHint: "shot as a casual amateur snapshot with on-camera flash, slightly wonky framing, ordinary domestic background and the warmth of an unposed personal moment" },
81
+ { id: "documentary", label: "Documentary", category: "documentary", description: "Long-form documentary portrait", term: "documentary portrait", promptHint: "shot in a long-form documentary portrait style, soft window light, subject lightly aware of the camera, environmental context behind them and an unhurried observational tone" },
82
+ { id: "snapshot", label: "Snapshot", category: "documentary", description: "Casual amateur snapshot", term: "casual amateur snapshot", promptHint: "shot as a casual amateur snapshot with on-camera flash, slightly wonky framing, ordinary domestic background and the warmth of an unposed personal moment" },
73
83
 
74
84
  // -------------------- Studio / Formal --------------------
75
85
  { id: "corporate-headshot", label: "Corporate Headshot", category: "studio-formal", description: "Linkedin-style headshot", promptHint: "shot as a polished corporate headshot, soft three-point studio lighting, blurred neutral office or grey backdrop, professional wardrobe and a confident closed-mouth smile" },
76
- { id: "personal-branding", label: "Personal Branding", category: "studio-formal", description: "Modern personal-brand portrait", promptHint: "shot as a modern personal-branding portrait, warm soft key light, lifestyle environment lightly blurred behind the subject and a relaxed open expression" },
77
- { id: "yearbook", label: "Yearbook", category: "studio-formal", description: "School yearbook portrait", promptHint: "shot as a school yearbook portrait with even soft front lighting, a graduated grey or marbled studio backdrop and a closed-mouth posed smile centered in the frame" },
78
- { id: "id-passport", label: "ID / Passport", category: "studio-formal", description: "Regulation passport photo", promptHint: "shot as a regulation passport photograph, dead-center face, neutral expression, plain off-white backdrop, even flat front lighting and no shadows under the chin" },
86
+ { id: "personal-branding", label: "Personal Branding", category: "studio-formal", description: "Modern personal-brand portrait", term: "personal branding portrait", promptHint: "shot as a modern personal-branding portrait, warm soft key light, lifestyle environment lightly blurred behind the subject and a relaxed open expression" },
87
+ { id: "yearbook", label: "Yearbook", category: "studio-formal", description: "School yearbook portrait", term: "yearbook portrait", promptHint: "shot as a school yearbook portrait with even soft front lighting, a graduated grey or marbled studio backdrop and a closed-mouth posed smile centered in the frame" },
88
+ { id: "id-passport", label: "ID / Passport", category: "studio-formal", description: "Regulation passport photo", term: "passport photo", promptHint: "shot as a regulation passport photograph, dead-center face, neutral expression, plain off-white backdrop, even flat front lighting and no shadows under the chin" },
79
89
  { id: "mugshot", label: "Mugshot", category: "studio-formal", description: "Police booking-style portrait", promptHint: "shot as a police booking mugshot, harsh fluorescent overhead lighting, height chart on the wall behind, dead-square frontal framing and a flat institutional color cast" },
80
90
  { id: "wedding-portrait", label: "Wedding Portrait", category: "studio-formal", description: "Romantic bridal-style portrait", promptHint: "shot as a wedding portrait, soft golden-hour backlight, romantic shallow depth of field, dreamy pastel color grade and an intimate posed embrace or solo bridal stance" },
81
91
  { id: "family-portrait", label: "Family Portrait", category: "studio-formal", description: "Posed family group shot", promptHint: "shot as a posed family portrait, warm even studio lighting, neutral backdrop, coordinated wardrobe and the group arranged in a balanced pyramid composition" },
@@ -85,24 +95,24 @@ export const PHOTO_GENRES: ReadonlyArray<PhotoGenre> = [
85
95
  // -------------------- Selfie sub-types --------------------
86
96
  { id: "mirror-selfie", label: "Mirror Selfie", category: "selfie", description: "Phone-in-mirror full-body selfie", promptHint: "shot as a smartphone mirror selfie, the phone visible in one raised hand reflected in the mirror, full or three-quarter body framing, a domestic bedroom or bathroom background and natural ambient light" },
87
97
  { id: "gym-mirror-selfie", label: "Gym Mirror Selfie", category: "selfie", description: "Locker-room gym mirror selfie", promptHint: "shot as a gym mirror selfie, three-quarter side-back angle reflected in a wall-length gym mirror, phone clearly raised in one hand, fitness wardrobe, busy weight-rack background and bright overhead gym lighting" },
88
- { id: "front-cam-selfie", label: "Front Cam Selfie", category: "selfie", description: "Arm-extended front camera selfie", promptHint: "shot as a front-camera selfie taken at arm's length, the lens slightly above the subject's eye line, soft ambient lighting, natural skin texture and the casual intimacy of a phone-held self portrait" },
98
+ { id: "front-cam-selfie", label: "Front Cam Selfie", category: "selfie", description: "Arm-extended front camera selfie", term: "front-camera selfie", promptHint: "shot as a front-camera selfie taken at arm's length, the lens slightly above the subject's eye line, soft ambient lighting, natural skin texture and the casual intimacy of a phone-held self portrait" },
89
99
  { id: "bathroom-mirror-selfie", label: "Bathroom Mirror Selfie", category: "selfie", description: "Bathroom-mirror selfie with flash", promptHint: "shot as a bathroom mirror selfie with a small on-phone flash kicking off the glass, tiled walls and a sink or shelf in frame, casual outfit and the slightly unfocused intimacy of a private moment" },
90
- { id: "bereal-dual", label: "BeReal Dual", category: "selfie", description: "Front+back simultaneous dual frame", promptHint: "framed as a BeReal-style dual capture with a small inset front-camera selfie tucked in the corner of a wider rear-camera environmental shot, casual unstaged moment and slightly soft phone-camera quality" },
91
- { id: "flip-cam-selfie", label: "Flip-Cam Selfie", category: "selfie", description: "Accidental low-quality flip cam", promptHint: "shot as an accidental flip-cam selfie, low-resolution camcorder feel, harsh on-board video light, off-center framing and a candid ordinary expression caught mid-thought" },
100
+ { id: "bereal-dual", label: "BeReal Dual", category: "selfie", description: "Front+back simultaneous dual frame", term: "bereal dual-camera capture", promptHint: "framed as a BeReal-style dual capture with a small inset front-camera selfie tucked in the corner of a wider rear-camera environmental shot, casual unstaged moment and slightly soft phone-camera quality" },
101
+ { id: "flip-cam-selfie", label: "Flip-Cam Selfie", category: "selfie", description: "Accidental low-quality flip cam", term: "lo-fi camcorder selfie", promptHint: "shot as an accidental flip-cam selfie, low-resolution camcorder feel, harsh on-board video light, off-center framing and a candid ordinary expression caught mid-thought" },
92
102
  { id: "group-selfie", label: "Group Selfie", category: "selfie", description: "Multiple-subject phone selfie", promptHint: "shot as a group phone selfie taken at arm's length, several faces clustered into the frame, one arm visibly extended holding the phone and a bright shared moment with cheerful expressions" },
93
- { id: "lofi-baddie-selfie", label: "Lo-Fi 2010s Selfie", category: "selfie", description: "Early-iPhone low-light selfie", promptHint: "shot as a lo-fi 2010s iPhone selfie with grainy low-light noise, slight green-yellow color cast, mirror reflection of an early-era phone and the unpolished aesthetic of an early-Instagram baddie post" },
103
+ { id: "lofi-baddie-selfie", label: "Lo-Fi 2010s Selfie", category: "selfie", description: "Early-iPhone low-light selfie", term: "lo-fi 2010s iphone selfie", promptHint: "shot as a lo-fi 2010s iPhone selfie with grainy low-light noise, slight green-yellow color cast, mirror reflection of an early-era phone and the unpolished aesthetic of an early-Instagram baddie post" },
94
104
 
95
105
  // -------------------- Print / Context --------------------
96
- { id: "album-cover", label: "Album Cover", category: "print-context", description: "Square album cover composition", promptHint: "composed as a square album cover, bold central subject, dramatic single-color or saturated graphic backdrop, deliberate negative space for an artist title and a stylized lighting setup" },
97
- { id: "movie-poster", label: "Movie Poster", category: "print-context", description: "Cinematic theatrical poster", promptHint: "composed as a theatrical movie poster, dramatic key art lighting, layered subjects in a dynamic composition, a cinematic teal-and-orange color grade and clear space along the bottom for credits" },
98
- { id: "advertising", label: "Advertising", category: "print-context", description: "Glossy ad-campaign photograph", promptHint: "shot as a glossy advertising photograph, hyper-clean studio lighting, idealized colors, the product or wardrobe positioned as the visual hero and a print-ready composition with copy space" },
106
+ { id: "album-cover", label: "Album Cover", category: "print-context", description: "Square album cover composition", term: "album cover photography", promptHint: "composed as a square album cover, bold central subject, dramatic single-color or saturated graphic backdrop, deliberate negative space for an artist title and a stylized lighting setup" },
107
+ { id: "movie-poster", label: "Movie Poster", category: "print-context", description: "Cinematic theatrical poster", term: "movie poster key art", promptHint: "composed as a theatrical movie poster, dramatic key art lighting, layered subjects in a dynamic composition, a cinematic teal-and-orange color grade and clear space along the bottom for credits" },
108
+ { id: "advertising", label: "Advertising", category: "print-context", description: "Glossy ad-campaign photograph", term: "glossy advertising photography", promptHint: "shot as a glossy advertising photograph, hyper-clean studio lighting, idealized colors, the product or wardrobe positioned as the visual hero and a print-ready composition with copy space" },
99
109
  { id: "food-photography", label: "Food Photography", category: "print-context", description: "Overhead or 45-degree food shot", promptHint: "shot as professional food photography, soft window-style key light, a 45-degree or overhead angle, glossy fresh ingredients in shallow focus and a styled rustic surface beneath" },
100
- { id: "real-estate", label: "Real Estate", category: "print-context", description: "Wide architectural interior", promptHint: "shot as a wide-angle real-estate listing photograph, ultra-wide lens emphasizing space, neutral white-balanced light, all rooms tidied to perfection and clean horizontal/vertical lines" },
101
- { id: "sports-action", label: "Sports Action", category: "print-context", description: "Telephoto frozen sports moment", promptHint: "shot as a telephoto sports-action photograph, frozen peak-action moment, blurred crowd background, dramatic stadium lighting and a slightly desaturated press-photo grade" },
110
+ { id: "real-estate", label: "Real Estate", category: "print-context", description: "Wide architectural interior", term: "real estate listing photography", promptHint: "shot as a wide-angle real-estate listing photograph, ultra-wide lens emphasizing space, neutral white-balanced light, all rooms tidied to perfection and clean horizontal/vertical lines" },
111
+ { id: "sports-action", label: "Sports Action", category: "print-context", description: "Telephoto frozen sports moment", term: "sports action photography", promptHint: "shot as a telephoto sports-action photograph, frozen peak-action moment, blurred crowd background, dramatic stadium lighting and a slightly desaturated press-photo grade" },
102
112
 
103
113
  // -------------------- Lifestyle --------------------
104
- { id: "point-and-shoot", label: "Point-and-Shoot / Disposable", category: "lifestyle", description: "Disposable / P&S casual aesthetic", promptHint: "shot in a point-and-shoot disposable-camera aesthetic, harsh on-camera flash blowing out the foreground, slight motion blur, casual unposed framing and the warm grainy quality of a single-use 35mm camera" },
105
- { id: "lifestyle-blog", label: "Lifestyle Blog", category: "lifestyle", description: "Soft natural-light home blogger feel", promptHint: "shot as a lifestyle-blog image, soft natural window light, cozy home or coffee morning-routine setting, gentle pastel color grade and the airy aspirational warmth of an instagram-blogger feed" },
114
+ { id: "point-and-shoot", label: "Point-and-Shoot / Disposable", category: "lifestyle", description: "Disposable / P&S casual aesthetic", term: "point-and-shoot disposable camera snapshot", promptHint: "shot in a point-and-shoot disposable-camera aesthetic, harsh on-camera flash blowing out the foreground, slight motion blur, casual unposed framing and the warm grainy quality of a single-use 35mm camera" },
115
+ { id: "lifestyle-blog", label: "Lifestyle Blog", category: "lifestyle", description: "Soft natural-light home blogger feel", term: "lifestyle blog photography", promptHint: "shot as a lifestyle-blog image, soft natural window light, cozy home or coffee morning-routine setting, gentle pastel color grade and the airy aspirational warmth of an instagram-blogger feed" },
106
116
 
107
117
  // -------------------- Commercial --------------------
108
118
  { id: "product-shot", label: "Product Shot", category: "commercial", description: "Clean isolated e-commerce product", promptHint: "shot as a clean e-commerce product photograph, the subject isolated on a neutral seamless background, even shadowless studio lighting and a sharp catalog-ready composition" },
@@ -128,6 +138,11 @@ export function getPhotoGenrePromptHint(id: string | undefined | null): string {
128
138
  return getPhotoGenre(id)?.promptHint ?? ""
129
139
  }
130
140
 
141
+ /** Compact-mode sibling of `getPhotoGenrePromptHint` — the short trade term. */
142
+ export function getPhotoGenreTerm(id: string | undefined | null): string {
143
+ return resolveTerm(getPhotoGenre(id))
144
+ }
145
+
131
146
  export const PHOTO_GENRE_IDS: ReadonlyArray<string> = PHOTO_GENRES.map((p) => p.id)
132
147
 
133
148
  export const PHOTO_GENRE_CATEGORY_LABELS: Readonly<Record<PhotoGenreCategory, string>> = {