merge: 로컬 글자 크기 개선과 최신 원격 main 통합

This commit is contained in:
2026-09-16 00:41:02 +00:00
82 changed files with 3660 additions and 368 deletions
@@ -0,0 +1,2914 @@
{
"main": {
"lobby.info": {
"result": {
"data": {
"myGeneral": {
"id": 7,
"name": "가나다라마바사아자"
},
"serverId": "che_fixture_season",
"profile": "che",
"gameIdx": 101,
"year": 185,
"month": 1,
"turnTerm": 10,
"serverTime": "2026-08-13T00:00:00.000Z",
"serverWallTime": "2026-08-13T00:00:00.000Z",
"clockMode": "realtime",
"clockRunning": true,
"clockStartsAt": null,
"clockRecovery": null,
"turnEngineRunning": true,
"scenarioTitle": "",
"autorunUser": null
}
}
},
"auth.status": {
"result": {
"data": {
"ok": true
}
}
},
"dashboard.getContextBundleDelta": {
"result": {
"data": {
"context": {
"kind": "snapshot",
"revision": "AAAAAAAAAAAAAAAAAAAAAA",
"data": {
"general": {
"id": 7,
"name": "가나다라마바사아자",
"nationId": 1,
"cityId": 1,
"troopId": 7,
"npcState": 0,
"officerLevel": 12,
"officerLevelText": "군주",
"officerCityName": null,
"generalType": "용장",
"leadershipBonus": 6,
"picture": null,
"imageServer": 0,
"stats": {
"leadership": 70,
"strength": 60,
"intelligence": 50
},
"gold": 1000,
"rice": 2000,
"crew": 300,
"train": 80,
"atmos": 90,
"injury": 0,
"experience": 100,
"dedication": 200,
"age": 25,
"retirementYear": 70,
"defenceTrain": 80,
"killTurn": 5,
"remainingMinutes": 7,
"troop": {
"name": "백마대",
"status": "present",
"leaderCityName": "업"
},
"refreshScore": {
"current": 3,
"total": 120,
"text": "보통"
},
"progression": {
"experienceLevel": 1,
"dedicationLevel": 2,
"statExperience": {
"leadership": 5,
"strength": 10,
"intelligence": 15
},
"statUpgradeLimit": 20,
"dex": [350, 100000, 500000, 1000000, 1275975]
},
"items": {
"horse": null,
"weapon": null,
"book": null,
"item": null
},
"itemNames": {
"horse": "적토마",
"weapon": "청룡언월도",
"book": "육도",
"item": "옥벽"
},
"crewTypeId": 1100,
"crewTypeName": "보병",
"traits": {
"personal": "대담",
"specialDomestic": "상재",
"specialWar": "무쌍"
},
"turnTime": "0185-01-01T00:00:00.000Z",
"nextTurnMonthOffset": 0
},
"city": {
"id": 1,
"name": "업",
"level": 8,
"levelName": "특",
"nationId": 1,
"nationName": "대한민국천하통일국",
"nationColor": "#008000",
"region": 1,
"regionName": "중원",
"population": 100000,
"populationMax": 200000,
"agriculture": 1000,
"agricultureMax": 2000,
"commerce": 1000,
"commerceMax": 2000,
"security": 1000,
"securityMax": 2000,
"trust": 80,
"trade": 100,
"defence": 1000,
"defenceMax": 2000,
"wall": 1000,
"wallMax": 2000,
"supplyState": 1,
"frontState": 0,
"state": 0,
"officers": {
"2": {
"id": 10,
"name": "가나다라마바사아자",
"npcState": 6
},
"3": {
"id": 9,
"name": "가나다라마바사아자",
"npcState": 2
},
"4": {
"id": 8,
"name": "가나다라마바사아자",
"npcState": 0
}
}
},
"nation": {
"id": 1,
"name": "가나다라마바사아자",
"color": "#008000",
"level": 3,
"gold": 10000,
"rice": 20000,
"tech": 100,
"rate": 20,
"bill": 100,
"capitalCityId": 1,
"typeCode": "che_유가",
"typeName": "유가",
"typePros": "농상↑ 민심↑",
"typeCons": "쌀수입↓",
"population": {
"cityCount": 2,
"current": 150000,
"max": 620500
},
"crew": {
"generalCount": 2,
"current": 500,
"max": 7000
},
"power": 1234,
"taxRate": 20,
"strategicCommandLimit": 2,
"diplomaticLimit": 0,
"prohibitScout": false,
"prohibitWar": true,
"techLevel": 0,
"techLimited": false,
"topChiefs": {
"11": {
"id": 2,
"name": "가나다라마바사아자",
"npcState": 1
},
"12": {
"id": 1,
"name": "가나다라마바사아자",
"npcState": 0
}
},
"impossibleStrategicCommands": [
{
"name": "수몰",
"remainingTurns": 2,
"availableYear": 190,
"availableMonth": 5
}
]
},
"settings": {},
"penalties": {}
},
"sourceRevision": "AAAAAAAAAAAAAAAAAAAAAA"
},
"commandTable": {
"kind": "snapshot",
"revision": "CCCCCCCCCCCCCCCCCCCCCC",
"sourceRevision": "CCCCCCCCCCCCCCCCCCCCCC",
"data": {
"general": [],
"nation": [],
"inputOptions": {
"cities": [
{
"value": 1,
"label": "도시 1"
},
{
"value": 2,
"label": "도시 2"
},
{
"value": 3,
"label": "도시 3"
},
{
"value": 4,
"label": "도시 4"
},
{
"value": 5,
"label": "도시 5"
},
{
"value": 6,
"label": "도시 6"
},
{
"value": 7,
"label": "도시 7"
},
{
"value": 8,
"label": "도시 8"
},
{
"value": 9,
"label": "도시 9"
},
{
"value": 10,
"label": "도시 10"
},
{
"value": 11,
"label": "도시 11"
},
{
"value": 12,
"label": "도시 12"
},
{
"value": 13,
"label": "도시 13"
},
{
"value": 14,
"label": "도시 14"
},
{
"value": 15,
"label": "도시 15"
},
{
"value": 16,
"label": "도시 16"
},
{
"value": 17,
"label": "도시 17"
},
{
"value": 18,
"label": "도시 18"
},
{
"value": 19,
"label": "도시 19"
},
{
"value": 20,
"label": "도시 20"
}
],
"nations": [],
"generals": [],
"crewTypes": [],
"armTypes": [],
"nationTypes": [],
"colors": [],
"items": {}
}
}
},
"boardAccess": {
"kind": "snapshot",
"revision": "DDDDDDDDDDDDDDDDDDDDDD",
"sourceRevision": "DDDDDDDDDDDDDDDDDDDDDD",
"data": {
"permission": 4,
"canMeeting": true,
"canSecret": true
}
}
}
}
},
"world.getState": {
"result": {
"data": {
"currentYear": 185,
"currentMonth": 1,
"tickSeconds": 600,
"config": {
"npcMode": 1,
"const": {},
"environment": {}
},
"meta": {}
}
}
},
"world.getMapLayout": {
"result": {
"data": {
"mapName": "che",
"cityList": [
{
"id": 1,
"name": "업",
"level": 8,
"region": 1,
"x": 200,
"y": 120,
"path": []
}
],
"regionMap": {
"1": "하북"
},
"levelMap": {
"8": "특"
}
}
}
},
"turns.reserved.getGeneral": {
"result": {
"data": {
"turns": [],
"revision": 0,
"autorunLimit": null
}
}
},
"general.getRecentRecords": {
"result": {
"data": {
"global": [
{
"id": 3,
"text": "장수 동향 기록"
}
],
"general": [
{
"id": 2,
"text": "개인 기록"
}
],
"history": [
{
"id": 1,
"text": "중원 정세 기록"
}
]
}
}
},
"general.getFrontStatus": {
"result": {
"data": {
"serverId": "che_fixture_season",
"onlineUserCount": 1,
"onlineNations": "위(1)",
"onlineGenerals": "메뉴검증장수",
"nationNotice": "<p>국가 방침</p>",
"lastExecuted": "2026-08-13T00:05:06.000Z",
"latestVote": {
"id": 9,
"title": "메뉴 설문",
"hasVoted": false
}
}
}
},
"tournament.getState": {
"result": {
"data": {
"stage": 5,
"type": 0
}
}
},
"world.getMap": {
"result": {
"data": {
"result": true,
"version": 0,
"startYear": 180,
"year": 185,
"month": 1,
"cityList": [[1, 8, 0, 1, 1, 1]],
"nationList": [[1, "대한민국천하통일국", "#008000", 1]],
"spyList": {},
"shownByGeneralList": [],
"myCity": 1,
"myNation": 1
}
}
},
"messages.getRecent": {
"result": {
"data": {
"private": [],
"national": [],
"public": [],
"diplomacy": [],
"permission": 4,
"sequence": -1,
"hasMore": {
"private": false,
"national": false,
"public": false,
"diplomacy": false
},
"latestRead": {
"private": 0,
"national": 0,
"public": 0,
"diplomacy": 0
},
"canRespondDiplomacy": false
}
}
},
"messages.getContacts": {
"result": {
"data": {
"nation": []
}
}
}
},
"chief": {
"lobby.info": {
"result": {
"data": {
"myGeneral": {
"id": 1,
"name": "가나다라마바사아자"
},
"year": 200,
"month": 1,
"turnTerm": 10,
"userCnt": 1,
"maxUserCnt": 100,
"npcCnt": 0,
"nationCnt": 2
}
}
},
"auth.status": {
"result": {
"data": {
"ok": true
}
}
},
"nation.getChiefCenter": {
"result": {
"data": {
"me": {
"id": 1,
"officerLevel": 5,
"nationId": 1
},
"nation": {
"id": 1,
"name": "대한민국천하통일국",
"level": 1
},
"currentYear": 200,
"currentMonth": 1,
"turnTermMinutes": 10,
"maxTurns": 12,
"chiefs": [
{
"officerLevel": 12,
"name": "가나다라마바사아자",
"npcState": 0,
"turnTime": "2026-08-30T01:46:47.590Z",
"revision": 0,
"turns": [
{
"index": 0,
"action": "che_포상",
"args": {
"destGeneralId": 2,
"isGold": false,
"amount": 300
}
},
{
"index": 1,
"action": "휴식",
"args": {}
},
{
"index": 2,
"action": "휴식",
"args": {}
},
{
"index": 3,
"action": "휴식",
"args": {}
},
{
"index": 4,
"action": "휴식",
"args": {}
},
{
"index": 5,
"action": "휴식",
"args": {}
},
{
"index": 6,
"action": "휴식",
"args": {}
},
{
"index": 7,
"action": "휴식",
"args": {}
},
{
"index": 8,
"action": "휴식",
"args": {}
},
{
"index": 9,
"action": "휴식",
"args": {}
},
{
"index": 10,
"action": "휴식",
"args": {}
},
{
"index": 11,
"action": "휴식",
"args": {}
}
]
},
{
"officerLevel": 10,
"name": "가나다라마바사아자",
"npcState": 0,
"turnTime": "2026-08-30T01:46:47.590Z",
"revision": 0,
"turns": [
{
"index": 0,
"action": "휴식",
"args": {}
},
{
"index": 1,
"action": "휴식",
"args": {}
},
{
"index": 2,
"action": "휴식",
"args": {}
},
{
"index": 3,
"action": "휴식",
"args": {}
},
{
"index": 4,
"action": "휴식",
"args": {}
},
{
"index": 5,
"action": "휴식",
"args": {}
},
{
"index": 6,
"action": "휴식",
"args": {}
},
{
"index": 7,
"action": "휴식",
"args": {}
},
{
"index": 8,
"action": "휴식",
"args": {}
},
{
"index": 9,
"action": "휴식",
"args": {}
},
{
"index": 10,
"action": "휴식",
"args": {}
},
{
"index": 11,
"action": "휴식",
"args": {}
}
]
},
{
"officerLevel": 8,
"name": "가나다라마바사아자",
"npcState": 2,
"turnTime": "2026-08-30T01:46:47.590Z",
"revision": 0,
"turns": [
{
"index": 0,
"action": "휴식",
"args": {}
},
{
"index": 1,
"action": "휴식",
"args": {}
},
{
"index": 2,
"action": "휴식",
"args": {}
},
{
"index": 3,
"action": "휴식",
"args": {}
},
{
"index": 4,
"action": "휴식",
"args": {}
},
{
"index": 5,
"action": "휴식",
"args": {}
},
{
"index": 6,
"action": "휴식",
"args": {}
},
{
"index": 7,
"action": "휴식",
"args": {}
},
{
"index": 8,
"action": "휴식",
"args": {}
},
{
"index": 9,
"action": "휴식",
"args": {}
},
{
"index": 10,
"action": "휴식",
"args": {}
},
{
"index": 11,
"action": "휴식",
"args": {}
}
]
},
{
"officerLevel": 6,
"name": "가나다라마바사아자",
"npcState": 0,
"turnTime": "2026-08-30T01:46:47.590Z",
"revision": 0,
"turns": [
{
"index": 0,
"action": "휴식",
"args": {}
},
{
"index": 1,
"action": "휴식",
"args": {}
},
{
"index": 2,
"action": "휴식",
"args": {}
},
{
"index": 3,
"action": "휴식",
"args": {}
},
{
"index": 4,
"action": "휴식",
"args": {}
},
{
"index": 5,
"action": "휴식",
"args": {}
},
{
"index": 6,
"action": "휴식",
"args": {}
},
{
"index": 7,
"action": "휴식",
"args": {}
},
{
"index": 8,
"action": "휴식",
"args": {}
},
{
"index": 9,
"action": "휴식",
"args": {}
},
{
"index": 10,
"action": "휴식",
"args": {}
},
{
"index": 11,
"action": "휴식",
"args": {}
}
]
},
{
"officerLevel": 11,
"name": "가나다라마바사아자",
"npcState": 0,
"turnTime": "2026-08-30T01:46:47.590Z",
"revision": 0,
"turns": [
{
"index": 0,
"action": "휴식",
"args": {}
},
{
"index": 1,
"action": "휴식",
"args": {}
},
{
"index": 2,
"action": "휴식",
"args": {}
},
{
"index": 3,
"action": "휴식",
"args": {}
},
{
"index": 4,
"action": "휴식",
"args": {}
},
{
"index": 5,
"action": "휴식",
"args": {}
},
{
"index": 6,
"action": "휴식",
"args": {}
},
{
"index": 7,
"action": "휴식",
"args": {}
},
{
"index": 8,
"action": "휴식",
"args": {}
},
{
"index": 9,
"action": "휴식",
"args": {}
},
{
"index": 10,
"action": "휴식",
"args": {}
},
{
"index": 11,
"action": "휴식",
"args": {}
}
]
},
{
"officerLevel": 9,
"name": "가나다라마바사아자",
"npcState": 0,
"turnTime": "2026-08-30T01:46:47.590Z",
"revision": 0,
"turns": [
{
"index": 0,
"action": "휴식",
"args": {}
},
{
"index": 1,
"action": "휴식",
"args": {}
},
{
"index": 2,
"action": "휴식",
"args": {}
},
{
"index": 3,
"action": "휴식",
"args": {}
},
{
"index": 4,
"action": "휴식",
"args": {}
},
{
"index": 5,
"action": "휴식",
"args": {}
},
{
"index": 6,
"action": "휴식",
"args": {}
},
{
"index": 7,
"action": "휴식",
"args": {}
},
{
"index": 8,
"action": "휴식",
"args": {}
},
{
"index": 9,
"action": "휴식",
"args": {}
},
{
"index": 10,
"action": "휴식",
"args": {}
},
{
"index": 11,
"action": "휴식",
"args": {}
}
]
},
{
"officerLevel": 7,
"name": "가나다라마바사아자",
"npcState": 0,
"turnTime": "2026-08-30T01:46:47.590Z",
"revision": 0,
"turns": [
{
"index": 0,
"action": "휴식",
"args": {}
},
{
"index": 1,
"action": "휴식",
"args": {}
},
{
"index": 2,
"action": "휴식",
"args": {}
},
{
"index": 3,
"action": "휴식",
"args": {}
},
{
"index": 4,
"action": "휴식",
"args": {}
},
{
"index": 5,
"action": "휴식",
"args": {}
},
{
"index": 6,
"action": "휴식",
"args": {}
},
{
"index": 7,
"action": "휴식",
"args": {}
},
{
"index": 8,
"action": "휴식",
"args": {}
},
{
"index": 9,
"action": "휴식",
"args": {}
},
{
"index": 10,
"action": "휴식",
"args": {}
},
{
"index": 11,
"action": "휴식",
"args": {}
}
]
},
{
"officerLevel": 5,
"name": "가나다라마바사아자",
"npcState": 0,
"turnTime": "2026-08-30T01:46:47.590Z",
"revision": 0,
"turns": [
{
"index": 0,
"action": "휴식",
"args": {}
},
{
"index": 1,
"action": "휴식",
"args": {}
},
{
"index": 2,
"action": "휴식",
"args": {}
},
{
"index": 3,
"action": "휴식",
"args": {}
},
{
"index": 4,
"action": "휴식",
"args": {}
},
{
"index": 5,
"action": "휴식",
"args": {}
},
{
"index": 6,
"action": "휴식",
"args": {}
},
{
"index": 7,
"action": "휴식",
"args": {}
},
{
"index": 8,
"action": "휴식",
"args": {}
},
{
"index": 9,
"action": "휴식",
"args": {}
},
{
"index": 10,
"action": "휴식",
"args": {}
},
{
"index": 11,
"action": "휴식",
"args": {}
}
]
}
]
}
}
},
"turns.getCommandTable": {
"result": {
"data": {
"general": [
{
"category": "계략",
"values": [
{
"key": "che_화계",
"name": "화계",
"reqArg": true,
"possible": false,
"status": "blocked",
"reason": "현재 조건에서는 실행할 수 없습니다.",
"inputFields": [
{
"key": "destCityId",
"label": "대상 도시",
"kind": "select",
"required": true,
"optionSource": "cities"
}
]
},
{
"key": "che_선동",
"name": "선동",
"reqArg": true,
"possible": true,
"status": "needsInput",
"inputFields": [
{
"key": "destCityId",
"label": "대상 도시",
"kind": "select",
"required": true,
"optionSource": "cities"
}
]
},
{
"key": "che_탈취",
"name": "탈취",
"reqArg": true,
"possible": true,
"status": "needsInput",
"inputFields": [
{
"key": "destCityId",
"label": "대상 도시",
"kind": "select",
"required": true,
"optionSource": "cities"
}
]
},
{
"key": "che_파괴",
"name": "파괴",
"reqArg": true,
"possible": true,
"status": "needsInput",
"inputFields": [
{
"key": "destCityId",
"label": "대상 도시",
"kind": "select",
"required": true,
"optionSource": "cities"
}
]
}
]
},
{
"category": "내정",
"values": [
{
"key": "che_징병",
"name": "징병",
"reqArg": true,
"possible": true,
"status": "needsInput",
"inputFields": [
{
"key": "crewType",
"label": "병종",
"kind": "select",
"required": true,
"optionSource": "crewTypes"
},
{
"key": "amount",
"label": "수량",
"kind": "number",
"required": true,
"min": 0,
"step": 1
}
]
},
{
"key": "che_모병",
"name": "모병",
"reqArg": true,
"possible": true,
"status": "needsInput",
"inputFields": [
{
"key": "crewType",
"label": "병종",
"kind": "select",
"required": true,
"optionSource": "crewTypes"
},
{
"key": "amount",
"label": "수량",
"kind": "number",
"required": true,
"min": 0,
"step": 1
}
]
}
]
},
{
"category": "군사",
"values": [
{
"key": "che_출병",
"name": "출병",
"reqArg": true,
"possible": true,
"status": "needsInput",
"inputFields": [
{
"key": "destCityId",
"label": "대상 도시",
"kind": "select",
"required": true,
"optionSource": "cities"
}
]
},
{
"key": "che_첩보",
"name": "첩보",
"reqArg": true,
"possible": true,
"status": "needsInput",
"inputFields": [
{
"key": "destCityId",
"label": "대상 도시",
"kind": "select",
"required": true,
"optionSource": "cities"
}
]
}
]
}
],
"nation": [
{
"category": "인사",
"values": [
{
"key": "che_발령",
"name": "발령",
"reqArg": true,
"possible": true,
"status": "needsInput",
"inputFields": [
{
"key": "destGeneralId",
"label": "대상 장수",
"kind": "select",
"required": true,
"optionSource": "generals"
},
{
"key": "destCityId",
"label": "대상 도시",
"kind": "select",
"required": true,
"optionSource": "cities"
}
]
},
{
"key": "che_포상",
"name": "포상",
"reqArg": true,
"possible": true,
"status": "needsInput",
"inputFields": [
{
"key": "isGold",
"label": "물자",
"kind": "boolean",
"required": true
},
{
"key": "amount",
"label": "수량",
"kind": "number",
"required": true,
"min": 0,
"step": 1
},
{
"key": "destGeneralId",
"label": "대상 장수",
"kind": "select",
"required": true,
"optionSource": "generals"
}
]
},
{
"key": "che_몰수",
"name": "몰수",
"reqArg": true,
"possible": true,
"status": "needsInput",
"inputFields": [
{
"key": "isGold",
"label": "물자",
"kind": "boolean",
"required": true
},
{
"key": "amount",
"label": "수량",
"kind": "number",
"required": true,
"min": 0,
"step": 1
},
{
"key": "destGeneralId",
"label": "대상 장수",
"kind": "select",
"required": true,
"optionSource": "generals"
}
]
},
{
"key": "che_부대탈퇴지시",
"name": "부대 탈퇴 지시",
"reqArg": true,
"possible": true,
"status": "needsInput",
"inputFields": [
{
"key": "destGeneralId",
"label": "대상 장수",
"kind": "select",
"required": true,
"optionSource": "generals"
}
]
}
]
},
{
"category": "외교",
"values": [
{
"key": "che_물자원조",
"name": "원조",
"reqArg": true,
"possible": true,
"status": "needsInput",
"inputFields": [
{
"key": "destNationId",
"label": "대상 국가",
"kind": "select",
"required": true,
"optionSource": "nations"
},
{
"key": "amountList",
"label": "지원 물자",
"kind": "numberTuple",
"required": true,
"min": 0,
"step": 1,
"tupleLabels": ["금", "쌀"]
}
]
},
{
"key": "che_불가침제의",
"name": "불가침 제의",
"reqArg": true,
"possible": true,
"status": "needsInput",
"inputFields": [
{
"key": "destNationId",
"label": "대상 국가",
"kind": "select",
"required": true,
"optionSource": "nations"
},
{
"key": "year",
"label": "기간(년)",
"kind": "number",
"required": true,
"min": 191,
"max": 210,
"step": 1,
"defaultValue": 191
},
{
"key": "month",
"label": "기간(월)",
"kind": "number",
"required": true,
"min": 1,
"max": 12,
"step": 1,
"defaultValue": 1
}
]
},
{
"key": "che_선전포고",
"name": "선전포고",
"reqArg": true,
"possible": true,
"status": "needsInput",
"inputFields": [
{
"key": "destNationId",
"label": "대상 국가",
"kind": "select",
"required": true,
"optionSource": "nations"
}
]
},
{
"key": "che_종전제의",
"name": "종전 제의",
"reqArg": true,
"possible": true,
"status": "needsInput",
"inputFields": [
{
"key": "destNationId",
"label": "대상 국가",
"kind": "select",
"required": true,
"optionSource": "nations"
}
]
},
{
"key": "che_불가침파기제의",
"name": "불가침 파기 제의",
"reqArg": true,
"possible": true,
"status": "needsInput",
"inputFields": [
{
"key": "destNationId",
"label": "대상 국가",
"kind": "select",
"required": true,
"optionSource": "nations"
}
]
}
]
},
{
"category": "특수",
"values": [
{
"key": "che_초토화",
"name": "초토화",
"reqArg": true,
"possible": true,
"status": "needsInput",
"inputFields": [
{
"key": "destCityId",
"label": "대상 도시",
"kind": "select",
"required": true,
"optionSource": "cities"
}
]
},
{
"key": "che_천도",
"name": "천도",
"reqArg": true,
"possible": true,
"status": "needsInput",
"inputFields": [
{
"key": "destCityId",
"label": "대상 도시",
"kind": "select",
"required": true,
"optionSource": "cities"
}
]
},
{
"key": "che_증축",
"name": "증축",
"reqArg": false,
"possible": true,
"status": "available",
"inputFields": []
},
{
"key": "che_감축",
"name": "감축",
"reqArg": false,
"possible": true,
"status": "available",
"inputFields": []
}
]
},
{
"category": "전략",
"values": [
{
"key": "che_백성동원",
"name": "백성동원",
"reqArg": true,
"possible": true,
"status": "needsInput",
"inputFields": [
{
"key": "destCityId",
"label": "대상 도시",
"kind": "select",
"required": true,
"optionSource": "cities"
}
]
},
{
"key": "che_수몰",
"name": "수몰",
"reqArg": true,
"possible": true,
"status": "needsInput",
"inputFields": [
{
"key": "destCityId",
"label": "대상 도시",
"kind": "select",
"required": true,
"optionSource": "cities"
}
]
},
{
"key": "che_허보",
"name": "허보",
"reqArg": true,
"possible": true,
"status": "needsInput",
"inputFields": [
{
"key": "destCityId",
"label": "대상 도시",
"kind": "select",
"required": true,
"optionSource": "cities"
}
]
},
{
"key": "che_이호경식",
"name": "이호경식",
"reqArg": true,
"possible": true,
"status": "needsInput",
"inputFields": [
{
"key": "destNationId",
"label": "대상 국가",
"kind": "select",
"required": true,
"optionSource": "nations"
}
]
},
{
"key": "che_급습",
"name": "급습",
"reqArg": true,
"possible": true,
"status": "needsInput",
"inputFields": [
{
"key": "destNationId",
"label": "대상 국가",
"kind": "select",
"required": true,
"optionSource": "nations"
}
]
},
{
"key": "che_피장파장",
"name": "피장파장",
"reqArg": true,
"possible": true,
"status": "needsInput",
"inputFields": [
{
"key": "destNationId",
"label": "대상 국가",
"kind": "select",
"required": true,
"optionSource": "nations"
},
{
"key": "commandType",
"label": "대응 명령",
"kind": "select",
"required": true,
"options": [
{
"value": "che_수몰",
"label": "수몰"
}
]
}
]
}
]
}
],
"inputOptions": {
"cities": [
{
"value": 1,
"label": "업 (아국)"
},
{
"value": 2,
"label": "허창 (적국)",
"description": "적국 · 예주 · 대도시"
},
{
"value": 3,
"label": "단양 (오)"
}
],
"nations": [
{
"value": 1,
"label": "아국",
"color": "#008000"
},
{
"value": 2,
"label": "적국",
"color": "#800000",
"description": "수도 허창"
},
{
"value": 3,
"label": "불가침국",
"color": "#000080",
"description": "수도 단양"
}
],
"nationTargets": {
"che_물자원조": [
{
"value": 2,
"label": "적국",
"color": "#800000",
"availableNow": true,
"description": "현재 원조 대상 · 교역"
},
{
"value": 3,
"label": "불가침국",
"color": "#000080",
"availableNow": true,
"description": "현재 원조 대상 · 불가침 12턴"
},
{
"value": 1,
"label": "아국",
"color": "#008000",
"availableNow": false,
"description": "아국은 대상이 아닙니다."
}
],
"che_불가침제의": [
{
"value": 2,
"label": "적국",
"color": "#800000",
"availableNow": true,
"description": "현재 제의 가능 · 교역"
},
{
"value": 3,
"label": "불가침국",
"color": "#000080",
"availableNow": true,
"description": "현재 제의 가능 · 불가침 12턴"
},
{
"value": 1,
"label": "아국",
"color": "#008000",
"availableNow": false,
"description": "아국은 대상이 아닙니다."
}
],
"che_선전포고": [
{
"value": 2,
"label": "적국",
"color": "#800000",
"availableNow": true,
"description": "현재 선전포고 가능 · 교역"
},
{
"value": 3,
"label": "불가침국",
"color": "#000080",
"availableNow": false,
"description": "현재 외교 관계에서는 선전포고 불가"
},
{
"value": 1,
"label": "아국",
"color": "#008000",
"availableNow": false,
"description": "아국은 대상이 아닙니다."
}
],
"che_종전제의": [
{
"value": 2,
"label": "적국",
"color": "#800000",
"availableNow": true,
"description": "현재 종전 제의 가능 · 전쟁 6턴"
},
{
"value": 3,
"label": "불가침국",
"color": "#000080",
"availableNow": false,
"description": "전쟁·선포 중인 국가가 아닙니다."
},
{
"value": 1,
"label": "아국",
"color": "#008000",
"availableNow": false,
"description": "아국은 대상이 아닙니다."
}
],
"che_불가침파기제의": [
{
"value": 3,
"label": "불가침국",
"color": "#000080",
"availableNow": true,
"description": "현재 불가침 파기 제의 가능 · 불가침 12턴"
},
{
"value": 2,
"label": "적국",
"color": "#800000",
"availableNow": false,
"description": "불가침 중인 국가가 아닙니다."
},
{
"value": 1,
"label": "아국",
"color": "#008000",
"availableNow": false,
"description": "아국은 대상이 아닙니다."
}
]
},
"generals": [
{
"value": 1,
"label": "장수 (아국 · 업)"
},
{
"value": 2,
"label": "관우 (아국 · 업)"
}
],
"generalTargets": {
"che_포상": [
{
"value": 1,
"label": "장수 (업)",
"gold": 5000,
"rice": 400,
"crew": 500,
"description": "금 5,000 · 쌀 400 · 병력 500"
},
{
"value": 2,
"label": "관우 (업)",
"gold": 100,
"rice": 4000,
"crew": 1200,
"troopId": 2,
"description": "금 100 · 쌀 4,000 · 병력 1,200"
},
{
"value": 3,
"label": "여포NPC (업)",
"npcState": 2,
"gold": 3000,
"rice": 500,
"crew": 1500,
"troopId": 2,
"description": "금 3,000 · 쌀 500 · 병력 1,500"
}
],
"che_몰수": [
{
"value": 1,
"label": "장수 (업)",
"gold": 5000,
"rice": 400,
"crew": 500,
"description": "금 5,000 · 쌀 400 · 병력 500"
},
{
"value": 2,
"label": "관우 (업)",
"gold": 100,
"rice": 4000,
"crew": 1200,
"troopId": 2,
"description": "금 100 · 쌀 4,000 · 병력 1,200"
},
{
"value": 3,
"label": "여포NPC (업)",
"npcState": 2,
"gold": 3000,
"rice": 500,
"crew": 1500,
"troopId": 2,
"description": "금 3,000 · 쌀 500 · 병력 1,500"
}
],
"che_발령": [
{
"value": 1,
"label": "장수 (업)",
"targetNames": {
"name": "장수",
"nationName": "대한민국천하통일국",
"cityName": "업",
"troopName": null
},
"description": "통솔 70 · 무력 80 · 지력 90\n병력 500 · 훈련 0 · 사기 0\n금 5,000 · 쌀 400",
"gold": 5000,
"rice": 400,
"crew": 500,
"troopId": 0,
"npcState": 0
},
{
"value": 2,
"label": "관우 (업)",
"targetNames": {
"name": "관우",
"nationName": "대한민국천하통일국",
"cityName": "업",
"troopName": "청룡대"
},
"description": "통솔 100 · 무력 95 · 지력 70\n병력 1,200 · 훈련 80 · 사기 70\n금 100 · 쌀 4,000",
"gold": 100,
"rice": 4000,
"crew": 1200,
"troopId": 2,
"npcState": 0
},
{
"value": 3,
"label": "여포NPC (업)",
"targetNames": {
"name": "여포NPC",
"nationName": "대한민국천하통일국",
"cityName": "업",
"troopName": "청룡대"
},
"description": "통솔 90 · 무력 100 · 지력 0\n병력 1,500 · 훈련 100 · 사기 100\n금 3,000 · 쌀 500",
"gold": 3000,
"rice": 500,
"crew": 1500,
"troopId": 2,
"npcState": 2
}
],
"che_부대탈퇴지시": [
{
"value": 3,
"label": "여포NPC (아국 · 업)",
"npcState": 2,
"availableNow": true,
"crew": 1500,
"troopId": 2,
"description": "현재 탈퇴 지시 가능 · 병력 1,500 · 탑승 부대 청룡대"
},
{
"value": 1,
"label": "장수 (아국 · 업)",
"availableNow": false,
"crew": 500,
"description": "현재 탈퇴 지시 불가 · 탑승 부대 없음"
},
{
"value": 2,
"label": "관우 (아국 · 업)",
"availableNow": false,
"crew": 1200,
"troopId": 2,
"description": "현재 탈퇴 지시 불가 · 탑승 부대 청룡대 (부대장)"
}
]
},
"crewTypes": [
{
"value": 1100,
"label": "보병"
}
],
"armTypes": [
{
"value": 1,
"label": "보병"
}
],
"nationTypes": [
{
"value": "che_도적",
"label": "도적",
"description": "금 수입 증가, 쌀 수입 감소"
}
],
"colors": [
{
"value": 0,
"label": "색상 1",
"color": "#ff0000"
}
],
"items": {
"horse": [
{
"value": "None",
"label": "판매/해제"
}
]
},
"recruitment": {
"techLevel": 1,
"leadership": 68,
"fullLeadership": 70,
"currentCrewTypeId": 1100,
"currentCrewTypeName": "보병",
"crew": 500,
"gold": 12345,
"groups": [
{
"armType": 1,
"armName": "보병",
"values": [
{
"id": 1100,
"armType": 1,
"name": "보병",
"available": true,
"special": false,
"attack": 125,
"defence": 175,
"speed": 7,
"avoid": 10,
"baseCost": 10.35,
"baseRice": 10.35,
"info": ["표준적인 보병입니다.", "보병은 방어특화입니다."]
},
{
"id": 1101,
"armType": 1,
"name": "정예병",
"available": false,
"special": true,
"attack": 175,
"defence": 225,
"speed": 8,
"avoid": 20,
"baseCost": 13.8,
"baseRice": 11.5,
"info": [
"강력하지만 기술이 필요합니다.",
"기술력 2000 이상 필요",
"중원 지역 소유시 가능",
"저 소유시 가능"
]
}
]
}
]
},
"amountPresets": {
"che_포상": {
"values": [100, 500, 1000, 5000, 10000],
"defaultValue": 1000,
"min": 100,
"max": 10000,
"step": 1
},
"che_몰수": {
"values": [100, 500, 1000, 5000, 10000],
"defaultValue": 1000,
"min": 100,
"max": 10000,
"step": 1
},
"che_물자원조": {
"values": [10000, 20000, 30000],
"defaultValue": 1000,
"min": 1000,
"max": 30000,
"step": 10
}
},
"context": {
"actorGold": 1000,
"actorRice": 1000,
"citySecurity": 500,
"nationGold": 5000,
"nationRice": 6000,
"nationLevel": 1
}
}
}
}
},
"world.getMap": {
"result": {
"data": {
"result": true,
"version": 0,
"startYear": 180,
"year": 200,
"month": 1,
"cityList": [
[1, 8, 0, 1, 1, 1],
[2, 7, 41, 2, 2, 1]
],
"nationList": [
[1, "대한민국천하통일국", "#008000", 1],
[2, "대한민국천하통일국", "#800000", 2]
],
"spyList": {},
"shownByGeneralList": [],
"myCity": 1,
"myNation": 1
}
}
},
"world.getMapLayout": {
"result": {
"data": {
"mapName": "che",
"cityList": [
{
"id": 1,
"name": "업",
"level": 8,
"region": 1,
"x": 100,
"y": 100,
"path": [2]
},
{
"id": 2,
"name": "허창",
"level": 7,
"region": 2,
"x": 240,
"y": 180,
"path": [1]
}
],
"regionMap": {
"1": "하북",
"2": "예주"
},
"levelMap": {
"7": "대",
"8": "특"
}
}
}
}
},
"personnel": {
"lobby.info": {
"result": {
"data": {
"myGeneral": {
"id": 1,
"name": "가나다라마바사아자"
}
}
}
},
"auth.status": {
"result": {
"data": {
"ok": true
}
}
},
"nation.getPersonnelInfo": {
"result": {
"data": {
"me": {
"id": 1,
"officerLevel": 12,
"canManage": true,
"canChangePermissions": true,
"canKick": true
},
"nation": {
"id": 1,
"name": "대한민국천하통일국",
"color": "#777777",
"level": 3,
"typeCode": "che_법가",
"capitalCityId": 1,
"chiefSet": 0
},
"chiefStatMin": 65,
"generals": [
{
"id": 1,
"name": "가나다라마바사아자",
"npcState": 0,
"officerLevel": 12,
"cityId": 1,
"cityName": "허창",
"troopId": 0,
"troopName": null,
"picture": "default.jpg",
"imageServer": 0,
"officerCity": 0,
"officerCityName": null,
"stats": {
"leadership": 70,
"strength": 70,
"intelligence": 70
},
"experience": 100,
"dedication": 200,
"injury": 0,
"gold": 1000,
"rice": 1000,
"crew": 100,
"personality": null,
"specialDomestic": null,
"specialWar": null,
"belong": 10,
"permission": "normal"
},
{
"id": 2,
"name": "가나다라마바사아자",
"npcState": 0,
"officerLevel": 11,
"cityId": 1,
"cityName": "허창",
"troopId": 0,
"troopName": null,
"picture": "default.jpg",
"imageServer": 0,
"officerCity": 0,
"officerCityName": null,
"stats": {
"leadership": 70,
"strength": 70,
"intelligence": 70
},
"experience": 100,
"dedication": 200,
"injury": 0,
"gold": 1000,
"rice": 1000,
"crew": 100,
"personality": null,
"specialDomestic": null,
"specialWar": null,
"belong": 10,
"permission": "normal"
},
{
"id": 3,
"name": "가나다라마바사아자",
"npcState": 0,
"officerLevel": 4,
"cityId": 1,
"cityName": "허창",
"troopId": 0,
"troopName": null,
"picture": "default.jpg",
"imageServer": 0,
"officerCity": 1,
"officerCityName": "허창",
"stats": {
"leadership": 70,
"strength": 70,
"intelligence": 70
},
"experience": 100,
"dedication": 200,
"injury": 0,
"gold": 1000,
"rice": 1000,
"crew": 100,
"personality": null,
"specialDomestic": null,
"specialWar": null,
"belong": 10,
"permission": "normal"
},
{
"id": 4,
"name": "가나다라마바사아자",
"npcState": 0,
"officerLevel": 3,
"cityId": 1,
"cityName": "허창",
"troopId": 0,
"troopName": null,
"picture": "default.jpg",
"imageServer": 0,
"officerCity": 1,
"officerCityName": "허창",
"stats": {
"leadership": 70,
"strength": 70,
"intelligence": 70
},
"experience": 100,
"dedication": 200,
"injury": 0,
"gold": 1000,
"rice": 1000,
"crew": 100,
"personality": null,
"specialDomestic": null,
"specialWar": null,
"belong": 10,
"permission": "normal"
},
{
"id": 5,
"name": "가나다라마바사아자",
"npcState": 0,
"officerLevel": 2,
"cityId": 1,
"cityName": "허창",
"troopId": 0,
"troopName": null,
"picture": "default.jpg",
"imageServer": 0,
"officerCity": 1,
"officerCityName": "허창",
"stats": {
"leadership": 70,
"strength": 70,
"intelligence": 70
},
"experience": 100,
"dedication": 200,
"injury": 0,
"gold": 1000,
"rice": 1000,
"crew": 100,
"personality": null,
"specialDomestic": null,
"specialWar": null,
"belong": 10,
"permission": "normal"
},
{
"id": 6,
"name": "가나다라마바사아자",
"npcState": 2,
"officerLevel": 1,
"cityId": 1,
"cityName": "허창",
"troopId": 0,
"troopName": null,
"picture": "default.jpg",
"imageServer": 0,
"officerCity": 0,
"officerCityName": null,
"stats": {
"leadership": 70,
"strength": 70,
"intelligence": 70
},
"experience": 100,
"dedication": 200,
"injury": 0,
"gold": 1000,
"rice": 1000,
"crew": 100,
"personality": null,
"specialDomestic": null,
"specialWar": null,
"belong": 10,
"permission": "normal"
},
{
"id": 7,
"name": "가나다라마바사아자",
"npcState": 0,
"officerLevel": 1,
"cityId": 1,
"cityName": "허창",
"troopId": 0,
"troopName": null,
"picture": "default.jpg",
"imageServer": 0,
"officerCity": 0,
"officerCityName": null,
"stats": {
"leadership": 70,
"strength": 70,
"intelligence": 70
},
"experience": 100,
"dedication": 200,
"injury": 0,
"gold": 1000,
"rice": 1000,
"crew": 100,
"personality": null,
"specialDomestic": null,
"specialWar": null,
"belong": 10,
"permission": "ambassador"
},
{
"id": 8,
"name": "가나다라마바사아자",
"npcState": 0,
"officerLevel": 1,
"cityId": 1,
"cityName": "허창",
"troopId": 0,
"troopName": null,
"picture": "default.jpg",
"imageServer": 0,
"officerCity": 0,
"officerCityName": null,
"stats": {
"leadership": 70,
"strength": 70,
"intelligence": 70
},
"experience": 100,
"dedication": 200,
"injury": 0,
"gold": 1000,
"rice": 1000,
"crew": 100,
"personality": null,
"specialDomestic": null,
"specialWar": null,
"belong": 10,
"permission": "auditor"
},
{
"id": 9,
"name": "가나다라마바사아자",
"npcState": 0,
"officerLevel": 1,
"cityId": 1,
"cityName": "허창",
"troopId": 0,
"troopName": null,
"picture": "default.jpg",
"imageServer": 0,
"officerCity": 0,
"officerCityName": null,
"stats": {
"leadership": 70,
"strength": 70,
"intelligence": 70
},
"experience": 100,
"dedication": 200,
"injury": 0,
"gold": 1000,
"rice": 1000,
"crew": 100,
"personality": null,
"specialDomestic": null,
"specialWar": null,
"belong": 10,
"permission": "normal"
}
],
"chiefAssignments": {
"11": {
"id": 2,
"name": "가나다라마바사아자",
"npcState": 0,
"officerLevel": 11,
"cityId": 1,
"cityName": "허창",
"troopId": 0,
"troopName": null,
"picture": "default.jpg",
"imageServer": 0,
"officerCity": 0,
"officerCityName": null,
"stats": {
"leadership": 70,
"strength": 70,
"intelligence": 70
},
"experience": 100,
"dedication": 200,
"injury": 0,
"gold": 1000,
"rice": 1000,
"crew": 100,
"personality": null,
"specialDomestic": null,
"specialWar": null,
"belong": 10,
"permission": "normal"
},
"12": {
"id": 1,
"name": "가나다라마바사아자",
"npcState": 0,
"officerLevel": 12,
"cityId": 1,
"cityName": "허창",
"troopId": 0,
"troopName": null,
"picture": "default.jpg",
"imageServer": 0,
"officerCity": 0,
"officerCityName": null,
"stats": {
"leadership": 70,
"strength": 70,
"intelligence": 70
},
"experience": 100,
"dedication": 200,
"injury": 0,
"gold": 1000,
"rice": 1000,
"crew": 100,
"personality": null,
"specialDomestic": null,
"specialWar": null,
"belong": 10,
"permission": "normal"
}
},
"cityAssignments": [
{
"id": 1,
"name": "허창",
"level": 7,
"region": 2,
"officerSet": 8,
"officers": {
"2": {
"id": 5,
"name": "가나다라마바사아자",
"npcState": 0,
"officerLevel": 2,
"cityId": 1,
"cityName": "허창",
"troopId": 0,
"troopName": null,
"picture": "default.jpg",
"imageServer": 0,
"officerCity": 1,
"officerCityName": "허창",
"stats": {
"leadership": 70,
"strength": 70,
"intelligence": 70
},
"experience": 100,
"dedication": 200,
"injury": 0,
"gold": 1000,
"rice": 1000,
"crew": 100,
"personality": null,
"specialDomestic": null,
"specialWar": null,
"belong": 10,
"permission": "normal"
},
"3": {
"id": 4,
"name": "가나다라마바사아자",
"npcState": 0,
"officerLevel": 3,
"cityId": 1,
"cityName": "허창",
"troopId": 0,
"troopName": null,
"picture": "default.jpg",
"imageServer": 0,
"officerCity": 1,
"officerCityName": "허창",
"stats": {
"leadership": 70,
"strength": 70,
"intelligence": 70
},
"experience": 100,
"dedication": 200,
"injury": 0,
"gold": 1000,
"rice": 1000,
"crew": 100,
"personality": null,
"specialDomestic": null,
"specialWar": null,
"belong": 10,
"permission": "normal"
},
"4": {
"id": 3,
"name": "가나다라마바사아자",
"npcState": 0,
"officerLevel": 4,
"cityId": 1,
"cityName": "허창",
"troopId": 0,
"troopName": null,
"picture": "default.jpg",
"imageServer": 0,
"officerCity": 1,
"officerCityName": "허창",
"stats": {
"leadership": 70,
"strength": 70,
"intelligence": 70
},
"experience": 100,
"dedication": 200,
"injury": 0,
"gold": 1000,
"rice": 1000,
"crew": 100,
"personality": null,
"specialDomestic": null,
"specialWar": null,
"belong": 10,
"permission": "normal"
}
}
},
{
"id": 2,
"name": "낙양",
"level": 6,
"region": 2,
"officerSet": 0,
"officers": {
"2": null,
"3": null,
"4": null
}
}
],
"awards": {
"tigers": [
{
"id": 3,
"name": "하후돈",
"value": 12
}
],
"eagles": [
{
"id": 4,
"name": "곽가",
"value": 9
}
]
},
"permissionCandidates": {
"ambassadors": [
{
"id": 6,
"name": "가나다라마바사아자",
"npcState": 0,
"permission": "normal",
"maxPermission": 4
},
{
"id": 7,
"name": "가나다라마바사아자",
"npcState": 0,
"permission": "ambassador",
"maxPermission": 4
},
{
"id": 9,
"name": "가나다라마바사아자",
"npcState": 0,
"permission": "normal",
"maxPermission": 4
}
],
"auditors": [
{
"id": 6,
"name": "가나다라마바사아자",
"npcState": 0,
"permission": "normal",
"maxPermission": 4
},
{
"id": 8,
"name": "가나다라마바사아자",
"npcState": 0,
"permission": "auditor",
"maxPermission": 4
},
{
"id": 9,
"name": "가나다라마바사아자",
"npcState": 0,
"permission": "normal",
"maxPermission": 4
}
]
}
}
}
}
},
"possession": {
"lobby.info": {
"result": {
"data": {
"myGeneral": null,
"year": 180,
"month": 1,
"turnTerm": 5
}
}
},
"auth.status": {
"result": {
"data": {
"ok": true
}
}
},
"join.getConfig": {
"result": {
"data": {
"rules": {
"stat": {
"total": 165,
"min": 15,
"max": 80,
"bonusMin": 3,
"bonusMax": 5
},
"allowDirectCreation": false,
"allowCustomName": true
},
"user": {
"id": "npc-user",
"displayName": "빙의사용자",
"canCreateGeneral": true,
"icons": [],
"preferredPicture": null
},
"personalities": [
{
"key": "Random",
"name": "???",
"info": ""
}
],
"warSpecials": [],
"nations": [],
"serverInfo": {
"currentYear": 180,
"currentMonth": 1,
"tickMinutes": 5,
"maxGeneral": 500,
"userGeneralCount": 0,
"npcGeneralCount": 12
},
"inherit": {
"totalPoint": 0,
"costs": {
"inheritBornSpecialPoint": 0,
"inheritBornTurntimePoint": 0,
"inheritBornCityPoint": 0,
"inheritBornStatPoint": 0
},
"availableCities": [],
"turnTimeZones": [],
"availableSpecialWar": []
},
"selectionPool": {
"enabled": false
},
"npcPossession": {
"enabled": true
}
}
}
},
"join.listPossessCandidates": {
"result": {
"data": {
"tokenNonce": 101,
"validUntil": "2026-09-15T15:10:08.460Z",
"pickMoreFrom": "2026-09-15T15:08:37.460Z",
"pickMoreSeconds": 0,
"candidates": [
{
"id": 1,
"name": "가나다라마바사아자",
"nation": {
"id": 0,
"name": "대한민국천하통일국",
"color": "#aaaaaa"
},
"stats": {
"leadership": 40,
"strength": 50,
"intelligence": 60
},
"picture": "default.jpg",
"imageServer": 1,
"personality": {
"code": "che_안전",
"name": "안전",
"info": "안전을 중시합니다."
},
"specialDomestic": {
"code": "che_인덕",
"name": "인덕",
"info": "인덕 설명"
},
"specialWar": {
"code": "che_무쌍",
"name": "무쌍",
"info": "무쌍 설명"
},
"keepCount": 3
},
{
"id": 2,
"name": "가나다라마바사아자",
"nation": {
"id": 0,
"name": "대한민국천하통일국",
"color": "#aaaaaa"
},
"stats": {
"leadership": 41,
"strength": 51,
"intelligence": 61
},
"picture": "default.jpg",
"imageServer": 0,
"personality": {
"code": "che_안전",
"name": "안전",
"info": "안전을 중시합니다."
},
"specialDomestic": {
"code": "che_인덕",
"name": "인덕",
"info": "인덕 설명"
},
"specialWar": {
"code": "che_무쌍",
"name": "무쌍",
"info": "무쌍 설명"
},
"keepCount": 3
},
{
"id": 3,
"name": "가나다라마바사아자",
"nation": {
"id": 0,
"name": "대한민국천하통일국",
"color": "#aaaaaa"
},
"stats": {
"leadership": 42,
"strength": 52,
"intelligence": 62
},
"picture": "default.jpg",
"imageServer": 0,
"personality": {
"code": "che_안전",
"name": "안전",
"info": "안전을 중시합니다."
},
"specialDomestic": {
"code": "che_인덕",
"name": "인덕",
"info": "인덕 설명"
},
"specialWar": {
"code": "che_무쌍",
"name": "무쌍",
"info": "무쌍 설명"
},
"keepCount": 3
},
{
"id": 4,
"name": "가나다라마바사아자",
"nation": {
"id": 0,
"name": "대한민국천하통일국",
"color": "#aaaaaa"
},
"stats": {
"leadership": 43,
"strength": 53,
"intelligence": 63
},
"picture": "default.jpg",
"imageServer": 0,
"personality": {
"code": "che_안전",
"name": "안전",
"info": "안전을 중시합니다."
},
"specialDomestic": {
"code": "che_인덕",
"name": "인덕",
"info": "인덕 설명"
},
"specialWar": {
"code": "che_무쌍",
"name": "무쌍",
"info": "무쌍 설명"
},
"keepCount": 3
},
{
"id": 5,
"name": "가나다라마바사아자",
"nation": {
"id": 0,
"name": "대한민국천하통일국",
"color": "#aaaaaa"
},
"stats": {
"leadership": 44,
"strength": 54,
"intelligence": 64
},
"picture": "default.jpg",
"imageServer": 0,
"personality": {
"code": "che_안전",
"name": "안전",
"info": "안전을 중시합니다."
},
"specialDomestic": {
"code": "che_인덕",
"name": "인덕",
"info": "인덕 설명"
},
"specialWar": {
"code": "che_무쌍",
"name": "무쌍",
"info": "무쌍 설명"
},
"keepCount": 3
}
]
}
}
}
}
}
@@ -20,6 +20,7 @@ export default defineConfig({
testDir: '.', testDir: '.',
testMatch: [ testMatch: [
'troop.spec.ts', 'troop.spec.ts',
'typographyPolicy.spec.ts',
'board.spec.ts', 'board.spec.ts',
'inGameInfo.spec.ts', 'inGameInfo.spec.ts',
'infoMobileLayout.spec.ts', 'infoMobileLayout.spec.ts',
@@ -0,0 +1,194 @@
import { readFile } from 'node:fs/promises';
import { resolve } from 'node:path';
import { expect, test, type Page } from '@playwright/test';
import { gameProfile, gameTrpcRoute } from './gameTestPaths.js';
// 기존 화면 fixture의 읽기 응답을 고정했다. 실제 계정이나 게임 서버에는 접근하지 않는다.
const fixtureText = await readFile(new URL('./fixtures/typography.json', import.meta.url), 'utf8');
const imageRoot = process.env.FRONTEND_PARITY_IMAGE_ROOT ?? resolve(import.meta.dirname, '../../../../image');
const fontRoot = process.env.TYPOGRAPHY_FONT_ROOT;
const names = [
{ label: '전각9자', general: '가나다라마바사아자', nation: '대한민국천하통일국' },
{ label: '반각18자', general: 'WWWWWWWWWWWWWWWWWW', nation: 'MMMMMMMMMMMMMMMMMM' },
] as const;
const installAssets = async (page: Page): Promise<void> => {
await page.route(/(?:\/image\/|sam-image\.hided\.net\/)/u, async (route) => {
const url = new URL(route.request().url());
const relative = decodeURIComponent(url.pathname.replace(/^\/image\//u, '').replace(/^\//u, ''));
if (relative.split('/').includes('..')) throw new Error('Invalid typography image path');
await route.fulfill({
body: await readFile(resolve(imageRoot, relative)),
contentType: relative.endsWith('.png')
? 'image/png'
: relative.endsWith('.gif')
? 'image/gif'
: 'image/jpeg',
});
});
if (fontRoot) {
await page.route('**/pretendard.css', (route) =>
route.fulfill({ path: resolve(fontRoot, 'source.css'), contentType: 'text/css' })
);
await page.route('**/*.woff2', (route) =>
route.fulfill({
path: resolve(fontRoot, new URL(route.request().url()).pathname.split('/').at(-1)!),
contentType: 'font/woff2',
})
);
}
};
const install = async (page: Page, scene: string, general: string, nation: string): Promise<void> => {
const fixtures = JSON.parse(
fixtureText.replaceAll(names[0].general, general).replaceAll(names[0].nation, nation)
) as Record<string, Record<string, unknown>>;
await page.addInitScript((profile) => {
localStorage.setItem('sammo-game-token', 'ga_typography_fixture');
localStorage.setItem('sammo-game-profile', profile);
localStorage.removeItem('sam_customCSS');
}, gameProfile);
await page.route('**/events**', (route) => route.abort());
await page.route(gameTrpcRoute, async (route) => {
const operations = decodeURIComponent(new URL(route.request().url()).pathname.split('/trpc/')[1]!).split(',');
const responses = operations.map((operation) => {
const response = fixtures[scene]?.[operation];
if (response !== undefined) return response;
if (operation === 'public.recordAccess') return { result: { data: { recorded: true } } };
throw new Error(`Uncovered typography fixture: ${scene}/${operation}`);
});
await route.fulfill({ contentType: 'application/json', body: JSON.stringify(responses) });
});
await installAssets(page);
};
const waitForFonts = async (page: Page): Promise<void> => {
await page.evaluate(async () => {
await document.fonts.ready;
});
expect(
await page.evaluate(() =>
[...document.fonts].some((font) => font.family.includes('Pretendard') && font.status === 'loaded')
)
).toBe(true);
};
for (const width of [500, 1000]) {
for (const name of names) {
test(`메인 주요 이름과 제목을 보존한다 ${width}px ${name.label}`, async ({ page }, testInfo) => {
await page.setViewportSize({ width, height: 900 });
await install(page, 'main', name.general, name.nation);
await page.goto('./');
const general = page.locator('.battle-general-name:visible').first();
await expect(general).toContainText(name.general);
const nation = page.locator('.city-nation:visible').first();
await expect(nation).toContainText(name.nation);
await waitForFonts(page);
for (const label of [general, nation]) {
expect(await label.evaluate((element) => element.scrollWidth <= element.clientWidth + 1)).toBe(true);
}
await expect(page.locator('.game-shell__title')).toHaveCSS('font-size', '24px');
await page.screenshot({ path: testInfo.outputPath('main-maximum-name.png'), fullPage: true });
});
test(`네 단계와 밀집 화면 보류 계약 ${width}px ${name.label}`, async ({ page }, testInfo) => {
await page.setViewportSize({ width, height: 900 });
await install(page, 'personnel', name.general, name.nation);
await page.goto('nation/personnel');
await expect(page.locator('.nation-heading')).toContainText(name.nation);
await expect(page.locator('.chief-entry-copy strong').first()).toHaveText(name.general);
await waitForFonts(page);
await expect(page.locator('.nation-heading')).toHaveCSS('font-size', width === 500 ? '16px' : '24px');
// 500px의 15px 이름/10px 잠금은 확대 시 표시 이름이 줄어들어 보류했다.
await expect(page.locator('.chief-entry-copy strong').first()).toHaveCSS(
'font-size',
width === 500 ? '15px' : '16px'
);
const geometry = await page.locator('#personnel-container').evaluate((element) => ({
width: element.getBoundingClientRect().width,
scrollWidth: element.scrollWidth,
controls: [...element.querySelectorAll<HTMLElement>('.personnel-change-button')].map((button) => {
const rect = button.getBoundingClientRect();
return { width: rect.width, height: rect.height, text: button.innerText };
}),
}));
expect(geometry.scrollWidth).toBeLessThanOrEqual(width + 1);
expect(geometry.controls.every((control) => control.width > 0 && control.height >= 24)).toBe(true);
await testInfo.attach('geometry', {
body: JSON.stringify(geometry, null, 2),
contentType: 'application/json',
});
await page.screenshot({ path: testInfo.outputPath('personnel-maximum-name.png'), fullPage: true });
});
}
test(`사령부 12턴 요약의 기존 밀도를 유지한다 ${width}px`, async ({ page }, testInfo) => {
await page.setViewportSize({ width, height: 900 });
await install(page, 'chief', names[0].general, names[0].nation);
await page.goto('chief-center');
const row = page.locator('.chief-overview .chief-card.compact .chief-row').first();
await expect(row).toBeVisible();
await waitForFonts(page);
await expect(row).toHaveCSS('font-size', '8.8px');
await expect(row).toHaveCSS('line-height', '11.25px');
await expect(page.locator('.chief-overview .compact-name').first()).toHaveCSS('font-size', '10.4px');
expect((await row.boundingBox())?.height).toBe(11.25);
await page.screenshot({ path: testInfo.outputPath('chief-deferred-density.png'), fullPage: true });
});
for (const length of [4, 7, 9, 18]) {
test(`빙의 이름 길이별 축소를 유지한다 ${width}px ${length}`, async ({ page }, testInfo) => {
const general = length === 18 ? names[1].general : names[0].general.slice(0, length);
await page.setViewportSize({ width, height: 900 });
await install(page, 'possession', general, names[0].nation);
await page.goto('join');
const title = page.locator('.npc-card-name').first();
await expect(title).toHaveText(general);
await waitForFonts(page);
await expect(title).toHaveCSS('font-size', length >= 9 ? '12px' : '16px');
await expect(title).toHaveCSS('white-space', 'nowrap');
expect((await title.boundingBox())?.height).toBe(25);
await page.screenshot({ path: testInfo.outputPath('possession-name-length.png'), fullPage: true });
});
}
test(`전투 로그의 장수명과 병력 축소를 유지한다 ${width}px`, async ({ page }, testInfo) => {
await page.setViewportSize({ width, height: 900 });
await installAssets(page);
const log =
'◆217년 7월:<div class="small_war_log">마귀 ' +
'<span class="name_plate">【Hide_D】</span> <span class="crew_plate">0(-3714)</span> ' +
'<span class="war_type_defense">←</span> <span class="crew_plate">3955(-3545)</span> ' +
'백이 <span class="name_plate">【경국지색소교】</span> 19:57</div>';
await page.route(gameTrpcRoute, async (route) => {
const operations = decodeURIComponent(new URL(route.request().url()).pathname.split('/trpc/')[1]!).split(
','
);
const data: Record<string, unknown> = {
'public.getMapLayout': { mapName: 'che', cityList: [] },
'public.getCachedMap': {
year: 217,
month: 7,
cityList: [],
nationList: [],
history: [{ id: 1, text: log }],
},
'public.getWorldTrend': { year: 217, month: 7, turnTerm: 10 },
'public.getNationList': [],
'public.getGeneralList': [],
};
await route.fulfill({
contentType: 'application/json',
body: JSON.stringify(operations.map((operation) => ({ result: { data: data[operation] } }))),
});
});
await page.goto('public');
const summary = page.locator('.small_war_log').first();
await expect(summary).toContainText('【경국지색소교】');
await expect(summary).toHaveCSS('font-size', '14px');
await expect(summary.locator('.name_plate').first()).toHaveCSS('font-size', '10.5px');
await expect(summary.locator('.crew_plate').first()).toHaveCSS('font-size', '12.6px');
await waitForFonts(page);
await page.screenshot({ path: testInfo.outputPath('battle-log-exception.png'), fullPage: true });
});
}
+3 -3
View File
@@ -27,7 +27,7 @@ body {
background-repeat: repeat-y; background-repeat: repeat-y;
color: #fff; color: #fff;
font-family: var(--sammo-font-sans); font-family: var(--sammo-font-sans);
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: 1.3; line-height: 1.3;
} }
@@ -143,7 +143,7 @@ input[inputmode='search'] {
} }
.small_war_log .name_plate { .small_war_log .name_plate {
font-size: 0.75em; font-size: var(--sammo-font-size-war-name);
} }
.small_war_log .name_plate_cover { .small_war_log .name_plate_cover {
@@ -152,5 +152,5 @@ input[inputmode='search'] {
.small_war_log .crew_plate { .small_war_log .crew_plate {
color: orangered; color: orangered;
font-size: 90%; font-size: var(--sammo-font-size-war-crew);
} }
@@ -23,12 +23,12 @@
} }
.game-shell__title { .game-shell__title {
font-size: 1.6rem; font-size: var(--sammo-font-size-title);
font-weight: 600; font-weight: 600;
} }
.game-shell__subtitle { .game-shell__subtitle {
font-size: 0.85rem; font-size: var(--sammo-font-size-normal);
color: var(--sammo-color-text-muted); color: var(--sammo-color-text-muted);
} }
@@ -44,11 +44,11 @@
background: var(--sammo-color-action-bg); background: var(--sammo-color-action-bg);
color: inherit; color: inherit;
text-decoration: none; text-decoration: none;
font-size: 0.8rem; font-size: var(--sammo-font-size-small);
cursor: pointer; cursor: pointer;
} }
.game-feedback--error { .game-feedback--error {
color: var(--sammo-color-error); color: var(--sammo-color-error);
font-size: 0.85rem; font-size: var(--sammo-font-size-normal);
} }
@@ -133,7 +133,7 @@
.legacy-sort-indicator { .legacy-sort-indicator {
margin-left: 2px; margin-left: 2px;
color: #9ee7ba; color: #9ee7ba;
font-size: 0.75em; font-size: var(--sammo-font-size-small);
opacity: 0.65; opacity: 0.65;
} }
@@ -16,7 +16,7 @@
background-image: var(--sammo-texture-walnut); background-image: var(--sammo-texture-walnut);
color: var(--sammo-color-text); color: var(--sammo-color-text);
font-family: var(--sammo-font-sans); font-family: var(--sammo-font-sans);
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: 1.5; line-height: 1.5;
} }
@@ -35,7 +35,7 @@
} }
.ref-shell__title { .ref-shell__title {
font-size: 17px; font-size: var(--sammo-font-size-emphasis);
font-weight: 500; font-weight: 500;
} }
@@ -1,4 +1,22 @@
:root { :root {
/* 검증된 화면이 공유하는 네 단계. 콘텐츠 내부 축소/숨김은 별도 계약이다. */
--sammo-font-size-small: calc(var(--sammo-font-size-normal) * 12 / 14);
--sammo-font-size-normal: 14px;
--sammo-font-size-emphasis: 16px;
--sammo-font-size-title: 24px;
/* 크기 변경을 보류한 밀집 UI와 콘텐츠의 상대 축소 계약. */
--sammo-font-size-nation-card: 12px;
--sammo-font-size-chief-compact-base: 0.75rem;
--sammo-font-size-chief-compact-row: 0.55rem;
--sammo-font-size-chief-compact-header: 0.65rem;
--sammo-font-size-chief-compact-name: 0.6rem;
--sammo-font-size-hall-name: 11px;
--sammo-font-size-hall-secondary: 95%;
--sammo-font-size-personnel-mobile-name: 15px;
--sammo-font-size-personnel-mobile-lock: 10px;
--sammo-font-size-bracket-bet-button: 11px;
--sammo-font-size-war-name: 0.75em;
--sammo-font-size-war-crew: 90%;
--sammo-font-sans: Pretendard, 'Apple SD Gothic Neo', 'Noto Sans KR', 'Malgun Gothic', sans-serif; --sammo-font-sans: Pretendard, 'Apple SD Gothic Neo', 'Noto Sans KR', 'Malgun Gothic', sans-serif;
--sammo-color-text: #fff; --sammo-color-text: #fff;
--sammo-color-text-muted: rgba(232, 221, 196, 0.7); --sammo-color-text-muted: rgba(232, 221, 196, 0.7);
@@ -352,7 +352,7 @@ const officerLevelOptions = [
.general-title { .general-title {
font-weight: 600; font-weight: 600;
font-size: 14px; font-size: var(--sammo-font-size-normal);
} }
.general-subtitle { .general-subtitle {
@@ -371,7 +371,7 @@ const officerLevelOptions = [
background: #3498db; background: #3498db;
color: #fff; color: #fff;
padding: 4px 9px; padding: 4px 9px;
font-size: 12px; font-size: var(--sammo-font-size-small);
font-weight: 700; font-weight: 700;
cursor: pointer; cursor: pointer;
} }
@@ -419,7 +419,7 @@ const officerLevelOptions = [
display: grid; display: grid;
grid-template-columns: auto minmax(0, 1fr); grid-template-columns: auto minmax(0, 1fr);
color: #ddd; color: #ddd;
font-size: 12px; font-size: var(--sammo-font-size-small);
} }
.field span { .field span {
@@ -438,7 +438,7 @@ const officerLevelOptions = [
background: #ddd; background: #ddd;
color: #303030; color: #303030;
padding: 6px 10px; padding: 6px 10px;
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: 21px; line-height: 21px;
box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.075); box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.075);
} }
@@ -107,7 +107,7 @@ const handleClick = () => {
.chief-card.compact { .chief-card.compact {
padding: 0; padding: 0;
font-size: 0.75rem; font-size: var(--sammo-font-size-chief-compact-base);
} }
.chief-header { .chief-header {
@@ -131,20 +131,20 @@ const handleClick = () => {
} }
.chief-level { .chief-level {
font-size: 0.75rem; font-size: var(--sammo-font-size-small);
color: rgba(232, 221, 196, 0.7); color: rgba(232, 221, 196, 0.7);
} }
.chief-name { .chief-name {
overflow: hidden; overflow: hidden;
font-size: 0.8rem; font-size: var(--sammo-font-size-small);
font-weight: 600; font-weight: 600;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
} }
.chief-me { .chief-me {
font-size: 0.65rem; font-size: var(--sammo-font-size-small);
padding: 2px 6px; padding: 2px 6px;
border-radius: 0; border-radius: 0;
background: rgba(201, 164, 90, 0.2); background: rgba(201, 164, 90, 0.2);
@@ -166,7 +166,7 @@ const handleClick = () => {
/* Ref draws no rule between reservation rows and keeps them left aligned. */ /* Ref draws no rule between reservation rows and keeps them left aligned. */
border: 0; border: 0;
text-align: left; text-align: left;
font-size: 0.75rem; font-size: var(--sammo-font-size-small);
} }
.chief-card.compact .chief-row { .chief-card.compact .chief-row {
@@ -175,7 +175,7 @@ const handleClick = () => {
height: 13px; height: 13px;
min-height: 0; min-height: 0;
padding: 0 2px; padding: 0 2px;
font-size: 0.55rem; font-size: var(--sammo-font-size-chief-compact-row);
line-height: 11px; line-height: 11px;
} }
@@ -183,7 +183,7 @@ const handleClick = () => {
box-sizing: border-box; box-sizing: border-box;
height: 20px; height: 20px;
min-height: 0; min-height: 0;
font-size: 0.65rem; font-size: var(--sammo-font-size-chief-compact-header);
} }
.compact-name, .compact-name,
@@ -210,7 +210,7 @@ const handleClick = () => {
.chief-card.compact .chief-level, .chief-card.compact .chief-level,
.chief-card.compact .chief-name { .chief-card.compact .chief-name {
font-size: 0.6rem; font-size: var(--sammo-font-size-chief-compact-name);
} }
.chief-row.rest { .chief-row.rest {
@@ -270,13 +270,18 @@ watch(
</template> </template>
<style scoped> <style scoped>
/* UI 보조 글자는 부모의 80%가 아니라 공통 소형 크기를 사용한다. */
small {
font-size: var(--sammo-font-size-small);
}
.recruitment-command-form { .recruitment-command-form {
box-sizing: border-box; box-sizing: border-box;
width: 100%; width: 100%;
min-width: 0; min-width: 0;
color: #fff; color: #fff;
background: #1d1d1d; background: #1d1d1d;
font: 14px/1.25 var(--sammo-font-sans); font: var(--sammo-font-size-normal)/1.25 var(--sammo-font-sans);
} }
.recruitment-intro { .recruitment-intro {
padding: 6px; padding: 6px;
@@ -335,7 +340,7 @@ watch(
} }
.crew-group > header strong { .crew-group > header strong {
padding: 0 12px; padding: 0 12px;
font-size: 1.3em; font-size: var(--sammo-font-size-title);
} }
.crew-group > header button { .crew-group > header button {
min-height: 34px; min-height: 34px;
@@ -377,7 +382,7 @@ watch(
} }
.crew-name small { .crew-name small {
display: block; display: block;
font-size: 0.72em; font-size: var(--sammo-font-size-small);
} }
.crew-row small { .crew-row small {
display: none; display: none;
@@ -509,11 +514,11 @@ watch(
} }
.crew-row small { .crew-row small {
display: block; display: block;
font-size: 0.62em; font-size: var(--sammo-font-size-small);
line-height: 1; line-height: 1;
} }
.crew-row .crew-name small { .crew-row .crew-name small {
font-size: 0.72em; font-size: var(--sammo-font-size-small);
} }
.crew-header .attack, .crew-header .attack,
.crew-header .defence, .crew-header .defence,
@@ -521,18 +526,18 @@ watch(
.crew-header .avoid, .crew-header .avoid,
.crew-header .cost, .crew-header .cost,
.crew-header .rice { .crew-header .rice {
font-size: 0.78em; font-size: var(--sammo-font-size-small);
} }
.crew-group > header { .crew-group > header {
grid-template-columns: 7fr 5fr; grid-template-columns: 7fr 5fr;
} }
.crew-group > header button { .crew-group > header button {
font-size: 0.82em; font-size: var(--sammo-font-size-small);
} }
.crew-info { .crew-info {
overflow: hidden; overflow: hidden;
overflow-wrap: anywhere; overflow-wrap: anywhere;
font-size: 0.9em; font-size: var(--sammo-font-size-small);
} }
} }
@@ -832,13 +832,18 @@ const clickOutsideMenu = (event: Event) => {
</template> </template>
<style scoped> <style scoped>
/* UI 보조 글자는 부모의 80%가 아니라 공통 소형 크기를 사용한다. */
small {
font-size: var(--sammo-font-size-small);
}
.reserved-command-editor { .reserved-command-editor {
position: relative; position: relative;
width: 100%; width: 100%;
min-width: 0; min-width: 0;
color: #fff; color: #fff;
background: #1d1d1d; background: #1d1d1d;
font: 14px/1.05 var(--sammo-font-sans); font: var(--sammo-font-size-normal)/1.05 var(--sammo-font-sans);
} }
.reserved-command-editor.picker-open { .reserved-command-editor.picker-open {
z-index: 50; z-index: 50;
@@ -850,7 +855,7 @@ const clickOutsideMenu = (event: Event) => {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
gap: 5px; gap: 5px;
font-size: 16.8px; font-size: var(--sammo-font-size-emphasis);
font-weight: 400; font-weight: 400;
} }
.identity strong { .identity strong {
@@ -1069,7 +1074,7 @@ const clickOutsideMenu = (event: Event) => {
background: #102c35; background: #102c35;
box-shadow: 0 3px 8px #000; box-shadow: 0 3px 8px #000;
color: #aaffff; color: #aaffff;
font-size: 0.78rem; font-size: var(--sammo-font-size-small);
font-weight: 400; font-weight: 400;
line-height: 1.35; line-height: 1.35;
text-align: left; text-align: left;
@@ -1091,7 +1096,7 @@ const clickOutsideMenu = (event: Event) => {
visibility: visible; visibility: visible;
} }
.action-column small { .action-column small {
font-size: 0.72em; font-size: var(--sammo-font-size-small);
line-height: 1; line-height: 1;
} }
.reserved-command-editor.mobile .action-column > div.autonomous { .reserved-command-editor.mobile .action-column > div.autonomous {
@@ -52,7 +52,7 @@ defineProps<{
box-shadow: 0 3px 12px rgb(0 0 0 / 65%); box-shadow: 0 3px 12px rgb(0 0 0 / 65%);
color: #f5f5f5; color: #f5f5f5;
font-family: var(--sammo-font-sans); font-family: var(--sammo-font-sans);
font-size: 12.5px; font-size: var(--sammo-font-size-small);
font-weight: 400; font-weight: 400;
line-height: 1.45; line-height: 1.45;
text-align: left; text-align: left;
@@ -66,7 +66,7 @@ defineProps<{
.directory-tooltip__content strong { .directory-tooltip__content strong {
margin-bottom: 4px; margin-bottom: 4px;
color: #7fd4ff; color: #7fd4ff;
font-size: 13px; font-size: var(--sammo-font-size-small);
} }
.directory-tooltip--enabled:hover > .directory-tooltip__content, .directory-tooltip--enabled:hover > .directory-tooltip__content,
.directory-tooltip--enabled:focus > .directory-tooltip__content { .directory-tooltip--enabled:focus > .directory-tooltip__content {
@@ -355,12 +355,17 @@ const sortHelp = (header: Header): string =>
</template> </template>
<style scoped> <style scoped>
/* UI 보조 글자는 부모의 80%가 아니라 공통 소형 크기를 사용한다. */
small {
font-size: var(--sammo-font-size-small);
}
.directory-table { .directory-table {
width: 1000px; width: 1000px;
border-collapse: collapse; border-collapse: collapse;
table-layout: auto; table-layout: auto;
padding: 0; padding: 0;
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: 1.3; line-height: 1.3;
word-break: break-all; word-break: break-all;
} }
@@ -414,7 +419,7 @@ const sortHelp = (header: Header): string =>
display: grid; display: grid;
grid-template-columns: 66px repeat(4, minmax(0, 1fr)); grid-template-columns: 66px repeat(4, minmax(0, 1fr));
color: inherit; color: inherit;
font-size: 12px; font-size: var(--sammo-font-size-small);
line-height: 1.2; line-height: 1.2;
} }
.general-card + .general-card { .general-card + .general-card {
@@ -453,7 +458,7 @@ const sortHelp = (header: Header): string =>
min-height: 32px; min-height: 32px;
flex-direction: row; flex-direction: row;
gap: 4px; gap: 4px;
font-size: 14px; font-size: var(--sammo-font-size-normal);
} }
.name-field, .name-field,
.nation-field { .nation-field {
@@ -461,11 +466,11 @@ const sortHelp = (header: Header): string =>
} }
.field-label { .field-label {
color: #a8d8bd; color: #a8d8bd;
font-size: 10px; font-size: var(--sammo-font-size-small);
line-height: 1; line-height: 1;
} }
.identity-field .field-label { .identity-field .field-label {
font-size: 11px; font-size: var(--sammo-font-size-small);
} }
.general-card-loading { .general-card-loading {
min-height: 65px; min-height: 65px;
@@ -699,6 +699,11 @@ watch(
</template> </template>
<style scoped> <style scoped>
/* UI 보조 글자는 부모의 80%가 아니라 공통 소형 크기를 사용한다. */
small {
font-size: var(--sammo-font-size-small);
}
.target-search-toggle { .target-search-toggle {
margin: 6px 8px; margin: 6px 8px;
} }
@@ -714,7 +719,7 @@ watch(
flex: 1 1 140px; flex: 1 1 140px;
width: 140px; width: 140px;
margin: 0; margin: 0;
font-size: 16px; font-size: var(--sammo-font-size-emphasis);
} }
.target-search small { .target-search small {
flex-basis: 100%; flex-basis: 100%;
@@ -725,7 +730,7 @@ watch(
.command-argument-form { .command-argument-form {
border: 1px solid rgba(201, 164, 90, 0.35); border: 1px solid rgba(201, 164, 90, 0.35);
font-size: 0.75rem; font-size: var(--sammo-font-size-small);
} }
.command-map { .command-map {
@@ -765,7 +770,7 @@ watch(
.status-key { .status-key {
border-radius: 2px; border-radius: 2px;
padding: 0 4px; padding: 0 4px;
font-size: 10px; font-size: var(--sammo-font-size-small);
font-weight: 700; font-weight: 700;
} }
@@ -877,7 +882,7 @@ watch(
.target-state { .target-state {
grid-column: 3; grid-column: 3;
color: #aee6a7; color: #aee6a7;
font-size: 10px; font-size: var(--sammo-font-size-small);
text-align: right; text-align: right;
} }
@@ -174,6 +174,11 @@ const commandTitle = (command: CommandAvailability) =>
</template> </template>
<style scoped> <style scoped>
/* UI 보조 글자는 부모의 80%가 아니라 공통 소형 크기를 사용한다. */
small {
font-size: var(--sammo-font-size-small);
}
.command-form { .command-form {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -194,7 +199,7 @@ const commandTitle = (command: CommandAvailability) =>
--legacy-button-color: #fff; --legacy-button-color: #fff;
min-height: 0; min-height: 0;
padding-inline: 4px; padding-inline: 4px;
font-size: 12px; font-size: var(--sammo-font-size-small);
} }
.category-btn.legacy-button--lumen.active { .category-btn.legacy-button--lumen.active {
@@ -220,7 +225,7 @@ const commandTitle = (command: CommandAvailability) =>
align-items: center; align-items: center;
justify-content: center; justify-content: center;
text-align: center; text-align: center;
font-size: 12px; font-size: var(--sammo-font-size-small);
} }
.command-item.ok { .command-item.ok {
@@ -251,7 +256,7 @@ const commandTitle = (command: CommandAvailability) =>
.command-duration { .command-duration {
display: block; display: block;
font-size: 0.875em; font-size: var(--sammo-font-size-small);
font-weight: 400; font-weight: 400;
line-height: 1.1; line-height: 1.1;
white-space: nowrap; white-space: nowrap;
@@ -260,7 +265,7 @@ const commandTitle = (command: CommandAvailability) =>
.command-cost { .command-cost {
display: block; display: block;
color: #f3d58b; color: #f3d58b;
font-size: 0.875em; font-size: var(--sammo-font-size-small);
font-weight: 400; font-weight: 400;
line-height: 1.1; line-height: 1.1;
overflow-wrap: anywhere; overflow-wrap: anywhere;
@@ -465,7 +465,7 @@ const specialText = computed(() => {
background-color: #172a52; background-color: #172a52;
background-image: var(--sammo-texture-blue); background-image: var(--sammo-texture-blue);
color: #fff; color: #fff;
font-size: 12px; font-size: var(--sammo-font-size-small);
} }
.general-basic-grid { .general-basic-grid {
@@ -523,7 +523,7 @@ const specialText = computed(() => {
.general-title { .general-title {
grid-column: 2 / 8; grid-column: 2 / 8;
grid-row: 1; grid-row: 1;
font-size: 12px; font-size: var(--sammo-font-size-small);
font-weight: 700; font-weight: 700;
line-height: 18px; line-height: 18px;
} }
@@ -75,7 +75,7 @@ const unavailableText: Record<GeneralRecordType, string> = {
color: orange; color: orange;
background-color: #000; background-color: #000;
background-image: var(--sammo-texture-green); background-image: var(--sammo-texture-green);
font-size: 1.3em; font-size: var(--sammo-font-size-title);
font-weight: 500; font-weight: 500;
} }
@@ -48,7 +48,7 @@ const detail = computed(() => (props.autorun ? formatAutorunUserDetail(props.aut
background: #18181b; background: #18181b;
box-shadow: 0 4px 12px rgb(0 0 0 / 45%); box-shadow: 0 4px 12px rgb(0 0 0 / 45%);
color: #f4f4f5; color: #f4f4f5;
font-size: 12px; font-size: var(--sammo-font-size-small);
font-weight: 400; font-weight: 400;
line-height: 1.4; line-height: 1.4;
opacity: 0; opacity: 0;
@@ -106,7 +106,7 @@ watch(
background-color: #302016; background-color: #302016;
background-image: var(--sammo-texture-walnut); background-image: var(--sammo-texture-walnut);
color: #fff; color: #fff;
font-size: 14px; font-size: var(--sammo-font-size-normal);
font-weight: 400; font-weight: 400;
line-height: 21px; line-height: 21px;
} }
@@ -169,7 +169,7 @@ watch(
.execution-status > span { .execution-status > span {
display: block; display: block;
white-space: nowrap; white-space: nowrap;
font-size: 12px; font-size: var(--sammo-font-size-small);
} }
.execution-status:disabled { .execution-status:disabled {
opacity: 1; opacity: 1;
@@ -287,7 +287,7 @@ const onAction = (action: NonNullable<MainNavigationLinkItem['action']>) => {
width: 125px; width: 125px;
padding: 6px 4px; padding: 6px 4px;
font-family: inherit; font-family: inherit;
font-size: 16px; font-size: var(--sammo-font-size-emphasis);
line-height: 1.5; line-height: 1.5;
text-align: center; text-align: center;
cursor: pointer; cursor: pointer;
@@ -299,13 +299,13 @@ const onAction = (action: NonNullable<MainNavigationLinkItem['action']>) => {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
padding: 2px 1px; padding: 2px 1px;
font-size: 12px; font-size: var(--sammo-font-size-small);
line-height: 1.15; line-height: 1.15;
} }
.auto-refresh-trigger strong { .auto-refresh-trigger strong {
color: #bbb; color: #bbb;
font-size: 11px; font-size: var(--sammo-font-size-small);
line-height: 1; line-height: 1;
} }
@@ -315,7 +315,7 @@ const onAction = (action: NonNullable<MainNavigationLinkItem['action']>) => {
.manual-refresh-trigger { .manual-refresh-trigger {
padding: 0; padding: 0;
font-size: 22px; font-size: var(--sammo-font-size-title);
line-height: 1; line-height: 1;
} }
@@ -360,7 +360,7 @@ const onAction = (action: NonNullable<MainNavigationLinkItem['action']>) => {
.bottom-popup li { .bottom-popup li {
break-inside: avoid; break-inside: avoid;
min-width: 125px; min-width: 125px;
font-size: 16px; font-size: var(--sammo-font-size-emphasis);
} }
.bottom-popup :deep(.main-menu-link), .bottom-popup :deep(.main-menu-link),
@@ -373,7 +373,7 @@ const onAction = (action: NonNullable<MainNavigationLinkItem['action']>) => {
justify-content: flex-start; justify-content: flex-start;
padding: 5px 16px; padding: 5px 16px;
font-family: inherit; font-family: inherit;
font-size: 16px; font-size: var(--sammo-font-size-emphasis);
line-height: 1.5; line-height: 1.5;
text-align: left; text-align: left;
text-decoration: none; text-decoration: none;
@@ -94,7 +94,7 @@ const lumenClasses = computed(() =>
background-image: var(--sammo-texture-walnut); background-image: var(--sammo-texture-walnut);
color: #fff; color: #fff;
font-family: inherit; font-family: inherit;
font-size: 14px; font-size: var(--sammo-font-size-normal);
font-weight: 400; font-weight: 400;
line-height: 1.5; line-height: 1.5;
text-align: center; text-align: center;
@@ -75,7 +75,7 @@ const emit = defineEmits<{
.main-turn-controls__auto strong { .main-turn-controls__auto strong {
color: #bbb; color: #bbb;
font-size: 0.85em; font-size: var(--sammo-font-size-small);
} }
.main-turn-controls__auto.active strong { .main-turn-controls__auto.active strong {
@@ -102,7 +102,7 @@ const { touchstart, touchmove, touchend, touchcancel } = useMapCityTouch(
position: absolute; position: absolute;
box-sizing: border-box; box-sizing: border-box;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
font-size: 0.65rem; font-size: var(--sammo-font-size-small);
color: rgba(232, 221, 196, 0.8); color: rgba(232, 221, 196, 0.8);
cursor: pointer; cursor: pointer;
touch-action: manipulation; touch-action: manipulation;
@@ -216,7 +216,7 @@ const cityStateStyle = computed(() => ({
.city-base { .city-base {
position: absolute; position: absolute;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
font-size: 0.65rem; font-size: var(--sammo-font-size-small);
color: #fff; color: #fff;
cursor: pointer; cursor: pointer;
touch-action: manipulation; touch-action: manipulation;
@@ -296,7 +296,7 @@ const cityStateStyle = computed(() => ({
bottom: -10px; bottom: -10px;
background: rgba(0, 0, 0, 0.5); background: rgba(0, 0, 0, 0.5);
white-space: nowrap; white-space: nowrap;
font-size: 0.6rem; font-size: var(--sammo-font-size-small);
color: rgba(232, 221, 196, 0.9); color: rgba(232, 221, 196, 0.9);
} }
@@ -816,7 +816,7 @@ const selectCity = (cityId: number) => {
left top, left top,
right top; right top;
background-repeat: no-repeat; background-repeat: no-repeat;
font-size: 14px; font-size: var(--sammo-font-size-normal);
font-weight: 700; font-weight: 700;
line-height: 20px; line-height: 20px;
text-align: center; text-align: center;
@@ -834,7 +834,7 @@ const selectCity = (cityId: number) => {
padding: 5px 8px; padding: 5px 8px;
background: #000; background: #000;
color: #fff; color: #fff;
font-size: 12px; font-size: var(--sammo-font-size-small);
font-weight: 400; font-weight: 400;
line-height: 18px; line-height: 18px;
text-align: left; text-align: left;
@@ -880,7 +880,7 @@ const selectCity = (cityId: number) => {
background: #345c85; background: #345c85;
color: #fff; color: #fff;
cursor: pointer; cursor: pointer;
font-size: 17px; font-size: var(--sammo-font-size-emphasis);
line-height: 1; line-height: 1;
pointer-events: auto; pointer-events: auto;
} }
@@ -928,7 +928,7 @@ const selectCity = (cityId: number) => {
padding: 3px 7px; padding: 3px 7px;
background: #345c85; background: #345c85;
color: #fff; color: #fff;
font-size: 11px; font-size: var(--sammo-font-size-small);
line-height: 18px; line-height: 18px;
cursor: pointer; cursor: pointer;
text-align: left; text-align: left;
@@ -998,7 +998,7 @@ const selectCity = (cityId: number) => {
padding: 0; padding: 0;
background: rgb(30, 164, 255); background: rgb(30, 164, 255);
color: #fff; color: #fff;
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: 15px; line-height: 15px;
white-space: nowrap; white-space: nowrap;
} }
@@ -1013,7 +1013,7 @@ const selectCity = (cityId: number) => {
padding: 1px 4px; padding: 1px 4px;
background: rgba(5, 27, 43, 0.92); background: rgba(5, 27, 43, 0.92);
color: #d9f3ff; color: #d9f3ff;
font-size: 10px; font-size: var(--sammo-font-size-small);
font-weight: 700; font-weight: 700;
line-height: 14px; line-height: 14px;
pointer-events: none; pointer-events: none;
@@ -273,7 +273,7 @@ const forwardResponse = (messageId: number, response: boolean) => {
<style scoped> <style scoped>
.MessagePanel { .MessagePanel {
color: #fff; color: #fff;
font-size: 14px; font-size: var(--sammo-font-size-normal);
} }
.MessageInputForm { .MessageInputForm {
@@ -375,7 +375,7 @@ const forwardResponse = (messageId: number, response: boolean) => {
border: 1px solid transparent; border: 1px solid transparent;
border-radius: 3px; border-radius: 3px;
padding: 2px 6px; padding: 2px 6px;
font-size: 11.2px; font-size: var(--sammo-font-size-small);
line-height: 1.5; line-height: 1.5;
cursor: pointer; cursor: pointer;
} }
@@ -329,7 +329,7 @@ onBeforeUnmount(() => {
min-height: 64px; min-height: 64px;
outline: 1px solid gray; outline: 1px solid gray;
color: #fff; color: #fff;
font-size: 12.5px; font-size: var(--sammo-font-size-small);
word-break: break-all; word-break: break-all;
} }
@@ -414,7 +414,7 @@ button.msg-target {
} }
.msg-time { .msg-time {
font-size: 0.75em; font-size: var(--sammo-font-size-small);
font-weight: 400; font-weight: 400;
} }
@@ -429,7 +429,7 @@ button.msg-target {
background: transparent; background: transparent;
padding: 2px 4px; padding: 2px 4px;
color: #ffc107; color: #ffc107;
font-size: 8px; font-size: var(--sammo-font-size-small);
cursor: pointer; cursor: pointer;
} }
@@ -479,7 +479,7 @@ button.msg-target {
.message-response .legacy-button { .message-response .legacy-button {
min-width: 42px; min-width: 42px;
padding: 2px 8px; padding: 2px 8px;
font-size: 12.5px; font-size: var(--sammo-font-size-small);
cursor: pointer; cursor: pointer;
} }
@@ -214,7 +214,7 @@ const displayChiefName = (chief: NationChief | undefined): string => {
min-width: 0; min-width: 0;
height: 193px; height: 193px;
color: #fff; color: #fff;
font-size: 12px; font-size: var(--sammo-font-size-nation-card);
} }
.nation-grid { .nation-grid {
@@ -42,7 +42,7 @@ const formattedLogs = computed(() =>
min-width: 0; min-width: 0;
color: #fff; color: #fff;
font-family: var(--sammo-font-sans); font-family: var(--sammo-font-sans);
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: 1.35; line-height: 1.35;
} }
@@ -17,7 +17,7 @@ defineProps<{
.record-panel { .record-panel {
min-width: 0; min-width: 0;
color: #fff; color: #fff;
font-size: 14px; font-size: var(--sammo-font-size-normal);
font-weight: 400; font-weight: 400;
line-height: 21px; line-height: 21px;
} }
@@ -67,7 +67,7 @@ const props = defineProps<{
} }
.tag { .tag {
font-size: 0.65rem; font-size: var(--sammo-font-size-small);
padding: 2px 4px; padding: 2px 4px;
border: 1px solid rgba(201, 164, 90, 0.4); border: 1px solid rgba(201, 164, 90, 0.4);
} }
@@ -76,7 +76,7 @@ const props = defineProps<{
display: grid; display: grid;
grid-template-columns: repeat(auto-fit, minmax(90px, 1fr)); grid-template-columns: repeat(auto-fit, minmax(90px, 1fr));
gap: 4px; gap: 4px;
font-size: 0.75rem; font-size: var(--sammo-font-size-small);
} }
.empty { .empty {
@@ -203,7 +203,7 @@ onBeforeUnmount(() => document.removeEventListener('pointerdown', handleDocument
border-radius: 2px; border-radius: 2px;
color: #111; color: #111;
background: #fff; background: #fff;
font-size: 12px; font-size: var(--sammo-font-size-small);
font-weight: 700; font-weight: 700;
line-height: 1; line-height: 1;
} }
@@ -212,7 +212,7 @@ onBeforeUnmount(() => document.removeEventListener('pointerdown', handleDocument
margin: 0; margin: 0;
padding: 6px 8px; padding: 6px 8px;
color: #bbb; color: #bbb;
font-size: 11px; font-size: var(--sammo-font-size-small);
} }
.permission-multiselect-help { .permission-multiselect-help {
border-top: 1px solid #454545; border-top: 1px solid #454545;
@@ -216,6 +216,11 @@ onBeforeUnmount(() => {
</template> </template>
<style scoped> <style scoped>
/* UI 보조 글자는 부모의 80%가 아니라 공통 소형 크기를 사용한다. */
small {
font-size: var(--sammo-font-size-small);
}
.personnel-picker-backdrop { .personnel-picker-backdrop {
position: fixed; position: fixed;
z-index: 2050; z-index: 2050;
@@ -237,7 +242,7 @@ onBeforeUnmount(() => {
border: 1px solid #78653d; border: 1px solid #78653d;
border-radius: 14px; border-radius: 14px;
box-shadow: 0 24px 70px rgb(0 0 0 / 78%); box-shadow: 0 24px 70px rgb(0 0 0 / 78%);
font: 14px/1.45 var(--sammo-font-sans); font: var(--sammo-font-size-normal)/1.45 var(--sammo-font-sans);
} }
.personnel-picker-header { .personnel-picker-header {
display: flex; display: flex;
@@ -251,13 +256,13 @@ onBeforeUnmount(() => {
.personnel-picker-eyebrow { .personnel-picker-eyebrow {
margin: 0 0 3px; margin: 0 0 3px;
color: #cbb171; color: #cbb171;
font-size: 11px; font-size: var(--sammo-font-size-small);
font-weight: 700; font-weight: 700;
letter-spacing: 0.13em; letter-spacing: 0.13em;
} }
.personnel-picker h2 { .personnel-picker h2 {
margin: 0; margin: 0;
font-size: 22px; font-size: var(--sammo-font-size-title);
line-height: 1.25; line-height: 1.25;
} }
.personnel-picker-header p:last-child { .personnel-picker-header p:last-child {
@@ -273,7 +278,7 @@ onBeforeUnmount(() => {
padding: 0; padding: 0;
color: #ddd7ca; color: #ddd7ca;
background: rgb(0 0 0 / 28%); background: rgb(0 0 0 / 28%);
font-size: 24px; font-size: var(--sammo-font-size-title);
line-height: 1; line-height: 1;
cursor: pointer; cursor: pointer;
} }
@@ -371,7 +376,7 @@ onBeforeUnmount(() => {
place-items: center; place-items: center;
color: #d8be79; color: #d8be79;
background: #25271f; background: #25271f;
font: 700 24px/1 var(--sammo-font-sans); font: 700 var(--sammo-font-size-title)/1 var(--sammo-font-sans);
} }
.personnel-picker-card-body, .personnel-picker-card-body,
.personnel-picker-card-title, .personnel-picker-card-title,
@@ -385,7 +390,7 @@ onBeforeUnmount(() => {
} }
.personnel-picker-card-title strong, .personnel-picker-card-title strong,
.vacancy-card strong { .vacancy-card strong {
font-size: 16px; font-size: var(--sammo-font-size-emphasis);
} }
.personnel-picker-card-title small, .personnel-picker-card-title small,
.vacancy-card small { .vacancy-card small {
@@ -397,7 +402,7 @@ onBeforeUnmount(() => {
color: #13150f; color: #13150f;
background: #d5bb6f; background: #d5bb6f;
border-radius: 999px; border-radius: 999px;
font-size: 10px; font-size: var(--sammo-font-size-small);
font-weight: 800; font-weight: 800;
} }
.personnel-picker-badges { .personnel-picker-badges {
@@ -412,7 +417,7 @@ onBeforeUnmount(() => {
background: #32352d; background: #32352d;
border: 1px solid #555948; border: 1px solid #555948;
border-radius: 999px; border-radius: 999px;
font-size: 10px; font-size: var(--sammo-font-size-small);
} }
.personnel-picker-stats { .personnel-picker-stats {
display: grid; display: grid;
@@ -431,7 +436,7 @@ onBeforeUnmount(() => {
.personnel-picker-stats small, .personnel-picker-stats small,
.personnel-picker-details small { .personnel-picker-details small {
color: #aaa99f; color: #aaa99f;
font-size: 10px; font-size: var(--sammo-font-size-small);
} }
.personnel-picker-stats strong { .personnel-picker-stats strong {
color: #f1d47e; color: #f1d47e;
@@ -342,7 +342,7 @@ const mobilePairs = computed(() => {
border-radius: 3px; border-radius: 3px;
color: #fff3cd; color: #fff3cd;
background: #59400e; background: #59400e;
font: 700 11px/1 var(--sammo-font-sans); font: 700 var(--sammo-font-size-bracket-bet-button)/1 var(--sammo-font-sans);
cursor: pointer; cursor: pointer;
} }
.bracket-bet-button:hover, .bracket-bet-button:hover,
@@ -418,12 +418,12 @@ const mobilePairs = computed(() => {
left: 50%; left: 50%;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
color: #ffd25e; color: #ffd25e;
font-size: 12px; font-size: var(--sammo-font-size-small);
} }
.tournament-bracket > p { .tournament-bracket > p {
margin: 8px 0 0; margin: 8px 0 0;
color: skyblue; color: skyblue;
font-size: 18px; font-size: var(--sammo-font-size-emphasis);
} }
@media (max-width: 800px) { @media (max-width: 800px) {
.desktop-bracket { .desktop-bracket {
@@ -434,13 +434,13 @@ const mobilePairs = computed(() => {
} }
.tournament-bracket > p { .tournament-bracket > p {
padding: 0 8px; padding: 0 8px;
font-size: 13px; font-size: var(--sammo-font-size-small);
} }
} }
/* Betting uses the same paired cards at every viewport; rounds remain selectable. */ /* Betting uses the same paired cards at every viewport; rounds remain selectable. */
.inline-betting-bracket { .inline-betting-bracket {
font-size: var(--bet-font-normal, 14px); font-size: var(--sammo-font-size-normal);
} }
.inline-betting-bracket .mobile-bracket { .inline-betting-bracket .mobile-bracket {
display: block; display: block;
@@ -471,14 +471,14 @@ const mobilePairs = computed(() => {
text-align: left; text-align: left;
} }
.bracket-candidate-identity :deep(.general-identity-name) { .bracket-candidate-identity :deep(.general-identity-name) {
font-size: var(--bet-font-large, 16px); font-size: var(--sammo-font-size-emphasis);
font-weight: 700; font-weight: 700;
white-space: normal; white-space: normal;
overflow-wrap: anywhere; overflow-wrap: anywhere;
} }
.bracket-core-stat { .bracket-core-stat {
color: #fff; color: #fff;
font-size: var(--bet-font-normal, 14px); font-size: var(--sammo-font-size-normal);
} }
.bracket-bet-summary { .bracket-bet-summary {
display: grid; display: grid;
@@ -511,13 +511,13 @@ const mobilePairs = computed(() => {
} }
} }
.bracket-info-identity :deep(.general-identity-name) { .bracket-info-identity :deep(.general-identity-name) {
font-size: 16px; font-size: var(--sammo-font-size-emphasis);
line-height: 18px; line-height: 18px;
} }
.bracket-info-identity :deep(.general-identity-details) { .bracket-info-identity :deep(.general-identity-details) {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: 18px; line-height: 18px;
text-align: left; text-align: left;
overflow-wrap: anywhere; overflow-wrap: anywhere;
@@ -92,7 +92,7 @@ const pointsOf = (participant: StandingParticipant): number => (participant.win
padding: 3px; padding: 3px;
background: #000; background: #000;
color: #fff; color: #fff;
font-size: 14px; font-size: var(--sammo-font-size-normal);
font-weight: 400; font-weight: 400;
text-align: center; text-align: center;
} }
@@ -129,7 +129,7 @@ const pointsOf = (participant: StandingParticipant): number => (participant.win
min-width: 0; min-width: 0;
flex-direction: column; flex-direction: column;
color: #d8cfca; color: #d8cfca;
font-size: 12px; font-size: var(--sammo-font-size-small);
font-variant-numeric: tabular-nums; font-variant-numeric: tabular-nums;
line-height: 14px; line-height: 14px;
white-space: nowrap; white-space: nowrap;
@@ -156,7 +156,7 @@ const pointsOf = (participant: StandingParticipant): number => (participant.win
grid-template-columns: 28px minmax(0, 1fr); grid-template-columns: 28px minmax(0, 1fr);
} }
.standing-summary { .standing-summary {
font-size: 12px; font-size: var(--sammo-font-size-small);
line-height: 15px; line-height: 15px;
} }
} }
@@ -62,7 +62,7 @@ defineProps<{
.tournament-page-title { .tournament-page-title {
min-width: 0; min-width: 0;
overflow: hidden; overflow: hidden;
font-size: 16px; font-size: var(--sammo-font-size-emphasis);
font-weight: 400; font-weight: 400;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
@@ -76,7 +76,7 @@ defineProps<{
button { button {
--legacy-button-height: 44px; --legacy-button-height: 44px;
margin: 0; margin: 0;
font-size: 14px; font-size: var(--sammo-font-size-normal);
} }
.tournament-page-tabs button { .tournament-page-tabs button {
min-width: 72px; min-width: 72px;
@@ -100,7 +100,7 @@ button:focus-visible {
padding-inline: 2px; padding-inline: 2px;
} }
.tournament-page-title { .tournament-page-title {
font-size: 13px; font-size: var(--sammo-font-size-small);
} }
.tournament-page-actions, .tournament-page-actions,
.tournament-page-tabs { .tournament-page-tabs {
@@ -220,7 +220,7 @@ onBeforeUnmount(() => {
.game-feedback-copy strong { .game-feedback-copy strong {
color: #e5c982; color: #e5c982;
font-size: 0.78rem; font-size: var(--sammo-font-size-small);
} }
.game-feedback-close { .game-feedback-close {
@@ -231,7 +231,7 @@ onBeforeUnmount(() => {
background: transparent; background: transparent;
border: 0; border: 0;
cursor: pointer; cursor: pointer;
font-size: 1.25rem; font-size: var(--sammo-font-size-title);
line-height: 1; line-height: 1;
} }
@@ -276,7 +276,7 @@ onBeforeUnmount(() => {
.game-dialog-panel h2 { .game-dialog-panel h2 {
color: #e5c982; color: #e5c982;
font-size: 1rem; font-size: var(--sammo-font-size-emphasis);
} }
.game-dialog-panel p { .game-dialog-panel p {
@@ -30,7 +30,7 @@ const { reconnecting } = useGameServerConnectionRecovery();
border-top: 0; border-top: 0;
background: #fff3bf; background: #fff3bf;
color: #3d3100; color: #3d3100;
font: 13px/1.45 var(--sammo-font-sans); font: var(--sammo-font-size-small)/1.45 var(--sammo-font-sans);
text-align: center; text-align: center;
box-shadow: 0 2px 6px rgb(0 0 0 / 25%); box-shadow: 0 2px 6px rgb(0 0 0 / 25%);
} }
@@ -102,7 +102,7 @@ const experiencePercent = computed(() =>
max-width: 100%; max-width: 100%;
overflow: hidden; overflow: hidden;
border-top: 1px solid #666; border-top: 1px solid #666;
font-size: 12px; font-size: var(--sammo-font-size-small);
} }
.stat-grid { .stat-grid {
@@ -427,7 +427,7 @@ onBeforeUnmount(() => editor.value?.destroy());
} }
.legacy-html-editor__image-toolbar span { .legacy-html-editor__image-toolbar span {
padding: 0 4px; padding: 0 4px;
font-size: 12px; font-size: var(--sammo-font-size-small);
} }
.legacy-html-editor__image-toolbar button { .legacy-html-editor__image-toolbar button {
border: 1px solid transparent; border: 1px solid transparent;
@@ -453,7 +453,7 @@ onBeforeUnmount(() => editor.value?.destroy());
align-items: center; align-items: center;
gap: 0; gap: 0;
color: inherit; color: inherit;
font-size: 12px; font-size: var(--sammo-font-size-small);
} }
.legacy-html-editor__select select { .legacy-html-editor__select select {
min-width: 0; min-width: 0;
@@ -49,14 +49,14 @@ withDefaults(defineProps<Props>(), {
.panel-title { .panel-title {
margin: 0; margin: 0;
color: #fff; color: #fff;
font-size: 14px; font-size: var(--sammo-font-size-normal);
font-weight: 700; font-weight: 700;
} }
.panel-subtitle { .panel-subtitle {
margin: 1px 0 0; margin: 1px 0 0;
color: #ccc; color: #ccc;
font-size: 11px; font-size: var(--sammo-font-size-small);
} }
.panel-actions { .panel-actions {
@@ -68,6 +68,6 @@ withDefaults(defineProps<Props>(), {
.panel-body { .panel-body {
padding: 6px; padding: 6px;
color: #fff; color: #fff;
font-size: 14px; font-size: var(--sammo-font-size-normal);
} }
</style> </style>
@@ -112,7 +112,7 @@ watch(
box-shadow: 0 3px 12px rgb(0 0 0 / 65%); box-shadow: 0 3px 12px rgb(0 0 0 / 65%);
color: #f5f5f5; color: #f5f5f5;
font-family: var(--sammo-font-sans); font-family: var(--sammo-font-sans);
font-size: 12.5px; font-size: var(--sammo-font-size-small);
line-height: 1.45; line-height: 1.45;
text-align: left; text-align: left;
} }
@@ -147,7 +147,7 @@ watch(
.rich-tooltip-content__title { .rich-tooltip-content__title {
margin-bottom: 4px; margin-bottom: 4px;
color: #7fd4ff; color: #7fd4ff;
font-size: 13px; font-size: var(--sammo-font-size-small);
font-weight: 700; font-weight: 700;
} }
+2 -2
View File
@@ -517,7 +517,7 @@ onMounted(() => {
margin: 0 auto; margin: 0 auto;
color: #fff; color: #fff;
font-family: var(--sammo-font-sans); font-family: var(--sammo-font-sans);
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: 21px; line-height: 21px;
} }
.legacy-auction-page.resource-page { .legacy-auction-page.resource-page {
@@ -549,7 +549,7 @@ onMounted(() => {
} }
.top-back-bar h1 { .top-back-bar h1 {
margin: 0; margin: 0;
font-size: 24px; font-size: var(--sammo-font-size-title);
font-weight: 500; font-weight: 500;
line-height: 32px; line-height: 32px;
text-align: center; text-align: center;
@@ -405,7 +405,7 @@ onMounted(() => {
} }
:deep(.panel-title) { :deep(.panel-title) {
color: skyblue; color: skyblue;
font-size: 18px; font-size: var(--sammo-font-size-emphasis);
font-weight: 500; font-weight: 500;
} }
:deep(.panel-header) { :deep(.panel-header) {
@@ -443,7 +443,7 @@ onMounted(() => {
} }
.battle-top h1 { .battle-top h1 {
margin: 0; margin: 0;
font-size: 24px; font-size: var(--sammo-font-size-title);
font-weight: 400; font-weight: 400;
line-height: 32px; line-height: 32px;
text-align: center; text-align: center;
@@ -1368,7 +1368,7 @@ const shouldShowUI = computed(() => !loading.value && !!options.value);
padding: 2px 6px; padding: 2px 6px;
background: #444; background: #444;
color: #aaa; color: #aaa;
font-size: 11px; font-size: var(--sammo-font-size-small);
} }
.independence-notice p { .independence-notice p {
@@ -1403,7 +1403,7 @@ button {
border-radius: 5.25px; border-radius: 5.25px;
padding: 5.25px 10.5px; padding: 5.25px 10.5px;
color: #fff; color: #fff;
font-size: 14px; font-size: var(--sammo-font-size-normal);
font-weight: 700; font-weight: 700;
line-height: 21px; line-height: 21px;
vertical-align: middle; vertical-align: middle;
@@ -1465,12 +1465,12 @@ button:disabled {
.error { .error {
color: #f5b7b1; color: #f5b7b1;
font-size: 0.85rem; font-size: var(--sammo-font-size-normal);
} }
.status { .status {
color: #f5d08a; color: #f5d08a;
font-size: 0.85rem; font-size: var(--sammo-font-size-normal);
} }
.settings-grid { .settings-grid {
@@ -1484,7 +1484,7 @@ button:disabled {
display: grid; display: grid;
grid-template-columns: auto minmax(0, 1fr); grid-template-columns: auto minmax(0, 1fr);
color: #ddd; color: #ddd;
font-size: 14px; font-size: var(--sammo-font-size-normal);
} }
.unit-after { .unit-after {
@@ -1507,7 +1507,7 @@ button:disabled {
background: #ddd; background: #ddd;
color: #303030; color: #303030;
padding: 5.25px 10.5px; padding: 5.25px 10.5px;
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: 21px; line-height: 21px;
box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.075); box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.075);
transition: transition:
@@ -1571,7 +1571,7 @@ button:disabled {
border: 1px solid #111; border: 1px solid #111;
background: #444; background: #444;
color: #ddd; color: #ddd;
font-size: 14px; font-size: var(--sammo-font-size-normal);
white-space: nowrap; white-space: nowrap;
} }
@@ -1595,7 +1595,7 @@ button:disabled {
padding: 6px 14px; padding: 6px 14px;
border-radius: 5px; border-radius: 5px;
background: #444; background: #444;
font-size: 14px; font-size: var(--sammo-font-size-normal);
} }
.defender-toolbar > div { .defender-toolbar > div {
@@ -1653,7 +1653,7 @@ button:disabled {
.log-body { .log-body {
min-height: 0; min-height: 0;
line-height: 1.5; line-height: 1.5;
font-size: 0.85rem; font-size: var(--sammo-font-size-normal);
} }
.modal-backdrop { .modal-backdrop {
@@ -1686,7 +1686,7 @@ button:disabled {
.modal h3 { .modal h3 {
margin: 0; margin: 0;
font-size: 1rem; font-size: var(--sammo-font-size-emphasis);
} }
.modal-body { .modal-body {
@@ -1696,7 +1696,7 @@ button:disabled {
} }
.hint { .hint {
font-size: 0.75rem; font-size: var(--sammo-font-size-small);
color: rgba(232, 221, 196, 0.7); color: rgba(232, 221, 196, 0.7);
} }
@@ -179,6 +179,11 @@ watch(viewMode, () => {
</template> </template>
<style scoped> <style scoped>
/* UI 보조 글자는 부모의 80%가 아니라 공통 소형 크기를 사용한다. */
small {
font-size: var(--sammo-font-size-small);
}
:global(body:has(.legacy-ranking-page)) { :global(body:has(.legacy-ranking-page)) {
min-width: 500px; min-width: 500px;
overflow-x: hidden; overflow-x: hidden;
@@ -191,7 +196,7 @@ watch(viewMode, () => {
background-color: transparent; background-color: transparent;
color: #fff; color: #fff;
font-family: var(--sammo-font-sans); font-family: var(--sammo-font-sans);
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: 1.3; line-height: 1.3;
} }
@@ -251,7 +256,7 @@ watch(viewMode, () => {
} }
.legacy-banner { .legacy-banner {
font-size: 13px; font-size: var(--sammo-font-size-small);
} }
.legacy-banner a { .legacy-banner a {
@@ -278,7 +283,7 @@ watch(viewMode, () => {
margin: 0; margin: 0;
border-bottom: 1px solid gray; border-bottom: 1px solid gray;
padding: 2px; padding: 2px;
font-size: calc(19px + 0.784615vw); font-size: var(--sammo-font-size-title);
font-weight: 500; font-weight: 500;
line-height: 1.2; line-height: 1.2;
text-align: center; text-align: center;
@@ -341,7 +346,7 @@ watch(viewMode, () => {
.hall-nation, .hall-nation,
.hall-name { .hall-name {
font-size: 11px; font-size: var(--sammo-font-size-hall-name);
} }
.hall-name { .hall-name {
@@ -352,7 +357,7 @@ watch(viewMode, () => {
} }
.hall-name small { .hall-name small {
font-size: 95%; font-size: var(--sammo-font-size-hall-secondary);
} }
.hall-value { .hall-value {
@@ -377,7 +382,7 @@ watch(viewMode, () => {
} }
.rankType { .rankType {
font-size: 28px; font-size: var(--sammo-font-size-title);
} }
} }
</style> </style>
+22 -21
View File
@@ -281,11 +281,12 @@ const placeBet = async (target: TournamentBracketSlot) => {
</template> </template>
<style scoped> <style scoped>
/* UI 보조 글자는 부모의 80%가 아니라 공통 소형 크기를 사용한다. */
small {
font-size: var(--sammo-font-size-small);
}
.betting-page { .betting-page {
--bet-font-title: 24px;
--bet-font-large: 16px;
--bet-font-normal: 14px;
--bet-font-small: 12px;
width: 100%; width: 100%;
max-width: 1200px; max-width: 1200px;
min-width: 0; min-width: 0;
@@ -293,7 +294,7 @@ const placeBet = async (target: TournamentBracketSlot) => {
margin: 0 auto; margin: 0 auto;
color: #fff; color: #fff;
font-family: var(--sammo-font-sans); font-family: var(--sammo-font-sans);
font-size: var(--bet-font-normal); font-size: var(--sammo-font-size-normal);
line-height: 1.3; line-height: 1.3;
text-align: center; text-align: center;
} }
@@ -323,7 +324,7 @@ const placeBet = async (target: TournamentBracketSlot) => {
--legacy-button-height: 44px; --legacy-button-height: 44px;
min-width: 72px; min-width: 72px;
padding: 10px 16px; padding: 10px 16px;
font-size: var(--bet-font-normal); font-size: var(--sammo-font-size-normal);
} }
.error { .error {
min-height: 32px; min-height: 32px;
@@ -333,7 +334,7 @@ const placeBet = async (target: TournamentBracketSlot) => {
.state { .state {
min-height: 42px; min-height: 42px;
padding: 5px; padding: 5px;
font-size: var(--bet-font-title); font-size: var(--sammo-font-size-title);
} }
.state span { .state span {
color: cyan; color: cyan;
@@ -342,11 +343,11 @@ const placeBet = async (target: TournamentBracketSlot) => {
min-height: 50px; min-height: 50px;
padding: 5px; padding: 5px;
color: limegreen; color: limegreen;
font-size: var(--bet-font-title); font-size: var(--sammo-font-size-title);
} }
.section-title small { .section-title small {
color: orange; color: orange;
font-size: var(--bet-font-normal); font-size: var(--sammo-font-size-normal);
} }
select { select {
width: 100%; width: 100%;
@@ -408,7 +409,7 @@ select:disabled {
border-radius: 3px; border-radius: 3px;
color: #fff; color: #fff;
background: #201610; background: #201610;
font-size: var(--bet-font-normal); font-size: var(--sammo-font-size-normal);
} }
.inline-bet .bracket-bet-button { .inline-bet .bracket-bet-button {
position: static; position: static;
@@ -422,7 +423,7 @@ select:disabled {
} }
.bet-message { .bet-message {
grid-column: 1 / -1; grid-column: 1 / -1;
font-size: var(--bet-font-small); font-size: var(--sammo-font-size-small);
line-height: 16px; line-height: 16px;
color: #b8e6ac; color: #b8e6ac;
overflow-wrap: anywhere; overflow-wrap: anywhere;
@@ -434,7 +435,7 @@ select:disabled {
min-height: 50px; min-height: 50px;
padding: 8px; padding: 8px;
color: yellow; color: yellow;
font-size: var(--bet-font-title); font-size: var(--sammo-font-size-title);
} }
.ranking-placeholder { .ranking-placeholder {
min-height: 40px; min-height: 40px;
@@ -452,7 +453,7 @@ select:disabled {
width: 100%; width: 100%;
border-collapse: collapse; border-collapse: collapse;
font-variant-numeric: tabular-nums; font-variant-numeric: tabular-nums;
font-size: var(--bet-font-small); font-size: var(--sammo-font-size-small);
line-height: 14px; line-height: 14px;
} }
.ranking-table th, .ranking-table th,
@@ -467,7 +468,7 @@ select:disabled {
.ranking-table thead tr:first-child th { .ranking-table thead tr:first-child th {
height: 18px; height: 18px;
background: #000; background: #000;
font-size: var(--bet-font-large); font-size: var(--sammo-font-size-emphasis);
line-height: 18px; line-height: 18px;
font-weight: normal; font-weight: normal;
} }
@@ -498,14 +499,14 @@ select:disabled {
@media (max-width: 800px) { @media (max-width: 800px) {
.betting-page { .betting-page {
max-width: 100%; max-width: 100%;
font-size: var(--bet-font-normal); font-size: var(--sammo-font-size-normal);
} }
.state { .state {
font-size: var(--bet-font-large); font-size: var(--sammo-font-size-emphasis);
} }
.section-title, .section-title,
.ranking-title { .ranking-title {
font-size: var(--bet-font-title); font-size: var(--sammo-font-size-title);
} }
.ranking-placeholder { .ranking-placeholder {
display: none; display: none;
@@ -533,7 +534,7 @@ select:disabled {
.ranking-table { .ranking-table {
display: none; display: none;
min-width: 390px; min-width: 390px;
font-size: var(--bet-font-small); font-size: var(--sammo-font-size-small);
} }
.ranking-table.mobile-active { .ranking-table.mobile-active {
display: table; display: table;
@@ -552,7 +553,7 @@ select:disabled {
} }
} }
.betting-page small { .betting-page small {
font-size: var(--bet-font-small); font-size: var(--sammo-font-size-small);
} }
.bet-preset { .bet-preset {
position: relative; position: relative;
@@ -582,9 +583,9 @@ select:disabled {
display: none; display: none;
} }
.betting-page :deep(.tournament-page-title) { .betting-page :deep(.tournament-page-title) {
font-size: var(--bet-font-large); font-size: var(--sammo-font-size-emphasis);
} }
.betting-page :deep(.tournament-page-header button) { .betting-page :deep(.tournament-page-header button) {
font-size: var(--bet-font-normal); font-size: var(--sammo-font-size-normal);
} }
</style> </style>
+4 -4
View File
@@ -271,7 +271,7 @@ onMounted(() => {
padding: 8px; padding: 8px;
color: #000; color: #000;
background: #fff; background: #fff;
font: 16px/normal var(--sammo-font-sans); font: var(--sammo-font-size-emphasis)/normal var(--sammo-font-sans);
} }
.legacy-board-page { .legacy-board-page {
@@ -280,7 +280,7 @@ onMounted(() => {
color: #fff; color: #fff;
background: transparent; background: transparent;
font-family: var(--sammo-font-sans); font-family: var(--sammo-font-sans);
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: 1.3; line-height: 1.3;
} }
@@ -309,7 +309,7 @@ onMounted(() => {
.top-back-bar h1 { .top-back-bar h1 {
margin: 0; margin: 0;
font-size: 24px; font-size: var(--sammo-font-size-title);
font-weight: 500; font-weight: 500;
line-height: 32px; line-height: 32px;
text-align: center; text-align: center;
@@ -440,7 +440,7 @@ onMounted(() => {
.date { .date {
width: 83.333px; width: 83.333px;
flex: 0 0 auto; flex: 0 0 auto;
font-size: 0.9em; font-size: var(--sammo-font-size-small);
} }
.article-body { .article-body {
+15 -15
View File
@@ -511,7 +511,7 @@ const repeatTurns = async (amount: number) => {
padding: 8px; padding: 8px;
display: grid; display: grid;
gap: 6px; gap: 6px;
font-size: 0.75rem; font-size: var(--sammo-font-size-small);
margin-top: 12px; margin-top: 12px;
} }
@@ -522,7 +522,7 @@ const repeatTurns = async (amount: number) => {
.command-selected .meta { .command-selected .meta {
display: flex; display: flex;
gap: 8px; gap: 8px;
font-size: 0.7rem; font-size: var(--sammo-font-size-small);
color: rgba(232, 221, 196, 0.6); color: rgba(232, 221, 196, 0.6);
} }
@@ -535,7 +535,7 @@ const repeatTurns = async (amount: number) => {
.turn-actions button { .turn-actions button {
border: 1px solid rgba(201, 164, 90, 0.3); border: 1px solid rgba(201, 164, 90, 0.3);
padding: 4px 8px; padding: 4px 8px;
font-size: 0.75rem; font-size: var(--sammo-font-size-small);
background: rgba(12, 12, 12, 0.6); background: rgba(12, 12, 12, 0.6);
color: inherit; color: inherit;
cursor: pointer; cursor: pointer;
@@ -555,7 +555,7 @@ const repeatTurns = async (amount: number) => {
flex-wrap: wrap; flex-wrap: wrap;
justify-content: space-between; justify-content: space-between;
gap: 8px; gap: 8px;
font-size: 0.75rem; font-size: var(--sammo-font-size-small);
} }
.turn-info { .turn-info {
@@ -584,7 +584,7 @@ const repeatTurns = async (amount: number) => {
.turn-buttons button { .turn-buttons button {
border: 1px solid rgba(201, 164, 90, 0.3); border: 1px solid rgba(201, 164, 90, 0.3);
padding: 4px 8px; padding: 4px 8px;
font-size: 0.7rem; font-size: var(--sammo-font-size-small);
background: rgba(12, 12, 12, 0.6); background: rgba(12, 12, 12, 0.6);
color: inherit; color: inherit;
cursor: pointer; cursor: pointer;
@@ -655,7 +655,7 @@ const repeatTurns = async (amount: number) => {
.chief-page { .chief-page {
margin: 0 auto; margin: 0 auto;
color: #fff; color: #fff;
font: 14px/21px var(--sammo-font-sans); font: var(--sammo-font-size-normal)/21px var(--sammo-font-sans);
} }
.chief-top { .chief-top {
height: 32px; height: 32px;
@@ -665,7 +665,7 @@ const repeatTurns = async (amount: number) => {
} }
.chief-top h1 { .chief-top h1 {
margin: 0; margin: 0;
font-size: 24px; font-size: var(--sammo-font-size-title);
font-weight: 400; font-weight: 400;
line-height: 32px; line-height: 32px;
text-align: center; text-align: center;
@@ -731,7 +731,7 @@ const repeatTurns = async (amount: number) => {
justify-content: center; justify-content: center;
padding: 0; padding: 0;
background-color: transparent; background-color: transparent;
font-size: 16.8px; font-size: var(--sammo-font-size-emphasis);
line-height: 14.7px; line-height: 14.7px;
} }
.chief-grid-row :deep(.chief-title) { .chief-grid-row :deep(.chief-title) {
@@ -742,7 +742,7 @@ const repeatTurns = async (amount: number) => {
} }
.chief-grid-row :deep(.chief-level), .chief-grid-row :deep(.chief-level),
.chief-grid-row :deep(.chief-name) { .chief-grid-row :deep(.chief-name) {
font-size: 16.8px; font-size: var(--sammo-font-size-emphasis);
font-weight: 400; font-weight: 400;
line-height: 14.7px; line-height: 14.7px;
color: inherit; color: inherit;
@@ -758,7 +758,7 @@ const repeatTurns = async (amount: number) => {
gap: 0; gap: 0;
padding: 0; padding: 0;
border: 0; border: 0;
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: 14.7px; line-height: 14.7px;
color: #fff; color: #fff;
text-align: center; text-align: center;
@@ -832,7 +832,7 @@ const repeatTurns = async (amount: number) => {
padding: 0; padding: 0;
gap: 0; gap: 0;
text-align: center; text-align: center;
font-size: 0.55rem; font-size: var(--sammo-font-size-chief-compact-row);
line-height: 11.25px !important; line-height: 11.25px !important;
} }
.chief-overview :deep(.chief-card.compact .chief-header) { .chief-overview :deep(.chief-card.compact .chief-header) {
@@ -859,7 +859,7 @@ const repeatTurns = async (amount: number) => {
width: 12px; width: 12px;
height: 155px; height: 155px;
color: #fff; color: #fff;
font-size: 0.55rem; font-size: var(--sammo-font-size-chief-compact-row);
line-height: 11.25px; line-height: 11.25px;
text-align: center; text-align: center;
} }
@@ -884,7 +884,7 @@ const repeatTurns = async (amount: number) => {
justify-content: center; justify-content: center;
padding: 0; padding: 0;
background-color: transparent; background-color: transparent;
font-size: 16.8px; font-size: var(--sammo-font-size-emphasis);
line-height: 14.7px; line-height: 14.7px;
} }
.mobile-readonly :deep(.chief-title) { .mobile-readonly :deep(.chief-title) {
@@ -895,7 +895,7 @@ const repeatTurns = async (amount: number) => {
} }
.mobile-readonly :deep(.chief-level), .mobile-readonly :deep(.chief-level),
.mobile-readonly :deep(.chief-name) { .mobile-readonly :deep(.chief-name) {
font-size: 16.8px; font-size: var(--sammo-font-size-emphasis);
font-weight: 400; font-weight: 400;
line-height: 14.7px; line-height: 14.7px;
color: inherit; color: inherit;
@@ -907,7 +907,7 @@ const repeatTurns = async (amount: number) => {
height: 30px; height: 30px;
grid-template-columns: 43.33px 216.67px; grid-template-columns: 43.33px 216.67px;
padding: 0; padding: 0;
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: 14.7px; line-height: 14.7px;
color: #fff; color: #fff;
} }
@@ -340,7 +340,7 @@ const commandBrief = (command: ReservedCommand): string =>
width: 1000px; width: 1000px;
margin: 0 auto; margin: 0 auto;
font-family: var(--sammo-font-sans); font-family: var(--sammo-font-sans);
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: 1.3; line-height: 1.3;
} }
.legacy-table { .legacy-table {
@@ -371,7 +371,7 @@ const commandBrief = (command: ReservedCommand): string =>
background: #6b6b6b; background: #6b6b6b;
color: #fff; color: #fff;
font-family: var(--sammo-font-sans); font-family: var(--sammo-font-sans);
font-size: 13.3333px; font-size: var(--sammo-font-size-normal);
} }
.selector { .selector {
transform: translateY(-2px); transform: translateY(-2px);
@@ -450,7 +450,7 @@ const commandBrief = (command: ReservedCommand): string =>
object-fit: fill; object-fit: fill;
} }
.turns--reserved { .turns--reserved {
font-size: x-small; font-size: var(--sammo-font-size-small);
} }
.turn-line { .turn-line {
display: block; display: block;
@@ -466,7 +466,7 @@ const commandBrief = (command: ReservedCommand): string =>
} }
.back-link { .back-link {
font-family: var(--sammo-font-sans); font-family: var(--sammo-font-sans);
font-size: 14px; font-size: var(--sammo-font-size-normal);
} }
.legacy-banner a { .legacy-banner a {
color: #fff; color: #fff;
@@ -542,7 +542,7 @@ const commandBrief = (command: ReservedCommand): string =>
.generals tbody td[data-label]::before { .generals tbody td[data-label]::before {
content: attr(data-label); content: attr(data-label);
margin-right: 3px; margin-right: 3px;
font-size: 11px; font-size: var(--sammo-font-size-small);
line-height: 1; line-height: 1;
color: #bbb; color: #bbb;
} }
@@ -659,7 +659,7 @@ onBeforeUnmount(() => {
color: #fff; color: #fff;
overflow-x: clip; overflow-x: clip;
font-family: var(--sammo-font-sans); font-family: var(--sammo-font-sans);
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: 1.3; line-height: 1.3;
} }
@@ -699,7 +699,7 @@ onBeforeUnmount(() => {
.panel-header h2 { .panel-header h2 {
margin: 0; margin: 0;
font-size: 14px; font-size: var(--sammo-font-size-normal);
font-weight: 500; font-weight: 500;
} }
@@ -809,7 +809,7 @@ onBeforeUnmount(() => {
.letter-header h3 { .letter-header h3 {
margin: 0; margin: 0;
font-size: 28px; font-size: var(--sammo-font-size-title);
font-weight: 400; font-weight: 400;
} }
@@ -817,7 +817,7 @@ onBeforeUnmount(() => {
position: absolute; position: absolute;
right: 10px; right: 10px;
bottom: 3px; bottom: 3px;
font-size: 14px; font-size: var(--sammo-font-size-normal);
} }
.letter-text { .letter-text {
@@ -308,7 +308,7 @@ onMounted(loadDetail);
margin: 8px auto 0; margin: 8px auto 0;
color: #fff; color: #fff;
font-family: var(--sammo-font-sans); font-family: var(--sammo-font-sans);
font-size: 16px; font-size: var(--sammo-font-size-emphasis);
line-height: normal; line-height: normal;
} }
@@ -351,7 +351,7 @@ onMounted(loadDetail);
} }
.large-text { .large-text {
font-size: x-large; font-size: var(--sammo-font-size-title);
} }
.centered { .centered {
@@ -387,7 +387,7 @@ onMounted(loadDetail);
background: buttonface; background: buttonface;
color: buttontext; color: buttontext;
font-family: var(--sammo-font-sans); font-family: var(--sammo-font-sans);
font-size: 13.3333px; font-size: var(--sammo-font-size-normal);
font-weight: 400; font-weight: 400;
line-height: normal; line-height: normal;
cursor: default; cursor: default;
@@ -411,6 +411,6 @@ onMounted(loadDetail);
} }
.banner { .banner {
font-size: 13px; font-size: var(--sammo-font-size-small);
} }
</style> </style>
@@ -186,7 +186,7 @@ watch(selectedSource, loadDynasty);
width: 1000px; width: 1000px;
background-color: transparent; background-color: transparent;
border-collapse: collapse; border-collapse: collapse;
font-size: 14px; font-size: var(--sammo-font-size-normal);
word-break: break-all; word-break: break-all;
} }
@@ -241,7 +241,7 @@ watch(selectedSource, loadDynasty);
} }
.large-text { .large-text {
font-size: x-large; font-size: var(--sammo-font-size-title);
} }
.label-column { .label-column {
@@ -261,7 +261,7 @@ watch(selectedSource, loadDynasty);
background: buttonface; background: buttonface;
color: buttontext; color: buttontext;
font-family: var(--sammo-font-sans); font-family: var(--sammo-font-sans);
font-size: 13.3333px; font-size: var(--sammo-font-size-normal);
font-weight: 400; font-weight: 400;
line-height: normal; line-height: normal;
cursor: default; cursor: default;
@@ -284,6 +284,6 @@ watch(selectedSource, loadDynasty);
} }
.banner { .banner {
font-size: 13px; font-size: var(--sammo-font-size-small);
} }
</style> </style>
@@ -133,10 +133,15 @@ onMounted(() => {
</template> </template>
<style scoped> <style scoped>
/* UI 보조 글자는 부모의 80%가 아니라 공통 소형 크기를 사용한다. */
small {
font-size: var(--sammo-font-size-small);
}
.directory-page { .directory-page {
width: 1000px; width: 1000px;
margin: 0 auto; margin: 0 auto;
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: 1.3; line-height: 1.3;
} }
.directory-table { .directory-table {
@@ -144,7 +149,7 @@ onMounted(() => {
border-collapse: collapse; border-collapse: collapse;
table-layout: auto; table-layout: auto;
padding: 0; padding: 0;
font-size: 14px; font-size: var(--sammo-font-size-normal);
word-break: break-all; word-break: break-all;
} }
.directory-table td { .directory-table td {
@@ -158,7 +163,7 @@ onMounted(() => {
} }
.legacy-button { .legacy-button {
padding: 5px 10px; padding: 5px 10px;
font-size: 14px; font-size: var(--sammo-font-size-normal);
} }
.directory-error { .directory-error {
width: 998px; width: 998px;
@@ -171,7 +171,7 @@ onMounted(async () => {
.global-page { .global-page {
width: 1000px; width: 1000px;
margin: 0 auto; margin: 0 auto;
font-size: 14px; font-size: var(--sammo-font-size-normal);
background-color: transparent; background-color: transparent;
background-image: none; background-image: none;
} }
@@ -188,7 +188,7 @@ onMounted(async () => {
text-align: center; text-align: center;
} }
.legacy-title strong { .legacy-title strong {
font-size: 24px; font-size: var(--sammo-font-size-title);
font-weight: 400; font-weight: 400;
line-height: 32px; line-height: 32px;
} }
@@ -206,7 +206,7 @@ onMounted(async () => {
background-image: var(--sammo-texture-walnut); background-image: var(--sammo-texture-walnut);
} }
.section h2 { .section h2 {
font-size: 16.8px; font-size: var(--sammo-font-size-emphasis);
font-weight: 400; font-weight: 400;
text-align: center; text-align: center;
margin: 0; margin: 0;
+11 -6
View File
@@ -193,6 +193,11 @@ onMounted(loadOptions);
</template> </template>
<style scoped> <style scoped>
/* UI 보조 글자는 부모의 80%가 아니라 공통 소형 크기를 사용한다. */
small {
font-size: var(--sammo-font-size-small);
}
/* Ref's document does not clip; the page column stays 500px wide instead. */ /* Ref's document does not clip; the page column stays 500px wide instead. */
:global(body:has(.legacy-hall-page)) { :global(body:has(.legacy-hall-page)) {
min-width: 500px; min-width: 500px;
@@ -204,7 +209,7 @@ onMounted(loadOptions);
margin: 0 auto; margin: 0 auto;
color: #fff; color: #fff;
font-family: var(--sammo-font-sans); font-family: var(--sammo-font-sans);
font-size: 14px; font-size: var(--sammo-font-size-normal);
} }
.legacy-hall-title, .legacy-hall-title,
@@ -274,7 +279,7 @@ onMounted(loadOptions);
} }
.legacy-banner { .legacy-banner {
font-size: 13px; font-size: var(--sammo-font-size-small);
} }
.legacy-banner a { .legacy-banner a {
@@ -296,7 +301,7 @@ onMounted(loadOptions);
margin: 0; margin: 0;
border-bottom: 1px solid gray; border-bottom: 1px solid gray;
padding: 2px; padding: 2px;
font-size: calc(19px + 0.784615vw); font-size: var(--sammo-font-size-title);
font-weight: 500; font-weight: 500;
line-height: 1.2; line-height: 1.2;
text-align: center; text-align: center;
@@ -344,7 +349,7 @@ onMounted(loadOptions);
.hall-server, .hall-server,
.hall-nation, .hall-nation,
.hall-name { .hall-name {
font-size: 11px; font-size: var(--sammo-font-size-hall-name);
} }
.hall-name { .hall-name {
@@ -355,7 +360,7 @@ onMounted(loadOptions);
} }
.hall-name small { .hall-name small {
font-size: 95%; font-size: var(--sammo-font-size-hall-secondary);
} }
.hall-value { .hall-value {
@@ -380,7 +385,7 @@ onMounted(loadOptions);
} }
.rankType { .rankType {
font-size: 28px; font-size: var(--sammo-font-size-title);
} }
} }
</style> </style>
+8 -3
View File
@@ -787,6 +787,11 @@ onMounted(() => {
</template> </template>
<style scoped> <style scoped>
/* UI 보조 글자는 부모의 80%가 아니라 공통 소형 크기를 사용한다. */
small {
font-size: var(--sammo-font-size-small);
}
.top-back-bar { .top-back-bar {
width: min(100%, 1000px); width: min(100%, 1000px);
height: 32px; height: 32px;
@@ -816,7 +821,7 @@ onMounted(() => {
padding: 0 7px; padding: 0 7px;
color: #fff; color: #fff;
min-height: 1597px; min-height: 1597px;
font: 14px/21px var(--sammo-font-sans); font: var(--sammo-font-size-normal)/21px var(--sammo-font-sans);
} }
.inherit-page.legacy-bg0 { .inherit-page.legacy-bg0 {
@@ -892,7 +897,7 @@ onMounted(() => {
} }
.section-title { .section-title {
font-size: 14px; font-size: var(--sammo-font-size-normal);
font-weight: 400; font-weight: 400;
text-align: center; text-align: center;
margin: 0 -8px; margin: 0 -8px;
@@ -969,7 +974,7 @@ onMounted(() => {
.stat-layout strong { .stat-layout strong {
text-align: left; text-align: left;
font-size: 12px; font-size: var(--sammo-font-size-small);
} }
.owner-result { .owner-result {
+36 -31
View File
@@ -1276,6 +1276,11 @@ onUnmounted(() => {
</template> </template>
<style scoped> <style scoped>
/* UI 보조 글자는 부모의 80%가 아니라 공통 소형 크기를 사용한다. */
small {
font-size: var(--sammo-font-size-small);
}
.join-page { .join-page {
min-height: 100vh; min-height: 100vh;
padding: 24px; padding: 24px;
@@ -1298,12 +1303,12 @@ onUnmounted(() => {
} }
.join-title { .join-title {
font-size: 1.6rem; font-size: var(--sammo-font-size-title);
font-weight: 600; font-weight: 600;
} }
.join-subtitle { .join-subtitle {
font-size: 0.85rem; font-size: var(--sammo-font-size-normal);
color: rgba(232, 221, 196, 0.7); color: rgba(232, 221, 196, 0.7);
} }
@@ -1315,14 +1320,14 @@ onUnmounted(() => {
.join-tabs button { .join-tabs button {
border: 1px solid rgba(201, 164, 90, 0.4); border: 1px solid rgba(201, 164, 90, 0.4);
padding: 6px 10px; padding: 6px 10px;
font-size: 0.8rem; font-size: var(--sammo-font-size-small);
} }
.simulator-link { .simulator-link {
border: 1px solid rgba(112, 170, 141, 0.55); border: 1px solid rgba(112, 170, 141, 0.55);
padding: 6px 10px; padding: 6px 10px;
color: #bfe2cd; color: #bfe2cd;
font-size: 0.8rem; font-size: var(--sammo-font-size-small);
text-decoration: none; text-decoration: none;
} }
@@ -1371,7 +1376,7 @@ onUnmounted(() => {
.nation-message { .nation-message {
margin: 0; margin: 0;
padding: 8px; padding: 8px;
font-size: 0.75rem; font-size: var(--sammo-font-size-small);
color: rgba(232, 221, 196, 0.7); color: rgba(232, 221, 196, 0.7);
} }
@@ -1400,12 +1405,12 @@ onUnmounted(() => {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 6px; gap: 6px;
font-size: 0.75rem; font-size: var(--sammo-font-size-small);
} }
.primary-field > span:first-child { .primary-field > span:first-child {
color: #f0d99e; color: #f0d99e;
font-size: 0.85rem; font-size: var(--sammo-font-size-normal);
font-weight: 700; font-weight: 700;
} }
@@ -1418,7 +1423,7 @@ onUnmounted(() => {
.primary-field > .form-input { .primary-field > .form-input {
min-height: 36px; min-height: 36px;
font-size: 1rem; font-size: var(--sammo-font-size-emphasis);
} }
.stat-actions { .stat-actions {
@@ -1433,7 +1438,7 @@ onUnmounted(() => {
height: 40px; height: 40px;
min-height: 40px; min-height: 40px;
padding: 8px 14px; padding: 8px 14px;
font-size: 0.875rem; font-size: var(--sammo-font-size-normal);
line-height: 1.2; line-height: 1.2;
} }
@@ -1449,7 +1454,7 @@ onUnmounted(() => {
.stat-summary { .stat-summary {
margin-top: 10px; margin-top: 10px;
font-size: 0.75rem; font-size: var(--sammo-font-size-small);
color: rgba(232, 221, 196, 0.7); color: rgba(232, 221, 196, 0.7);
} }
@@ -1467,7 +1472,7 @@ onUnmounted(() => {
.form-actions button { .form-actions button {
border: 1px solid rgba(201, 164, 90, 0.4); border: 1px solid rgba(201, 164, 90, 0.4);
padding: 6px 12px; padding: 6px 12px;
font-size: 0.8rem; font-size: var(--sammo-font-size-small);
} }
.form-actions .primary-action { .form-actions .primary-action {
@@ -1520,13 +1525,13 @@ onUnmounted(() => {
.advanced-title small { .advanced-title small {
color: #ccc; color: #ccc;
font-size: 0.7rem; font-size: var(--sammo-font-size-small);
font-weight: 400; font-weight: 400;
} }
.advanced-point-summary { .advanced-point-summary {
color: #ead8ac; color: #ead8ac;
font-size: 0.75rem; font-size: var(--sammo-font-size-small);
white-space: nowrap; white-space: nowrap;
} }
@@ -1546,7 +1551,7 @@ onUnmounted(() => {
border: 0; border: 0;
border-right: 1px solid rgba(201, 164, 90, 0.25); border-right: 1px solid rgba(201, 164, 90, 0.25);
color: rgba(232, 221, 196, 0.68); color: rgba(232, 221, 196, 0.68);
font-size: 0.8rem; font-size: var(--sammo-font-size-small);
} }
.context-tabs button:last-child { .context-tabs button:last-child {
@@ -1583,7 +1588,7 @@ onUnmounted(() => {
gap: 12px; gap: 12px;
margin-bottom: 8px; margin-bottom: 8px;
color: rgba(232, 221, 196, 0.75); color: rgba(232, 221, 196, 0.75);
font-size: 0.75rem; font-size: var(--sammo-font-size-small);
} }
.general-list-head label { .general-list-head label {
@@ -1602,7 +1607,7 @@ onUnmounted(() => {
.context-general-table { .context-general-table {
width: 100%; width: 100%;
border-collapse: collapse; border-collapse: collapse;
font-size: 0.75rem; font-size: var(--sammo-font-size-small);
} }
.context-general-table th, .context-general-table th,
@@ -1629,7 +1634,7 @@ onUnmounted(() => {
padding: 1px 3px; padding: 1px 3px;
background: rgba(111, 74, 141, 0.8); background: rgba(111, 74, 141, 0.8);
color: #fff; color: #fff;
font-size: 0.6rem; font-size: var(--sammo-font-size-small);
} }
.context-error, .context-error,
@@ -1637,7 +1642,7 @@ onUnmounted(() => {
padding: 12px; padding: 12px;
color: rgba(240, 150, 150, 0.9); color: rgba(240, 150, 150, 0.9);
text-align: center; text-align: center;
font-size: 0.75rem; font-size: var(--sammo-font-size-small);
} }
.sr-only { .sr-only {
@@ -1662,7 +1667,7 @@ onUnmounted(() => {
flex-wrap: wrap; flex-wrap: wrap;
justify-content: space-between; justify-content: space-between;
gap: 8px; gap: 8px;
font-size: 0.8rem; font-size: var(--sammo-font-size-small);
color: rgba(232, 221, 196, 0.85); color: rgba(232, 221, 196, 0.85);
} }
@@ -1678,7 +1683,7 @@ onUnmounted(() => {
} }
.bonus-title { .bonus-title {
font-size: 0.8rem; font-size: var(--sammo-font-size-small);
color: rgba(232, 221, 196, 0.8); color: rgba(232, 221, 196, 0.8);
} }
@@ -1690,7 +1695,7 @@ onUnmounted(() => {
.inherit-errors { .inherit-errors {
color: rgba(240, 150, 150, 0.9); color: rgba(240, 150, 150, 0.9);
font-size: 0.75rem; font-size: var(--sammo-font-size-small);
} }
.form-actions .ghost, .form-actions .ghost,
@@ -1708,7 +1713,7 @@ onUnmounted(() => {
.npc-token-status { .npc-token-status {
min-height: 22px; min-height: 22px;
text-align: center; text-align: center;
font-size: 0.75rem; font-size: var(--sammo-font-size-small);
} }
.npc-token-expired { .npc-token-expired {
@@ -1738,14 +1743,14 @@ onUnmounted(() => {
height: 25px; height: 25px;
overflow: hidden; overflow: hidden;
border: 1px solid rgba(201, 164, 90, 0.3); border: 1px solid rgba(201, 164, 90, 0.3);
font-size: 1rem; font-size: var(--sammo-font-size-emphasis);
line-height: 23px; line-height: 23px;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
} }
.npc-card-name--long { .npc-card-name--long {
font-size: 0.75rem; font-size: var(--sammo-font-size-small);
} }
.npc-card-image { .npc-card-image {
@@ -1755,7 +1760,7 @@ onUnmounted(() => {
.npc-card p { .npc-card p {
min-height: 78px; min-height: 78px;
font-size: 0.75rem; font-size: var(--sammo-font-size-small);
line-height: 1.3; line-height: 1.3;
} }
@@ -1789,14 +1794,14 @@ onUnmounted(() => {
width: 100%; width: 100%;
border: 1px solid rgba(201, 164, 90, 0.4); border: 1px solid rgba(201, 164, 90, 0.4);
padding: 4px 8px; padding: 4px 8px;
font-size: 0.75rem; font-size: var(--sammo-font-size-small);
} }
.npc-keep { .npc-keep {
display: block; display: block;
padding-left: 15px; padding-left: 15px;
text-indent: -15px; text-indent: -15px;
font-size: 0.75rem; font-size: var(--sammo-font-size-small);
} }
.npc-keep input { .npc-keep input {
@@ -1830,7 +1835,7 @@ onUnmounted(() => {
margin-bottom: 8px; margin-bottom: 8px;
color: rgba(240, 150, 150, 0.9); color: rgba(240, 150, 150, 0.9);
text-align: center; text-align: center;
font-size: 0.75rem; font-size: var(--sammo-font-size-small);
} }
.npc-general-list-wrap { .npc-general-list-wrap {
@@ -1843,7 +1848,7 @@ onUnmounted(() => {
width: 970px; width: 970px;
border-collapse: collapse; border-collapse: collapse;
table-layout: fixed; table-layout: fixed;
font-size: 12px; font-size: var(--sammo-font-size-small);
word-break: break-all; word-break: break-all;
} }
@@ -1872,7 +1877,7 @@ onUnmounted(() => {
} }
.npc-general-name small { .npc-general-name small {
font-size: 10px; font-size: var(--sammo-font-size-small);
} }
#btn-print-more-generals { #btn-print-more-generals {
@@ -1883,7 +1888,7 @@ onUnmounted(() => {
.muted { .muted {
color: rgba(232, 221, 196, 0.6); color: rgba(232, 221, 196, 0.6);
font-size: 0.75rem; font-size: var(--sammo-font-size-small);
} }
.ghost { .ghost {
+1 -1
View File
@@ -28,7 +28,7 @@ onMounted(() => {
h1 { h1 {
margin: 0 0 12px; margin: 0 0 12px;
font-size: 20px; font-size: var(--sammo-font-size-title);
font-weight: 400; font-weight: 400;
} }
+9 -9
View File
@@ -788,7 +788,7 @@ button {
.game-version-dialog__commit code { .game-version-dialog__commit code {
overflow-wrap: anywhere; overflow-wrap: anywhere;
color: #d7d7d7; color: #d7d7d7;
font-size: 0.85em; font-size: var(--sammo-font-size-small);
} }
/* /*
@@ -820,7 +820,7 @@ button {
.front-status-error { .front-status-error {
color: #ff8a80; color: #ff8a80;
font-size: 0.85rem; font-size: var(--sammo-font-size-normal);
} }
.legacy-game-info { .legacy-game-info {
@@ -834,7 +834,7 @@ button {
border-top: 1px solid #666; border-top: 1px solid #666;
background: #302016 var(--sammo-texture-walnut); background: #302016 var(--sammo-texture-walnut);
color: #fff; color: #fff;
font-size: 12px; font-size: var(--sammo-font-size-small);
line-height: 17px; line-height: 17px;
text-align: center; text-align: center;
} }
@@ -851,7 +851,7 @@ button {
.warning { .warning {
color: #f5d08a; color: #f5d08a;
font-size: 0.85rem; font-size: var(--sammo-font-size-normal);
} }
.survey-notice { .survey-notice {
@@ -866,7 +866,7 @@ button {
background: rgba(32, 28, 16, 0.96); background: rgba(32, 28, 16, 0.96);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.45); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.45);
color: #fff; color: #fff;
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: 1.3; line-height: 1.3;
} }
@@ -883,7 +883,7 @@ button {
.survey-notice-title button { .survey-notice-title button {
padding: 0 4px; padding: 0 4px;
cursor: pointer; cursor: pointer;
font-size: 20px; font-size: var(--sammo-font-size-title);
line-height: 1; line-height: 1;
} }
@@ -912,7 +912,7 @@ button {
background: rgba(12, 12, 12, 0.96); background: rgba(12, 12, 12, 0.96);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.45); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.45);
color: #fff; color: #fff;
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: 1.3; line-height: 1.3;
} }
@@ -933,7 +933,7 @@ button {
.private-message-notice-close { .private-message-notice-close {
padding: 0 4px; padding: 0 4px;
cursor: pointer; cursor: pointer;
font-size: 20px; font-size: var(--sammo-font-size-title);
line-height: 1; line-height: 1;
} }
@@ -1158,7 +1158,7 @@ button {
} }
.placeholder { .placeholder {
font-size: 0.85rem; font-size: var(--sammo-font-size-normal);
color: rgba(232, 221, 196, 0.7); color: rgba(232, 221, 196, 0.7);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
+3 -3
View File
@@ -629,7 +629,7 @@ onMounted(() => {
background-color: transparent; background-color: transparent;
background-image: var(--sammo-texture-walnut); background-image: var(--sammo-texture-walnut);
font-family: var(--sammo-font-sans); font-family: var(--sammo-font-sans);
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: 1.3; line-height: 1.3;
} }
.my-page-mobile-scroll-spacer { .my-page-mobile-scroll-spacer {
@@ -645,7 +645,7 @@ onMounted(() => {
gap: 0 4px; gap: 0 4px;
border: 1px solid #666; border: 1px solid #666;
background: transparent; background: transparent;
font-size: 14px; font-size: var(--sammo-font-size-normal);
} }
.title-row > span { .title-row > span {
flex-basis: 100%; flex-basis: 100%;
@@ -714,7 +714,7 @@ button:disabled {
border-bottom: 1px solid #666; border-bottom: 1px solid #666;
background-color: #14241b; background-color: #14241b;
background-image: var(--sammo-texture-green); background-image: var(--sammo-texture-green);
font-size: 1.25em; font-size: var(--sammo-font-size-emphasis);
font-weight: 500; font-weight: 500;
} }
.section-title { .section-title {
+12 -7
View File
@@ -314,6 +314,11 @@ onBeforeUnmount(() => {
</template> </template>
<style scoped> <style scoped>
/* UI 보조 글자는 부모의 80%가 아니라 공통 소형 크기를 사용한다. */
small {
font-size: var(--sammo-font-size-small);
}
.legacy-page { .legacy-page {
box-sizing: border-box; box-sizing: border-box;
width: 100%; width: 100%;
@@ -325,7 +330,7 @@ onBeforeUnmount(() => {
background-color: transparent; background-color: transparent;
background-image: var(--sammo-texture-walnut); background-image: var(--sammo-texture-walnut);
font-family: var(--sammo-font-sans); font-family: var(--sammo-font-sans);
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: 1.3; line-height: 1.3;
} }
.title-row { .title-row {
@@ -367,7 +372,7 @@ onBeforeUnmount(() => {
background-color: #14241b; background-color: #14241b;
background-image: var(--sammo-texture-green); background-image: var(--sammo-texture-green);
color: skyblue; color: skyblue;
font-size: 1.25em; font-size: var(--sammo-font-size-emphasis);
font-weight: 500; font-weight: 500;
} }
.settings-content { .settings-content {
@@ -440,7 +445,7 @@ onBeforeUnmount(() => {
padding: 12px; padding: 12px;
background: #171717 var(--sammo-texture-walnut); background: #171717 var(--sammo-texture-walnut);
color: #fff; color: #fff;
font: 14px/1.3 var(--sammo-font-sans); font: var(--sammo-font-size-normal)/1.3 var(--sammo-font-sans);
} }
.mobile-layout-dialog::backdrop { .mobile-layout-dialog::backdrop {
background: rgb(0 0 0 / 72%); background: rgb(0 0 0 / 72%);
@@ -461,7 +466,7 @@ onBeforeUnmount(() => {
} }
.mobile-layout-dialog__header h2 { .mobile-layout-dialog__header h2 {
color: skyblue; color: skyblue;
font-size: 18px; font-size: var(--sammo-font-size-emphasis);
} }
.mobile-layout-dialog__header form, .mobile-layout-dialog__header form,
.mobile-layout-dialog__actions form { .mobile-layout-dialog__actions form {
@@ -470,7 +475,7 @@ onBeforeUnmount(() => {
.mobile-layout-dialog__header button { .mobile-layout-dialog__header button {
min-width: 32px; min-width: 32px;
min-height: 32px; min-height: 32px;
font-size: 20px; font-size: var(--sammo-font-size-title);
} }
.mobile-layout-list { .mobile-layout-list {
display: grid; display: grid;
@@ -494,7 +499,7 @@ onBeforeUnmount(() => {
.mobile-layout-handle { .mobile-layout-handle {
color: #aaa; color: #aaa;
text-align: center; text-align: center;
font-size: 20px; font-size: var(--sammo-font-size-title);
} }
.mobile-layout-label { .mobile-layout-label {
min-width: 0; min-width: 0;
@@ -508,7 +513,7 @@ onBeforeUnmount(() => {
margin-right: 4px; margin-right: 4px;
border: 1px solid #7186a7; border: 1px solid #7186a7;
border-radius: 50%; border-radius: 50%;
font-size: 12px; font-size: var(--sammo-font-size-small);
} }
.mobile-layout-move-buttons { .mobile-layout-move-buttons {
gap: 4px; gap: 4px;
@@ -457,7 +457,7 @@ onMounted(() => {
margin: 0 auto; margin: 0 auto;
color: #fff; color: #fff;
font-family: var(--sammo-font-sans); font-family: var(--sammo-font-sans);
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: 1.5; line-height: 1.5;
} }
@@ -474,7 +474,7 @@ onMounted(() => {
.legacy-top-bar h1 { .legacy-top-bar h1 {
margin: 0; margin: 0;
font-size: 24px; font-size: var(--sammo-font-size-title);
font-weight: 500; font-weight: 500;
line-height: 32px; line-height: 32px;
text-align: center; text-align: center;
@@ -740,7 +740,7 @@ onMounted(async () => {
.nation-cities-page { .nation-cities-page {
width: 1000px; width: 1000px;
margin: 0 auto; margin: 0 auto;
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: 1.3; line-height: 1.3;
} }
.legacy-table { .legacy-table {
@@ -836,7 +836,7 @@ onMounted(async () => {
} }
.secret-commands { .secret-commands {
text-align: left !important; text-align: left !important;
font-size: 12px; font-size: var(--sammo-font-size-small);
} }
.bonus { .bonus {
color: cyan; color: cyan;
@@ -1015,12 +1015,17 @@ onBeforeUnmount(() => {
</template> </template>
<style scoped> <style scoped>
/* UI 보조 글자는 부모의 80%가 아니라 공통 소형 크기를 사용한다. */
small {
font-size: var(--sammo-font-size-small);
}
.general-page { .general-page {
width: 1000px; width: 1000px;
min-width: 1000px; min-width: 1000px;
height: 100vh; height: 100vh;
margin: 0 auto; margin: 0 auto;
font: 14px/21px var(--sammo-font-sans); font: var(--sammo-font-size-normal)/21px var(--sammo-font-sans);
color: #fff; color: #fff;
background-color: transparent; background-color: transparent;
} }
@@ -1035,10 +1040,10 @@ onBeforeUnmount(() => {
justify-content: center; justify-content: center;
background-color: transparent; background-color: transparent;
background-image: var(--sammo-texture-walnut); background-image: var(--sammo-texture-walnut);
font-size: 14px; font-size: var(--sammo-font-size-normal);
} }
.top-bar strong { .top-bar strong {
font-size: 22px; font-size: var(--sammo-font-size-title);
font-weight: 400; font-weight: 400;
} }
.left-actions, .left-actions,
@@ -1061,7 +1066,7 @@ onBeforeUnmount(() => {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
padding: 0; padding: 0;
font-size: 14px; font-size: var(--sammo-font-size-normal);
text-decoration: none; text-decoration: none;
} }
.nation-button { .nation-button {
@@ -1147,7 +1152,7 @@ table {
table-layout: fixed; table-layout: fixed;
background: #293033; background: #293033;
color: #f5f5f5; color: #f5f5f5;
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: normal; line-height: normal;
cursor: default; cursor: default;
} }
@@ -1198,7 +1203,7 @@ th {
} }
.sort-indicator { .sort-indicator {
color: #8dd4ff; color: #8dd4ff;
font-size: 10px; font-size: var(--sammo-font-size-small);
} }
.filter-head th { .filter-head th {
position: relative; position: relative;
@@ -1234,7 +1239,7 @@ th {
.floating-filter > input::placeholder, .floating-filter > input::placeholder,
.filter-popup input::placeholder { .filter-popup input::placeholder {
color: #8f999d; color: #8f999d;
font-size: 10px; font-size: var(--sammo-font-size-small);
} }
.filter-menu-button { .filter-menu-button {
display: inline-flex; display: inline-flex;
@@ -1292,7 +1297,7 @@ th {
background: #2d3436; background: #2d3436;
box-shadow: 0 2px 6px rgb(0 0 0 / 45%); box-shadow: 0 2px 6px rgb(0 0 0 / 45%);
color: #f5f5f5; color: #f5f5f5;
font-size: 12px; font-size: var(--sammo-font-size-small);
line-height: 18px; line-height: 18px;
text-align: left; text-align: left;
white-space: normal; white-space: normal;
@@ -1311,7 +1316,7 @@ th {
border-radius: 0; border-radius: 0;
background: #252a2c; background: #252a2c;
color: #fff; color: #fff;
font: 12px/18px var(--sammo-font-sans); font: var(--sammo-font-size-small)/18px var(--sammo-font-sans);
} }
.filter-condition select { .filter-condition select {
cursor: pointer; cursor: pointer;
@@ -138,7 +138,7 @@ onMounted(async () => {
.legacy-info-page { .legacy-info-page {
width: 1000px; width: 1000px;
margin: 0 auto; margin: 0 auto;
font-size: 14px; font-size: var(--sammo-font-size-normal);
} }
.legacy-table { .legacy-table {
width: 100%; width: 100%;
@@ -422,17 +422,22 @@ onBeforeUnmount(() => {
</template> </template>
<style scoped> <style scoped>
/* UI 보조 글자는 부모의 80%가 아니라 공통 소형 크기를 사용한다. */
small {
font-size: var(--sammo-font-size-small);
}
.directory-page { .directory-page {
width: 1000px; width: 1000px;
margin: 0 auto; margin: 0 auto;
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: 1.3; line-height: 1.3;
} }
.directory-table { .directory-table {
width: 1000px; width: 1000px;
border-collapse: collapse; border-collapse: collapse;
table-layout: auto; table-layout: auto;
font-size: 14px; font-size: var(--sammo-font-size-normal);
word-break: break-all; word-break: break-all;
background-color: transparent; background-color: transparent;
} }
@@ -456,7 +461,7 @@ onBeforeUnmount(() => {
padding: 5.25px 10.5px; padding: 5.25px 10.5px;
background-color: rgb(55 90 127); background-color: rgb(55 90 127);
color: #fff; color: #fff;
font-size: 14px; font-size: var(--sammo-font-size-normal);
font-weight: 700; font-weight: 700;
line-height: 21px; line-height: 21px;
cursor: pointer; cursor: pointer;
@@ -604,12 +604,17 @@ onMounted(() => void loadPersonnel());
</template> </template>
<style scoped> <style scoped>
/* UI 보조 글자는 부모의 80%가 아니라 공통 소형 크기를 사용한다. */
small {
font-size: var(--sammo-font-size-small);
}
.legacy-office { .legacy-office {
width: 1000px; width: 1000px;
min-height: 100vh; min-height: 100vh;
margin: 0 auto; margin: 0 auto;
color: #fff; color: #fff;
font: 14px/1.3 var(--sammo-font-sans); font: var(--sammo-font-size-normal)/1.3 var(--sammo-font-sans);
} }
.legacy-table { .legacy-table {
width: 1000px; width: 1000px;
@@ -672,7 +677,7 @@ select {
.nation-heading { .nation-heading {
height: 32px; height: 32px;
text-align: center; text-align: center;
font-size: 20px; font-size: var(--sammo-font-size-title);
} }
.chief-status { .chief-status {
margin-bottom: 0; margin-bottom: 0;
@@ -724,7 +729,7 @@ select {
color: #fff; color: #fff;
background: #24472e; background: #24472e;
text-align: center; text-align: center;
font-size: 17px; font-size: var(--sammo-font-size-emphasis);
font-weight: 700; font-weight: 700;
} }
.general-icon { .general-icon {
@@ -742,14 +747,14 @@ select {
} }
.chief-entry-copy strong { .chief-entry-copy strong {
overflow: hidden; overflow: hidden;
font-size: 18px; font-size: var(--sammo-font-size-emphasis);
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
} }
.chief-entry-copy small { .chief-entry-copy small {
overflow: hidden; overflow: hidden;
color: #c8c5bc; color: #c8c5bc;
font-size: 11px; font-size: var(--sammo-font-size-small);
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
} }
@@ -765,7 +770,7 @@ select {
grid-area: action; grid-area: action;
color: #e7b64c; color: #e7b64c;
text-align: center; text-align: center;
font-size: 11px; font-size: var(--sammo-font-size-small);
} }
.award-label { .award-label {
text-align: center; text-align: center;
@@ -823,7 +828,7 @@ select {
.city-header td { .city-header td {
height: 29px; height: 29px;
text-align: center; text-align: center;
font-size: 18px; font-size: var(--sammo-font-size-emphasis);
} }
.city-header-compact { .city-header-compact {
display: none; display: none;
@@ -834,20 +839,20 @@ select {
.region-heading { .region-heading {
height: 29px; height: 29px;
color: skyblue; color: skyblue;
font-size: 18px; font-size: var(--sammo-font-size-emphasis);
} }
.city-identity { .city-identity {
display: table-cell; display: table-cell;
width: 158px; width: 158px;
text-align: center; text-align: center;
font-size: 16.8px; font-size: var(--sammo-font-size-emphasis);
} }
.city-identity small, .city-identity small,
.city-identity strong { .city-identity strong {
display: block; display: block;
} }
.city-identity small { .city-identity small {
font-size: 10px; font-size: var(--sammo-font-size-small);
} }
.city-officer-cell { .city-officer-cell {
padding: 5px !important; padding: 5px !important;
@@ -871,7 +876,7 @@ select {
} }
.city-officer-copy small { .city-officer-copy small {
color: #c9c6bd; color: #c9c6bd;
font-size: 10px; font-size: var(--sammo-font-size-small);
} }
.city-change-button { .city-change-button {
min-width: 70px; min-width: 70px;
@@ -919,7 +924,7 @@ select {
margin-bottom: 10px; margin-bottom: 10px;
} }
.nation-heading { .nation-heading {
font-size: 18px; font-size: var(--sammo-font-size-emphasis);
} }
.chief-entry-cell { .chief-entry-cell {
padding: 4px !important; padding: 4px !important;
@@ -933,7 +938,7 @@ select {
} }
.chief-entry-role { .chief-entry-role {
padding: 5px 2px; padding: 5px 2px;
font-size: 12px; font-size: var(--sammo-font-size-small);
} }
.general-icon { .general-icon {
width: 48px; width: 48px;
@@ -941,22 +946,22 @@ select {
background-size: 48px 48px; background-size: 48px 48px;
} }
.chief-entry-copy strong { .chief-entry-copy strong {
font-size: 15px; font-size: var(--sammo-font-size-personnel-mobile-name);
} }
.chief-entry-copy small { .chief-entry-copy small {
font-size: 9px; font-size: var(--sammo-font-size-small);
} }
.personnel-change-button { .personnel-change-button {
min-height: 30px; min-height: 30px;
padding: 3px 5px; padding: 3px 5px;
font-size: 11px; font-size: var(--sammo-font-size-small);
line-height: 18px; line-height: 18px;
} }
.personnel-lock-label { .personnel-lock-label {
font-size: 10px; font-size: var(--sammo-font-size-personnel-mobile-lock);
} }
.award-label { .award-label {
font-size: 11px; font-size: var(--sammo-font-size-small);
white-space: nowrap; white-space: nowrap;
} }
.award-label-full { .award-label-full {
@@ -971,7 +976,7 @@ select {
} }
.city-header td { .city-header td {
height: 26px; height: 26px;
font-size: 13px; font-size: var(--sammo-font-size-small);
} }
.city-header-full { .city-header-full {
display: none; display: none;
@@ -981,14 +986,14 @@ select {
} }
.region-heading { .region-heading {
height: 25px; height: 25px;
font-size: 14px; font-size: var(--sammo-font-size-normal);
} }
.city-identity { .city-identity {
width: 16%; width: 16%;
font-size: 13px; font-size: var(--sammo-font-size-small);
} }
.city-identity small { .city-identity small {
font-size: 8px; font-size: var(--sammo-font-size-small);
} }
.city-officer-cell { .city-officer-cell {
padding: 4px !important; padding: 4px !important;
@@ -998,17 +1003,17 @@ select {
gap: 4px; gap: 4px;
} }
.city-officer-copy strong { .city-officer-copy strong {
font-size: 12px; font-size: var(--sammo-font-size-small);
} }
.city-officer-copy small { .city-officer-copy small {
font-size: 9px; font-size: var(--sammo-font-size-small);
} }
.city-change-button { .city-change-button {
width: 100%; width: 100%;
min-width: 0; min-width: 0;
} }
.legend { .legend {
font-size: 10px; font-size: var(--sammo-font-size-small);
} }
.kick-label { .kick-label {
width: auto; width: auto;
@@ -368,7 +368,7 @@ onMounted(load);
.secret-page { .secret-page {
width: auto; width: auto;
margin: 0; margin: 0;
font: 14px var(--sammo-font-sans); font: var(--sammo-font-size-normal) var(--sammo-font-sans);
color: #fff; color: #fff;
} }
.layout { .layout {
@@ -381,7 +381,7 @@ th,
.state { .state {
border: 1px solid gray; border: 1px solid gray;
padding: 0; padding: 0;
font-size: 14px; font-size: var(--sammo-font-size-normal);
word-break: break-all; word-break: break-all;
text-align: center; text-align: center;
font-weight: 400; font-weight: 400;
@@ -455,7 +455,7 @@ th,
} }
.turns { .turns {
text-align: left; text-align: left;
font-size: 11px; font-size: var(--sammo-font-size-small);
} }
.bonus { .bonus {
color: cyan; color: cyan;
@@ -483,13 +483,13 @@ th,
} }
.list th, .list th,
.list td { .list td {
font-size: 14px; font-size: var(--sammo-font-size-normal);
} }
.list tbody tr { .list tbody tr {
height: auto; height: auto;
} }
.list tbody td { .list tbody td {
font-size: 12px; font-size: var(--sammo-font-size-small);
} }
.list :is(th, td):nth-child(1), .list :is(th, td):nth-child(1),
.list :is(th, td):nth-child(2) { .list :is(th, td):nth-child(2) {
@@ -592,7 +592,7 @@ th,
min-width: 0; min-width: 0;
padding: 0 2px; padding: 0 2px;
border: 0; border: 0;
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: 18.2px; line-height: 18.2px;
overflow-wrap: anywhere; overflow-wrap: anywhere;
align-content: center; align-content: center;
@@ -600,7 +600,7 @@ th,
.list tbody td[data-label]::before { .list tbody td[data-label]::before {
content: attr(data-label); content: attr(data-label);
margin-right: 3px; margin-right: 3px;
font-size: 11px; font-size: var(--sammo-font-size-small);
line-height: 1; line-height: 1;
color: #bbb; color: #bbb;
} }
@@ -609,13 +609,13 @@ th,
} }
.general-level { .general-level {
margin-left: 3px; margin-left: 3px;
font-size: 11px; font-size: var(--sammo-font-size-small);
line-height: 1; line-height: 1;
color: #bbb; color: #bbb;
white-space: nowrap; white-space: nowrap;
} }
.list tbody .turns { .list tbody .turns {
font-size: 11px; font-size: var(--sammo-font-size-small);
line-height: 1.3; line-height: 1.3;
border-left: 1px solid gray; border-left: 1px solid gray;
padding-inline: 4px; padding-inline: 4px;
@@ -474,7 +474,7 @@ onMounted(() => void loadStratFinan());
margin: 0 auto; margin: 0 auto;
color: #fff; color: #fff;
background: var(--sammo-texture-walnut); background: var(--sammo-texture-walnut);
font: 14px/1.3 var(--sammo-font-sans); font: var(--sammo-font-size-normal)/1.3 var(--sammo-font-sans);
} }
.tiptap-compat-controls { .tiptap-compat-controls {
display: none; display: none;
@@ -510,7 +510,7 @@ textarea:focus-visible {
.finance-title { .finance-title {
height: 25.47px; height: 25.47px;
text-align: center; text-align: center;
font-size: 19.6px; font-size: var(--sammo-font-size-title);
line-height: 25.47px; line-height: 25.47px;
} }
.diplomacy-title { .diplomacy-title {
+14 -9
View File
@@ -555,6 +555,11 @@ const submitPriority = async (section: PrioritySectionKey) => {
</template> </template>
<style scoped> <style scoped>
/* UI 보조 글자는 부모의 80%가 아니라 공통 소형 크기를 사용한다. */
small {
font-size: var(--sammo-font-size-small);
}
/* /*
* The document contract belongs to this page only. An unscoped html/body rule * The document contract belongs to this page only. An unscoped html/body rule
* here leaked a 21px line-height and a 500px min-width onto every other screen. * here leaked a 21px line-height and a 500px min-width onto every other screen.
@@ -566,7 +571,7 @@ const submitPriority = async (section: PrioritySectionKey) => {
margin: 0; margin: 0;
background: #000; background: #000;
font-family: var(--sammo-font-sans); font-family: var(--sammo-font-sans);
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: 21px; line-height: 21px;
} }
@@ -576,7 +581,7 @@ const submitPriority = async (section: PrioritySectionKey) => {
box-sizing: border-box; box-sizing: border-box;
color: #fff; color: #fff;
font-family: var(--sammo-font-sans); font-family: var(--sammo-font-sans);
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: 21px; line-height: 21px;
} }
.sortable-compat-controls { .sortable-compat-controls {
@@ -605,7 +610,7 @@ const submitPriority = async (section: PrioritySectionKey) => {
} }
.top-back-bar strong { .top-back-bar strong {
font-size: 24px; font-size: var(--sammo-font-size-title);
line-height: 32px; line-height: 32px;
font-weight: 400; font-weight: 400;
} }
@@ -653,7 +658,7 @@ const submitPriority = async (section: PrioritySectionKey) => {
min-height: 21px; min-height: 21px;
padding: 0 12px; padding: 0 12px;
color: #8e8e8e; color: #8e8e8e;
font-size: 12.25px; font-size: var(--sammo-font-size-small);
line-height: 18.375px; line-height: 18.375px;
text-align: right; text-align: right;
box-sizing: border-box; box-sizing: border-box;
@@ -709,7 +714,7 @@ const submitPriority = async (section: PrioritySectionKey) => {
min-height: 18.375px; min-height: 18.375px;
margin: 0; margin: 0;
color: #888; color: #888;
font-size: 12.25px; font-size: var(--sammo-font-size-small);
line-height: 18.375px; line-height: 18.375px;
text-align: right; text-align: right;
} }
@@ -807,7 +812,7 @@ const submitPriority = async (section: PrioritySectionKey) => {
} }
.priority-description small { .priority-description small {
font-size: 12.25px; font-size: var(--sammo-font-size-small);
line-height: 18.375px; line-height: 18.375px;
} }
@@ -867,7 +872,7 @@ const submitPriority = async (section: PrioritySectionKey) => {
} }
.drag-handle { .drag-handle {
font-size: 18px; font-size: var(--sammo-font-size-emphasis);
} }
.help-button { .help-button {
@@ -879,7 +884,7 @@ const submitPriority = async (section: PrioritySectionKey) => {
background: #444; background: #444;
border: 1px solid #3d3d3d; border: 1px solid #3d3d3d;
border-radius: 3px; border-radius: 3px;
font-size: 12.25px; font-size: var(--sammo-font-size-small);
line-height: 18.375px; line-height: 18.375px;
cursor: pointer; cursor: pointer;
} }
@@ -896,7 +901,7 @@ const submitPriority = async (section: PrioritySectionKey) => {
border: 1px solid #777; border: 1px solid #777;
border-radius: 4px; border-radius: 4px;
content: attr(data-text); content: attr(data-text);
font-size: 12px; font-size: var(--sammo-font-size-small);
line-height: 18px; line-height: 18px;
text-align: left; text-align: left;
white-space: pre-line; white-space: pre-line;
+3 -3
View File
@@ -252,7 +252,7 @@ onMounted(() => {
margin: 0 auto; margin: 0 auto;
color: #fff; color: #fff;
font-family: var(--sammo-font-sans); font-family: var(--sammo-font-sans);
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: 1.3; line-height: 1.3;
} }
@@ -261,7 +261,7 @@ onMounted(() => {
border-collapse: collapse; border-collapse: collapse;
padding: 0; padding: 0;
table-layout: fixed; table-layout: fixed;
font-size: 14px; font-size: var(--sammo-font-size-normal);
word-break: break-all; word-break: break-all;
} }
@@ -395,7 +395,7 @@ onMounted(() => {
} }
.banner { .banner {
font-size: 12px; font-size: var(--sammo-font-size-small);
} }
.banner a { .banner a {
@@ -422,7 +422,7 @@ onMounted(() => {
background-color: #302016; background-color: #302016;
background-image: var(--sammo-texture-walnut); background-image: var(--sammo-texture-walnut);
font-family: var(--sammo-font-sans); font-family: var(--sammo-font-sans);
font-size: 14px; font-size: var(--sammo-font-size-normal);
} }
.title-row, .title-row,
@@ -443,7 +443,7 @@ onMounted(() => {
.title-row h1 { .title-row h1 {
margin: 0; margin: 0;
color: skyblue; color: skyblue;
font-size: 18px; font-size: var(--sammo-font-size-emphasis);
} }
.title-row nav, .title-row nav,
@@ -615,7 +615,7 @@ th {
.detail-grid :deep(.panel-title) { .detail-grid :deep(.panel-title) {
color: skyblue; color: skyblue;
font-size: 18px; font-size: var(--sammo-font-size-emphasis);
font-weight: 500; font-weight: 500;
} }
@@ -642,7 +642,7 @@ th {
.hall-battle-record__heading span { .hall-battle-record__heading span {
color: #bbb; color: #bbb;
font-size: 12px; font-size: var(--sammo-font-size-small);
} }
.hall-battle-record dl { .hall-battle-record dl {
+7 -7
View File
@@ -256,7 +256,7 @@ onMounted(() => {
<style scoped> <style scoped>
.page-hint { .page-hint {
margin-top: 6px; margin-top: 6px;
font-size: 0.75rem; font-size: var(--sammo-font-size-small);
color: rgba(232, 221, 196, 0.5); color: rgba(232, 221, 196, 0.5);
} }
@@ -279,7 +279,7 @@ onMounted(() => {
} }
.placeholder { .placeholder {
font-size: 0.85rem; font-size: var(--sammo-font-size-normal);
color: rgba(232, 221, 196, 0.7); color: rgba(232, 221, 196, 0.7);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -295,7 +295,7 @@ onMounted(() => {
.public-table { .public-table {
width: 100%; width: 100%;
border-collapse: collapse; border-collapse: collapse;
font-size: 0.8rem; font-size: var(--sammo-font-size-small);
} }
.public-table th, .public-table th,
@@ -306,7 +306,7 @@ onMounted(() => {
} }
.public-table thead th { .public-table thead th {
font-size: 0.7rem; font-size: var(--sammo-font-size-small);
color: rgba(232, 221, 196, 0.6); color: rgba(232, 221, 196, 0.6);
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.05em; letter-spacing: 0.05em;
@@ -325,7 +325,7 @@ onMounted(() => {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
font-size: 0.6rem; font-size: var(--sammo-font-size-small);
padding: 2px 4px; padding: 2px 4px;
margin-right: 6px; margin-right: 6px;
border: 1px solid rgba(201, 164, 90, 0.4); border: 1px solid rgba(201, 164, 90, 0.4);
@@ -346,11 +346,11 @@ onMounted(() => {
background: rgba(16, 16, 16, 0.8); background: rgba(16, 16, 16, 0.8);
color: rgba(232, 221, 196, 0.9); color: rgba(232, 221, 196, 0.9);
padding: 6px 8px; padding: 6px 8px;
font-size: 0.75rem; font-size: var(--sammo-font-size-small);
} }
.list-count { .list-count {
font-size: 0.7rem; font-size: var(--sammo-font-size-small);
color: rgba(232, 221, 196, 0.6); color: rgba(232, 221, 196, 0.6);
white-space: nowrap; white-space: nowrap;
} }
@@ -540,7 +540,7 @@ onBeforeUnmount(() => {
border-right-color: #000; border-right-color: #000;
border-bottom-color: #000; border-bottom-color: #000;
border-spacing: 0; border-spacing: 0;
font-size: 14px; font-size: var(--sammo-font-size-normal);
text-align: center; text-align: center;
word-break: break-all; word-break: break-all;
} }
@@ -578,7 +578,7 @@ onBeforeUnmount(() => {
margin: 0; margin: 0;
padding: 0; padding: 0;
color: inherit; color: inherit;
font-size: 14px; font-size: var(--sammo-font-size-normal);
font-weight: 700; font-weight: 700;
line-height: 18.2px; line-height: 18.2px;
} }
+3 -3
View File
@@ -424,7 +424,7 @@ onMounted(() => {
margin: 0 auto; margin: 0 auto;
color: #fff; color: #fff;
font-family: var(--sammo-font-sans); font-family: var(--sammo-font-sans);
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: 1.5; line-height: 1.5;
} }
@@ -464,13 +464,13 @@ onMounted(() => {
} }
#vote-title { #vote-title {
font-size: 1.8em; font-size: var(--sammo-font-size-title);
line-height: 1.5; line-height: 1.5;
text-align: center; text-align: center;
} }
#vote-old-title { #vote-old-title {
font-size: 1.5em; font-size: var(--sammo-font-size-title);
line-height: 1.5; line-height: 1.5;
text-align: center; text-align: center;
} }
+17 -12
View File
@@ -375,6 +375,11 @@ const start = async () => {
</template> </template>
<style scoped> <style scoped>
/* UI 보조 글자는 부모의 80%가 아니라 공통 소형 크기를 사용한다. */
small {
font-size: var(--sammo-font-size-small);
}
.legacy-page { .legacy-page {
width: 100%; width: 100%;
max-width: 1200px; max-width: 1200px;
@@ -383,7 +388,7 @@ const start = async () => {
margin: 0 auto; margin: 0 auto;
color: #fff; color: #fff;
font-family: var(--sammo-font-sans); font-family: var(--sammo-font-sans);
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: 1.3; line-height: 1.3;
text-align: center; text-align: center;
} }
@@ -392,7 +397,7 @@ const start = async () => {
text-align: left; text-align: left;
} }
.tournament-guide { .tournament-guide {
font-size: 12px; font-size: var(--sammo-font-size-small);
line-height: 14px; line-height: 14px;
} }
.tournament-footer { .tournament-footer {
@@ -419,7 +424,7 @@ const start = async () => {
--legacy-button-height: 44px; --legacy-button-height: 44px;
min-width: 72px; min-width: 72px;
padding: 10px 16px; padding: 10px 16px;
font-size: 14px; font-size: var(--sammo-font-size-normal);
} }
.operator-row, .operator-row,
.state-row, .state-row,
@@ -451,10 +456,10 @@ button:not(.legacy-button):focus-visible {
} }
.operator-row span { .operator-row span {
color: orange; color: orange;
font-size: 24px; font-size: var(--sammo-font-size-title);
} }
.state-row { .state-row {
font-size: 24px; font-size: var(--sammo-font-size-title);
} }
.state-row .type { .state-row .type {
color: cyan; color: cyan;
@@ -463,7 +468,7 @@ button:not(.legacy-button):focus-visible {
min-height: 38px; min-height: 38px;
padding: 5px; padding: 5px;
color: magenta; color: magenta;
font-size: 24px; font-size: var(--sammo-font-size-title);
} }
.fight { .fight {
padding: 8px; padding: 8px;
@@ -473,7 +478,7 @@ button:not(.legacy-button):focus-visible {
margin: 0; margin: 0;
text-align: center; text-align: center;
color: orange; color: orange;
font-size: 18px; font-size: var(--sammo-font-size-emphasis);
} }
.fight p { .fight p {
margin: 2px 10px; margin: 2px 10px;
@@ -496,7 +501,7 @@ button:not(.legacy-button):focus-visible {
padding: 4px; padding: 4px;
background: #000; background: #000;
color: orange; color: orange;
font-size: 14px; font-size: var(--sammo-font-size-normal);
font-weight: 400; font-weight: 400;
text-align: center; text-align: center;
} }
@@ -525,13 +530,13 @@ button:not(.legacy-button):focus-visible {
@media (max-width: 800px) { @media (max-width: 800px) {
.legacy-page { .legacy-page {
max-width: 100%; max-width: 100%;
font-size: 13px; font-size: var(--sammo-font-size-small);
} }
.state-row { .state-row {
font-size: 18px; font-size: var(--sammo-font-size-emphasis);
} }
.section-title { .section-title {
font-size: 20px; font-size: var(--sammo-font-size-title);
} }
.group-tabs { .group-tabs {
display: grid; display: grid;
@@ -568,7 +573,7 @@ button:not(.legacy-button):focus-visible {
} }
.tournament-guide { .tournament-guide {
padding: 10px; padding: 10px;
font-size: 11px; font-size: var(--sammo-font-size-small);
line-height: 16px; line-height: 16px;
} }
.tournament-footer { .tournament-footer {
+3 -3
View File
@@ -225,7 +225,7 @@ onMounted(() => {
padding: 0; padding: 0;
color: #fff; color: #fff;
font-family: var(--sammo-font-sans); font-family: var(--sammo-font-sans);
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: normal; line-height: normal;
} }
@@ -233,7 +233,7 @@ onMounted(() => {
border-collapse: collapse; border-collapse: collapse;
padding: 0; padding: 0;
color: #fff; color: #fff;
font-size: 14px; font-size: var(--sammo-font-size-normal);
} }
/* /*
@@ -291,7 +291,7 @@ onMounted(() => {
.chart-title { .chart-title {
height: 34px; height: 34px;
font-size: 24px; font-size: var(--sammo-font-size-title);
} }
.chart-row { .chart-row {
+4 -4
View File
@@ -369,7 +369,7 @@ onMounted(() => {
color: #fff; color: #fff;
background: transparent; background: transparent;
font-family: var(--sammo-font-sans); font-family: var(--sammo-font-sans);
font-size: 14px; font-size: var(--sammo-font-size-normal);
line-height: 1.5; line-height: 1.5;
} }
@@ -395,7 +395,7 @@ onMounted(() => {
.topBackBar h2 { .topBackBar h2 {
margin: 0; margin: 0;
font-size: 24px; font-size: var(--sammo-font-size-title);
font-weight: 500; font-weight: 500;
line-height: 32px; line-height: 32px;
text-align: center; text-align: center;
@@ -455,7 +455,7 @@ onMounted(() => {
.makeTitle { .makeTitle {
grid-column: 1/3; grid-column: 1/3;
padding: 0.15em; padding: 0.15em;
font-size: 1.2em; font-size: var(--sammo-font-size-emphasis);
line-height: 1.2; line-height: 1.2;
} }
@@ -521,7 +521,7 @@ onMounted(() => {
grid-column: 4/5; grid-column: 4/5;
grid-row: 1/3; grid-row: 1/3;
overflow: hidden; overflow: hidden;
font-size: 85%; font-size: var(--sammo-font-size-small);
text-align: left; text-align: left;
} }
+3 -3
View File
@@ -258,7 +258,7 @@ onMounted(async () => {
margin: 0 auto; margin: 0 auto;
color: #fff; color: #fff;
font-family: var(--sammo-font-sans); font-family: var(--sammo-font-sans);
font-size: 14px; font-size: var(--sammo-font-size-normal);
background-color: transparent; background-color: transparent;
} }
@@ -279,7 +279,7 @@ onMounted(async () => {
.yearbook-title strong { .yearbook-title strong {
display: inline-block; display: inline-block;
line-height: 32px; line-height: 32px;
font-size: 20px; font-size: var(--sammo-font-size-title);
letter-spacing: 0.35em; letter-spacing: 0.35em;
} }
@@ -355,7 +355,7 @@ onMounted(async () => {
.nation-position table { .nation-position table {
width: 100%; width: 100%;
border-collapse: collapse; border-collapse: collapse;
font-size: 14px; font-size: var(--sammo-font-size-normal);
text-align: center; text-align: center;
} }
+79
View File
@@ -131,3 +131,82 @@ than forcing it into either family.
The CSS variables contain `/image/game/*` URLs but do not import or copy image The CSS variables contain `/image/game/*` URLs but do not import or copy image
files. Caddy continues to own `/image/*`; Vite must not rewrite the image tree files. Caddy continues to own `/image/*`; Vite must not rewrite the image tree
as application assets. as application assets.
## Game typography tiers
The game UI uses four starting sizes from `assets/styles/tokens.css`:
| Token suffix (`--sammo-font-size-`) | CSS size | Role |
| --- | --- | --- |
| `small` | `normal × 12 / 14` (12px) | Compact controls, metadata, secondary labels |
| `normal` | 14px | Body, tables, ordinary controls |
| `emphasis` | 16px | Emphasized names and section labels |
| `title` | 24px | Page and major section headings |
This is an intentional Core UX policy adopted on 2026-09-15. It is a starting
policy for verified UI, not a claim that every rendered glyph has one of four
computed sizes. Existing geometry and media queries remain owned by each page.
A breakpoint can choose another tier (for example, the personnel nation heading
uses 16px on its narrow layout and 24px on its wide layout).
Use the tokens for new UI. Do not round arbitrary content or all remaining
relative sizes automatically. Before moving an existing label to a tier, compare
actual Chromium screenshots and text geometry at 500px and 1000px, with the
same font, data, DPR and zoom. Also check the real mobile viewport modes: a
390px-wide device scales a 500px layout to approximately 78% and a 1000px layout
to 39%; these do not change the CSS token values. A page with a fixed 1000px
minimum width can still render at about 39% in 500px mode because Chromium
fits the overflowing content. Record `visualViewport.scale` for each route;
do not infer every route's scale from the selected mode alone.
### Preserved exceptions
- Battle log `.small_war_log .name_plate` remains `0.75em`, and `.crew_plate`
remains `90%`. Legacy inline `0.9em` conversions and zero-sized hidden markers
remain unchanged. At a 14px parent these are 10.5px and 12.6px respectively;
nested content must be calculated from its actual parent.
- NPC possession names retain their existing length rule: 4 and 7 characters
render at 16px, and the existing `length >= 9` branch renders at 12px. Do not
remove the smaller branch or enlarge long names to match adjacent labels.
- Player HTML, editor size choices, and personal CSS remain content/user settings.
Scoped `small` rules normalize UI metadata without rewriting injected HTML.
### Deferred conversions
| Area | Preserved size | Reason |
| --- | --- | --- |
| Chief overview compact rows and turn indices | `0.55rem` (8.8px) | 12px text overlaps the existing 11.25px rows |
| Chief compact header/name | `0.65rem` / `0.6rem` | Preserve the same dense card contract |
| Narrow personnel chief name / lock label | 15px / 10px | Enlarging them reduces visible maximum-length names |
| Best generals / hall name and nation cells | 11px; inner `small` 95% | 12px worsens overflow in the fixed name cells |
| General selection and main nation basic card | Existing local/inherited sizes | Maximum-width names already overflow; conversion is deferred |
User-created general names and founded/renamed nation names are limited by
legacy width 18 (CJK counts 2, ASCII counts 1): test both 9 CJK characters and
18 wide ASCII characters. Selection-pool and scenario names have a different
source contract and are not proven bounded by that user-input guard.
Existing ellipsis, horizontal scrolling, and pre-existing maximum-name overflow
are not fixed by these tokens. The deferred areas need a separate layout decision
before their fonts are enlarged. The `typographyPolicy.spec.ts` fixture tests
protect the safe main labels, personnel breakpoints, dense chief rows, NPC
length branches, and battle log ratios. They use mocked read responses and do
not constitute live game or public deployment verification.
### Relative small tier and exception variables (2026-09-15)
`small` is `calc(var(--sammo-font-size-normal) * 12 / 14)`. The reference is the
14px normal tier, not the immediate parent. An 80% declaration on nested `small`
elements would shrink repeatedly and would yield 12.8px inside a 16px parent;
the token keeps UI metadata at 12px regardless of nesting.
The retained exceptions are also named in `tokens.css`: `nation-card`,
`chief-compact-{base,row,header,name}`, `hall-{name,secondary}`,
`personnel-mobile-{name,lock}`, `bracket-bet-button`, and `war-{name,crew}`
(all with the `--sammo-font-size-` prefix). Their values preserve the previous
rendering, including rem/em/% semantics. Zero-sized hidden markers and arbitrary
user HTML remain content contracts. The betting page and bracket now reference
the shared tier variables directly instead of the redundant `--bet-font-*` aliases.
The historical deferral reasons above describe the original 12px proposal.