Lane H — flat lists under a leading block, and block anatomy (2026-10-09)
Status: Reference · Date: 2026-10-09 · Evidence appendix for list-surfaces-spec-2026-10-09.md. Frame, crop and script paths refer to the session scratch directory (not committed); App Store frames are re-fetchable from the store URLs in the tables.
Scope: owner rulings of 2026-10-09 (neutral controls, photos carry identity, minimal inline icons, a leading brand block forces the list below to be SUBTLE and FLAT, T1 pure white, the T0 block was badly built). Everything below is measured from App Store frames on disk plus the design-system sources fetched today. Nothing under /home/sungkyu08/Dev/twomore-v2 was modified. Working files: bench/lane_h/ (helpers grid.py, bands.py, runs.py, radius.py; crops in bench/lane_h/rows/; contact sheets bench/lane_h/contact-{A,B,C}-*.png).
0. How the numbers were measured (read this first)
- Each frame is a marketing mock-up, so pt = px / (screen width in px / 390 pt). The screen width was measured per frame (colour runs across the screen edge,
bench/lane_h/runs.py), not assumed from the 1242 px canvas. 393-pt Dynamic-Island mocks (Monzo, Wise, Revolut, Cash App, Playtomic) use 393 pt. Row pitches, tile sizes, hairlines and card edges were then measured withbands.py(vertical ink bands inside a pixel column) orruns.py(colour runs), then divided by the scale; I did not read them by eye except where marked "eyeballed". - Scales used (screen px / px per pt): Toss
hi/839333328_{0,2,5}1061 px / 2.72 · 카카오뱅크hi/1258016944_{0,2,7}960 px (x 141–1100) / 2.46 · 카카오페이hi/1464496236_2876 px / 2.25 · 당근hi/1018769995_{1,7}880 px / 2.26 · 네이버hi/393499958_6about 794 px / 2.04 · 카카오톡hi/362057947_5about 859 px / 2.2 · 배민hi/378084485_{2,3}900 px / 2.31 · Bandlane_h/hi/542613198_{2,3}about 955 / 910 px, 2.45 / 2.35 · 테니스프렌즈lane_h/hi/6758872979_{3,5}full-bleed 1242 px / 3.185 (a 414-pt device would be 3.0, so values are up to 6 % higher) · Monzoframes_c/monzo/1052238659_0702 px / 1.786 · Wiseframes_c/wise/612261027_0598 px / 1.52 (low-res mock) · Revolutframes_c/revolut/932493382_6928 px / 2.36 · Cash Appframes_c/cashapp/711923939_0918 px / 2.34 · Playtomicframes_c/playtomic/1242321076_4918 px / 2.354. Spond755596884_5and Strava426826309_5are cropped by the frame edge, so they are described, not measured. - Calibration cross-checks that passed: Toss 송금 button 33 pt (TDS Button "tiny" is 32), Toss account icon 31 pt (TDS AssetIcon
smallis 30), Toss rows 17/13 pt text (TDS2RowTypeCis 17 bold + 13 medium); 카카오톡 avatar 48 pt; Cash App/Monzo side margins 16 pt. Error bar: ±2 pt on sizes below 60 pt, ±4 % on pitches, ±8 % on Wise and 테니스프렌즈. - Font sizes are inferred from ink height (digits/comma lines ≈ 1.04 × font size, plain Hangul lines ≈ 0.9 ×); they are marked "≈". Where TDS gives the exact role, I quote the role.
- Viewport for "% of screen" = 844 pt (390 × 844).
- Seen on disk: Band hi-res and 테니스프렌즈 hi-res were fetched today (
bench/lane_h/hi/) because the earlier lanes only had 222–392 px thumbnails. The 테니스프렌즈 match card measures 105 pt tall at hi-res; the earlier lane's 76–80 pt estimate (lane-b-category.md) came from the thumbnail and should be replaced.
1. Rows beneath a leading block — per app
Column key: pitch = distance between two consecutive row tops (same feature); "sep" = what separates rows; text line sizes are ≈ pt; accents = saturated (C*ab > 30) objects per row; "block → row" = distance from the block's bottom to the first row's top.
| # | App · screen · frame | Block above | Row pitch | Sep | Leading visual | Text lines (≈ pt) | Inline glyphs | Right edge | Accents / row | Block → first row |
|---|---|---|---|---|---|---|---|---|---|---|
| 1 | Toss home · 토스뱅크 header + 최근 쓴 계좌 · hi/839333328_0, crops/toss_f0 | white header card 55 pt on grey #EEF0F2 | 59.4 pt (161.5 px) | none inside the card; one hairline above the footer link row | product logo tile (squircle, pale blue #E0ECFE) 31 pt | 2: 17 bold (digits) / 13 grey | 0 | grey pill 송금/내역, 53 × 33 pt, fill #F0F2F2 (L* 95.3) | 1 (logo) | 62 pt to first icon (label 최근 쓴 계좌 13 grey in between); header card → next card 9.2 pt |
| 2 | Toss 혜택 · flat list, no cards · crops/toss_f5 | title row "혜택 … P 1,000원 >" | 72.6 pt (197 px) | none | 3D glyph on a pale-grey disc #F2F4F6, disc 56 pt | 2: 17 semibold ink / 15 blue link text ("포인트 받기") | 0 | nothing (one "방송중" grey pill) | 2 (glyph, blue sub) | ≈ 28 pt |
| 3 | Toss 증권 · 내 투자 · crops/toss_f2 | no container: 17 bold title, numeral 30/700 (ink 31.7), delta 15 red | first row only | n/a | logo disc 41.6 pt | 2 left 17 / 13, 2 right (17 bold amount, 15 red delta) | 0 | amount + delta, no chevron | 2 (logo, red) | delta → controls 20, → section label 36, → row 25 (numeral top → row top 182 pt) |
| 4 | 카카오뱅크 · 내 계좌 · hi/1258016944_2 | numeral only (총 9개 ≈ 14, 3,456,789원 ink 22.0 ≈ 21–22 bold) on white, 1 px hairline 23 pt under it, no container | 64.6 pt (159 px) | none | bank logo disc 35 pt (one solid brand colour each) | 2–3: ≈ 17 bold / ≈ 14 grey (+ grey 출금가능 line, + outline chip row 36 pt on the first row) | 0 | grey pill 이체 58 × 36.6 pt, fill #F4F4F4 (L* 96.2); no chevron | 1 | numeral bottom → first logo top 50 pt (hairline at +23) |
| 5 | 카카오뱅크 · 홈 · hi/1258016944_0 | hero card 138 pt (gradient border), then a white card with rows | 62.6 pt (154 px) | none | flat-3D pictogram in pale circle 35 pt | 2: ≈ 17 bold / ≈ 13 grey | 0 | pill only on the first row, others empty | 1 | hero → next card 8 pt |
| 6 | 카카오뱅크 mini · hi/1258016944_7 | pale-blue hero card 93.5 pt | 62.6 pt (154 px) | none | pictogram disc 36 pt | 2: ≈ 17 bold / ≈ 14 grey (+ 12 outline micro-chip "82%달성") | 0 | nothing | 1 | hero → next card 9.4 pt; hero → first row text 33 pt |
| 7 | 카카오페이 · 자산 · hi/1464496236_2 | white card, label 14 grey + numeral 17,450,000원 (ink 25.8, ≈ 25/700) | 60.0 pt (135 px) | none | bank logo, rounded square 33.3 pt (bank colour) | 2, label first: 12 grey above, ≈ 17 bold amount below | 0 | grey pill 송금; no chevron | 1 | numeral bottom → logo top 43.6 pt |
| 8 | 당근페이 · 진행중인 거래 · crops/danggeun_f7 | white balance card 149 pt on #F7F8F9, then a 5-icon row | ≈ 68 pt (eyeballed) | thin line inside the card | photo thumb ≈ 42 pt (eyeballed), r ≈ 8 | 2: 14 grey status / ≈ 17 bold amount | 0 | outline pill 자세히 (hairline, not filled) | 0–1 | balance card → icon row 31 pt |
| 9 | 당근 feed · hi/1018769995_1 | filter chip row (전체 = ink-filled chip, others grey) | 147 pt (332 px) | 1 px hairline #F3F4F5, inset to the rail | product photo 116 pt square, r ≈ 8 | 4: ≈ 16 regular / ≈ 13 grey (pin glyph) / ≈ 16 bold price / chip 12 | 1 pin + 2 count glyphs | ⋮ kebab top, like/comment counts bottom | 0–1 (orange-tint "바로구매" chip #FEF2EC) | chips → first photo 16 pt |
| 10 | 네이버 마이 · 최근 본 · crops/naver_f6 | profile line, 멤버십 strip 44 pt, 5-icon service card (white cards r ≈ 16 on #EFF3F8), tab row | 112 pt (229 px) | 1 px hairline, inset to the rail | photo 88 pt square, r ≈ 8 | 3: ≈ 16 regular / ≈ 14 grey / chip 13 (grey tag #F6F6F6) | 1 (magnifier in the chip) | nothing | 0 | tab row → first row 128 pt (notice box 71 pt and a date line between) |
| 11 | 카카오톡 친구 · crops/kakaotalk_f5 | grey info card #F3F3F3, 104 pt, then a 업데이트 프로필 avatar strip | 65.9 pt (145 px) | none | photo avatar, squircle 48 pt | 2: ≈ 17 regular / ≈ 14 grey | 0 | grey pill 선물하기 ≈ 68 × 32 pt, #F4F4F4 | 0 | section header (15 bold + chevron) sits between |
| 12 | 배민 · 배민클럽 list · crops/baemin_f2 | cyan promo banner 135 pt, then "기본순" label | 162 pt (375 px) | 1 px hairline, full-bleed | photo 121 pt, r ≈ 8, purple label bar on it | 5: blue "최근 주문한 가게" / 18 bold name / 14 grey (blue words) / rating row / delivery row + 4 outline tags | ≥ 4 (clock, star, W-circle, 배민클럽 mark) | "광고 ⓘ" grey top-right | ≥ 5 | banner → first thumb 45 pt |
| 13 | Band · home · lane_h/hi/542613198_2 | none (header, 내 밴드 label) | tile grid, not rows: tile 98 pt, column pitch 124 pt, row pitch 147 pt | none, no card | squircle photo tile (corner ≈ 28 % of side, lane C) | 1 caption, 2 lines, ≈ 14, centred | 0 | unread dot (blue) | ≤ 1 | not measured |
| 14 | Monzo · home activity · frames_c/monzo/…_0 | red card 139 pt, then a white Activity card | 62.8 pt (112.5 px) | 1 px hairline inset from logo-left to amount-right | merchant logo, squircle 31.9 pt | 2: ≈ 16 regular / ≈ 12 grey | 0 | amount ≈ 17 (pence smaller; income in green); no chevron | 0–1 | card → Activity card 25 pt; card → first row 83 pt; first two rows are tinted rounded rows (grey, green) 55 pt |
| 15 | Wise · home currencies · frames_c/wise/…_0 | centred numeral + 4 lime circles + segmented tabs on white | 81 pt (123 px) | none | flag circle ≈ 48 pt | 1 line ≈ 20 medium | 0 (the "+" row has one) | chevron | 1 (flag) | segmented track → "Add a currency" row centre 56 pt |
| 16 | Revolut · Invest · frames_c/revolut/…_6 | full-bleed gradient hero (numeral + 4 ghost circles) | 79.6 pt (188 px) | none, dark card #1A1A1A | merchant logo circle 30 pt (group icon 42) | 2: ≈ 17 / ≈ 15 grey; right 2: amount + green delta | 0 | amount + delta | 1 (green delta) | action labels → card 34 pt |
| 17 | Cash App · Money · frames_c/cashapp/…_0 | white card, margin 16 pt, on #F0F0F0 | card rows: 112.6 pt tall, 24.6 pt gap | cards | none (ring / sparkline graphic right) | 3: 17 label / ≈ 38 numeral / 15 grey | 1 (chevron) | ring or sparkline | 1–2 (green) | card → next card 24.6 pt |
| 18 | Playtomic · club home · frames_c/playtomic/…_4 | media hero photo 129 pt, title beneath (24 bold), "Near you" 15 grey, heart outline right, 4 underline tabs | no rows captured | — | — | — | heart (action) | — | 0 | photo → title cap-top 30 pt; title → sub 12 pt; sub → tabs 45 pt |
| 19 | Strava · feed · frames_c/strava/…_5 | none | post, not a row: 6 tiers (avatar-shield + name/meta, title 20, 4 stat columns, photo r ≈ 8, kudos line, 3 action glyphs) | hairline between posts | photo | — | 4 (action targets) | — | 1–2 (orange medals) | not measured (frame cropped) |
| 20 | Spond · group event list · frames_c/spond/…_5 | photo hero with white title and two white chips on the photo, then underline tabs | white cards (r ≈ 6) on grey, with date block (month 11 / day 22 bold), title bold, 2 grey lines, 3 coloured ring counts; red 4-pt left rule when a response is due | cards | date block (text, no photo) | 4 | 3 count glyphs | — | 2–3 | not measured (frame cropped) |
| 21 | 테니스프렌즈 · 홈 match card · lane_h/hi/6758872979_3 | greeting row + banner + empty-state card | card 105.2 pt tall (335 px), 32 pt gap | white card r ≈ 14 | full-height photo thumb 104 pt, flush left | 4: 11 grey club / 14 bold title / 13 bold date / chips 10–11 | 3 (person, ball dot, court-count chip) | dark "마감" chip top, "1/3" bottom | 3 | section title → card 36 pt |
| 22 | 테니스프렌즈 · 내 정보 activity rows · …_5 | lime profile card 141 pt + 3 stat tiles | 49.3 pt (157 px) | 0.6 pt hairline, inset | coloured 24-pt glyph | 1 line ≈ 14 | 1 leading glyph | chevron | 1 | stat tiles → "활동" label 30 pt |
Read-across (Section 6 lists the falsifiable form): the seven Korean fintech/social lists with ≤ 56 pt leading visuals (rows 1, 2, 4, 5, 6, 7, 11) separate rows by space only and put a neutral grey pill or nothing at the right edge; the three thumb-led lists (9, 10, 12) and Monzo (14) use a 1 px hairline; the three commerce/sport lists with ≥ 3 accents per row (12, 21, and Spond) are the only ones with several saturated objects per row.
2. Block anatomy — per app
Column key: margin = distance from screen edge to block edge; pad = inside padding T / R / B / L; "action" = buttons inside the block.
| # | Block · frame | Margin | Pad (T/R/B/L) | Align | Elements in reading order (≈ pt) | Actions (count · style · position) | Radius | Height (% of 844) | Fill | Over the edge? | Gap to content below |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | Toss · 토스뱅크 header · hi/839333328_0 | 8.5 | — / ≈ 26 / — / 22.8 (TDS horizontalPadding medium = 24) | left, one line | title 17 bold, chevron 16 grey right | 0 (whole card is the target; trailing chevron) | ≈ 17 | 55.1 (6.5 %) | white card on #EEF0F2 | no | 9.2 |
| 2 | Toss 증권 · 내 투자 · crops/toss_f2 | 0 (text at 23.5 = TDS medium 24) | none (no container) | left stack | section title 17 bold → numeral 30/700 with chevron → delta 15 red → sort text left + segmented control right (28.7 pt) | 1 segmented control, neutral, right | — | numeral block ≈ 90 pt | white page | no | label → first row 36 + 25 |
| 3 | 카카오뱅크 · 홈 hero · hi/1258016944_0 | 15.9 / 15.5 | 29 / 17.5 / 18 / 17 | left stack, action right | 36-pt brand disc → 17 bold balance → 14 grey account name; second row: two outline chips 35 pt ("세이프박스 990,000원", "저금통") | 1 neutral pill 이체 58 × 36.6 (top-right, centred on the two text lines) + 2 outline chips bottom-left | ≈ 20–24 (eyeballed) | 138 (16.4 %) | pale yellow gradient + 1 px yellow→cyan border | no | 8 |
| 4 | 카카오뱅크 mini · pale hero · hi/1258016944_7 | 15.9 / 16.3 | 27.6 / 17 / 27.6 / 17 | left stack, one row, action right | 36-pt white disc with logo → 97,032원 ≈ 17 bold → "김민희의 mini" ≈ 14 grey-blue | 1 translucent grey pill 이체, right, vertically centred | 17.1 | 93.5 (11.1 %) | solid pale blue #C3DDEC (L* ≈ 87, C* ≈ 12) | no | 9.4 |
| 5 | 당근페이 · 당근머니 card · hi/1018769995_7 | 15.5 | ≈ 17 / 15.5 / 18 / 15.5 | left stack | brand icon 20 + 당근머니 ≈ 17 bold + outline chip 12 ("매월 이자 받기") + chevron → numeral 10,000원 ≈ 25/700 → action row | 2: grey segmented pill [충전 | 송금] 34.5 pt (left) + dark inverse pill 결제 34.5 pt (right) | ≈ 12–16 (edge test 11.5; Seed card r4 = 16) | 149.4 (17.7 %) | white on #F7F8F9 | no | 31 (to icon row) |
| 6 | Monzo · balance card · frames_c/monzo/…_0 | 16.2 | 17 / 13.4 / 10.6 / 13.4 | split rows, left stack | wordmark (white) left + numeral ≈ 34 right → account line 13 left + "Balance" 13 right → pill row | 3: two darker-translucent pills (glyph + label, 31 pt) left, one round "⋯" 31 pt right | 16.8 | 139.4 (16.5 %) | solid #FE3830 (L* 56) | no | 25 |
| 7 | Cash App · Money card · frames_c/cashapp/…_0 | 15.7 | — / — / — / 16.6 | left stack | label 14 grey → numeral ≈ 38/700 (ink 32.3) → meta 16 grey → 2 pills → "Paychecks" row (label + grey amount + chevron) | 2: equal-width black pills 46.3 pt tall, gap 8.5, full width | ≈ 16–20 (eyeballed) | ≥ 150 (top cut) | white on #F0F0F0 | no | 24.6 |
| 8 | 테니스프렌즈 · 프로필 lime · lane_h/hi/6758872979_5 | 19.8 | 18.8 / 19 / 22 / 19.2 | left stack, edit tile right, numeral right | avatar 47 (blue ring) + 12 → name ≈ 16 bold + status ≈ 10–11; row 2: shield glyph + "매너 점수 >" ≈ 10–11 bold left, numeral "36.5" ≈ 20/700 + "/ 100" 14 muted right; bar 6.3 pt tall | 1 translucent tile 31 pt (edit glyph), top-right | 12.6 | 141 (16.7 %) | solid lime #CCFC00 (L* 92.8, C* 98) | soft lime glow ≈ 10 pt below | 21 |
| 9 | 배민 · 한그릇 header · hi/378084485_3 | 0 (full-bleed) | status bar 47 + nav row 45; promo stack centred | centred | back arrow + "한그릇" 17/600 white → sub 14 regular white → headline ≈ 24/800 white, 2 lines → outline bowl glyph bottom-right | 0 | the white tab sheet (top corners ≈ 11, measured at hi/378084485_3) is laid over the block's lower edge | 227 incl. status bar and nav row (26.9 %); promo stack ≈ 135 | solid #7476FE (L* 55.9, C* 77) | yes: the white sheet starts on top of the block (purple visible behind its corner arcs) | 0 (sheet starts at the block's lower edge) |
| 10 | Wise · account · frames_c/wise/…_0 | page rail | none | centred | lime disc 48 → numeral ≈ 46/800 → pill "Account details" 28 pt pale-green with chevron → 4 lime circles 56 pt with 16 labels → segmented tabs | 4 equal circles, evenly spread (outside any container) | circles | — (screen top cropped) | white | no | segmented track → rows ≈ 40 |
| 11 | Revolut · Invest hero · frames_c/revolut/…_6 | full-bleed | centred stack | centred | 15 label → numeral ≈ 48/700 (+ small cents) → delta 15 → 4 ghost circles 60 pt, labels 15 | 4 equal translucent-grey circles, evenly spread | — | — (screen top cropped) | gradient teal → black | the first list card begins as the gradient ends | 34 |
| 12 | Playtomic · club header · frames_c/playtomic/…_4 | 0 (photo full-bleed) | — | left | photo 129 pt → title 24 bold (30 below photo) → "Near you" 15 grey → 4 underline tabs | 1 heart outline, right of the title | photo corners r ≈ 20 at the top | photo 15.3 % | photo | no | tabs → date strip 22 |
Pattern counts (n = 12 blocks above): left-stacked 8 (Toss ×2, 카카오뱅크 ×2, 당근페이, Cash App, 테니스프렌즈, Playtomic), split top row 1 (Monzo), centred 3 (Wise, Revolut, 배민); a single saturated container exists in 4 (Monzo, 테니스프렌즈, 배민, Revolut), a neutral/tinted container in 5; buttons inside or at the block: 0 in 2 (Toss header, 배민), 1 in 5 (Toss 증권 segmented, 카카오뱅크 ×2, 테니스프렌즈, Playtomic heart), ≥ 2 in 5 (Monzo 3, 당근 2, Cash App 2, Wise 4, Revolut 4; equal-width spread in 3 of them: Cash App, Wise, Revolut). Margin to the screen edge: 15.5–16.3 in 5 of 7 contained blocks (카카오뱅크 ×2, 당근, Monzo, Cash App), 19.8 in 테니스프렌즈, 8.5 in Toss. Corner radius 16.8–17.1 in 3 measured blocks (Toss, Monzo, 카카오뱅크 mini), 12.6 in 테니스프렌즈. Height of blocks that carry numeral + meta + action: 138–149 pt (16.4–17.7 %, n = 4: 카카오뱅크 hero, Monzo, 테니스프렌즈, 당근); single-row blocks 55–94 pt (6.5–11.1 %).
3. Design-system row and section specs (actual values)
3.1 Toss TDS Mobile — @toss/tds-mobile 2.5.1 (read from the published package, dist/esm/index.d.ts + dist/esm/index.js, fetched 2026-10-09 with npm pack @toss/tds-mobile)
Docs: https://tossmini-docs.toss.im/tds-mobile/ · https://tossmini-docs.toss.im/tds-mobile/components/ListRow/list-row-components/ · https://tossmini-docs.toss.im/tds-react-native/components/list-row/ (React Native sibling; its verticalPadding ladder differs: 8/16/24/32, default 24).
| Item | Value | Source |
|---|---|---|
| ListRow vertical padding | small 8, medium 12 (default), large 16, xlarge 24 | ListRowProps.verticalPadding JSDoc in index.d.ts |
| ListRow horizontal padding | small 16, medium 24 (default) | ListRowProps.horizontalPadding |
| Row min height | minHeight: 44px | index.js ListRow li style |
| Divider | border: indented (default) or none; the line is 1 px, drawn at the TOP of each row, margin-left: 24px, width calc(100% - 24px), colour token hairLine | index.js (::before, hairlineIndent: 24) |
| Leading asset sizes | AssetSize: xsmall 24 · small 30 · medium 36 · large 40 · xlarge 52 · xxlarge 60. ListRow.AssetIcon takes xsmall/small/medium. AssetImage: square 52 × 52, circle 40 × 40, original image height 56, 3D emoji 40, 2D emoji 24 | index.js size map; docs page "list-row-components" |
| Leading shapes | squircle (default), original, card, circle-background, circle-masking | docs page |
| Text roles, 2 lines | 2RowTypeA 17 bold grey800 + 15 regular grey600 · 2RowTypeB 20 semibold + 15 · 2RowTypeC 17 bold + 13 medium grey600 · 2RowTypeD 15 regular grey600 over 17 bold grey800 (label-first) · 2RowTypeE 15 over 20 semibold · 2RowTypeF 13 medium over 17 bold · right side Right2RowTypeA 17 bold + 15, B 17 bold + 13 | index.js Texts switch |
| Type ladder | t1 30 · t2 26 · t3 22 · t4 20 · t5 17 · t6 15 · t7 13 (1.5 × line height) | CLAUDE.md / TDS typography; ListRow uses t5 → t7 |
| Measured match | Toss home rows 59.4 pt pitch, 31 pt tile, 17/13 text, 24 pt padding = 2RowTypeC, AssetIcon small (30), verticalPadding medium (12 × 2 + 2 lines ≈ 36 + gaps) | frames above |
3.2 당근 SEED — daangn/seed-design, branch dev (pushed 2026-10-08), Rootage specs
Docs: https://seed-design.io/react/components/list (HTTP 200; the page is a props table, the numbers are in the specs) · specs: https://github.com/daangn/seed-design/blob/dev/packages/rootage/components/list-item.yaml · list-header.yaml · divider.yaml · avatar.yaml · image-frame.yaml · tokens packages/rootage/__generated__/{dimension,font-size,line-height,radius}.json (raw copies in bench/lane_h/seed/).
| Item | Value | Source |
|---|---|---|
| ListItem root | paddingY x3 = 12, paddingX global-gutter = x4 = 16, transparent at rest; pressed: background bg.transparent-pressed inset by marginX x1_5 = 6 with radius x2_5 = 10 while the content scales (an inset rounded press surface, not a full-width band — consistent with our no-press-band law) | list-item.yaml |
| Body | gap x0_5 = 2, paddingRight x2_5 = 10 | same |
| Title | t5 = 16 / 22, regular, fg.neutral | same + font-size.json, line-height.json |
| Detail | t3 = 13 / 18, regular, fg.neutral-subtle | same |
| Prefix | paddingRight x3 = 12; prefix icon 22 | same |
| Suffix | gap x1 = 4; suffix text t5 16/22 subtle; suffix icon 18 | same |
| Computed row height | two lines 12 + 22 + 2 + 18 + 12 = 66; one line 46 | derived |
| ListHeader | paddingX 16, paddingY x2 = 8, gap x2_5 = 10, t4 = 14/19; mediumWeak = 500 subtle, boldSolid = 700 neutral | list-header.yaml |
| Divider | thickness 1 px; ListDivider is an explicit sibling, no divider by default | divider.yaml, docs page |
| Avatar sizes | 20, 24, 36, 42, 48, 56, 64, 80, 96, 108 | avatar.yaml |
| ImageFrame | default borderRadius="r2" = 8, optional stroke | docs image-frame.mdx, radius.json |
| Radius ladder | r1 4 · r2 8 · r3 12 · r4 16 · r5 20 · r6 24 · full 9999 | radius.json |
| Spacing tokens | spacing-x.global-gutter 16 · spacing-y.component-default 12 · between-text 6 · nav-to-title 20 | dimension.json |
| Font sizes | t3 13 · t4 14 · t5 16 · t6 18 · t7 20 · t8 22 | font-size.json |
3.3 Band
No public design-system documentation or token source was found (three searches 2026-10-09, Korean and English, results were BAND-IT hardware and ad products). Band values in this note are measured only (lane_h/hi/542613198_{2,3}).
3.4 Our flat primitives (read from packages/ui/src, docs/design/detail-pages-flat-canon-audit-2026-09-05.md)
| Primitive | Value |
|---|---|
Seam ladder SEAM (seams.ts) | element $1 4 · item $2 8 · block/chrome $3 12 · rail/hero/band $4 16 · section $6 24 · tail $9 48 |
FlatColumn | top SEAM.hero 16; gap SEAM.section 24 on both sides of one full-bleed section Divider (flat-column-defaults.ts); Divider = 1 px $borderSubtle (hairline.ts), SEAM.section above and below |
ListRow (list-row-visual.ts) | regular min height 40 (ROW_HEIGHT_LIST), padding-y $2 8, title cardBody; dense 36, padding-y $1 4, title cardMeta; 44-pt touch floor closed by hitSlop; first/last row drop their outer padding (RowList edge rule); rows carry no divider |
FactRow (fact-row-visual.ts) | min height 36, padding $2 per side compact, $3 roomy (rows with a second line); spacing only, never a per-row divider |
CellRow / StatStrip | cell gap 8, cell padding 8, optional 1 px divider with 4 px each side, cell min height 56 |
| Club-detail row canon | row padding-y $3 12, min height 44 (36 dense), avatar 40 (AVATAR_SIZE.MD), leading → text $3 12, title → sub $0/$1, bottom hairline on 4 of 6 rows, rail 16, list tail 48; DuesRow ≤ 1 trailing pill (ActionButton secondary sm shape="pill") |
Avatar ladder (box-sizes.ts) | XS 28 · SM 32 · MD 40 · LG 44 · HERO 56 · XL 80 · 2XL 88; no 48 rung |
Text roles (text.tsx) | pageTitle 24/32·700 · displaySm 20/28·700 · cardTitle 16/24·600 · cardBody 14/22 · cardMeta 13/18 (research: 13/500 secondary) · badge 12/18·600 |
Today's 홈 session card (board render scratchpad/tone-0.png, 121 px card on a 320-px phone) | ≈ 147 pt tall + ≈ 16 pt gap, Card frame, 3 inline glyph lines + recruitment bar + bookmark (≈ 163 pt pitch) |
Takeaway: the club-detail row canon (12 pt padding, 40 pt avatar, 12 pt gap, 64 pt pitch) is already inside the peer band for fintech/social rows; the bulky element today is the Card-framed, 147-pt session card, not the row primitives.
4. Recommended spec for TwoMore (pt; token in brackets; peers each value follows)
Principle: under a leading brand block on a pure-white page, the list is spacing-only, neutral, and one density step quieter than the block. Every value below is a peer median or a design-system value from Sections 1–3; where a peer set splits, the split is stated.
4.1 The seam between block and list (T1 pure white)
| Seam | Value | Follows |
|---|---|---|
| Block bottom → section header | 24 [SEAM.section $6] | Monzo card → Activity card 25; 테니스프렌즈 lime → stat tiles 21; 당근페이 → icon row 31. The 8–9 pt gaps (Toss header, 카카오뱅크 hero and mini) exist only where the next element is another card on a tinted canvas; on white there is nothing to lift from, so they do not apply. |
| Section header → first row | 8 [SEAM.item $2] | Seed ListHeader paddingY 8 (list-header.yaml); Toss 증권 section label → first row 24 |
| Block bottom → first row top, total | 24 + 24 (header line) + 8 = 56 | numeral → first row 43.6 (카카오페이) to 50 (카카오뱅크 내 계좌, with a hairline at +23), Toss 증권 label → row 25, Monzo card → row 83 |
| Row-to-row (no separator) | 24 between a row's last text line and the next row's first line = 2 × 12 [$3] | Toss 23.6 (toss_f0), 카카오페이 21.8, 카카오뱅크 26.8, Monzo ≈ 17–26 |
| Page rail | 16 [$4] | Seed global-gutter 16; Cash App 15.7; Monzo 16.2; 당근페이 15.5; 카카오뱅크 15.9 |
4.2 Row grammar (no Card, no border, no fill; Pressable row; rail 16)
Common: padding-y 12 [$3], leading → text gap 12 [$3] (Seed prefix 12; club canon), title → sub 4 [$1] (Seed body gap 2, DuesRow $1), 0 inline glyphs per row (peers: 0 in 9 of 11 fintech/social lists, 1 in Naver and 당근; glyphs only as action targets), at most 1 saturated object (peers 0–1), right edge holds ONE thing: a neutral pill, a numeral, or nothing — never a chevron next to a pill or numeral.
| Session row, compact (홈, under the day block) | Session row, discovery (번개 찾기) | Club row | Dues row | |
|---|---|---|---|---|
| Leading | venue tile 48 × 48, r 8 [$2]; map tile with 1 px inset $border unless the photo is the venue's own | venue tile 88 × 88, r 8 | ClubAvatar 40 [AVATAR_SIZE.MD] | PersonRow avatar 40 |
| Pitch | 72 (48 + 2 × 12) | 112 (88 + 2 × 12) | 64 (40 + 2 × 12) | 64 |
| Line 1 | start time, promoted: 16/24·700 $text, tabular (the T2 18/700 role if adopted) | venue name 16/24·600 | club name 16/24·600 | member name 16/24·600 |
| Line 2 | venue name 13/18·500 $textSecondary | start time 14/20·700 $text | region 13/18·500 $textSecondary | only what varies: 부분납 or the manager's note, 13/18·500 |
| Line 3 | — | format and tier as MetaSegments, 13/18·500 $textSecondary | — | — |
| Right edge | recruit count "6/8" 13/700 $text; if a state fires (취소, 마감, 진행 중) the canonical SessionStatusBadge 12/18·600 takes the same slot; no chevron | bookmark outline glyph 20 top-right (the one action target) + "6/8" bottom-right 13/700 | none in 내 클럽; one neutral pill 32 tall in discovery lists (가입) | at most one neutral pill 32–36 tall (입금 확인) |
| Separator | none (spacing only) | 1 px hairline inset to the rail, last row none | none | none |
| Accents / inline glyphs | ≤ 1 (status badge) / 0 | ≤ 1 / 0 (bookmark is an action) | 0 / 0 | 0 / 0 |
| Peers followed | Toss 혜택 (56 tile, 72.6 pitch, 17/13); Toss home (17 bold number line over 13 grey, 2RowTypeC); 카카오톡 (48 photo, 65.9); Monzo/Revolut/Toss 증권 (numeral right, no chevron) | Naver 마이 (88 photo, 112, hairline, 3 lines); 당근 feed (kebab top-right, counts bottom-right, hairline); 테니스프렌즈 (1/3 bottom-right) | 카카오톡 friends (name + one grey line, pill right, no separators, 65.9); Toss/카카오뱅크 pill 33 / 36.6, fill #F4F4F4 | Toss home / 카카오뱅크 내 계좌 (bold, grey sub, grey pill, no chevron, no separators) — already how DuesRow is built |
Before → after on 홈 (measured): today's session card ≈ 147 pt + 16 gap (≈ 163 pitch, Card frame, three glyph lines + recruitment bar); compact row 72 pt (−56 %), no frame, no bar, 0 glyphs. Discovery 112 pt vs 163 (−31 %) and still photo-led; the leading tile is the smallest photo size any peer uses (Naver 88).
4.3 Block anatomy (all three blocks share one frame)
Shared frame: margin 16 [$4] (5 of 7 contained peers 15.5–16.3); radius 16 [Seed r4; Toss 16.9, Monzo 16.8, 카카오뱅크 mini 17.1]; padding 16 on all four sides [$4] (peer pads 11–29, median ≈ 17); fill solid $primary, white ink; no shadow, no gradient, no illustration (research row 6); left-stacked (8 of 12 peer blocks); labels 14/20·700 white at alpha 0.8 (research row 7); numeral 36–40/700 (peer "answer" numerals: Cash App ≈ 38, Monzo ≈ 34, Toss 증권 30, Revolut 48, Wise 46); bar 6 tall (테니스프렌즈 6.3); at most ONE action, ghost-inverse (translucent white 16–20 % fill, white 14–15/600 label, label only, no glyph), 32 tall (Toss 33, 테니스프렌즈 31, 카카오뱅크 36.6), min width 56, right edge on the 16 pad, vertically centred on the text block (카카오뱅크 hero and mini put the pill exactly there); bottom gap to the list 24.
| 홈 day block | 기록 ELO block | 프로필 identity block | |
|---|---|---|---|
| Rows, top to bottom | (1) eyebrow 14/20·700 α0.8: relative day + date, e.g. "내일, 9월 19일 (토)", plain text, no pill · gap 4 · (2) numeral row 40: "2" 36/40·700 with unit "개" 15/600 on the baseline · gap 4 · (3) meta 14/20·700 α0.8: "첫 시작 09:00", left-aligned under the numeral, no clock glyph | (1) eyebrow row 20: "ELO" 14/700 α0.8 left, tier text "NTRP 3.5–4.0" 14/700 α0.8 right, plain text · gap 4 · (2) numeral "1,482" 40/44·700 · gap 12 · (3) bar 6, track white α0.28, fill optic · gap 8 · (4) caption "마스터까지 518점" 14/20·700 α0.8 | (1) row 56: avatar 56 [AVATAR_SIZE.HERO] with the optic NTRP chip 24 at bottom-right · gap 12 · name pageTitle 24/32·700 + one sub line 14/20·500 α0.8, vertically centred on the avatar; icon action top-right · gap 12 · (2) row 24: "신뢰 등급 ›" 14/700 α0.8 left, tier value 16/24·700 right |
| Action | 1: pill "일정 보기" at the right edge, centred on the numeral row. Variant without a button: whole block pressable with a trailing chevron 16 α0.8 on the eyebrow row (Toss 토스뱅크 header) | none; whole block pressable, chevron 16 α0.8 after the tier text | 1 icon button 32 ghost-inverse (edit glyph) top-right, aligned to the avatar top (테니스프렌즈 edit tile 31); row 2 tappable, chevron after the label opens TrustTierInfoSheet |
| Height | 16 + 20 + 4 + 40 + 4 + 20 + 16 = 120 (14.2 % of 844) | 16 + 20 + 4 + 44 + 12 + 6 + 8 + 20 + 16 = 146 (17.3 %) | 16 + 56 + 12 + 24 + 16 = 124 (14.7 %); 138 with a bar |
| Peers followed | 카카오뱅크 hero/mini (left stack, pill right-centred, 93–138 pt); Monzo (left/right label row, pills bottom); Cash App (numeral over meta) | 테니스프렌즈 (label row with value right, 6.3 bar, caption); Cash App/Monzo numeral scale; 138–149 pt peer band | 테니스프렌즈 (avatar 47 + 12 gap, name over sub, edit tile top-right, label-left/value-right row 2, 141 pt); 카카오톡 / Spond / Seed avatar 48, Seed 56 |
What was off in T0 (VtDayBlock, VtEloBlock, VtIdentityBlock in visual-tone.jsx) | "첫 시작" with a clock glyph is pushed to the right and bottom-aligned with paddingBottom 4 against a left numeral on another baseline; a qualifier pill sits beside the date; no action slot | a qualifier pill with a gold dot in the eyebrow row; caption left with nothing on the right | a qualifier pill ("신뢰 멤버") under a 28-pt name, then a wrapping row of two glyph+text facts (shield, calendar icons); name 28 vs club canon 24 |
Open choices for the owner (each has peer evidence on both sides): (1) an action pill inside the block versus a pressable block with a chevron (of the nine peers with a container or full-bleed hero, 7 hold buttons: 카카오뱅크 ×2, 당근, Monzo, Cash App, 테니스프렌즈, Revolut; 1 is chevron-only, Toss; 1 has none, 배민 한그릇; Wise's four circles sit outside any container); (2) avatar 56 (our HERO) versus 48 (카카오톡, Spond, Seed, 테니스프렌즈 47) — 48 needs a new AVATAR_SIZE rung, 44 [LG] exists; (3) time-first versus venue-first on the session row (lane C counted 7 of 19 time-led, 6 of 19 title-led); (4) a hairline on thumb-led rows versus the Divider law "rows carry no divider" — every thumb-led peer (당근 116, Naver 88, 배민 121) draws one, as does Monzo with 32-pt logos; (5) no chevron on rows that end in a pill or an amount (9 peer frames: Toss home and 증권, 카카오뱅크 ×2, 카카오페이, 카카오톡, Monzo, Revolut, 당근페이; Wise's rows end in a chevron alone) versus our affordance law "one cue per tappable row"; (6) neutral pill fill: peers use #F4F4F4 / #F0F2F2 (L* 96.2 / 95.3); our proposed control track $borderSubtle #DFE7E1 is L* 90.9 — roughly twice the lightness step from white, so row pills would read as louder than every peer's.
5. Falsifiable observations (each fails if a named frame shows otherwise)
- In the seven Korean fintech/social lists with leading visuals of 31–56 pt (
hi/839333328_0,crops/toss_f5,hi/1258016944_{0,2,7},hi/1464496236_2,crops/kakaotalk_f5), no hairline separates two rows; spacing alone does. Thumb-led lists draw one (hi/1018769995_1,crops/naver_f6,crops/baemin_f2, Monzo…_0). - Two-line rows with a 31–36 pt leading visual have a pitch of 59.4–64.6 pt (Toss 59.4, 카카오페이 60.0, Monzo 62.8, 카카오뱅크 62.6 and 64.6, 카카오뱅크 mini 62.6); median 62.6. A frame outside 56–68 pt falsifies the band.
- Rows that carry an action put a neutral pill at the right edge in 4 of 4 Korean fintech/social frames: Toss
송금(sampled#F0F2F2, L* 95.3), 카카오뱅크이체(#F4F4F4, L* 96.2), 카카오톡선물하기(#F4F4F4); 카카오페이송금reads the same grey but was not sampled. The three sampled pills are 32–37 pt tall and none of the four rows also shows a chevron. A coloured fill on one of those pills falsifies it. - Saturated objects per row: 0–1 in 9 of the 11 fintech/social lists in Section 1 (rows 1, 4–11 and Monzo); 2 in Toss 혜택 and Toss 증권 (a coloured glyph plus one coloured text line); ≥ 3 only in
crops/baemin_f2,lane_h/hi/6758872979_3and Spond. A fintech/social row with 3 accents falsifies it. - Inline glyphs per row: 0 in Toss ×3, 카카오뱅크 ×3, 카카오페이, 카카오톡, Monzo; 1 in Naver (chip magnifier) and 당근 (pin, plus 2 count glyphs bottom-right).
- Row type text pairing: Toss home and 증권 render 17 bold over 13 grey (
TDS 2RowTypeC), 카카오페이 inverts it (12 grey label over 17 bold amount,TDS 2RowTypeD); in both, the NUMBER is the bold line and the name is the grey line. - Of the four solid-colour leading blocks (Monzo, 테니스프렌즈, 배민 한그릇, Revolut), three put the rows on a lifted surface: Monzo and 테니스프렌즈 in white cards (rounded; 테니스프렌즈 r ≈ 12–14), Revolut in a dark card. The fourth, 배민 한그릇 (
hi/378084485_3), is the one precedent for flat hairline rows directly under a solid block: a white sheet whose colour equals the page, with ≈ 11-pt top corners laid over the block's lower edge (purple visible behind the corner arcs, x 170–185, y 1319–1330). The bare-row hubs without a colour block are 카카오뱅크 내 계좌, Toss 증권 and Wise. Counter-evidence needed: a solid-colour block followed by hairline-free rows on a page canvas. - Contained blocks that hold a numeral, a meta line and an action measure 138–149 pt (카카오뱅크 hero 138, Monzo 139.4, 테니스프렌즈 141, 당근페이 149.4), 16.4–17.7 % of an 844-pt screen; single-row blocks 55–94 pt.
- Block margins to the screen edge are 15.5–16.3 pt in five of seven contained blocks; radii measured on edges are 16.8–17.1 pt in three (Toss, Monzo, 카카오뱅크 mini) and 12.6 pt in 테니스프렌즈.
- Blocks hold at most one primary-looking thing: the Monzo pills, 당근 결제, Cash App pills and 카카오뱅크 이체 are all monotone (black, dark ink, translucent grey, darker-tint of the block); no peer block carries a second brand colour or a lime/accent button. A coloured button inside a peer block falsifies it.
- 테니스프렌즈 type is small: smallest labels ≈ 9–10 pt, chips 10–11 pt (
lane_h/hi/6758872979_3, bands in Section 1), below our 13/500 floor; treat its numbers as layout evidence only, not type evidence. - Our own club-detail canon (padding 12, avatar 40, gap 12, pitch 64, one trailing pill) sits inside observation 2's band. The 147-pt Card session card matches only the commerce thumb rows (당근 147, 배민 162); no fintech or social row exceeds 112 pt except those thumb rows.
6. Caveats
- Frames are vendor marketing mock-ups. Dates inside them range from 2025-04 to 2026-02; screens may be staged (Toss 혜택 list, 카카오뱅크 mini). Scale comes from the measured screen width and the assumed 390/393 pt device; a different device width moves every pt value by up to ±6 %. Wise (low-res), 테니스프렌즈 (scale 3.185 vs 3.0) and 네이버/카카오톡 (frame edges read from the rounded outline) carry the largest error.
- Font sizes are inferred from ink height; only Toss is anchored by the TDS role table. Heights of 3-line peers in commerce apps include padding I could not separate.
- Row pitch is measured between repeated features inside the same frame; a first/last row at a card edge is excluded. Monzo's first two rows are tinted highlight rows and are excluded from the 62.8 pitch.
- Strava and Spond frames are cropped by the mock-up; they appear as structure, not as numbers. Playtomic rows were not captured (the frames show a club header and a zoomed marketing card), so there is no Playtomic row measurement.
- Band has no public design-system source; its numbers are measured only.
- The Toss and Seed specs are component defaults, not what each app necessarily ships; the Toss app agreed with TDS on 17/13, 30 pt icons, 24 pt padding, and 32 pt buttons.
- Colour of block fills was sampled as modal pixel colour (
#CCFC00,#FE3830,#7476FE,#C3DDEC); gradients (카카오뱅크 hero, Revolut) were not sampled. - Nothing was viewed on a device, and nothing here was built; spec values are proposals for wireframes, not code changes.
- No sub-agents, no git writes, nothing under the repo modified. The 2026-10-08 benchmark frames were re-used, and Band/테니스프렌즈 hi-res frames were downloaded (public App Store images) into
bench/lane_h/hi/.
Appendix — files
- Contact sheets of the rows-under-block crops:
bench/lane_h/contact-A-kr-fintech-rows.png(Toss ×3, 카카오뱅크 ×3, 카카오페이, 당근페이),bench/lane_h/contact-B-kr-feeds-community-rows.png(당근 feed, Naver, 카카오톡, Band, 배민 한그릇, 테니스프렌즈 ×2),bench/lane_h/contact-C-global-rows.png(Monzo, Wise, Revolut, Cash App, Playtomic, Spond, Strava). Per-crop images inbench/lane_h/rows/. Built withpython3 sample.py --contact <out> <crops…>. - Helpers (each prints the numbers quoted above):
bench/lane_h/bands.py(ink bands in a column),runs.py(colour runs along a line, edge and card finding),radius.pyand the inline bounding-box script (corner radii),grid.py(labelled px grid overlay, used for reading coordinates). - Source copies:
bench/lane_h/seed/*.yaml,tok_*.json(Seed specs and tokens);bench/lane_h/npm/x/package/dist/esm/index.{js,d.ts}(TDS Mobile 2.5.1). - Repo files read for Section 3.4:
packages/ui/src/{seams,flat-column-defaults,divider-visual,hairline,fact-row-visual,row-list-visual,list-row-visual,cell-row-visual,box-sizes,text}.ts(x),packages/features/clubs/src/{club-detail/club-schedule-rows,dues/dues-row}.tsx,packages/app/src/presentation/components/{person-row,sessions/session-card-v2}.tsx,docs/design/detail-pages-flat-language-2026-09-05.md,docs/design/detail-pages-flat-canon-audit-2026-09-05.md,docs/twomore_design_system/wireframes/visual-tone.jsx(VtDayBlock,VtEloBlock,VtIdentityBlock),docs/design/research/colour-system-research-2026-10-09.md§1–§4.