@maccesar/titools 2.9.0 → 2.10.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maccesar/titools",
3
- "version": "2.9.0",
3
+ "version": "2.10.0",
4
4
  "description": "Titanium SDK skills and agents for AI coding assistants (Claude Code, Gemini CLI, Codex CLI)",
5
5
  "main": "lib/index.js",
6
6
  "type": "module",
@@ -112,13 +112,23 @@ purgetss create 'MyApp' -d -v fa
112
112
  # -v: Copy icon fonts (fa, mi, ms, f7)
113
113
  ```
114
114
 
115
- ## What's New in v7.6.0
115
+ ## What's New in v7.7.0
116
116
 
117
- - `brand` commandcomplete Titanium branding set (launcher icons, adaptive, iOS 18+ Dark/Tinted, marketplace) from logos in `./purgetss/brand/`
118
- - `images` command multi-density UI images (Android res-*dpi + iPhone @1x/@2x/@3x) from `./purgetss/images/`
119
- - `semantic` command Titanium semantic colors for Light/Dark mode (palette mode + single mode)
120
- - `brand:` and `images:` config sections auto-injected into older configs
121
- - Percentages as strings (`'15%'`) for self-documenting clarity in brand/images configs
117
+ - `brand:` config restructured flat keys replaced by purpose-based groups: `brand.logos`, `brand.padding`, `brand.android`, `brand.ios`, `brand.colors`
118
+ - Separate Android brand inputs — `logos.androidLauncher` / `--icon-logo` for Android launcher icons; `logos.androidSplash` / `--splash-logo` for Android 12+ splash artwork. Drop `logo-icon.*` and `logo-splash.*` into `purgetss/brand/`
119
+ - `--android-adaptive-padding` (default `19%`) and `--android-legacy-padding` (default `10%`) replace the single `--padding`. The shortcut `--padding` now sets both Android paddings to the same value for one run
120
+ - Legacy Android splash fallback regenerated — `app/assets/android/default.png` (Alloy) or `Resources/android/default.png` (Classic). `cleanup-legacy` no longer removes `default.png`
121
+ - New official doc: [Values and Units](references/values-and-units.md) — explains `ti.ui.defaultunit` interpretation of PurgeTSS unitless values
122
+
123
+ ## What's New in v7.6.x
124
+
125
+ - `brand` command — complete Titanium branding set (launcher icons, adaptive, iOS 18+ Dark/Tinted, marketplace) from logos in `./purgetss/brand/` (v7.6.0)
126
+ - `images` command — multi-density UI images (Android res-*dpi + iPhone @1x/@2x/@3x) from `./purgetss/images/` (v7.6.0)
127
+ - `semantic` command — Titanium semantic colors for Light/Dark mode (palette mode + single mode) (v7.6.0)
128
+ - `brand:` and `images:` config sections auto-injected into older configs (v7.6.0)
129
+ - Percentages as strings (`'15%'`) for self-documenting clarity in brand/images configs (v7.6.0)
130
+ - Confirmation prompt for destructive writes in `brand` / `images` (`y` / `N` / `a`); auto-skipped on non-TTY, with `-y`, or `PURGETSS_YES=1` (v7.6.1)
131
+ - `semantic` command works in Classic projects — writes to `Resources/semantic.colors.json` (v7.6.2)
122
132
 
123
133
  ## What's New in v7.5.3
124
134
 
@@ -401,6 +411,7 @@ purgetss create 'MyApp' -d -v fa
401
411
  > - [Installation & Setup](references/installation-setup.md) - First run, VS Code, LiveView
402
412
  > - [CLI Commands](references/cli-commands.md) - All `purgetss` commands
403
413
  > - [Migration Guide](references/migration-guide.md) - Migrating existing apps from manual TSS to PurgeTSS
414
+ > - **[Values and Units](references/values-and-units.md)** - How `ti.ui.defaultunit` in `tiapp.xml` interprets the unitless numeric values PurgeTSS writes (foundational concept for spacing, sizes, typography)
404
415
  >
405
416
  > ### Customization
406
417
  > - [Deep Customization](references/customization-deep-dive.md) - config.cjs, colors, spacing, Ti Elements
@@ -1,6 +1,6 @@
1
1
  # App Icons & Branding
2
2
 
3
- The `purgetss brand` command (shipped in PurgeTSS v7.6.0) generates the complete Titanium branding set from a single SVG or PNG logo: launcher icons across every Android density, the adaptive-icon trio (foreground + background + monochrome), iOS 18+ Dark and Tinted variants, marketplace artwork, and optional notification/splash icons. Alloy and Classic layouts are auto-detected.
3
+ The `purgetss brand` command (introduced in PurgeTSS v7.6.0, restructured in v7.7.0) generates the complete Titanium branding set from a single SVG or PNG logo — with optional Android-specific overrides when you need them: launcher icons across every Android density, the adaptive-icon trio (foreground + background + monochrome), iOS 18+ Dark and Tinted variants, marketplace artwork, and optional notification/splash icons. Alloy and Classic layouts are auto-detected.
4
4
 
5
5
  For the terse flag reference, see the [`brand` command reference](./cli-commands.md#brand-command). For sibling UI assets, see [Multi-Density Images](./multi-density-images.md).
6
6
 
@@ -41,22 +41,30 @@ PurgeTSS auto-discovers logo files under this folder, the same way `purgetss/fon
41
41
  ```text
42
42
  purgetss/brand/
43
43
  ├── logo.svg required — main logo (or logo.png)
44
+ ├── logo-icon.svg optional — square Android launcher mark
44
45
  ├── logo-mono.svg optional — monochrome layer + notifications
45
46
  ├── logo-dark.svg optional — iOS 18+ dark variant
47
+ ├── logo-splash.svg optional — Android 12+ splash icon override
46
48
  └── logo-tinted.svg optional — iOS 18+ tinted variant
47
49
  ```
48
50
 
49
- Only `logo.svg` (or `logo.png`) is required. The other three are **opt-in refinements**:
51
+ Only `logo.svg` (or `logo.png`) is required. Everything else is **opt-in refinement**:
50
52
 
51
53
  | File | Required? | What it's for | Fallback when omitted |
52
54
  | --- | --- | --- | --- |
53
55
  | `logo.svg` / `logo.png` | **Required** | Main colored logo. Feeds every density and variant. | — |
56
+ | `logo-icon.svg` / `.png` | Optional | Square Android launcher mark — use when `logo.svg` is a wide wordmark or non-square lockup. | Main logo is reused for Android launcher icons. |
54
57
  | `logo-mono.svg` / `.png` | Optional | Android adaptive monochrome layer (themed icons on Android 13+) and notification icons. | Main logo is whitened automatically. |
58
+ | `logo-splash.svg` / `.png` | Optional | Android 12+ `splash_icon.png` artwork (only used when `--splash` / `android.splash: true`). | Falls back to the launcher artwork. |
55
59
  | `logo-dark.svg` / `.png` | Optional | iOS 18+ Dark appearance variant. | Main logo on a transparent background (Apple HIG default). |
56
60
  | `logo-tinted.svg` / `.png` | Optional | iOS 18+ Tinted appearance variant. | Grayscale of the main logo on black. |
57
61
 
62
+ Provide a dedicated `logo-icon` when the main logo is a horizontal wordmark, a vertical lockup, or anything else that looks fine in a 1024×1024 branding canvas but feels cramped inside an Android launcher mask.
63
+
58
64
  Provide a dedicated `logo-mono` when the colored logo has detail that would collapse into a featureless blob under naive whitening (e.g. a painter's palette with colored dots — the monochrome variant should have cutouts instead).
59
65
 
66
+ Provide a dedicated `logo-splash` when the Android 12+ splash should use a different composition than the launcher icon. PurgeTSS generates the file, but Titanium still needs a custom Android splash theme if you want the system splash to use it instead of `ic_launcher`.
67
+
60
68
  Provide a dedicated `logo-dark` when dark-mode brand guidelines use a different lockup or color treatment; provide `logo-tinted` when you want a pre-simplified silhouette that tints better than a naive grayscale of the colored version.
61
69
 
62
70
  > **INFO**
@@ -76,40 +84,106 @@ Or in `purgetss/config.cjs`:
76
84
 
77
85
  ```javascript
78
86
  brand: {
79
- logo: './docs/snap-logo.svg',
80
- monochromeLogo: './docs/snap-logo-mono.svg'
87
+ logos: {
88
+ primary: './docs/snap-logo.svg',
89
+ androidLauncher: './docs/snap-app-icon.svg',
90
+ monochrome: './docs/snap-logo-mono.svg'
91
+ }
81
92
  }
82
93
  ```
83
94
 
84
95
  Precedence: **CLI flags win over config values, and config values win over auto-discovery.**
85
96
 
86
- ## The `brand:` config section
97
+ ## The `brand:` config section (v7.7.0 grouped structure)
87
98
 
88
- On the first run, `purgetss brand` injects a `brand:` block into your existing `purgetss/config.cjs` (between `purge:` and `theme:`) with these defaults:
99
+ On the first run, `purgetss brand` injects a `brand:` block into your existing `purgetss/config.cjs` (between `purge:` and `theme:`) with these defaults. The structure is grouped by purpose:
89
100
 
90
101
  ```javascript
91
102
  brand: {
92
- splash: false, // also generate splash_icon.png × 5
93
- padding: '15%', // Android safe-zone. Range: 12% tight (mature logos) 20% conservative. Spec floor 19.44%.
94
- iosPadding: '4%', // iOS aesthetic. Range: 2% bold — 8% conservative. No launcher mask.
95
- darkBgColor: null, // opaque dark bg for DefaultIcon-Dark.png (null = transparent per Apple HIG)
96
- bgColor: '#FFFFFF', // Android adaptive bg + iOS/marketplace flatten
97
- notification: false, // also generate ic_stat_notify.png × 5
103
+ logos: {
104
+ // Optional overrides. If omitted, PurgeTSS auto-discovers files from purgetss/brand/:
105
+ // primary: './docs/logo.svg',
106
+ // androidLauncher: './docs/app-icon.svg',
107
+ // androidSplash: './docs/splash.svg',
108
+ // monochrome: './docs/logo-mono.svg',
109
+ // iosDark: './docs/logo-dark.svg',
110
+ // iosTinted: './docs/logo-tinted.svg'
111
+ },
112
+ padding: {
113
+ ios: '4%', // iOS aesthetic padding. Range 2-8%. No launcher mask.
114
+ androidLegacy: '10%', // legacy ic_launcher.png padding %
115
+ androidAdaptive: '19%' // adaptive icon safe-zone %. Spec floor 19.44%.
116
+ },
117
+ android: {
118
+ splash: false, // also generate splash_icon.png × 5
119
+ notification: false // also generate ic_stat_notify.png × 5
120
+ },
121
+ colors: {
122
+ background: '#FFFFFF' // Android adaptive bg + iOS/marketplace flatten
123
+ },
124
+ // Optional iOS overrides:
125
+ // ios: {
126
+ // dark: false, // skip DefaultIcon-Dark.png
127
+ // tinted: false, // skip DefaultIcon-Tinted.png
128
+ // darkBackground: '#111' // opaque dark bg for DefaultIcon-Dark.png (null = transparent per Apple HIG)
129
+ // },
98
130
  confirmOverwrites: true // prompt before overwriting files (set false to skip)
99
131
  }
100
132
  ```
101
133
 
134
+ The recommended workflow is convention-first: drop files in `purgetss/brand/`, let auto-discovery pick them up, and only set `brand.logos.*` when you have a persistent override. CLI flags still win for one-off runs.
135
+
136
+ ### `brand.logos`
137
+
138
+ All `logos.*` keys are optional path overrides. If you omit them, PurgeTSS auto-discovers files from `purgetss/brand/`.
139
+
140
+ | Key | Auto-discovers | Purpose |
141
+ | --- | --- | --- |
142
+ | `logos.primary` | `purgetss/brand/logo.svg` | Main brand source. |
143
+ | `logos.androidLauncher` | `purgetss/brand/logo-icon.svg` | Square Android launcher mark — use when the main logo is a wordmark. |
144
+ | `logos.androidSplash` | `purgetss/brand/logo-splash.svg` | Android 12+ splash artwork. |
145
+ | `logos.monochrome` | `purgetss/brand/logo-mono.svg` | Android themed icons + notification icons. |
146
+ | `logos.iosDark` | `purgetss/brand/logo-dark.svg` | iOS dark variant. |
147
+ | `logos.iosTinted` | `purgetss/brand/logo-tinted.svg` | iOS tinted variant. |
148
+
149
+ ### `brand.padding`
150
+
151
+ All padding values accept either numbers or percentage strings like `'19%'`.
152
+
102
153
  | Key | Default | Purpose |
103
154
  | --- | --- | --- |
104
- | `splash` | `false` | When `true`, also emits `splash_icon.png` × 5 densities. |
105
- | `padding` | `'15%'` | Per-side safe-zone padding inside the 1024×1024 Android canvas. |
106
- | `iosPadding` | `'4%'` | Aesthetic padding for the iOS square icon. Smaller than Android because iOS has no launcher mask. |
107
- | `darkBgColor` | `null` | Opaque background baked into `DefaultIcon-Dark.png`. `null` = transparent per Apple HIG (iOS paints its own gradient). |
108
- | `bgColor` | `'#FFFFFF'` | Triple-purpose (see [Brand color](#brand-color) below). |
109
- | `notification` | `false` | When `true`, also emits `ic_stat_notify.png` × 5 densities. |
110
- | `confirmOverwrites` | `true` | When `false`, the `[y/N/a]` prompt is skipped. |
155
+ | `padding.ios` | `'4%'` | Visual inset for `DefaultIcon-ios.png`, `DefaultIcon-Dark.png`, `DefaultIcon-Tinted.png`, marketplace artwork. |
156
+ | `padding.androidLegacy` | `'10%'` | Visual inset for legacy `ic_launcher.png`. |
157
+ | `padding.androidAdaptive` | `'19%'` | Visual inset for adaptive Android foreground (`ic_launcher_foreground.png`). Adjust this first when icons look cropped inside launcher masks. |
158
+
159
+ ### `brand.android`
160
+
161
+ | Key | Default | Purpose |
162
+ | --- | --- | --- |
163
+ | `android.splash` | `false` | When `true`, also generates `drawable-*/splash_icon.png`. |
164
+ | `android.notification` | `false` | When `true`, also generates `drawable-*/ic_stat_notify.png`. |
111
165
 
112
- Change whatever you want to override globally; CLI flags still win for one-off runs.
166
+ ### `brand.ios` (optional)
167
+
168
+ If omitted, PurgeTSS behaves as if `ios.dark = true`, `ios.tinted = true`, `ios.darkBackground = null`.
169
+
170
+ | Key | Default | Purpose |
171
+ | --- | --- | --- |
172
+ | `ios.dark` | `true` | Set to `false` to skip `DefaultIcon-Dark.png`. |
173
+ | `ios.tinted` | `true` | Set to `false` to skip `DefaultIcon-Tinted.png`. |
174
+ | `ios.darkBackground` | `null` | When `null`, `DefaultIcon-Dark.png` stays transparent per Apple HIG. Set a hex to bake in an opaque dark background. |
175
+
176
+ ### `brand.colors`
177
+
178
+ | Key | Default | Purpose |
179
+ | --- | --- | --- |
180
+ | `colors.background` | `'#FFFFFF'` | Triple-purpose: Android adaptive background layer, iOS alpha flatten for `DefaultIcon-ios.png`, marketplace flatten for `iTunesConnect.png` / `MarketplaceArtwork.png` when overridden. |
181
+
182
+ ### `brand.confirmOverwrites`
183
+
184
+ | Key | Default | Purpose |
185
+ | --- | --- | --- |
186
+ | `confirmOverwrites` | `true` | When `false`, the `[y/N/a]` prompt is skipped. |
113
187
 
114
188
  ## Overwrite confirmation
115
189
 
@@ -151,14 +225,17 @@ The output is automatically routed to the right directory for your project layou
151
225
  ├── iTunesConnect.png ← 1024×1024, App Store submission
152
226
  ├── MarketplaceArtwork.png ← 512×512, Google Play submission
153
227
  └── app/
154
- └── assets/android/res/
155
- ├── mipmap-mdpi/ 108×108 foreground + background + monochrome + legacy
156
- ├── mipmap-hdpi/ ← 162×162
157
- ├── mipmap-xhdpi/ 216×216
158
- ├── mipmap-xxhdpi/ 324×324
159
- ├── mipmap-xxxhdpi/ 432×432
160
- └── mipmap-anydpi-v26/
161
- └── ic_launcher.xmladaptive-icon binder
228
+ └── assets/android/
229
+ ├── default.png legacy Titanium Android splash fallback (v7.7.0)
230
+ └── res/
231
+ ├── mipmap-mdpi/ 108×108 foreground + background + monochrome + legacy
232
+ ├── mipmap-hdpi/ 162×162
233
+ ├── mipmap-xhdpi/ 216×216
234
+ ├── mipmap-xxhdpi/ ← 324×324
235
+ ├── mipmap-xxxhdpi/432×432
236
+ ├── drawable-*/ ← optional splash_icon.png when --splash is enabled
237
+ └── mipmap-anydpi-v26/
238
+ └── ic_launcher.xml ← adaptive-icon binder
162
239
  ```
163
240
 
164
241
  **Classic layout:**
@@ -166,12 +243,21 @@ The output is automatically routed to the right directory for your project layou
166
243
  ```text
167
244
  <project>/
168
245
  ├── DefaultIcon.png DefaultIcon-ios.png ... ← same root-level files as Alloy
246
+ ├── Resources/
247
+ │ └── android/default.png ← legacy Titanium Android splash fallback (v7.7.0)
169
248
  └── platform/
170
249
  └── android/res/
171
250
  ├── mipmap-*/ ← same 5 densities as Alloy
251
+ ├── drawable-*/ ← optional splash_icon.png when --splash is enabled
172
252
  └── mipmap-anydpi-v26/ic_launcher.xml
173
253
  ```
174
254
 
255
+ The Android outputs are related, but they are not interchangeable:
256
+
257
+ - `ic_launcher*` drives the app icon, and by default also feeds the Android 12+ system splash
258
+ - `splash_icon.png` is only generated when you ask for it with `--splash`
259
+ - `default.png` is the older Titanium Android splash fallback (regenerated since v7.7.0)
260
+
175
261
  ## Android dark mode
176
262
 
177
263
  > **INFO**
@@ -190,6 +276,37 @@ purgetss brand
190
276
 
191
277
  The monochrome layer is pure white (`RGB 255,255,255`) with alpha preserved. Android applies the user's tint on top at render time.
192
278
 
279
+ ## Android 12+ splash artwork
280
+
281
+ If you pass `--splash`, PurgeTSS generates `drawable-*/splash_icon.png` across Android densities.
282
+
283
+ ```bash
284
+ purgetss brand --splash
285
+ ```
286
+
287
+ If you want that artwork to differ from the launcher icon, provide `logo-splash.svg` or set `brand.logos.androidSplash`:
288
+
289
+ ```javascript
290
+ brand: {
291
+ android: {
292
+ splash: true
293
+ },
294
+ logos: {
295
+ androidSplash: './docs/snap-splash-mark.svg'
296
+ }
297
+ }
298
+ ```
299
+
300
+ > **INFO**
301
+ >
302
+ > Generating `splash_icon.png` does not automatically switch Titanium to use it for the Android 12+ system splash. Titanium still needs a custom splash theme that points `android:windowSplashScreenAnimatedIcon` to `@drawable/splash_icon`. If you do nothing, Android keeps using `ic_launcher`.
303
+
304
+ ## Android legacy splash fallback
305
+
306
+ Since v7.7.0, PurgeTSS regenerates `app/assets/android/default.png` in Alloy projects and `Resources/android/default.png` in Classic projects.
307
+
308
+ That file still matters as a fallback on older Titanium Android splash paths, which is why `cleanup-legacy` no longer removes it.
309
+
193
310
  ## iOS 18+ Dark and Tinted variants
194
311
 
195
312
  iOS 18 added two appearance variants on top of the standard app icon: **Dark** (for the dark appearance of the Home Screen) and **Tinted** (for the user-accent-colored mode).
@@ -232,18 +349,32 @@ If you never pass the flag, background stays `#FFFFFF` and the marketplace artwo
232
349
 
233
350
  ## Padding guidance
234
351
 
235
- `--padding` controls how much safe-zone padding (per side, expressed as a percentage) surrounds the logo inside the Android adaptive canvas. The default `15%` matches real-world production apps like Gmail and Chrome.
352
+ Since v7.7.0, PurgeTSS treats Android adaptive and Android legacy launcher icons as two related but different cases:
353
+
354
+ - `brand.padding.androidAdaptive` or `--android-adaptive-padding` for the adaptive foreground
355
+ - `brand.padding.androidLegacy` or `--android-legacy-padding` for `ic_launcher.png`
356
+ - `--padding` is a one-shot **shortcut** that sets both Android paddings to the same value for one run
357
+
358
+ The adaptive default is `19%`, which stays close to the Android safe-zone. The legacy default is `10%`, so the flat `ic_launcher.png` can keep a little more visual weight.
236
359
 
237
- | Padding | Logo fill | When to use |
360
+ ### Adaptive icon padding
361
+
362
+ | Padding | Logo fill | When to use |
238
363
  | ------- | --------- | ------------------------------------------------------------------------------------------------------ |
239
- | `12%` | 76% | Logos with built-in breathing room (circular wordmarks, letterforms inside a shape). Tight, bold look. |
240
- | `15%` | 70% | **Default**. Balanced, safe on Pixel, Oppo, Samsung, OneUI, and Nova. |
241
- | `18%` | 64% | Defensive: for intricate logos, fine serifs, multi-element designs. |
242
- | `20%` | 60% | Conservative, spec-compliant. Safe on every launcher, including legacy aggressive masks. |
364
+ | `15%` | 70% | Aggressive. Better for square symbols with lots of built-in breathing room. |
365
+ | `18%` | 64% | Defensive: for intricate logos, fine serifs, multi-element designs. |
366
+ | `19%` | 62% | **Default**. Close to the Android safe-zone and safer for adaptive masks. |
367
+ | `20%` | 60% | Conservative, spec-compliant. Safe on every launcher, including aggressive masks. |
243
368
 
244
369
  A useful visual check is the "corners" heuristic: imagine a circle inscribed in your 1024×1024 canvas with the given padding. If your logo's outermost corners fit inside that circle, you're safe on circular launchers (Pixel default, Oppo Android 15). If they poke out, they'll be clipped.
245
370
 
246
- The official Android spec floor is `19.44%` (108dp canvas, 66dp inscribed safe-zone circle). Modern launchers are more permissive: Gmail and Chrome ship at 10–14%, which is why `15%` is the default. The 19.44% floor is the theoretical worst-case for aggressive masks; if you're worried about legacy Samsung teardrop masks or similar, bump to `--padding 20` to stay inside the spec.
371
+ The official Android spec floor is `19.44%` (108dp canvas, 66dp inscribed safe-zone circle). That is the theoretical worst-case for aggressive adaptive masks, which is why the adaptive default now sits close to it.
372
+
373
+ ### Legacy icon padding
374
+
375
+ Legacy `ic_launcher.png` does not go through the same adaptive mask, so it can usually run tighter. That is why the default for `brand.padding.androidLegacy` is `10%`.
376
+
377
+ ### iOS padding
247
378
 
248
379
  `--ios-padding` is a separate lever — iOS has no launcher mask, so the range is different:
249
380
 
@@ -284,24 +415,28 @@ purgetss brand --cleanup-legacy --aggressive
284
415
 
285
416
  ### The icon looks cropped or cramped on my phone
286
417
 
287
- Your logo is probably landing too close to the launcher mask. Increase `--padding`:
418
+ Your adaptive foreground is probably landing too close to the launcher mask. Increase `--android-adaptive-padding`:
288
419
 
289
420
  ```bash
290
- purgetss brand --padding 20
421
+ purgetss brand --android-adaptive-padding 20
291
422
  ```
292
423
 
293
424
  Or set it in the config:
294
425
 
295
426
  ```javascript
296
- brand: { padding: '20%' }
427
+ brand: {
428
+ padding: {
429
+ androidAdaptive: '20%'
430
+ }
431
+ }
297
432
  ```
298
433
 
299
434
  ### The icon looks tiny / lost in the middle
300
435
 
301
- Padding is too generous. Lower it:
436
+ Adaptive padding is probably too generous. Lower it:
302
437
 
303
438
  ```bash
304
- purgetss brand --padding 12
439
+ purgetss brand --android-adaptive-padding 17
305
440
  ```
306
441
 
307
442
  ### The monochrome version looks like a white blob
@@ -355,7 +490,9 @@ All 5 Android densities, marketplace artwork, and iOS variants regenerate in one
355
490
  | Flag | Purpose |
356
491
  | --- | --- |
357
492
  | `--bg-color <hex>` | Background color for Android adaptive + iOS/marketplace flatten. |
358
- | `--padding <n>` | Android safe-zone % (range `12–20`, default `15`). |
493
+ | `--padding <n>` | Shortcut: sets BOTH Android paddings to the same value for one run. |
494
+ | `--android-adaptive-padding <n>` | Adaptive icon safe-zone % (default `19`). |
495
+ | `--android-legacy-padding <n>` | Legacy `ic_launcher.png` padding % (default `10`). |
359
496
  | `--ios-padding <n>` | iOS aesthetic padding % (range `2–8`, default `4`). |
360
497
 
361
498
  **Optional asset types**
@@ -369,9 +506,11 @@ All 5 Android densities, marketplace artwork, and iOS variants regenerate in one
369
506
 
370
507
  | Flag | Purpose |
371
508
  | --- | --- |
509
+ | `--icon-logo <path>` | Override `purgetss/brand/logo-icon.{svg,png}` for Android launcher icons. |
372
510
  | `--monochrome-logo <path>` | Override `purgetss/brand/logo-mono.{svg,png}`. |
373
511
  | `--dark-logo <path>` | Override `purgetss/brand/logo-dark.{svg,png}`. |
374
512
  | `--dark-bg-color <hex>` | Opaque dark bg for `DefaultIcon-Dark.png` (default: transparent per Apple HIG). |
513
+ | `--splash-logo <path>` | Override `purgetss/brand/logo-splash.{svg,png}` for Android 12+ splash artwork. |
375
514
  | `--tinted-logo <path>` | Override `purgetss/brand/logo-tinted.{svg,png}`. |
376
515
  | `--no-dark` | Skip `DefaultIcon-Dark.png`. |
377
516
  | `--no-tinted` | Skip `DefaultIcon-Tinted.png`. |
@@ -380,7 +519,7 @@ All 5 Android densities, marketplace artwork, and iOS variants regenerate in one
380
519
 
381
520
  | Flag | Purpose |
382
521
  | --- | --- |
383
- | `--cleanup-legacy` | Remove obsolete branding artifacts (reads `tiapp.xml` for safety rules). |
522
+ | `--cleanup-legacy` | Remove obsolete branding artifacts (reads `tiapp.xml` for safety rules). Keeps `default.png` on purpose. |
384
523
  | `--aggressive` | With `--cleanup-legacy`, also remove `ldpi` density folders. |
385
524
 
386
525
  **Diagnostics**
@@ -393,18 +532,21 @@ All 5 Android densities, marketplace artwork, and iOS variants regenerate in one
393
532
  ### Examples
394
533
 
395
534
  ```bash
396
- purgetss brand # uses purgetss/brand/logo.svg + config
397
- purgetss brand --bg-color "#0B1326" # override bg color
398
- purgetss brand --notification --splash # add notification + splash
399
- purgetss brand --no-tinted # skip iOS 18+ tinted variant
400
- purgetss brand --dry-run # preview without writing
401
- purgetss brand --cleanup-legacy --dry-run # preview legacy cleanup
535
+ purgetss brand # uses purgetss/brand/logo.svg + config
536
+ purgetss brand --bg-color "#0B1326" # override bg color
537
+ purgetss brand --icon-logo ./docs/app-icon.svg # dedicated square Android launcher mark
538
+ purgetss brand --splash --splash-logo ./docs/splash.svg # custom Android 12+ splash artwork
539
+ purgetss brand --notification --splash # add notification + splash
540
+ purgetss brand --no-tinted # skip iOS 18+ tinted variant
541
+ purgetss brand --dry-run # preview without writing
542
+ purgetss brand --cleanup-legacy --dry-run # preview legacy cleanup
402
543
  ```
403
544
 
404
545
  ## Community-Discovered Patterns
405
546
 
406
547
  - **Titanium SDK wiring lag for iOS 18+ variants.** Titanium SDK currently wires `DefaultIcon-ios.png` into the generated appiconset automatically, but `DefaultIcon-Dark.png` and `DefaultIcon-Tinted.png` are not picked up yet. Until [tidev/titanium-sdk#14122](https://github.com/tidev/titanium-sdk/issues/14122) merges, the practical workaround is: run `ti build -p ios` once, then open `build/iphone/Assets.xcassets/AppIcon.appiconset/` in Xcode and drag the two PNGs into the "Appearance" column of the asset catalog editor. The generated PNGs are already named and sized correctly — no resizing needed.
407
- - **Modern launchers ship tighter than the spec.** The Android adaptive-icon spec floor is `19.44%` padding, but shipped apps like Gmail and Chrome use `10–14%`. PurgeTSS's `15%` default sits in that real-world range rather than the conservative spec floor, which is why icons look tight-but-balanced out of the box.
548
+ - **Wordmark logos need a separate launcher mark.** When `logo.svg` is a wide wordmark or vertical lockup, it tends to look cramped inside Android launcher masks. Drop a square `logo-icon.svg` (or set `brand.logos.androidLauncher`) and the launcher icons get the dedicated mark while the rest of the brand set still uses the main logo. Same idea applies to Android 12+ splash with `logo-splash.svg`.
549
+ - **Three Android assets, three different jobs.** `ic_launcher*` drives the app icon and the default Android 12+ splash; `splash_icon.png` is generated only when you pass `--splash` and Titanium needs an explicit splash theme to actually use it; `default.png` is the older Titanium Android splash fallback (regenerated since v7.7.0, intentionally kept by `cleanup-legacy`). Knowing which file does what saves a lot of "but the icon didn't change" debugging.
408
550
 
409
551
  ## See also
410
552
 
@@ -1,6 +1,11 @@
1
1
  # PurgeTSS CLI Commands
2
2
 
3
- > **Info: What's new in v7.5.3 / v7.6.0**
3
+ > **Info: What's new in v7.5.3 / v7.6.x / v7.7.0**
4
+ > - **`brand:` config grouped (v7.7.0)** — the flat `brand:` block from v7.6.0 was reorganized into purpose-based sections: `brand.logos`, `brand.padding`, `brand.android`, `brand.ios`, and `brand.colors`. Old projects keep working — newly-generated configs use the grouped form.
5
+ > - **Separate Android brand inputs (v7.7.0)** — `brand` can now use one logo for the general brand set, another for Android launcher icons (`logos.androidLauncher` / `--icon-logo`), and another for Android 12+ splash artwork (`logos.androidSplash` / `--splash-logo`). Drop `logo-icon.*` and `logo-splash.*` into `purgetss/brand/` or set the paths in `config.cjs`.
6
+ > - **Legacy Android splash fallback (v7.7.0)** — `purgetss brand` now regenerates `app/assets/android/default.png` (Alloy) or `Resources/android/default.png` (Classic). `cleanup-legacy` no longer removes `default.png`.
7
+ > - **`semantic` works in Classic projects (v7.6.2)** — writes to `Resources/semantic.colors.json` for Classic, keeps writing to `app/assets/semantic.colors.json` for Alloy.
8
+ > - **Confirmation prompt for destructive writes (v7.6.1)** — `brand` and `images` ask `[y/N/a]` before overwriting (auto-skipped on non-TTY, with `-y`/`--yes`, or `PURGETSS_YES=1`).
4
9
  > - **New `brand` command (v7.6.0)** — generates the complete Titanium branding set (launcher icons, adaptive icons, iOS 18+ Dark/Tinted variants, marketplace artwork, optional notification/splash) from a single SVG or PNG logo. See [`brand` Command](#brand-command) and the deep-dive [app-branding.md](./app-branding.md).
5
10
  > - **New `images` command (v7.6.0)** — generates multi-density UI images (Android `res-*` densities + iPhone `@1x`/`@2x`/`@3x` scales) from sources in `./purgetss/images/`. See [`images` Command](#images-command) and the deep-dive [multi-density-images.md](./multi-density-images.md).
6
11
  > - **New `semantic` command (v7.6.0)** — generates Titanium semantic colors (Light/Dark) into `app/assets/semantic.colors.json` with two modes (tonal palette vs. single purpose-based color). See [`semantic` Command](#semantic-command) and the deep-dive [semantic-colors.md](./semantic-colors.md).
@@ -68,12 +73,33 @@ module.exports = {
68
73
  }
69
74
  },
70
75
  brand: {
71
- splash: false, // also generate splash_icon.png × 5
72
- padding: '15%', // Android safe-zone. Range: 12% tight (mature logos) 20% conservative. Spec floor 19.44%.
73
- iosPadding: '4%', // iOS aesthetic. Range: 2% bold — 8% conservative. No launcher mask.
74
- darkBgColor: null, // opaque dark bg for DefaultIcon-Dark.png (null = transparent per Apple HIG)
75
- bgColor: '#FFFFFF', // Android adaptive bg + iOS/marketplace flatten
76
- notification: false, // also generate ic_stat_notify.png × 5
76
+ logos: {
77
+ // Optional overrides. If omitted, PurgeTSS auto-discovers files from purgetss/brand/:
78
+ // primary: './docs/logo.svg',
79
+ // androidLauncher: './docs/app-icon.svg',
80
+ // androidSplash: './docs/splash.svg',
81
+ // monochrome: './docs/logo-mono.svg',
82
+ // iosDark: './docs/logo-dark.svg',
83
+ // iosTinted: './docs/logo-tinted.svg'
84
+ },
85
+ padding: {
86
+ ios: '4%', // iOS aesthetic padding. Range 2-8%.
87
+ androidLegacy: '10%', // legacy ic_launcher.png padding %
88
+ androidAdaptive: '19%' // adaptive icon safe-zone %. Spec floor 19.44%.
89
+ },
90
+ android: {
91
+ splash: false, // also generate splash_icon.png × 5
92
+ notification: false // also generate ic_stat_notify.png × 5
93
+ },
94
+ colors: {
95
+ background: '#FFFFFF' // Android adaptive bg + iOS/marketplace flatten
96
+ },
97
+ // Optional iOS overrides:
98
+ // ios: {
99
+ // dark: false,
100
+ // tinted: false,
101
+ // darkBackground: '#111111'
102
+ // },
77
103
  confirmOverwrites: true // prompt before overwriting files (set false to skip)
78
104
  },
79
105
  images: {
@@ -164,7 +190,7 @@ Recommended VSCode extensions:
164
190
 
165
191
  ## `brand` Command
166
192
 
167
- Introduced in v7.6.0. Generates the complete Titanium branding set (launcher icons, adaptive icons, iOS 18+ Dark/Tinted variants, marketplace artwork, optional notification/splash icons) from a single logo image. Alloy and Classic projects are auto-detected.
193
+ Introduced in v7.6.0, restructured in v7.7.0. Generates the complete Titanium branding set (launcher icons, adaptive icons, iOS 18+ Dark/Tinted variants, marketplace artwork, optional notification/splash icons) from a single logo image — with optional Android-specific logo overrides when you need them. Alloy and Classic projects are auto-detected.
168
194
 
169
195
  > **Tip**
170
196
  > This is a quick reference. See [app-branding.md](./app-branding.md) for the complete guide — workflow, padding guidance, Android dark mode, iOS 18+ variants, alpha channel handling, and troubleshooting.
@@ -176,25 +202,56 @@ purgetss brand path/to/logo.svg # positional logo path override
176
202
 
177
203
  ### Flags
178
204
 
205
+ **Project & output**
206
+
179
207
  | Flag | Purpose |
180
208
  | --- | --- |
181
209
  | `--project <path>` | Project root (defaults to cwd). |
182
210
  | `--dry-run` | Preview what would be generated without writing any files. |
183
211
  | `--output <dir>` | Stage into `<dir>` instead of writing in place. |
184
212
  | `-y, --yes` | Skip the overwrite confirmation prompt for this invocation. |
213
+
214
+ **Visual customization**
215
+
216
+ | Flag | Purpose |
217
+ | --- | --- |
185
218
  | `--bg-color <hex>` | Background color for Android adaptive + iOS/marketplace flatten. |
186
- | `--padding <n>` | Android safe-zone percentage (range `12-20`, default `15`). |
187
- | `--ios-padding <n>` | iOS aesthetic padding percentage (range `2-8`, default `4`). |
219
+ | `--padding <n>` | Shortcut: sets BOTH Android paddings to the same value for one run. |
220
+ | `--android-adaptive-padding <n>` | Adaptive icon safe-zone % (default `19`). |
221
+ | `--android-legacy-padding <n>` | Legacy `ic_launcher.png` padding % (default `10`). |
222
+ | `--ios-padding <n>` | iOS aesthetic padding % (range `2-8`, default `4`). |
223
+
224
+ **Optional asset types**
225
+
226
+ | Flag | Purpose |
227
+ | --- | --- |
188
228
  | `--notification` | Also emit `ic_stat_notify.png × 5`. |
189
229
  | `--splash` | Also emit `splash_icon.png × 5`. |
230
+
231
+ **Logo variants & overrides**
232
+
233
+ | Flag | Purpose |
234
+ | --- | --- |
235
+ | `--icon-logo <path>` | Override `purgetss/brand/logo-icon.{svg,png}` for Android launcher icons (square mark for non-square main logos). |
190
236
  | `--monochrome-logo <path>` | Override `purgetss/brand/logo-mono.{svg,png}`. |
191
237
  | `--dark-logo <path>` | Override `purgetss/brand/logo-dark.{svg,png}`. |
192
238
  | `--dark-bg-color <hex>` | Opaque dark bg for `DefaultIcon-Dark.png` (default: transparent per Apple HIG). |
239
+ | `--splash-logo <path>` | Override `purgetss/brand/logo-splash.{svg,png}` for Android 12+ splash artwork. |
193
240
  | `--tinted-logo <path>` | Override `purgetss/brand/logo-tinted.{svg,png}`. |
194
241
  | `--no-dark` | Skip `DefaultIcon-Dark.png`. |
195
242
  | `--no-tinted` | Skip `DefaultIcon-Tinted.png`. |
196
- | `--cleanup-legacy` | Remove obsolete branding artifacts (reads `tiapp.xml` for safety rules). |
243
+
244
+ **Legacy cleanup**
245
+
246
+ | Flag | Purpose |
247
+ | --- | --- |
248
+ | `--cleanup-legacy` | Remove obsolete branding artifacts (reads `tiapp.xml` for safety rules). Keeps `default.png` on purpose. |
197
249
  | `--aggressive` | With `--cleanup-legacy`, also remove `ldpi` density folders. |
250
+
251
+ **Diagnostics**
252
+
253
+ | Flag | Purpose |
254
+ | --- | --- |
198
255
  | `--notes` | Print full `tiapp.xml` snippets + padding tuning guide. |
199
256
  | `--debug` | Print extra diagnostics. |
200
257
 
@@ -202,22 +259,45 @@ purgetss brand path/to/logo.svg # positional logo path override
202
259
 
203
260
  - `[logo-path]` (optional) — overrides auto-discovery of `purgetss/brand/logo.{svg,png}`.
204
261
 
205
- ### Config block
262
+ ### Config block (v7.7.0 grouped structure)
206
263
 
207
264
  Defaults live under `brand:` in `purgetss/config.cjs` and are injected automatically:
208
265
 
209
266
  ```javascript
210
267
  brand: {
211
- splash: false, // also generate splash_icon.png × 5
212
- padding: '15%', // Android safe-zone. Range 12-20%.
213
- iosPadding: '4%', // iOS aesthetic padding. Range 2-8%.
214
- darkBgColor: null, // opaque dark bg for DefaultIcon-Dark.png (null = transparent per Apple HIG)
215
- bgColor: '#FFFFFF', // Android adaptive bg + iOS/marketplace flatten
216
- notification: false, // also generate ic_stat_notify.png × 5
268
+ logos: {
269
+ // Optional overrides. If omitted, PurgeTSS auto-discovers files from purgetss/brand/:
270
+ // primary: './docs/logo.svg',
271
+ // androidLauncher: './docs/app-icon.svg',
272
+ // androidSplash: './docs/splash.svg',
273
+ // monochrome: './docs/logo-mono.svg',
274
+ // iosDark: './docs/logo-dark.svg',
275
+ // iosTinted: './docs/logo-tinted.svg'
276
+ },
277
+ padding: {
278
+ ios: '4%', // iOS aesthetic padding. Range 2-8%.
279
+ androidLegacy: '10%', // legacy ic_launcher.png padding %
280
+ androidAdaptive: '19%' // adaptive icon safe-zone %. Spec floor 19.44%.
281
+ },
282
+ android: {
283
+ splash: false, // also generate splash_icon.png × 5
284
+ notification: false // also generate ic_stat_notify.png × 5
285
+ },
286
+ colors: {
287
+ background: '#FFFFFF' // Android adaptive bg + iOS/marketplace flatten
288
+ },
289
+ // Optional iOS overrides:
290
+ // ios: {
291
+ // dark: false, // skip DefaultIcon-Dark.png
292
+ // tinted: false, // skip DefaultIcon-Tinted.png
293
+ // darkBackground: '#111' // opaque dark bg for DefaultIcon-Dark.png
294
+ // },
217
295
  confirmOverwrites: true // prompt before overwriting files
218
296
  }
219
297
  ```
220
298
 
299
+ The recommended workflow is convention-first: drop files in `purgetss/brand/`, let auto-discovery pick them up. Treat `brand.logos.*` as optional overrides for one-off paths or when masters live outside `purgetss/brand/`.
300
+
221
301
  ### Confirmation prompt
222
302
 
223
303
  `brand` writes in place, so it asks `Continue? [y/N/a]` before overwriting anything. Choose `a` (always) to write `confirmOverwrites: false` into `config.cjs` and silence the prompt on future runs. The prompt is skipped automatically when `stdin` is not a TTY (`alloy.jmk` hook, CI, pipes), when `-y`/`--yes` is passed, or when `PURGETSS_YES=1` is set.
@@ -225,14 +305,24 @@ brand: {
225
305
  ### Examples
226
306
 
227
307
  ```bash
228
- purgetss brand # uses purgetss/brand/logo.svg + config
229
- purgetss brand --bg-color "#0B1326" # override bg color
230
- purgetss brand --notification --splash # add notification + splash
231
- purgetss brand --no-tinted # skip iOS 18+ tinted variant
232
- purgetss brand --dry-run # preview without writing
233
- purgetss brand --cleanup-legacy --dry-run # preview legacy cleanup
308
+ purgetss brand # uses purgetss/brand/logo.svg + config
309
+ purgetss brand --bg-color "#0B1326" # override bg color
310
+ purgetss brand --icon-logo ./docs/app-icon.svg # dedicated square Android launcher mark
311
+ purgetss brand --splash --splash-logo ./docs/splash.svg # custom Android 12+ splash artwork
312
+ purgetss brand --notification --splash # add notification + splash
313
+ purgetss brand --no-tinted # skip iOS 18+ tinted variant
314
+ purgetss brand --dry-run # preview without writing
315
+ purgetss brand --cleanup-legacy --dry-run # preview legacy cleanup
234
316
  ```
235
317
 
318
+ ### Android output groups
319
+
320
+ `brand` writes three Android-facing asset groups, each with a different job:
321
+
322
+ - `ic_launcher*` for the app icon and the default Android 12+ system splash path
323
+ - `splash_icon.png` when you pass `--splash` and want custom Android 12+ splash artwork
324
+ - `default.png` as the older Titanium Android splash fallback (regenerated since v7.7.0)
325
+
236
326
  ## `images` Command
237
327
 
238
328
  Introduced in v7.6.0. Generates multi-density variants of your UI images (buttons, illustrations, logos, screen graphics) from a single high-resolution source per image. Alloy and Classic projects are auto-detected.
@@ -35,12 +35,33 @@ module.exports = {
35
35
  }
36
36
  },
37
37
  brand: {
38
- splash: false, // also generate splash_icon.png × 5
39
- padding: '15%', // Android safe-zone. Range: 12% tight (mature logos) 20% conservative. Spec floor 19.44%.
40
- iosPadding: '4%', // iOS aesthetic. Range: 2% bold — 8% conservative. No launcher mask.
41
- darkBgColor: null, // opaque dark bg for DefaultIcon-Dark.png (null = transparent per Apple HIG)
42
- bgColor: '#FFFFFF', // Android adaptive bg + iOS/marketplace flatten
43
- notification: false, // also generate ic_stat_notify.png × 5
38
+ logos: {
39
+ // Optional overrides. If omitted, PurgeTSS auto-discovers files from purgetss/brand/:
40
+ // primary: './docs/logo.svg',
41
+ // androidLauncher: './docs/app-icon.svg',
42
+ // androidSplash: './docs/splash.svg',
43
+ // monochrome: './docs/logo-mono.svg',
44
+ // iosDark: './docs/logo-dark.svg',
45
+ // iosTinted: './docs/logo-tinted.svg'
46
+ },
47
+ padding: {
48
+ ios: '4%', // iOS aesthetic padding. Range 2-8%.
49
+ androidLegacy: '10%', // legacy ic_launcher.png padding %
50
+ androidAdaptive: '19%' // adaptive icon safe-zone %. Spec floor 19.44%.
51
+ },
52
+ android: {
53
+ splash: false, // also generate splash_icon.png × 5
54
+ notification: false // also generate ic_stat_notify.png × 5
55
+ },
56
+ colors: {
57
+ background: '#FFFFFF' // Android adaptive bg + iOS/marketplace flatten
58
+ },
59
+ // Optional iOS overrides:
60
+ // ios: {
61
+ // dark: false, // skip DefaultIcon-Dark.png
62
+ // tinted: false, // skip DefaultIcon-Tinted.png
63
+ // darkBackground: '#111' // opaque dark bg for DefaultIcon-Dark.png (null = transparent per Apple HIG)
64
+ // },
44
65
  confirmOverwrites: true // prompt before overwriting files (set false to skip)
45
66
  },
46
67
  images: {
@@ -0,0 +1,120 @@
1
+ # Values and Units
2
+
3
+ PurgeTSS writes plain numeric values into your TSS files. **Titanium decides how to interpret them at runtime**, based on `ti.ui.defaultunit` in `tiapp.xml`.
4
+
5
+ This is a foundational concept worth knowing before you start tweaking spacing scales, custom colors, or arbitrary values — it's the difference between "8 pixels" and "8 dp" being the same number on disk but very different on a high-DPI device.
6
+
7
+ ## The short version
8
+
9
+ Numeric values produced by PurgeTSS utility classes are **unitless**. When PurgeTSS compiles `rounded-lg` to:
10
+
11
+ ```tss
12
+ '.rounded-lg': { borderRadius: 8 }
13
+ ```
14
+
15
+ the `8` is **not a pixel value**. Titanium reads it at runtime using the unit declared in `tiapp.xml`:
16
+
17
+ ```xml
18
+ <ti:app>
19
+ <property name="ti.ui.defaultunit" type="string">dp</property>
20
+ </ti:app>
21
+ ```
22
+
23
+ The Alloy project template has used `dp` by default for years, so most PurgeTSS projects are working with **density-independent pixels**, not raw pixels. In practice, `borderRadius: 8` usually means `8dp`, not `8px`.
24
+
25
+ ## Why this matters
26
+
27
+ Saying `rounded-lg` gives you "8 pixels" is only correct if your `tiapp.xml` explicitly sets `ti.ui.defaultunit` to `px`. Most projects do not.
28
+
29
+ A more accurate way to describe it is:
30
+
31
+ > `rounded-lg` applies `borderRadius: 8` — which Titanium interprets as **8 units of `ti.ui.defaultunit`**, defaulting to `dp` on standard Alloy projects.
32
+
33
+ This applies to every utility class that sets a dimension:
34
+
35
+ | Category | Utility classes |
36
+ | ---------- | -------------------------------------------------------------------------------------------- |
37
+ | Spacing | `m-*`, `p-*`, `mt-*`, `mb-*`, `mx-*`, `my-*`, `top-*`, `left-*`, `right-*`, `bottom-*` |
38
+ | Sizes | `w-*`, `h-*`, `size-*`, `wh-*` |
39
+ | Corners | `rounded-*`, `border-radius-*` |
40
+ | Borders | `border-*` (width) |
41
+ | Typography | `text-*` (font size), `letter-spacing-*`, `line-spacing-*` |
42
+ | Shadows | `drop-shadow-*`, `shadow-radius-*` |
43
+ | Elevation | `elevation-*`, `max-elevation-*` |
44
+ | Transforms | `translate-*`, `move-by-*` |
45
+ | Offsets | `x-offset-*`, `y-offset-*` |
46
+
47
+ ## Valid values for `ti.ui.defaultunit`
48
+
49
+ Titanium recognizes these unit identifiers:
50
+
51
+ | Value | Meaning | Notes |
52
+ | -------- | -------------------------- | --------------------------------------------------------------------------- |
53
+ | `dp` | Density-independent pixels | Alloy template default. Good default for cross-density consistency. |
54
+ | `dip` | Alias for `dp` | Same as `dp`. |
55
+ | `px` | Raw pixels | Usually a poor fit for UI sizing on high-DPI devices. |
56
+ | `mm` | Millimeters | Physical measurement. |
57
+ | `cm` | Centimeters | Physical measurement. |
58
+ | `in` | Inches | Physical measurement. |
59
+ | `pt` | Points (1/72 inch) | Physical measurement. |
60
+ | `system` | Platform default | iOS uses points; Android uses pixels. This is inconsistent across platforms. |
61
+
62
+ ## Forcing pixels explicitly
63
+
64
+ Some PurgeTSS classes use explicit pixel values written as **strings**:
65
+
66
+ ```tss
67
+ '.border-radius-px': { borderRadius: '1px' }
68
+ '.w-px': { width: '1px' }
69
+ '.h-px': { height: '1px' }
70
+ ```
71
+
72
+ If a value includes its own suffix, such as `'1px'`, `'2pt'`, or `'4mm'`, Titanium uses that unit directly and **ignores `ti.ui.defaultunit`**.
73
+
74
+ Use these when you actually need a 1px line or another exact unit (typical case: hairline dividers between rows).
75
+
76
+ ## Percentages are unit-independent
77
+
78
+ Fractional utility classes produce percentage strings. Titanium resolves those against the **parent size**, not against `ti.ui.defaultunit`:
79
+
80
+ ```tss
81
+ '.w-1/2': { width: '50%' }
82
+ '.h-full': { height: '100%' }
83
+ ```
84
+
85
+ These behave the same no matter which default unit your app uses.
86
+
87
+ ## Titanium constants are unit-independent
88
+
89
+ Utility classes that resolve to Titanium layout constants also ignore units:
90
+
91
+ ```tss
92
+ '.w-auto': { width: Ti.UI.SIZE }
93
+ '.h-screen': { height: Ti.UI.FILL }
94
+ ```
95
+
96
+ `Ti.UI.SIZE` and `Ti.UI.FILL` are layout directives, not numeric dimensions.
97
+
98
+ ## Checking your project's setting
99
+
100
+ Open `tiapp.xml` and look for:
101
+
102
+ ```xml
103
+ <property name="ti.ui.defaultunit" type="string">dp</property>
104
+ ```
105
+
106
+ If that property is missing, Titanium falls back to `system`. That means iOS and Android can interpret the same number differently, so it is better to set `dp` explicitly.
107
+
108
+ ## Summary
109
+
110
+ - PurgeTSS writes **unitless numeric values** into `app.tss`.
111
+ - Titanium resolves those values using `ti.ui.defaultunit` in `tiapp.xml`.
112
+ - In most Alloy projects, that unit is `dp`, **not raw pixels**.
113
+ - Values ending in `-px` (written as quoted strings) force raw pixels regardless of the project setting.
114
+ - Percentage-based and `auto`/`screen` utilities are unit-independent.
115
+
116
+ ## Related
117
+
118
+ - [Arbitrary Values](./arbitrary-values.md) — parentheses notation `(20px)`, `(2rem)`, `(#ff0000)` for one-off values.
119
+ - [Customization Deep Dive](./customization-deep-dive.md) — defining your own spacing scale via `theme.spacing`.
120
+ - [Class Index](./class-index.md) — the full set of generated classes and their numeric vs. percentage vs. constant outputs.