Owner review 6, lane L: the roster role badge, no inline text for actions, and stopping a match (2026-10-12)
Status: Draft · Date: 2026-10-12 · Lane L of owner review 6. Inputs: FvkRoster, FvkTextAction, FvkScoreEntry, FvkScoreStop, FvkHostReviewSheet and FvkToast as built in the kit today, the library (Button, Dialog, overlay rule S-1 to S-7, ScoreEntry, Host review sheet), the review 4 and 5 rulings and lane D, and sources fetched on 2026-10-12. Audience: Korean club members aged 40 to 60. Nothing outside this file was changed.
Owner, review 6. "Rendering the 호스트 or 게스트 badge next to the NTRP rating doesn't look clean. Any good visual improvement suggestion?" And: "the 경기를 끝까지 못 했나요? should be a proper process, not an inline text. No inline text in the honor system. We don't use an inline text for action. How can we get players to terminate the match without completing the score entry? How about 경기 종료 button? Would it be clear enough? Should we then show a modal because it's a destructive action?"
0. Evidence tags and limits
| Tag | Meaning |
|---|---|
| C | Read in our code, kit or library today, with path:line. |
| W | Fetched or searched on 2026-10-12 (link given). Text only, no pixels. |
| X | Not reached. Said so rather than guessed. |
Not reached today:
- Apple HIG and Material 3 pages return only a title through the fetch tool. The HIG points below come from the fetch's summary of the alerts page and are cross-checked against the library's own Dialog rationale (library
Dialog"Why", C). - NN/g's links-versus-buttons article and Toss TDS TextButton docs did not come back in search. No NN/g or TDS claim about text buttons is made below.
- Korean federation (KTA, KATO) wording for retirement and stoppage: a search returned nothing (X). The only attested vocabulary is what the kit already uses (기권, 부전승, 중단, 실격;
flat-v2-kit.jsxstop reasons, C) and the data-feed convention RET and W/O (Sportradar status workflow, via review 4 lane E). - Peer apps for the roster (KakaoTalk, Band, 당근, Meetup, Strava, Slack, Playtomic, Google Meet) were not fetched: only Discord's crown is attested (W). The peer table in §1.2 says which rows are memory and which are fetched.
- The roster was not screenshotted; the geometry in §1.1 is computed from the code (C).
1. The roster role badge
1.1 What the kit draws today (C)
FvkRoster (flat-v2-kit-content.jsx:2923-3010): one row of four cells (two per row from 150% text, line 2937 stacked), each a 48 avatar, 4, the name 15/22·600 centred, then a flex spacer and a 24-high row (line 3000) holding the Level circle (24, grows to 36 at 200%) and, 8 after it, a Tag: 호스트 for the host, 게스트 for a guest. Cell min height 102.
The arithmetic of the clutter, at 390 wide with a 16 rail (cell about 87 wide):
- Level circle 24 + gap 8 + Tag sm (24 high, padding 8 each side, a 13/18·600 label of about 39) = about 79 of 87. The two chips fill the line edge to edge.
- At 150% the cell is about 167 wide but the Level circle is 36 and the label grows: still one line, but the row now reads as "3.5 호스트" as one cluster, which is the owner's complaint. Two different kinds of fact (a skill number and a role) sit on one axis, in similar small chips.
- A role Tag shows in club sessions only (the exception is marked, never the members; comment at line 2919-2922).
1.2 How peers mark an organiser
| Product | Marker | Where | Text or glyph |
|---|---|---|---|
| Discord | Crown for the server owner, so people can find who to contact (Discord support, W) | In the member list, beside the name | Glyph only |
| KakaoTalk open chat (방장) | Crown on the host, a smaller mark for 부방장 (memory, X) | Beside the name in the member list | Glyph |
| Naver Band (리더, 공동리더) | A small "리더" label by the name (memory, X) | After the name | Text |
| 당근 모임 (모임장, 운영진) | A text badge by the name (memory, X) | After the name | Text |
| Meetup (Organizer, Host) | A text label under or beside the name (memory, X) | Name line | Text |
| Google Meet (Host) | Text in the people list, "Meeting host" under the name (memory, X) | Second line under the name | Text |
| Instagram Live | A "LIVE" pill overlapping the bottom edge of the avatar ring (memory, X) | On the avatar, bottom centre | Text pill |
Pattern, to the extent attested: in a list, the role is a glyph or a short text on the name line, never on the skill line. A pill that overlaps the avatar's bottom edge is the state marker on a face grid (the Live case). Nobody puts the role on the same line as a skill rating; only our roster has that rating.
1.3 Three options
All three take the Level circle off the role's line. All keep the name line free (names are never cut, memory rule). The role is spoken through the cell's accessible name in each: "정우진, 호스트, NTRP 3.5" (the Level circle is aria-hidden today, line 520-525 of the kit: the spoken name must carry the level, which is a fix in any option).
A. Avatar pill (recommended). The role is a Tag that overlaps the avatar's bottom edge, centred, like the Live pill.
- Values: Tag sm, 24 high, r6, padding 3 8, 13/18·600 (the kit's Tag, unchanged). Centred on the avatar's centre line; top at avatar top + 36, so it covers the bottom 12 of the 48 face and hangs 12 below it. Edge: 2 of the canvas colour around the pill (a ring so it lifts off the photo; the badged-icon host already uses a 2 ring for the same reason, library "Badged icon").
- The cell reserves the 12 hang for every cell, so names stay aligned across the row: avatar 48, then 12 + 4 gap under the avatar, then the name. Cell min height 102 becomes 114. A cell with no role leaves the space empty (names line up).
- Level circle: alone on the third line, centred (24, up to 36 at 200%), as today but without a neighbour.
- Tone: host = ink tier (strong), guest = neutral weak, so the host is the more visible without colour alone (the word is the signal).
- 200%: two cells per row (about 165 wide), the pill is about 60 wide and fits. The label wraps never (Tag law: one line,
flexShrink: 0). - Trade: it covers 12 of 48 px of the face (25%). Faces are already optional (initials for pickup), and the chin is the least informative part. It adds 12 to the row height and needs a cell with 12 spare under the avatar.
B. Glyph on the avatar, host only. A 20 disc (ink fill, white 12 glyph, 2 canvas ring) at the avatar's bottom right, centre 4 inside the avatar edge (like the notification badge on an icon host). Host only; a guest is marked with the Tag 게스트 under the name in place of the Level circle only when there is no level, otherwise nothing.
- Trade: Discord's crown works because members learn it; a 40-to-60 audience needs a word. A glyph also needs a registry icon we do not have (the kit has no crown or whistle; the brand is "amateur", a crown is the wrong tone). It also leaves the guest unsolved. Not recommended.
C. Role as plain text under the name; Level moves onto the avatar. Name, then a 13/18·500 secondary caption "호스트" or "게스트" with no chip; the Level circle hangs at the avatar's top right as an adornment.
- Trade: the Level circle is 24 to 36 and would cover a large part of a 48 face; shrinking it breaks the Level tag spec (24 / 32 / 36 / 36). It also moves the skill number, which is the thing members scan roster by, onto the photo, where pickup initials discs make it unreadable. A plain caption is quieter but a roster of four with one caption row is a new row type. Not recommended.
1.4 Recommendation
A, the avatar pill. It separates the role from the skill on a different axis (the face versus the line below), keeps the kit's Tag (no new component), reads without learning (a word), and matches the one attested face-grid pattern (a text pill on the avatar edge).
Decided by evidence: the role and the level must not share a line; a glyph alone is not enough for this audience. The owner's taste: whether covering 12 px of the face is acceptable (Q1 if the owner prefers the face fully clear: fall back to a name-line caption, which is a new row).
2. "We do not use inline text for an action"
2.1 What the kit says today
FvkTextAction(flat-v2-kit.jsx:1301-1380): kindlink(goes somewhere, role link) andcommand(does something, role button; 600 ink; the default). It is the only component drawing an action with no container. 44 target by slop.- The library already carries the other half of the answer: Button has a ghost tone ("no fill, ink label, pad 0 12 at every size so the text edge lands on the rail"; library line 1825-1830) and calls it "the quiet text action inside content". So a command with no container already exists as a Button. What the owner objects to is not a quiet verb; it is a sentence ("경기를 끝까지 못 했나요?") floating centred above a CTA, which reads as help text and does not look like something to press.
2.2 Standards
- Material 3: text buttons are the lowest-emphasis button: used for less prominent actions, especially when several options are offered, and in dialogs and cards so they do not compete with content (Android Compose TextButton reference, W; summary of the guidance, W). The label should stay on one line. A text button has its own role and state set; it is a button without a container, not text with a handler.
- Apple HIG: alerts reserve a Cancel and a destructive style for the button that does the destructive thing; reversible actions are better served by undo than by an alert (alerts page summary, W). HIG's plain-style button is likewise a button with button states (memory, X).
- Links versus buttons: the cross-source rule is that buttons are for doing and links are for going; a Button should not be styled as a link nor a link as a button (Wikimedia Codex, W; Balsamiq, W). Exceptions named by the same sources: a localised action such as expanding collapsed text, where a button would be too prominent. NN/g's own article was not reached (X).
- Toss TDS and 당근 Seed text buttons: not reached (X). Wanted's WDS text button is described as the secondary, low-priority button that reduces visual noise (WDS, W): same shape as Material.
The standards agree on one point: a quiet text-looking control is legitimate only as a button (a verb label, a button role, button states, a container-free tone that is still named in the system), and a command drawn as a sentence is the thing to remove.
2.3 Proposed law
A command is a Button. Anything that does something (saves, sends, marks, stops, retries, clears) is drawn with
FvkButtonin a tone and size from the Button spec (ghost for the quiet case); a sentence or a question is never a control. A text action is only a link: it names a place it goes to ("전체 보기 ›", "보기 ›", a Block's door, 이용약관).Exceptions, each earned by a container that already frames the action: (1) the Toast action (되돌리기, 처음부터) follows the snackbar convention of a text action at the right of the bar; (2) the Coachmark action (다음, 알겠어요) and (3) the Notice action (다시 시도, a Notice's action) sit inside a tinted or inverse container where a second container is noise; (4) a disclosure (접기, 펼치기, 더 보기, 답글 n개 더 보기) is an expand control, not a command.
With the law, FvkTextAction kind="command" is used only inside Toast, Coachmark and Notice. Everywhere else it becomes a Button, and kind="command" is renamed (or its default flipped) so a new use cannot slip in; a board check text-command fails a command text action outside those three hosts (same shape as the chevron check, library IA7).
One honest issue the audit found: the Block door (flat-v2-kit-content.jsx:3825) passes kind="command" but is a navigation (it names a place with a chevron). It is a link misclassified; the fix is to make it kind="link" with the eyebrow tone, not a Button.
2.4 Inventory and conversion
| # | Where (file:line) | What it does | Conversion |
|---|---|---|---|
| 1 | flat-v2-kit-controls.jsx:4217 stop link 경기를 끝까지 못 했나요? (ScoreEntry footer) | Opens the stop steps | Button tonal, md/lg, 경기 중단 in a footer pair (§3) |
| 2 | flat-v2-kit-controls.jsx:4581 기록 제외 (Host review sheet footer) | Voids the match | Out of the footer: MenuSheet row behind a header ⋯, then a danger Dialog (§4) |
| 3 | flat-v2-kit-content.jsx:3638 SectionHead command (boards: flat-v2-lib-rows.jsx:1775,1829, flat-v2-list-a.jsx:1109 모두 읽음; flat-v2-list-a.jsx:2068, 3838 선택, flat-v2-list-a.jsx pick) | Marks all read / enters a selection mode | Button ghost, sm (36), right-aligned in the head; its pad 0 12 puts the text edge on the rail (the bleed is already the Button's) |
| 4 | flat-v2-kit-controls.jsx:3693,3694 message bubble 다시 보내기, 삭제 | Resend / delete an unsent message | Two ghost sm Buttons (삭제 danger-toned label), right-aligned under the bubble |
| 5 | flat-v2-kit-controls.jsx:3568 comment 답글 달기 | Opens the reply composer | Kept: a localised action in a dense comment footer (the "localised action where a button is too prominent" exception). Owner may overrule: then ghost sm 13/18 |
| 6 | flat-v2-kit-controls.jsx:3604 답글 n개 더 보기 (chevron down) | Expands replies | Kept: a disclosure, not a command |
| 7 | flat-v2-kit-controls.jsx:2906 Toast action (되돌리기, 처음부터) | Undo / restart | Kept (exception 1): the snackbar convention. Because the standards require a button role, it keeps role=button and the 44 hit slop |
| 8 | flat-v2-kit-chrome.jsx:1177 Coachmark action | Advances / dismisses | Kept (exception 2) |
| 9 | flat-v2-kit-content.jsx:4826 Notice props.action; flat-v2-kit-controls.jsx:3176 offline strip 다시 시도 | Retries / acts on the notice | Kept (exception 3). If a Notice's action is the screen's one action, use an md Button inside the Notice (library Notice: "md for inline actions") |
| 10 | flat-v2-kit-content.jsx:4106 retry label 다시 시도 (statusState error) | Retries a failed action | It is a Button label already (label= swap); no change |
| 11 | flat-v2-kit-content.jsx:3825 Block door kind="command" | Opens a place | Reclassify as kind="link" (not a command) |
| 12 | flat-v2-kit-content.jsx:3510, 3636, flat-v2-kit-chrome.jsx:621,623, flat-v2-list-b.jsx:1687 | Navigate (보기 ›, 전체 보기 ›, 이용약관, 티어 안내 ›) | Kept: links |
| 13 | Boards that pass an action to a Toast: 되돌리기 on flat-v2-lib-controls.jsx:345, flat-v2-lib-overlays.jsx:175,1253,1297,1310,1322, flat-v2-lib-rows.jsx:2488, flat-v2-list-a.jsx:1202; 처음부터 on flat-v2-forms.jsx:1418,2062 | Undo / restart | Kept (exception 1) |
Sweep note: the audit used grep FvkTextAction and command= over the kit and the boards; any FvkTextAction with no kind defaults to command (line 1312), so the unlabelled ones (rows 4, 5, 6, 9 above) were found by reading each call site. A gate that fails a command text action outside Toast, Coachmark and Notice would catch a new one (and needs a canary: a known command text action in a fixture, per the gates-need-canaries rule).
3. Stopping a match without a full score
3.1 Where it starts
Today the only entry is the stop link inside the ScoreEntry sheet, enter mode only (flat-v2-kit-controls.jsx:4217, library line 2948). A player who knows at the court that the match will not finish has, to reach it: 점수 입력 on the row, then the link.
Recommendation: start it from the ScoreEntry sheet, as a footer button. Reasons:
- It is where the player already is when they discover they cannot enter a score; the keypad is up and the next move is "I cannot".
- A button on the match row or the match block would put a second CTA in a card (the canon bars CTAs in cards) and one more thing on every row for a rare event.
- The match's page does not exist as a destination in the honor-system model (the Block door opens the sheet).
3.2 The label
| Candidate | Reading for a 40-to-60 club player | Verdict |
|---|---|---|
| 경기 종료 | "The match is over": true of every match, including the finished ones being scored. The owner's own doubt is right. | No |
| 경기 중단 | "The match was stopped": says the match did not run to its end. Pairs with the existing outcome words 기권 / 부전승 / 중단 / 취소됨. | Yes, with one fix below |
| 중단 기록 | A noun phrase; "record a stop" is clear to an editor, not to a player at the court | No |
| 끝까지 못 했어요 | Plain and kind, but a sentence about the player, not a verb naming the result (Button content rule: "a one- or two-word verb that names the result") | No |
| 기권 | The retirement only; wrong for rain or no-show | No |
The fix: the kit's outcome word 중단 currently means "stopped for rain or time" (suspended; flat-v2-kit-controls.jsx:4262). A button 경기 중단 that opens a list containing 중단 collides. Rename that outcome's Tag word to 일시 중단, keep the long label "비나 시간 때문에 멈췄어요" and the radio unchanged. (Korean federation usage was not found, X: this is a naming decision on kit evidence only; the owner may prefer to keep it and rename the button.)
English: Stop match (two words, sentence case).
3.3 Is a confirmation modal needed?
- NN/g: confirm only serious, hard-to-reverse actions; frequent dialogs train click-through; prefer undo; be specific; name the outcome in the buttons (NN/g, Confirmation dialogs, W). Its sibling article says use undo for reversible changes and a confirm for loss that cannot be undone (NN/g, User control and freedom, W).
- HIG (summary, W): avoid alerts for reversible actions; use a destructive-style button naming the action when an alert is warranted.
- Our own S-1: a Dialog confirms a consequential action; "an undoable action gets a Toast with 되돌리기 instead" (library line 2388, C). The foundational law confirm-consequential-mutation applies to a mutation that is consequential and not otherwise confirmable; its rationale in lane D is that a default on a consequential claim is banned, not that every mutation takes a Dialog.
Is recording a stop destructive? No. It adds a result (a record) rather than removing one. It is reversible three ways: the 8-second Toast undo (되돌리기, library line 505 and the ScoreEntry Content paragraph), the host review (the honor system's appeal path) and the host's own correction. It is consequential for ratings, but the sheet already shows the whole fact before the commit.
So: no modal. The stop steps are the confirmation, if the last screen states the outcome back:
- the last screen's
subnames the outcome and the team in words, e.g. "한 팀이 도중에 그만뒀어요 · 박서연, 이도윤 팀"; the Team lines show the outcome Tag (기권) on that team's line, the same marker the match row will carry; - the commit Button is named by the action ("기권 저장", "부전승 저장", "중단 저장"), not a bare 저장 (Button content rule: never 확인 for a commit);
- the Toast says what was recorded and offers 되돌리기 for 8 s.
One exception earns a Dialog: 기록에서 제외 (void), host and officials only, since it strikes the match from every player's record. A danger Dialog: title "이 경기를 기록에서 뺄까요?", body "두 팀의 기록과 레이팅에 반영되지 않아요", buttons 닫기 (tonal, one third) and 기록에서 빼기 (danger, two thirds). The Dialog law needs a named object and a consequence, which this has. Its audience is the host, who is also the one who can undo it from the review list (if it can: Q2).
3.4 Recommendation, in full
Footer. In enter mode the footer is a Button pair, the tonal on the left at one third and the primary at two thirds (the Dialog-pair geometry the Button spec already defines; library line 1827): 경기 중단 (tonal) and 점수 저장 (primary, soft until the score is valid). The stop link is deleted. In appeal and host modes there is no stop button (unchanged).
- Values: lg 52, gap 12, in the 350 line the tonal is about 113 wide and the primary about 225; 경기 중단 at 17/24·600 is about 68 plus 40 padding, which fits at 100%. At 150% and 200% the pair stacks with the commit on top (library Button "200% text" rule).
- Risk: a stop button next to Save on a keypad sheet can be mis-tapped. Mitigation is geometry (the tonal is a third of the line, left, away from the thumb) and the next screen being a choice, not a commit: tapping 경기 중단 only opens "무슨 일이 있었나요?".
Steps (merge two screens into one by sequential reveal, the wizard law; the kit's Reason and Who screens are separate today, flat-v2-kit-controls.jsx:4283-4325):
- Reason (title "무슨 일이 있었나요?", back arrow): four radio Cells (host and officials see six). On choosing 기권, 부전승 or 실격 a second group is revealed below on the same screen, titled "어느 팀이에요?", two radio Cells (the player's own team marked (나)). 중단 and 취소됨 reveal nothing. Footer: one primary 다음, soft until the needed choices are made.
- Score so far (the keypad up, optional for 부전승 and 취소됨): the Team lines with the outcome Tag; a 중단 also asks "이어서 할까요?" with the two radio Cells. Footer: one primary named by the outcome: 기권 저장, 부전승 저장, 중단 저장, 취소 저장. (취소됨 uses the label 경기 취소 저장 so that a bare 취소 never appears.)
- Done: the Sheet closes and a Toast says 기권으로 기록했어요 with 되돌리기 (8 s), withdrawing it while nobody has appealed and no later match has started (the same rule as a saved score).
Taps for a retirement: 점수 입력, 경기 중단, reason, team, 다음, the four digits of 6-4 3-1, the commit = 11, against 13 today (the old count is 7 non-digit taps plus 4 digits). Without digits (a walkover): 점수 입력, 경기 중단, reason, team, 다음, commit = 6.
Every screen and its copy (Korean in the app; English as the i18n pair):
| Screen | Title | Body | Footer |
|---|---|---|---|
| ScoreEntry (enter) | match name | set table | 경기 중단 (tonal, 1/3) · 점수 저장 (primary, 2/3); "Stop match" · "Save score" |
| Stop 1 | 무슨 일이 있었나요? / What happened? | four or six radio Cells; revealed: 어느 팀이에요? / Which team? | 다음 / Next |
| Stop 2 | 그때까지 점수 / The score so far | set table with outcome Tag; for 중단: 이어서 할까요? radios | 기권 저장 / Save as retired (and the other outcomes) |
| Toast | none | 기권으로 기록했어요 / Recorded as retired | 되돌리기 / Undo (8 s) |
| Void Dialog (host only) | 이 경기를 기록에서 뺄까요? | 두 팀의 기록과 레이팅에 반영되지 않아요 | 닫기 · 기록에서 빼기 |
3.5 What is decided by evidence and what is taste
Decided by evidence: no modal for a reversible, additive record (NN/g, HIG, our S-1); a Dialog for the one subtractive outcome (void); the button is a Button (law §2.3); 경기 종료 is ambiguous. The owner's taste: the label 경기 중단 against 기권 (Q3 below), and whether a pair in the footer is wanted over a single Button plus a Menu (Q4).
4. The host review sheet
Today (flat-v2-kit-controls.jsx:4521-4640): the footer holds the centred text action 기록 제외, 8 above the pair 그대로 유지 (tonal) and 점수 고치기 / 이 점수로 바꾸기 (primary).
4.1 Options
A. Radios and one 저장 (the owner's example). Rows 그대로 유지, {이름} 님이 말한 점수로 (only with a proposal), 점수 고치기, 기록에서 제외, then one 저장.
- Gain: one grammar for a decision with several mutually exclusive outcomes; no inline text; one primary.
- Cost: the common path (keep the score) goes from 1 tap to 2, and soft-disabling 저장 until a pick is made is needed (a default on a consequential claim is banned, lane D). A host clearing three reviews pays 3 extra taps. 점수 고치기 would have to open the keypad after 저장, so the radio hides a step, and 기록에서 제외 would sit in a flat list beside harmless options with no Dialog (breaks §3.3).
B. Keep the pair, move the rare destructive action into a MenuSheet (recommended). The footer is the pair only: 그대로 유지 (tonal, one third) and 점수 고치기 or 이 점수로 바꾸기 (primary, two thirds), no centred text. A ⋯ IconButton in the Sheet's title row (beside ×) opens a MenuSheet titled with the match, with one row 기록에서 제외; choosing it asks the void Dialog of §3.3. This is rule S-2 (a command for an object) plus S-1 (confirm a consequential action), already in the library's overlay table.
- Gain: the 80 percent path stays at 1 tap; the destructive one is rare, gets the confirm it deserves, and is out of the thumb zone; the footer is the library's pair exactly.
- Cost: the rare path takes 3 taps (⋯, row, Dialog button) and the action is less discoverable. The sheet's
Controlsline changes from "two buttons, one text action" to "two buttons, one icon". - Accessibility: the IconButton has an
aria-labelof "더보기" (the registry's overflow label), so the action is reachable by a screen reader.
4.2 Recommendation
B. Evidence: the review is a short decision made many times by the host; the rare, subtractive outcome is the only one that needs friction (NN/g: reserve confirmation for the serious, avoid it for routine). The owner's radio idea (A) is the better form if the host review is meant to be a considered, one-off decision per match; at three or more reviews a session it is a cost. The owner's taste decides, Q5.
5. Questions for the owner
- Roster. Is covering the bottom 12 px of the face with the 호스트 / 게스트 pill acceptable? (If not: a name-line caption, which is a new row.)
- Void. Can the host restore a match that was voided from the review list? If not, the void Dialog's body must say "되돌릴 수 없어요".
- The label. 경기 중단 for the button, and rename the rain outcome's word to 일시 중단 so the two do not collide. Agreed?
- The footer. A tonal 경기 중단 beside 점수 저장 in the keypad sheet (a mis-tap risk, mitigated by geometry), or a single 점수 저장 and a ⋯ menu holding 경기 중단?
- Host review. The pair with the void behind a ⋯ menu (B, recommended), or radios and one 저장 (A)?
- Comment 답글 달기. Keep as a text action under the "localised action" exception, or convert to a ghost sm Button?
6. Implementation
Kit and library (wireframes first, per the wireframe-first rule; REGROUND per board only):
flat-v2-kit-content.jsxFvkRoster(line 2923): the role Tag moves to the avatar's bottom edge (Option A values in §1.3), the cell min height 102 becomes 114, the Level circle sits alone on its line, and the cell's spoken name carries the role and the level ("{이름}, 호스트, NTRP {n}"); update the header comment (line 2919).flat-v2-kit.jsxFvkTextAction(line 1312): flip the defaultkindfromcommandtolink; keepcommandonly for Toast, Coachmark and Notice hosts.flat-v2-kit-content.jsxline 3825: the Block door becomeskind="link"; line 3638: SectionHeadcommanddraws a ghost smFvkButton.flat-v2-kit-controls.jsxlines 3693-3694: resend and delete become ghost sm Buttons.flat-v2-kit-controls.jsxFvkScoreEntry(line 4094): delete the stop link block (line 4210-4220), render aFvkButtonPairin enter mode (경기 중단 tonal, 점수 저장 primary);FvkScoreStop(line 4267): merge the reason and who screens by sequential reveal, rename the last button to the outcome-named commit, thesubstates the outcome and the team, add the outcome Tag to the Team lines; rename the suspended outcome Tag word to 일시 중단 inFVK_STOP_REASONS(line 4256 onwards) and inFVK_OUTCOMES.flat-v2-kit-controls.jsxFvkHostReviewSheet(line 4521): remove the centred 기록 제외 block (line 4570-4580); add the ⋯ IconButton in the title row and a MenuSheet board; add the void Dialog board.docs/design/flat-v2-component-library-2026-10-09.md: Button (add the law: a command is a Button; text actions are links; the three exceptions), ScoreEntry (Door, Anatomy item 4, Stop step, Content, Accessibility), Host review sheet (Anatomy, Controls), Roster spec and the Tag Label; the overlay table (void Dialog, S-1; the MenuSheet row, S-2); the verb "경기 종료" is not used.- Boards:
flat-v2-lib-rows.jsx(id="roster", lines 1979-2030, and the 모두 읽음 heads at 1775 and 1829),flat-v2-detail.jsx(the session page roster at line 785; the ScoreEntry and host review boards at 2187-3034),flat-v2-list-a.jsx(1109, 2068, 3838),flat-v2-lib-social.jsx(1032, 1351),flat-v2-lib-controls.jsxandflat-v2-lib-overlays.jsx(Toast, unchanged). - Verifier: a board check
text-command(fails acommandtext action outside Toast, Coachmark and Notice) with a canary fixture that contains one on purpose; extend therostercheck so a Tag never shares the Level circle's line; extend the name-line check to the pill. - Terminology:
docs/design/terminology-guide.md(경기 중단, 일시 중단, 기권 저장; "경기 종료" reserved for the ordinary end); the i18n pairs in §3.4. - App code (after the boards are marked): the
Pressable-basedTextActionequivalents inpackages/ui/src, the score sheet inpackages/features/sessions/src/scorecard/, the roster in the session detail feature; a newdocs/architecture/screen-blueprint.mdentry for the changed screens.