Flat v2 brand touchpoints — icon, adaptive icon, notification, splash, web, lockup (2026-10-09)
Status: Draft · Date: 2026-10-09 · Gap A2 of flat-grammar-v2-migration-plan.md ("What the plan was missing", brand touchpoints). Owner scope ruling 2026-10-09: the two-green-ball mark is a placeholder and will be recreated, so this document recommends no recolour of it and offers no mark options. It fixes everything around the mark for every touchpoint outside the in-app UI (the field and background of each, keylines, sizes, colours, files) in scheme S2 Ball and Ink (colour-scheme-proposals-2026-10-09.md), draws each with a labelled MARK slot, briefs the new mark (section 11) and says what ships how (section 12). Board: /wireframes/flat-v2-brand. Grammar and library: flat-mobile-grammar-v2-2026-10-09.md, flat-v2-component-library-2026-10-09.md.
0. Rulings
| # | Ruling | The number behind it |
|---|---|---|
| B1 | One safe circle | The mark's enclosing circle is at most 66 / 108 = 61.1% of the layer it is drawn on (the Android adaptive hard limit); the same artwork serves every touchpoint. Keylines: iOS 68% (696 px), notification 22 / 24 (88 of 96 px), favicon tile 70% (bare 84%), Android 12 splash 160 / 288. |
| B2 | Icon field = ink #15181A | White and ball are drawn for comparison. Ball on ink is 13.95:1 (ball on white 1.28:1); the ink tile is ΔE2000 37.0 from the nearest peer tile (Playtomic blue), a ball field is ΔE 4.5 from 테니스프렌즈, a white field ΔE 30.3 from Kakao; ink is the same tile in default, dark and tinted. |
| B3 | iOS appearances | Three 1024² PNGs in ios.icon { light, dark, tinted }: light = ink field + mark in ball; dark = the same file; tinted = greyscale. Today one icon, so iOS derives the rest. |
| B4 | Android adaptive | Background #15181A, foreground inside the 66dp circle, a monochrome layer (absent today). Today 98.7% of the composite is #006633: the balls are the background colour. |
| B5 | Notification | 96² white-on-alpha silhouette, every interior gap at least 2 px. Accent #02914C: 4.07:1 on #FFFFFF, 4.05:1 on #1F1F1F, white glyph on it 4.07:1; replaces #006633 (7.12:1 and 2.31:1). |
| B6 | Splash | #FFFFFF and, in dark mode, #0F1211 on both platforms (today white only). iOS: the bare canvas (HIG). Android 12+: the mark at 160dp inside the 192dp circle, ink on white (17.84:1), ball on #0F1211 (14.73:1). |
| B7 | Web | theme-color #FFFFFF / #0F1211 by prefers-color-scheme; a real favicon.ico (today a 307 redirect), icon.svg with a bare-mark dark variant, apple-icon.png 180. |
| B8 | OG card | One grammar for five cards: white canvas, ink type, a ball Tag or numeral, one ink block, the lockup. Content inside a 1200 × 600 frame, because Kakao crops anything outside 1:1, 2:1 and 4:3 (1200 × 630 is 1.905:1). |
| B9 | Lockup | The mark plus "DABUSI" (all capitals) or "다붓이" in Pretendard Bold outlines, horizontal, stacked and Korean, 1u clear space (u = cap height). The Georgia wordmark in logo.tsx (one use, the login screen) retires. |
| B10 | System bars | Dark content on the white header, light on #0F1211; SystemBars replaces expo-status-bar's StatusBar; the gesture pill follows the in-app theme. |
1. Today (what ships, measured)
| Touchpoint | Where | What ships |
|---|---|---|
| iOS icon | apps/mobile/app.json:7, assets/icon.png | 1024², field #F5F8F5 (67.9% of pixels), balls #006633 (31.6%). One file; ios.icon { light, dark, tinted } is supported by SDK 57 and unused. Generated by scripts/generate-icon-assets.mjs. |
| Android adaptive | app.json:31-34, assets/adaptive-icon.png | Foreground balls #006633 over backgroundColor #006633: 98.7% of the composite is one colour; only the 11,605 seam pixels differ. No monochromeImage, so no themed icon. |
| Notification | app.json:119-127, assets/notification-icon.png | 96² white on alpha, 3,099 opaque pixels of 9,216: two overlapping discs, no seams. color #006633 is 7.12:1 on #FFFFFF and 2.31:1 on #1F1F1F. |
| Channel LED | packages/app/src/adapters/expo/notification.expo.ts:62 | The green constant #006633 is the lightColor of five Android channels (JS). |
| Splash | app.json:101 ("expo-splash-screen", no props) | Plugin defaults (read from node_modules/expo-splash-screen 57.0.9): backgroundColor #ffffff, no image, no dark colour set. A dark-mode launch is white. The app holds the splash until fonts load (apps/mobile/app/_layout.tsx:113, :327). |
| Web theme-color | apps/web/app/layout.tsx:76, globals.css:40 | themeColor: '#006D37', one static value; color-scheme: light. |
| Web icons | apps/web/app/icon.svg, favicon.ico/route.ts, public/favicon.png | icon.svg is the in-app 56 × 40 logomark (#006633, transparent, no dark query). favicon.ico is a route handler answering 307 to /icon.svg. No apple-icon, no manifest. favicon.png (192², ivory) comes from the generator. |
| OG cards | apps/web/app/opengraph-image.tsx, apps/web/lib/og-card.tsx | Root card #0F5132 with a 96px white wordmark; OgCard (match, profile, leaderboard) a #0F5132 to #0A3A23 gradient; OgSessionCard white with a 630² map tile, four emoji lines and chips from the old badge palette. Three grammars, none S2. |
| Share pages | apps/web/components/open-in-app-button.tsx:30-41, share-page-styles.ts | The only coloured control is a #0f5132 button (white label, radius 8, 48 tall); page canvas --tm-bg #f8fbf9. |
| Kakao feed | packages/app/src/adapters/share/share.native.ts:103-105 | imageUrl is the OG route, declared imageWidth 1200 and imageHeight 630. |
| In-app Logo | packages/ui/src/logo.tsx, login-screen.tsx:82 | A Georgia serif wordmark with ball glyphs for the o's, #006633, used once. The only serif in the product. |
| System bars | apps/mobile/app/_layout.tsx:347 | expo-status-bar's StatusBar bound to the app theme. No SystemBars, no navigation-bar control anywhere (grep of apps/mobile and packages). |
2. The slot and the keylines
The new mark is drawn once, inside one safe circle: its enclosing circle (not its bounding box) is at most 66 / 108 = 61.1% of the layer. Android forces the number (the inner 66 × 66dp is the only area no OEM mask clips), so the same artwork serves the adaptive foreground, the monochrome layer and the iOS layers; iOS gets it at 1.113 times the scale (keyline 68%). The board draws a disc at exactly each keyline, so the slot is the largest the mark may be.
| Touchpoint | Canvas | Slot diameter | Of canvas | Source |
|---|---|---|---|---|
| Android adaptive layers | 108dp | 66dp | 61.1% | Android Developers, adaptive icons: all layers 108 × 108dp, the outer 18dp reserved for masking, the inner 66 × 66dp "never clipped". |
| iOS icon | 1024² px | 696 px | 68% | Ours. The HIG says square unmasked layers and "keep primary content centered" and gives no number. |
| Notification small icon | 24dp = 96² at xxxhdpi | 88 px | 91.7% | Archived Android iconography: 24 × 24dp, optical square 22 × 22dp, flat, entirely white. Expo: "96x96 all-white png with transparency". |
| Favicon tile and apple-icon | 100-unit tile | 70 (tile), 84 (bare), 68 (apple) | 70%, 84%, 68% | Ours, for legibility at 16 px. |
| Android 12 splash | 288dp canvas | 160dp | 55.6% | Android Developers, splash screen: icon without an icon background is 288 × 288dp inside a 192dp circle. expo-splash-screen draws imageWidth into a 288 × multiplier canvas. |
| Lockup | u = wordmark cap height | 1.5u horizontal, 2.5u stacked | n/a | Ours (section 10). |
3. The icon field (B2)
Three fields, the same slot, on a home screen among seven bare colour tiles of peers (brand primaries, no artwork): Toss #3182F6, Kakao #FEE500, 당근 #FF6600, Naver #03C75A, Band #4FC962, Playtomic #335FFF, 테니스프렌즈 #CCFC00 (hexes from colour-scheme-proposals-2026-10-09.md section 1; 테니스프렌즈 is the modal pixel colour of its profile card in lane H). Reference wallpapers (assumed means) are #E6EAEF and #0B1016.
| Criterion | White #FFFFFF | Ink #15181A (recommended) | Ball #D6F04A |
|---|---|---|---|
| L* | 100.0 | 8.0 | 90.4 |
| Mark role colour and contrast on field | ink, 17.84:1 | ball, 13.95:1 | ink, 13.95:1 |
| Nearest peer tile (ΔE2000) | Kakao 30.3 | Playtomic 37.0 | 테니스프렌즈 4.5 (Kakao 11.9, Band 21.0, Naver 23.3) |
| Tile edge on the light wallpaper | 1.21:1 | 14.76:1 | 1.06:1 |
| Tile edge on the dark wallpaper | 19.09:1 | 1.07:1 | 14.93:1 |
| Dark appearance | needs a second composition | the same asset | needs a second composition |
| Echo in the app | the canvas | the hub block and the toast | the FAB and the CTA |
| Can the mark be ball-coloured? | no (ball on white 1.28:1) | yes | no (it is the field) |
The ink tile is the only field where the mark can be ball-coloured at a readable contrast, the only one far from every peer, the same composition in default, dark and tinted, and the hub block. The category sharpens it: 8 of 13 racket apps already use ball-yellow or lime as their solid accent (visual-benchmark-2026-10-08.md, finding 5), so a yellow tile sits in the crowd while a ball-coloured mark on ink uses the category colour the way the category does, as the accent. The cost: an ink tile dissolves on dark wallpapers (1.07:1; the mark carries recognition and iOS draws its own edge); white and ball dissolve on light ones. Said plainly: the recommended icon has no green in it. The field is ink, the mark's colours on it are ball or white, and the brand green survives as the court tile and, as a derived mid-tone, the notification accent. Edge contrast is symmetric (the ink tile holds 3:1 on any wallpaper lighter than grey 100, white on any darker than grey 149, ball on any darker than grey 130), so it does not decide.
4. iOS app icon (B3)
Three 1024² PNGs, square and unmasked, sRGB (Display P3 allowed), in ios.icon { light, dark, tinted } (SDK 57 types: the property is a string or an object of the three):
- light: the ink field with the mark in ball inside the 68% keyline, centred;
- dark: the same pixels (the field is already dark; the ball stays, as in the app's dark palette);
- tinted: a greyscale source, the mark at full white on the ink converted to grey, so the user's tint lands on the mark. The HIG gives no pixel rule for it: confirm in Icon Composer or on a device.
Apple (HIG app icons, changed 2026-06-08): the system generates the appearances you do not supply (default, dark, clear light, clear dark, tinted light, tinted dark); "keep your icon's features consistent across appearances"; "use your light app icon as the basis for your dark icon … avoid excessively bright images"; colour backgrounds give dark icons the most contrast; "providing layers with pre-defined masking negatively impacts specular highlight effects"; no baked highlights, shadows or glows; no text unless essential. An ink field needs no second composition, so dark is a copy. An imported background layer is full-bleed and opaque. Expo's icon plugin (@expo/prebuild-config 8.0.17) reads PNGs: it writes the universal, dark and tinted slots of the asset catalog, flattens the light and tinted files onto white (ours are opaque, so nothing changes) and keeps the dark file's transparency; it does not read an Icon Composer .icon file.
5. Android adaptive icon (B4)
adaptiveIcon.backgroundColor:#15181A;foregroundImage: the mark in ball on a transparent 1024² PNG inside the 66dp circle;monochromeImage: the same silhouette, one colour on alpha (Android 13+ themed icons; the field then comes from the user's wallpaper). Never bake a circle, squircle or shadow ("the layers must not have masks or background shadows").- Android Developers: two layers for the colour version and "a single layer for the monochrome version"; Android 16 QPR 2 themes apps that do not provide their own. The launcher's visible window is 72 × 72dp (the 108dp layer minus the 18dp edge on each side; the page states the 108, the 18 and the 66, the 72 is the arithmetic). Expo's plugin writes
ic_launcher_foreground,ic_launcher_monochromeand the background colour. - Interim, only if a native build ships before the mark:
adaptiveIcon.backgroundColor#F5F8F5(the ivory the iOS icon uses; the placeholder balls on it are 6.66:1). It fixes what ships; it recolours nothing;#15181Areplaces it when the mark lands.
6. Notification (B5)
Small icon. White on alpha at 96 × 96 (24dp at xxxhdpi), the mark inside the 22dp optical square (88 px), every interior gap or stroke at least 2 px at 96² (3 preferred), no gradient, no text. A 1 px gap is 0.25dp: 0.75 px at xxhdpi and 0.5 px at xhdpi, so it fades into the disc (the board draws 1, 2, 3 and 4 px seams at 96, 72 and 48 px). Android design: the app icon "appears in monochrome in the status bar".
Accent. expo-notifications color takes one value; the shade is #FFFFFF or #1F1F1F. Contrast computed with the shared colour helper (colour_lab.py wcag FG BG):
| Candidate | On #FFFFFF | On #1F1F1F | White glyph on it | Verdict |
|---|---|---|---|---|
#006633 (today) | 7.12 | 2.31 | 7.12 | fails on the dark shade |
#006D37 (brand green) | 6.48 | 2.55 | 6.48 | fails on the dark shade |
#D6F04A (ball) | 1.28 | 12.89 | 1.28 | fails on the light shade |
#15181A (ink) | 17.84 | 1.08 | 17.84 | fails on the dark shade |
#FFFFFF | 1.00 | 16.48 | 1.00 | fails on the light shade |
#02914C (derived) | 4.07 | 4.05 | 4.07 | passes both |
The dark shade has relative luminance 0.0137, so one colour is equally far from both shades at relative luminance 0.2086, where the ratio is 4.06:1: the ceiling for a single value. Bands: 3:1 on both needs relative luminance 0.141 to 0.300; 3.5:1 needs 0.173 to 0.250; 4:1 needs 0.205 to 0.2125. #02914C is the brand-green hue (OKLCH 152.7°) at relative luminance 0.2078. The rule is hue-independent: if the new mark's main hue is not green, keep the luminance and change the hue. The same luminance keeps a white glyph on an accent disc at 4.07:1 where Android draws the icon that way.
Android Developers (notification design): "Starting in Android 12 (API level 31), the system derives the icon color from the notification color you set in the app. If the app doesn't set the color, it uses the system theme color. Previously, the color was gray." Colourising the notification background applies, for most styles, only to foreground-service notifications. How widely the accent applies varies by version and maker, so it is designed to hold on both shades and is not relied on. The channel LED colour (notification.expo.ts:62) follows the accent (JS).
7. Splash (B6)
- Launch background
#FFFFFF, dark#0F1211, on both platforms (backgroundColorplusdark.backgroundColor). - iOS: no image, so the launch screen is the canvas colour. Apple (HIG launching): a launch screen is "nearly identical to the first screen", a solid colour when the first screen is one, no text, and no logos "unless they're a fixed part of your app's first screen"; it should match the appearance mode.
withIosSplashAssets.jsreturns before writing an imageset when there is noimage, andwithIosSplashColors.jswrites the dark colour whendark.backgroundColoris set. - Android 12+: the system draws an icon, so the mark is drawn at 160dp inside the 192dp circle (Android Developers: icon without an icon background is 288 × 288dp and fits a 192dp circle, with an icon background 240 × 240dp and a 160dp circle; "everything outside the circle turns invisible"). Two images: the mark in ink for the light splash, in ball for the
#0F1211splash. The plugin composes the PNG onto a transparent 288 × multiplier canvas and draws it atimageWidth× multiplier, so the file is the mark on a 1024² square with its enclosing circle inscribed andimageWidthis 160. - The alternative, the mark on iOS as well (a top-level
image), is one config line and breaks the HIG; Korean peers commonly show a logo. The owner may prefer consistency with Android.
[
"expo-splash-screen",
{
"backgroundColor": "#FFFFFF",
"dark": { "backgroundColor": "#0F1211" },
"android": {
"image": "./assets/splash/mark-ink.png",
"imageWidth": 160,
"dark": { "image": "./assets/splash/mark-ball.png" }
}
}
]Expo Go and development builds do not show this splash; test on a release build (Expo docs). The splash is held until fonts load, so it is on screen long enough to be seen.
8. System bars (B10)
| Bar | Light | Dark | Source and note |
|---|---|---|---|
| Status bar content | dark over the header surface | light | StatusBar today (_layout.tsx:347); SystemBars style "dark" or "light" after. |
| Status bar fill | none: the header's #FFFFFF runs under it, edge to edge | the header's #0F1211 | Expo marks androidStatusBar.backgroundColor and translucent deprecated, "no effect" under edge-to-edge. |
| Header | 56 plus the top inset, no line at rest, an edge hairline once content scrolls under it | hairline white α0.14 | Library section 3. |
| Tab bar | 56 plus the bottom inset on the canvas, an edge hairline only while content lies below it | the same on #0F1211 | Library section 3; iOS home indicator inset 34. |
| Gesture navigation bar | fully transparent (Android 15 default); the pill dark on the white tab bar | light pill | react-native-edge-to-edge 1.8.1 README: the gesture bar is transparent, the button bar semi-opaque. |
| 3-button navigation bar | keep the system's semi-opaque scrim (contrast enforced) | the same, scrim dark | enforceNavigationBarContrast stays true; forcing it false makes the app own the bar style on every screen. |
Not set today: no SystemBars and no navigation-bar style, so the gesture pill follows the OS scheme, not the in-app theme (dark OS plus light in-app theme puts a light pill on the white tab bar). The library says to replace the built-in StatusBar, expo-status-bar and expo-navigation-bar with SystemBars under edge-to-edge:
import { SystemBars } from 'react-native-edge-to-edge';
// in place of the StatusBar element
<SystemBars style={tamaguiThemeName.startsWith('dark_') ? 'light' : 'dark'} />;A JS change (the native module is already in the binary), to confirm on the emulator rung before an OTA.
9. Web (B7, B8)
9.1 theme-color. #FFFFFF for light, #0F1211 for dark, by media query (MDN: theme-color takes a media attribute; Next.js viewport.themeColor accepts an array of { media, color }):
export const viewport: Viewport = {
width: 'device-width',
initialScale: 1,
themeColor: [
{ media: '(prefers-color-scheme: light)', color: '#FFFFFF' },
{ media: '(prefers-color-scheme: dark)', color: '#0F1211' },
],
};The app's colour scheme can be set in the app independent of the OS (useThemeStore), so a static media pair follows the OS only: add a small client effect that rewrites the tag from the resolved in-app mode when the two disagree.
9.2 Favicon set. Evil Martians (How to Favicon in 2026, 2026-01-21): favicon.ico 32 × 32, one SVG that can switch with prefers-color-scheme, apple-touch-icon 180 × 180, and for a PWA 192, 512 and a maskable 512 with the mark inside the central 409 circle. Next.js 16.4 file conventions: favicon.ico in app/, icon.svg and apple-icon.png anywhere in app/, link tags generated.
icon.svg: the ink tile in light; in dark the bare mark at 84% (a dark square on a dark tab strip dissolves: ink on the#35363Aactive tab is 1.48:1, ball on it 9.44:1).favicon.ico: a real 32 × 32 file replacing the route handler (a client that wants an ICO gets an SVG today).apple-icon.png: 180 × 180, ink full-bleed, the mark at the iOS keyline.- Only with a manifest:
icon-192.png,icon-512.png,icon-maskable-512.png.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<style>
.tile { fill: #15181A }
.mark { fill: #D6F04A }
@media (prefers-color-scheme: dark) {
.tile { fill: none }
.mark { transform: scale(1.2); transform-origin: 50px 50px }
}
</style>
<rect class="tile" width="100" height="100" rx="22"/>
<circle class="mark" cx="50" cy="50" r="35"/>
</svg>The mark shown is Fitted close, the chosen mark (section 11).
9.3 OG cards. One grammar for the root, session, club ranking, match and profile cards:
| Rule | Value |
|---|---|
| Frame | 1200 × 630 PNG; every element inside a centred 1200 × 600 frame (15 px clear top and bottom), 64 px at the sides, 56 px top and bottom. |
| Canvas, type | White; ink #0D100E (19.13:1); title 72/700, line 80, two lines, keep-all; subtitle 34/500 secondary #4F5851 (7.38:1); facts 30/600 and 30/500. |
| Brand | The horizontal lockup, 44 px high, top left (40 px bottom right on the session card). No wordmark footer. |
| Tag | Eyebrow and chips: 48 high, radius 12, gray100 fill, ink 26/600. Session status: ball fill, ink 28/700, 56 high. |
| The one block | Ink #15181A, 380 × 390, radius 32; label white α0.8 26/600; numeral in ball 104 to 140 / 700, tabular (ball on ink 13.95:1). The root card holds the slot instead. |
| Ball budget | One ball accent per card: the block numeral, the session status Tag, or the slot. Never two. |
| Session card | Keeps the 630² static-map tile left and the details column right; the emoji lines and old chip pairs become plain fact lines and one ball Tag. |
| Naming | A session or a match is named as its own page names it (L §5 MediaRow, Content): the venue is the title, the club and the day are the lines (a pickup has no club line). The match card's subtitle is the club and the day; its block is the score. |
Two grammars hold the one rule (2026-11-13): the root card (/opengraph-image, lib/og-root-card.tsx) draws a white canvas, ink type, the lockup top left and one 380 × 390 ink block holding the ball mark, with no domain line. The share cards sc-* (/s, /m, /p, /lb) keep the full ink Block, as ratified; the board flat-v2-brand draws both (FbOgRoot, FbOgBlock).
Kakao: the feed call declares 1200 × 630 (share.native.ts:103-105). Kakao staff (devtalk, 2025-12-12): the accepted og:image ratios are 1:1, 2:1 and 4:3 and others are auto-cropped around the most prominent content; the documentation gives only minimum sizes (200 × 200 default templates, 400 × 400 custom) and 5 MB, and the image is cached (version the URL with ?v=). Designing to a 2:1 frame costs 15 px of margin and guarantees no type is cropped. The 1200 × 630 file size follows long-standing Facebook guidance (repeated by many platforms; Facebook's current best-practices page asks for og:image:width and og:image:height tags and a changed URL when the image changes). The cards are specified in Pretendard; the edge route loads no fonts today and the OTFs are 1.58 MB each, so it renders satori's own until a subset is bundled.
9.4 Share pages. The landing pages /s, /m, /p, /lb are plain server HTML. They follow the mobile grammar in the web phase (D-last): white canvas, the horizontal lockup at the top, the OG image as the hero, title 24/32 bold, the open-in-app control as the ball button (52 tall, radius 12, ink label). With S1 only the button colour moves (one constant, #0f5132) and --tm-bg becomes #FFFFFF. They stay Korean. The page names a session as its card does: the venue is the h1, the club and the day are the lines under it.
10. Lockup and wordmark (B9)
"DABUSI" (all capitals, Pretendard Bold 700, tracking +6% of the cap height between letters, with the font's own kerning) and "다붓이" (tracking 0), outlined to paths, no live text in any logo file. Cap height 1448 / 2048 em (0.707 em); "Dabusi" is 6.126u wide (u = cap height); the Hangul word is set at the same scale and centred on the cap-height band. Colour: text ink #0D100E on white, white on ink, ink on ball. Horizontal: the mark 1.5u, a 0.6u gap, the wordmark vertically centred on the mark (822.6u by 150u). Stacked: the mark 2.5u, a 0.7u gap, the wordmark centred below (612.6u by 422u). Clear space 1u on every side. Minimum sizes: horizontal 96 px wide, stacked 72 px wide, the mark alone 16 px. The mark carries the colourway of its ground (ink on white, ball on ink, ink on ball).
Rule: the wordmark is DABUSI; the name in text is Dabusi. The capitals apply to the logo letters only. Captions, the store line ("Dabusi: 테니스 클럽 운영"), notification names, the browser tab and running copy keep "Dabusi" (다붓이 on Korean phones).
| Where | File | Form and size |
|---|---|---|
| Web sidebar (1200 up) | apps/web/components/app-nav.tsx | horizontal, 28 px high |
| Web rail (600 to 1199) | app-nav.tsx | the mark only, 32 px |
| OG cards | apps/web/lib/og-card.tsx | horizontal, 44 px high |
| Share pages | apps/web/app/{s,m,p,lb}/page.tsx | horizontal, 28 px high |
| Login screen | packages/app/src/presentation/screens/auth/login-screen.tsx:82 | stacked, 180 px wide |
11. Brief for the new mark
The mark for Dabusi (다붓이) is chosen: Fitted close (owner review 22). It had to pass these requirements, ship as these deliverables and clear the acceptance sheet on the board (the spec layer of the mark section).
Requirements (each is a size, a ratio or a ground, so the check is a render):
| # | Requirement | Test |
|---|---|---|
| R1 | Legible at 16 px | At 16 × 16 px on a light tab strip (#DEE1E6) and a dark one (#202124) it is the same mark; nothing finer than 1 px at 16. A separate small master is allowed (R9). |
| R2 | Notification silhouette | One colour on alpha inside 88 × 88 px of 96²; every interior gap or stroke at least 2 px (3 preferred); no gradient, no text; recognisable at 24dp (48 px at xhdpi, 72 px at xxhdpi). |
| R3 | Adaptive safe circle | The enclosing circle is at most 66dp of the 108dp layer, centred; clean edges; no baked mask, shadow or glow. |
| R4 | iOS grid | Square 1024² layers, content centred, enclosing circle at most 68% (696 px), clearly defined edges, sRGB, no text, the same features in default, dark and tinted. |
| R5 | One-colour silhouette | Reads as a single flat shape in one colour (themed icon, notification, bare dark favicon, one-colour print). Colour never carries meaning the shape does not. |
| R6 | Three grounds | A defined colourway on white (ink; the ball alone is 1.28:1), on ink #15181A (ball 13.95:1 or white 17.84:1) and on ball #D6F04A (ink 13.95:1); at least 3:1 between mark and ground in each. |
| R7 | Among the peer tiles | On a home screen among the seven peer colour tiles at 60pt, light and dark wallpaper, recognisable by silhouette in greyscale, not by colour alone; no peer's artwork echoed. |
| R8 | Ownable | The tennis element carries the 다붓이 idea (close together, fitted together), never a stock ball or racket on its own; checked against the peer set and a trademark search (KIPRIS) before adoption. |
| R9 | Two optical masters | A large master (48 px and up) and a small one (32 px and down) may differ in detail and stroke weight; the silhouette may not. |
| R10 | With the wordmark | Sits beside "DABUSI" and "다붓이" in the horizontal, stacked and Korean lockups (1.5u and 2.5u mark, 1u clear space), and holds at 96 px wide. |
The mark: Fitted close. A tennis ball is two dog-bone felt pieces fitted tightly along the seam: 다붓이 in the ball itself. Face-on, the seam is two arcs bowed toward each other, ")(", with the waist piece between them and the other piece wrapping both sides. Two tones (ball and white on ink, one ink colour elsewhere), one constant-width gap (8 units, 12 on the small master for 32 px and down), and a one-colour silhouette that is the circle with the seam cut out. It reads as a ball at 24 px and as a ball with two notches at 16 px.
Risk, kept honest: it is near the stock tennis ball, so the DABUSI wordmark carries the trademark weight and the device mark is filed as a composite with the word. Pepsi's globe and the yin-yang also split a circle with a wave; the two dog-bone arcs are what keep this a tennis ball (a hooked S was drawn and dropped: it read as a letter S). Checked against Wilson's W, Babolat, HEAD, Yonex, Playtomic, UTR, SwingVision, PlayByPoint and the Korean 한판 club app: none draws a ball seam. The other four directions (Two, snug; The D strings; 다 on the court; Close at the net) are recorded in the owner review 21 and 22 rulings, not here. A KIPRIS search is still owed before filing.
Deliverables:
| # | Deliverable | Contents |
|---|---|---|
| D1 | SVG master | 1000-unit square artboard, centred, outlined, keyline guides at 61.1% and 68%; colour, one-colour ink, reversed white, ball on ink. |
| D2 | iOS icon | ios-light.png, ios-dark.png, ios-tinted.png (1024², square, unmasked, opaque); Expo's icon plugin reads PNGs, not Icon Composer files (the HIG prefers SVG or PDF layers there). |
| D3 | Android adaptive | android-foreground.png (1024² transparent, mark inside the 66dp circle), android-monochrome.png (1024², one colour on alpha), background colour #15181A. |
| D4 | Notification | notification.png, 96² white on alpha, gaps at least 2 px, plus the 24dp vector. |
| D5 | Favicon set | icon.svg (tile in light, bare mark in dark by media query), favicon.ico 32 × 32, apple-icon.png 180 × 180; with a manifest also icon-192, icon-512, icon-maskable-512. |
| D6 | Splash | mark-ink.png and mark-ball.png, 1024² transparent, enclosing circle inscribed (Android only). |
| D7 | Lockups | Horizontal and stacked in ink, white and on-ball, with the clear-space and minimum-size sheet. |
| D8 | OG templates | The five cards of section 9.3 rebuilt with the real lockup (44 px high). |
| D9 | Acceptance sheet | The sheet on the board (sizes 16 to 96 on white, ink and ball, the 24dp silhouette) rendered with the chosen mark; the owner marks it. |
12. What ships how, and when
The app's runtimeVersion policy is appVersion (0.11.0), so a new binary needs a new app version and an OTA reaches only binaries with the version it was built for: nothing in the native rows can ship by OTA. Web files that hold the mark ship with the mark; nothing placeholder is ever deployed.
| Touchpoint | File or config | Channel | When |
|---|---|---|---|
| iOS icon: light, dark, tinted | app.json icon, ios.icon; three PNGs | native build | With the new mark's first native build (icons are in the binary and the store listing). |
| Android adaptive and monochrome | android.adaptiveIcon.* | native build | With the new mark. The one-line interim (backgroundColor #F5F8F5) can ride any earlier native build. |
| Notification icon and accent | expo-notifications plugin icon, color | native build | Expo: these properties "cannot be set at runtime and require building a new app binary to take effect". With the new mark. |
| Android channel LED colour | notification.expo.ts:62 | OTA | Any OTA; cosmetic. Set it to the new accent when the accent ships. |
| Splash colours and the dark colour | expo-splash-screen: backgroundColor, dark.backgroundColor | native build | Next native build. Needs no mark, so it does not wait for one: it fixes the white launch in dark mode. |
| Splash mark (Android) | android.image, android.dark.image | native build | With the new mark. |
| System bars | apps/mobile/app/_layout.tsx:347 to SystemBars | OTA | JS; confirm on the emulator rung first. With B9 (platform) of the migration plan. |
| Login screen lockup | packages/ui/src/logo.tsx, login-screen.tsx:82 | OTA | With the new mark (S-series build). |
| Web theme-color | apps/web/app/layout.tsx:76 | web deploy | With S1 (A2's web parts). |
| Web icons | apps/web/app/icon.svg, favicon.ico, apple-icon.png | web deploy | With the new mark (the files hold it). |
| OG cards | opengraph-image.tsx, lib/og-card.tsx | web deploy | With S1: the grammar ships wordmark-only (type, ball Tag, ink block); the lockup's mark joins with the new mark. |
| Share pages | open-in-app-button.tsx, share-page-styles.ts, globals.css | web deploy | Button and canvas colour with S1; the layout with the web phase. |
| Kakao feed image | share.native.ts:103-105 | OTA | With the OG grammar: keep 1200 × 630 with 2:1-safe content; declare 800 × 400 only if the route serves a 2:1 image. |
| App Store and Play listing art | store consoles | store | With the first store release of the new mark. |
13. Sources
- Apple, App icons (HIG, changed 2026-06-08): layers, shape, appearances, 1024 × 1024 px, colour spaces. Launching (launch screens).
- Android Developers: adaptive icons (108dp layers, 18dp masking edge, 66dp safe zone, the single monochrome layer, Android 13 themed icons, Android 16 QPR 2); splash screen (240 / 160 and 288 / 192dp icon rules, background, behaviour); notifications design (monochrome status-bar icon, Android 12 icon colour, colourised notifications);
Notification.color(accent colour, "stenciled in white", alpha ignored); archived Android Design iconography (24 × 24dp, 22 × 22dp optical square, entirely white), mirrored at stuff.mit.edu/afs/sipb/project/android/docs/design/style/iconography.html. - Expo SDK 57: expo-notifications (
icon"96x96 all-white png with transparency",color, plugin properties need a new binary); expo-splash-screen (backgroundColor,image,dark,imageWidth,resizeMode) read with the 57.0.9 plugin source;@expo/config-types(ios.icon,android.adaptiveIcon.monochromeImage). - react-native-edge-to-edge 1.8.1 README (Android 15 defaults,
SystemBars). - MDN, theme-color; Next.js, generateViewport and favicon, icon, apple-icon; Evil Martians, How to Favicon in 2026.
- Kakao Developers, message template components (image 5 MB, minimum 200 × 200 and 400 × 400); Kakao DevTalk, og:image ratio thread (1:1, 2:1, 4:3; cache and
?v=). Facebook, sharing best practices.
14. Judgement calls and what was not verified
- The touchpoints show Fitted close, the owner's chosen mark, in one colour; the board's "The mark" section carries its full test harness.
- Peer tile colours are brand primaries used as the dominant icon colour; the icons themselves were not sampled and no logo or artwork is drawn. Check the tiles against the real icons before relying on the ΔE numbers.
- The reference wallpapers are assumptions; edge contrast is symmetric and does not decide the field.
- The iOS keyline (68%) is ours; tinted icons are simulated and the greyscale source is Apple's tinted-icon workflow, to be confirmed in Icon Composer or on a device.
- The notification accent hue is derived at the brand-green hue; the luminance rule is hue-independent. Whether
expo-notificationscolour is applied to non-foreground-service notifications on Android 12 and later is not verified. - The iOS launch screen follows the HIG (bare canvas); the mark-on-iOS alternative is one config line.
- The Kakao ratio rule is a staff answer on DevTalk, not documentation; send a test feed after the OG change.
- OG type: the edge route loads no fonts today; sizes and hierarchy do not depend on the face. Korean strings in the cards, notification mocks and splash are invented sample text.
- Not verified: Apple's production-template grid; store-console requirements beyond the cited pages; a device pass of any native part (icons and splash need a release build).
15. Verification
Contrast numbers come from the shared colour helper (colour_lab.py, WCAG 2.x; the notification pairs through its wcag FG BG command). Geometry is computed from the same constants the board draws. The board's DOM check (Chromium, window 1800) reads every OG card element in the card's own 1200 × 630 pixels against the 1200 × 600 frame (5 of 5 cards pass, 0 clipped text boxes). Slot-based renders for review (SVG sources and PNG at 1024, 96 and 1200 × 630, plus the favicon set, splash marks and lockups) are produced by the same components and kept outside the repo. Nothing under apps/ changes.