- Shipped
- September 17, 2026 at 12:47 AM UTC
- Author
- Kamo
- Commit
- d2431c5
Behavior & Labeling gains a Lifestyle Logo slot beside the full logo, the simple logo and the tab icon, in both the company and the software (white-label) rows. It takes pixel artwork and vectors alike: an SVG or a raster is kept exactly as picked, an EPS/AI/PDF is converted on the way in (no browser can draw one), and a raster offers "Convert to vector", which opens the shared ImageToSVGConverter only when the member asks. Like the tab icon, each slot has a switch (an upload turns it on, server-side too) and a caption that says what a lifestyle surface will actually draw, from the unsaved form. The lifestyle logo defaults to the full logo when not set. For each brand, resolveLogoVariant in theme/brand.ts is the chain: the software lifestyle logo when in use, else the software full logo when it overrides the company one, else the company lifestyle logo when in use, else the company full logo. lifestyleLogo.ts states the same chain as captions; a test runs both over all 32 form states. Background Watermark offers Lifestyle Logo first, and it is the default: null and unknown values resolve to LIFESTYLE, which draws the full logo until a lifestyle logo exists, so no org's watermark changes until it uploads one. Every place that paints the watermark (BackgroundWatermark, Backdrop, the error and not-found pages) now goes through resolveWatermarkVariant / watermarkLogoFile. - /network/create: a Lifestyle logo group with the same intake, uploaded after the org exists as type=lifestyle; the watermark picker offers Lifestyle first and the form defaults to it. - Setup wizard: Logos gets company and white-label lifestyle slots (showing the live one when in use), Backgrounds offers the Lifestyle watermark, and orgDetails resolves the default the same way. - The org route's schema reads bgWatermark as a plain string. It .parse()s, so the old ["NONE","FULL","SIMPLE"] enum would have thrown on the whole org record for a LIFESTYLE row; Organization.fromJSON resolves unknown values instead. The four lifestyle fields ride the org record through OrgContext, and DynamicMetaLoader keeps **************** from config.json. Needs kamo-shared-library f22a867d and securityservice's upload types (pushed first), and the dictionary keys (pushed first, in every locale).