Skip to content

Commit c76ba4f

Browse files
author
web3blind
committed
Polish mobile game affordances
1 parent 7bb9a9c commit c76ba4f

15 files changed

Lines changed: 219 additions & 50 deletions

File tree

app/css/main.css

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,8 @@ body {
167167
/* Home dashboard */
168168
.home-dashboard { max-width: 480px; margin: 0 auto; }
169169
.home-summary { margin-bottom: 24px; }
170+
.home-summary-button { display: block; width: 100%; text-align: left; color: inherit; background: transparent; border: 1px solid transparent; border-radius: var(--radius); padding: 8px; cursor: pointer; }
171+
.home-summary-button:hover, .home-summary-button:focus-visible { border-color: var(--color-primary); outline: none; }
170172
.home-summary h1 { font-size: 1.5rem; margin-bottom: 8px; }
171173
.action-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
172174
.action-tile {
@@ -815,7 +817,8 @@ body {
815817
padding: 12px; background: var(--color-surface); border-radius: var(--radius-sm);
816818
border-left: 3px solid var(--color-border);
817819
}
818-
.sell-item-name { display: block; font-weight: 600; margin-bottom: 8px; text-transform: capitalize; }
820+
.sell-item-name { display: block; font-weight: 700; margin-bottom: 8px; text-transform: capitalize; color: var(--color-text); }
821+
.sell-item-rarity { margin-left: 4px; }
819822
.sell-item-controls { display: flex; gap: 8px; align-items: center; }
820823
.sell-price-input { max-width: 120px; }
821824

@@ -1867,3 +1870,12 @@ body,
18671870
.developers-card h2 { font-size: 1.1rem; margin-bottom: 10px; }
18681871
.developers-note { color: var(--color-text-muted); font-size: 0.95rem; }
18691872
.developers-reward-options { display: grid; gap: 10px; margin-top: 12px; }
1873+
1874+
1875+
.temple-deity-fallback { display: inline-flex; align-items: center; justify-content: center; width: 72px; height: 72px; font-size: 2.5rem; margin: 0 auto 8px; }
1876+
.temple-deity-image { min-width: 72px; min-height: 72px; }
1877+
.boss-lore { margin: 16px 0; padding: 14px; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius); text-align: left; }
1878+
.boss-lore h3 { margin-bottom: 8px; }
1879+
.boss-lore ul { margin: 8px 0 0 20px; }
1880+
.boss-motto { margin: 14px 0; padding-left: 12px; border-left: 3px solid var(--color-primary); color: var(--color-text); white-space: pre-line; }
1881+
.forecast-card-news { border-color: var(--color-accent); }

app/index.html

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
<link rel="icon" type="image/png" sizes="192x192" href="assets/icons/viz-magic-192.png?v=20260713a">
1414
<link rel="icon" type="image/png" sizes="512x512" href="assets/icons/viz-magic-512.png?v=20260713a">
1515
<link rel="apple-touch-icon" href="assets/icons/viz-magic-192.png?v=20260713a">
16-
<link rel="stylesheet" href="css/main.css?v=20260713b">
16+
<link rel="stylesheet" href="css/main.css?v=20260713c">
1717
<link rel="stylesheet" href="css/themes.css">
1818
<link rel="stylesheet" href="css/accessibility.css">
1919
</head>
@@ -124,8 +124,8 @@
124124
<script src="js/config.js?v=20260712a"></script>
125125

126126
<!-- I18n -->
127-
<script src="js/i18n/ru.js?v=20260713g"></script>
128-
<script src="js/i18n/en.js?v=20260713g"></script>
127+
<script src="js/i18n/ru.js?v=20260713h"></script>
128+
<script src="js/i18n/en.js?v=20260713h"></script>
129129

130130
<!-- Utilities -->
131131
<script src="js/utils/helpers.js?v=20260621l"></script>
@@ -169,7 +169,7 @@
169169
<script src="js/engine/marketplace.js"></script>
170170
<script src="js/engine/checkpoint.js"></script>
171171
<script src="js/engine/block-processor.js"></script>
172-
<script src="js/engine/world-events.js?v=20260712h"></script>
172+
<script src="js/engine/world-events.js?v=20260713a"></script>
173173
<script src="js/engine/world-boss.js"></script>
174174
<script src="js/engine/quest-system.js?v=20260621e"></script>
175175
<script src="js/engine/loci.js"></script>
@@ -184,32 +184,32 @@
184184
<script src="js/ui/components/toast.js?v=20260711b"></script>
185185
<script src="js/ui/components/modal.js"></script>
186186
<script src="js/ui/components/nav.js?v=20260713a"></script>
187-
<script src="js/ui/components/battle-narrator.js?v=20260713b"></script>
187+
<script src="js/ui/components/battle-narrator.js?v=20260713c"></script>
188188

189189
<!-- UI Screens -->
190190
<script src="js/ui/screens/landing.js"></script>
191191
<script src="js/ui/screens/login.js?v=20260711a"></script>
192192
<script src="js/ui/screens/onboarding.js"></script>
193-
<script src="js/ui/screens/home.js?v=20260713e"></script>
193+
<script src="js/ui/screens/home.js?v=20260713f"></script>
194194
<script src="js/ui/screens/character.js?v=20260713b"></script>
195195
<script src="js/ui/screens/hunt.js?v=20260713d"></script>
196-
<script src="js/ui/screens/inventory.js?v=20260621l"></script>
196+
<script src="js/ui/screens/inventory.js?v=20260713a"></script>
197197
<script src="js/ui/screens/chronicle.js?v=20260712a"></script>
198198
<script src="js/ui/screens/duel.js"></script>
199199
<script src="js/ui/screens/arena.js?v=20260621d"></script>
200200
<script src="js/ui/screens/guild.js?v=20260621l"></script>
201201
<script src="js/ui/screens/map.js?v=20260621h"></script>
202-
<script src="js/ui/screens/marketplace.js?v=20260713b"></script>
203-
<script src="js/ui/screens/crafting.js?v=20260713a"></script>
202+
<script src="js/ui/screens/marketplace.js?v=20260713c"></script>
203+
<script src="js/ui/screens/crafting.js?v=20260713b"></script>
204204
<script src="js/ui/screens/quests.js?v=20260712a"></script>
205-
<script src="js/ui/screens/world-boss.js"></script>
205+
<script src="js/ui/screens/world-boss.js?v=20260713a"></script>
206206
<script src="js/ui/screens/settings.js?v=20260713b"></script>
207207
<script src="js/ui/screens/help.js?v=20260713a"></script>
208208
<script src="js/ui/screens/leaderboard.js?v=20260712c"></script>
209-
<script src="js/ui/screens/temple.js?v=20260713a"></script>
209+
<script src="js/ui/screens/temple.js?v=20260713b"></script>
210210
<script src="js/ui/screens/developers.js?v=20260713a"></script>
211211

212212
<!-- Main App Controller (must be last) -->
213-
<script src="js/ui/app.js?v=20260713a"></script>
213+
<script src="js/ui/app.js?v=20260713b"></script>
214214
</body>
215215
</html>

app/js/engine/world-events.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,23 @@ var WorldEvents = (function() {
5858
}
5959
];
6060

61+
62+
/** Daily magical news: flavor-only, deterministic from block-day. */
63+
var MAGIC_NEWS = [
64+
{ icon: '📰', summaryKey: 'magic_news_sun_wolf' },
65+
{ icon: '🌲', summaryKey: 'magic_news_forest_patrol' },
66+
{ icon: '🪄', summaryKey: 'magic_news_wand_union' },
67+
{ icon: '🐸', summaryKey: 'magic_news_frog_court' },
68+
{ icon: '🐉', summaryKey: 'magic_news_dragon_shadow' },
69+
{ icon: '🕯️', summaryKey: 'magic_news_temple_candles' },
70+
{ icon: '🏪', summaryKey: 'magic_news_bazaar_prices' },
71+
{ icon: '📜', summaryKey: 'magic_news_chronicle_blots' },
72+
{ icon: '⚔️', summaryKey: 'magic_news_arena_helmets' },
73+
{ icon: '🔮', summaryKey: 'magic_news_prophet_sneeze' },
74+
{ icon: '🌧️', summaryKey: 'magic_news_upward_rain' },
75+
{ icon: '🧪', summaryKey: 'magic_news_healers_busy' }
76+
];
77+
6178
/** Magical weather definitions. These are in-world, not real-world forecasts. */
6279
var WEATHER = [
6380
{
@@ -418,6 +435,20 @@ var WorldEvents = (function() {
418435
return WEATHER[idx];
419436
}
420437

438+
439+
/**
440+
* Get optional daily magical news. Flavor-only; does not affect combat.
441+
* @param {number} blockNum
442+
* @returns {Object|null}
443+
*/
444+
function getCurrentMagicNews(blockNum) {
445+
var day = Math.floor(blockNum / 28800);
446+
if (day % 2 !== 0) return null;
447+
var idx = Math.floor(day / 2) % MAGIC_NEWS.length;
448+
if (idx < 0) idx = 0;
449+
return MAGIC_NEWS[idx];
450+
}
451+
421452
/**
422453
* Check if Weave Surge is active.
423454
* @param {number} blockNum
@@ -592,6 +623,7 @@ var WorldEvents = (function() {
592623
getCurrentSky: getCurrentSky,
593624
getForecastVariantCount: getForecastVariantCount,
594625
getCurrentFestival: getCurrentFestival,
626+
getCurrentMagicNews: getCurrentMagicNews,
595627
getActiveEvents: getActiveEvents,
596628
checkEventTriggers: checkEventTriggers,
597629
checkWeaveSurge: checkWeaveSurge,

app/js/i18n/en.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -886,6 +886,24 @@ var LangEN = {
886886
event_world_boss_desc: 'The Aether Dragon has awakened!',
887887
event_next_season: 'Season Change',
888888

889+
magic_news_sun_wolf: 'A squad of battle mages met a sun wolf in the enchanted forest. The best healers of the Third Kingdom are treating the entire squad for temporary blindness.',
890+
magic_news_forest_patrol: 'The forest watch asks mages not to feed talking stumps with promises. The stumps write everything down.',
891+
magic_news_wand_union: 'The union of old wands announced a day of silence. Sparks are allowed only in whispers.',
892+
magic_news_frog_court: 'The Frog Court acquitted the rain: witnesses confirmed it was falling upward for a valid reason.',
893+
magic_news_dragon_shadow: 'The shadow of the Aether Dragon was seen near the map edge. The shadow claims it was only walking.',
894+
magic_news_temple_candles: 'Temple candles burned without fire and argued about the proper shape of flame. Priests found the debate useful.',
895+
magic_news_bazaar_prices: 'At the Bazaar, prices haggled with themselves this morning. By noon two prices became apprentices to an appraiser.',
896+
magic_news_chronicle_blots: 'Living ink blots appeared in the Chronicle. They promise not to ruin texts if occasionally called letters.',
897+
magic_news_arena_helmets: 'The Arena bought helmets with memory. One helmet already remembers a victory that has not happened yet.',
898+
magic_news_prophet_sneeze: 'A prophet sneezed three times and predicted a draft. The council called the forecast accurate.',
899+
magic_news_upward_rain: 'In the northern lowland the rain went upward again. Fishers complain that clouds steal their bait.',
900+
magic_news_healers_busy: 'The best healers of the Third Kingdom opened appointments for consequences of curiosity.',
901+
boss_motto: 'Wherever you came from, there is no road back.\nGo forward.\nDo not hurry.\nDo not look back...',
902+
boss_lore_title: 'Scout Report',
903+
boss_lore_text: 'The Aether Dragon appears rarely, but its shadow changes the world before the fight. This is a shared event: every mage\'s contribution matters.',
904+
boss_lore_rule_1: 'An attack costs 2% mana and is written to the chain.',
905+
boss_lore_rule_2: 'The more total damage you contribute, the higher your reward share.',
906+
boss_lore_rule_3: 'When the battle window is closed, this screen shows preparation and the next awakening.',
889907
// World Boss
890908
boss_title: 'World Boss',
891909
boss_dormant: 'The Aether Dragon Slumbers',

app/js/i18n/ru.js

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -886,6 +886,24 @@ var LangRU = {
886886
event_world_boss_desc: 'Эфирный Дракон пробудился!',
887887
event_next_season: 'Смена Сезона',
888888

889+
magic_news_sun_wolf: 'Отряд боевых магов в зачарованном лесу наткнулся на солнечного волка. Временную слепоту всего отряда лечат лучшие знахари Третьего Царства.',
890+
magic_news_forest_patrol: 'Лесная стража просит не кормить говорящие пни обещаниями. Пни всё записывают и потом требуют продолжения.',
891+
magic_news_wand_union: 'Профсоюз старых жезлов объявил день тишины. Искры разрешены только шёпотом.',
892+
magic_news_frog_court: 'Жабий суд оправдал дождь: свидетели подтвердили, что он падал вверх по уважительной причине.',
893+
magic_news_dragon_shadow: 'Тень Эфирного Дракона замечена на границе карты. Сама тень утверждает, что просто гуляла.',
894+
magic_news_temple_candles: 'В Храме свечи горели без огня и спорили о форме пламени. Жрецы признали спор полезным.',
895+
magic_news_bazaar_prices: 'На Базаре цены утром торговались сами с собой. К полудню две цены ушли в ученики к оценщику.',
896+
magic_news_chronicle_blots: 'В Хронике появились живые кляксы. Они обещают не портить тексты, если их иногда называть буквами.',
897+
magic_news_arena_helmets: 'Арена закупила шлемы с памятью. Один шлем уже вспомнил победу, которой ещё не было.',
898+
magic_news_prophet_sneeze: 'Прорицатель чихнул три раза и предсказал сквозняк. Совет магов признал прогноз точным.',
899+
magic_news_upward_rain: 'В северной низине дождь опять пошёл вверх. Рыбаки жалуются, что облака уносят наживку.',
900+
magic_news_healers_busy: 'Лучшие знахари Третьего Царства открыли запись на лечение последствий любопытства.',
901+
boss_motto: 'Откуда бы ты ни пришёл, назад дороги нет.\nИди дальше.\nНе торопись.\nНе оглядывайся...',
902+
boss_lore_title: 'Что известно разведке',
903+
boss_lore_text: 'Эфирный Дракон появляется редко, но его тень заранее меняет поведение мира. Бой с ним — общее событие: важен вклад каждого мага.',
904+
boss_lore_rule_1: 'Атака стоит 2% маны и записывается в цепочку.',
905+
boss_lore_rule_2: 'Чем больше вклад в общий урон, тем выше доля награды.',
906+
boss_lore_rule_3: 'Если окно битвы закрыто, экран показывает подготовку и следующее пробуждение.',
889907
// World Boss
890908
boss_title: 'Мировой Босс',
891909
boss_dormant: 'Эфирный Дракон Дремлет',
@@ -1116,8 +1134,8 @@ var LangRU = {
11161134
help_section_crafting: 'Мастерская',
11171135
help_crafting_text: 'Откройте Мастерскую, выберите рецепт и нажмите «Создать». Материалы расходуются. Качество зависит от INT и хеша блока.',
11181136

1119-
help_section_marketplace: 'Рынок',
1120-
help_marketplace_text: 'Обзор → купите выставленные предметы. Продать → выставьте свои предметы за Печати Мира. Обмен → прямая передача предмета другому магу.',
1137+
help_section_marketplace: 'Базар',
1138+
help_marketplace_text: 'Базар — стихийное место торговли. Обзор → купите выставленные предметы. Продать → выставьте свои предметы за Печати Мира. Обмен → прямая передача предмета другому магу.',
11211139

11221140
help_section_leaderboard: 'Рейтинг',
11231141
help_leaderboard_text: 'Экран Рейтинга (вкладка с кубком) показывает топ-100 магов по опыту. Твоё место отображается в верхней части. Таблица обновляется автоматически по мере охоты.',

app/js/ui/components/battle-narrator.js

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,9 @@ var BattleNarrator = (function() {
9999
var hints = voiceGender === 'female' ? femaleHints : maleHints;
100100
for (var j = 0; j < pool.length; j++) {
101101
var name = (pool[j].name || '') + ' ' + (pool[j].voiceURI || '');
102-
if (hints.test(name)) return pool[j];
102+
if (hints.test(name)) return { voice: pool[j], matched: true };
103103
}
104-
return pool[0] || null;
104+
return { voice: pool[0] || null, matched: false };
105105
}
106106

107107
/**
@@ -132,11 +132,17 @@ var BattleNarrator = (function() {
132132
try {
133133
var utterance = new SpeechSynthesisUtterance(message);
134134
var lang = (Helpers.getCurrentLang && Helpers.getCurrentLang() === 'en') ? 'en-US' : 'ru-RU';
135-
var voice = _selectVoice(lang);
135+
var voiceChoice = _selectVoice(lang);
136+
var voice = voiceChoice && voiceChoice.voice ? voiceChoice.voice : null;
137+
var matchedVoice = !!(voiceChoice && voiceChoice.matched);
136138
utterance.lang = lang;
137139
if (voice) utterance.voice = voice;
138-
utterance.rate = (voiceTimbre === 'rough') ? 0.92 : (voiceTimbre === 'soft' ? 0.98 : 1);
139-
utterance.pitch = (voiceGender === 'male') ? (voiceTimbre === 'rough' ? 0.84 : 0.9) : (voiceTimbre === 'rough' ? 0.96 : 1.08);
140+
utterance.rate = (voiceTimbre === 'rough') ? 0.94 : (voiceTimbre === 'soft' ? 0.98 : 1);
141+
if (voiceGender === 'male') {
142+
utterance.pitch = matchedVoice ? (voiceTimbre === 'rough' ? 0.86 : 0.92) : 1;
143+
} else {
144+
utterance.pitch = (voiceTimbre === 'rough') ? 0.98 : 1.08;
145+
}
140146
utterance.volume = 1;
141147
window.speechSynthesis.cancel();
142148
window.speechSynthesis.speak(utterance);

app/js/ui/screens/crafting.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,8 +257,6 @@ var CraftingScreen = (function() {
257257
return html;
258258
}
259259

260-
html += '<button class="btn btn-secondary btn-sm craft-tab-back-btn" aria-label="' + t('craft_back') + '">' + t('craft_back') + '</button>';
261-
262260
// Enchantable items (equipped or in bag, with slots available)
263261
html += '<h2>' + t('enchant_title') + '</h2>';
264262
html += '<p class="enchant-desc">' + t('enchant_desc') + '</p>';

0 commit comments

Comments
 (0)