@indiegems/gem-web-sdk 10.3.0 → 10.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -320,11 +320,11 @@ Four things to know before you ship one:
320
320
  in" is not in general when the allowance refills. Each date's allowance is spent once, whatever
321
321
  the player does to their time zone.
322
322
 
323
- **When a completion pays a platform currency, show it where it happened.** The arcade draws the
324
- player's Gems and Tickets in its own chrome, and without a cue a payout lands there silently, in a
325
- corner the player is not looking at. At the moment your game shows the challenge complete, call
323
+ **When a completion pays a platform currency, show it where it happened.** The arcade shows the
324
+ player's Gems and Tickets in its own chrome, and without a cue a payout flies from the middle of
325
+ your frame, not from the payout the player is looking at. At the moment your game shows the challenge complete, call
326
326
  `gem.cueReward` with the currency that paid (`GEMS` or `ARCADE_TICKETS`) and the centre of its icon
327
- beside the payout on your completion screen, and the payout flies from there into the wallet:
327
+ beside the payout on your completion screen, and the payout flies from there into the Gem button:
328
328
  [inventory-and-catalogs.md](inventory-and-catalogs.md#showing-the-reward-land-in-the-arcades-wallet).
329
329
  **If it returns `false`, do nothing** — no celebration of your own, no counter, no flight;
330
330
  platform-currency display belongs to the arcade, and a game not connected to it shows no
@@ -50,7 +50,7 @@ either way.
50
50
  ```jsonc
51
51
  // package.json
52
52
  "dependencies": {
53
- "@indiegems/gem-web-sdk": "10.3.0"
53
+ "@indiegems/gem-web-sdk": "10.3.1"
54
54
  }
55
55
  ```
56
56
 
@@ -589,14 +589,15 @@ the source progression from a function the player calls, on a progression that o
589
589
  ### Showing the reward land in the arcade's wallet
590
590
 
591
591
  **Platform-currency display belongs to the arcade** (the creator's ruling, 2026-09-24) — Gems and
592
- Tickets alike. The arcade draws the player's platform currencies in its own chrome while your game
593
- runs, and moves a total when the platform confirms a grant. Your game keeps no counter or balance
592
+ Tickets alike. The arcade shows the player's platform currencies in its own chrome — in the Gem
593
+ Arcade, the Gem menu the player opens from the Gem button at the top-left of your frame; no wallet
594
+ is drawn over your game — and moves a total when the platform confirms a grant. Your game keeps no counter or balance
594
595
  of a platform currency of its own, draws no flight or celebration of its own, and shows no
595
596
  platform-currency amount at all when it is not connected to the arcade.
596
597
 
597
598
  What your game does is ask for the payout to start on **your** screen, from the currency's icon (or
598
- hero) beside the reward, so the currency flies from there into the wallet and the total bounces up
599
- as it lands. A Gems payout is cued from the gem:
599
+ hero) beside the reward, so the currency flies from there into the arcade — in the Gem Arcade,
600
+ into the Gem button, which pops as each mark lands. A Gems payout is cued from the gem:
600
601
 
601
602
  ```js
602
603
  const { x, y, width, height } = rewardGem.getBoundingClientRect(); // the gem element's own box
@@ -609,8 +610,10 @@ gem.cueReward({
609
610
 
610
611
  `origin` is the **centre of the gem on screen** — measure the gem element itself, not the row or
611
612
  panel around it. A Tickets payout is the same call with `currencySlug: 'ARCADE_TICKETS'`, from the
612
- ticket: the slug decides which total the payout flies into. **If `cueReward` returns `false`, do
613
- nothing**: there is no fallback celebration.
613
+ ticket: the slug decides what flies and which total moves. **A payout you do not cue still flies**
614
+ in the Gem Arcade, from the middle of your frame, once the platform confirms it — cue it so the
615
+ flight starts where the player is looking. **If `cueReward` returns `false`, do nothing**: there is
616
+ no fallback celebration.
614
617
  `false` means the arcade will not show it here — the bridge is not up, or the embedder has no wallet
615
618
  — and your game does not draw one of its own in its place.
616
619
 
@@ -898,7 +901,8 @@ buyButton.disabled = !gems || gems.balance < price; // can the player afford it?
898
901
  ```
899
902
 
900
903
  **Read it to decide, never to display.** Platform-currency display belongs to the arcade: its
901
- wallet shows the player's Gems and Tickets totals while your game runs, and your game keeps no
904
+ wallet — the Gem menu, in the Gem Arcade — shows the player's Gems and Tickets totals while your
905
+ game runs, and your game keeps no
902
906
  counter, balance or wallet total of either of its own ([brand-art.md](brand-art.md) §5). Use the
903
907
  balance to enable a purchase or to say "not enough Gems" — not to draw a number.
904
908
 
@@ -28,13 +28,13 @@
28
28
  },
29
29
  {
30
30
  "file": "brand-art.md",
31
- "sha256": "cf54939a0fcee1f5a6e11b9de52b5ed498ec8c373683e92aa5bc6654b12eb0ab",
32
- "updated": "2026-10-01T03:49:20Z"
31
+ "sha256": "87267dca53e5506b1aee77ac9819aef8025c8e0de2780e65a2ea3b7236a9c0ab",
32
+ "updated": "2026-10-11T18:48:12Z"
33
33
  },
34
34
  {
35
35
  "file": "changelog.md",
36
- "sha256": "daae6b71cecc9761bc1e3ed5603c5d8f366e0533ce4ecc6d6c57f546efe1a292",
37
- "updated": "2026-10-11T18:22:44Z"
36
+ "sha256": "25047a1c8498f92990b4d50768cf49d1cd4acd2a27dd42db595ca322aa56a2a9",
37
+ "updated": "2026-10-11T19:08:27Z"
38
38
  },
39
39
  {
40
40
  "file": "cross-promotion.md",
@@ -43,8 +43,8 @@
43
43
  },
44
44
  {
45
45
  "file": "daily-challenges.md",
46
- "sha256": "f4842b2fe01c8780020326f4722ab69dc01c1f40e1e6455cf2fb27752094383d",
47
- "updated": "2026-10-10T14:37:50Z"
46
+ "sha256": "0423168355c22724e705def15ca19a5651b7f0da3598ec5aabcc69c32e0bb401",
47
+ "updated": "2026-10-11T18:48:12Z"
48
48
  },
49
49
  {
50
50
  "file": "dedicated-server-flow.md",
@@ -68,13 +68,13 @@
68
68
  },
69
69
  {
70
70
  "file": "getting-started.md",
71
- "sha256": "fd566ed7d7f0b1b2b9bea823de5455d2ee9a66072e7303df1bc5c12c1acddcbe",
72
- "updated": "2026-10-11T18:22:44Z"
71
+ "sha256": "327be77c7b742f7ecfb3ca8f4869480e72942ea9f7293e25634c47c056a38eae",
72
+ "updated": "2026-10-11T19:08:27Z"
73
73
  },
74
74
  {
75
75
  "file": "inventory-and-catalogs.md",
76
- "sha256": "3e0f71db5b4f5d2d256289f90ffec3ed2887a70b1e72b02f55ec64815043d900",
77
- "updated": "2026-10-09T00:13:03Z"
76
+ "sha256": "fecd1299ef19bc50ea17abe96bbe49f62dc366a9fc0f354c843a42b2d5a2f9e2",
77
+ "updated": "2026-10-11T18:48:12Z"
78
78
  },
79
79
  {
80
80
  "file": "leaderboards.md",
@@ -123,8 +123,8 @@
123
123
  },
124
124
  {
125
125
  "file": "server-bundles.md",
126
- "sha256": "c6935f10ba645e8a9d3fd48c10f313324bfdbca6fcbd273dfade6579dcfd32e8",
127
- "updated": "2026-10-11T18:22:44Z"
126
+ "sha256": "c6bf3689c928b6cb24d86faa380e6ed4bece1f3dd6e8dfc71c1ff9de1ed0dd42",
127
+ "updated": "2026-10-11T19:08:27Z"
128
128
  },
129
129
  {
130
130
  "file": "serverless-functions-js.md",
@@ -148,8 +148,8 @@
148
148
  },
149
149
  {
150
150
  "file": "what-a-game-must-do.md",
151
- "sha256": "44fa07b8f379181cfac9a89c8fa672946d0e4aaeefe1fd3386cc3565abcb3c95",
152
- "updated": "2026-10-11T17:59:34Z"
151
+ "sha256": "c5797bd913fbd8c62fb3fbe83b6c8c6cb22f5aec984c0d56f3f0198c917fee7d",
152
+ "updated": "2026-10-11T18:48:12Z"
153
153
  }
154
154
  ]
155
155
  }
@@ -80,8 +80,8 @@ To check the download yourself: the package npm serves is, byte for byte, the fi
80
80
  also publishes on its download host, with the hash beside it:
81
81
 
82
82
  ```bash
83
- curl -fsSL -O https://downloads.gemarcade.com/sdk/v10.3.0/gem-web-sdk.tgz
84
- curl -fsSL https://downloads.gemarcade.com/sdk/v10.3.0/gem-web-sdk.tgz.sri
83
+ curl -fsSL -O https://downloads.gemarcade.com/sdk/v10.3.1/gem-web-sdk.tgz
84
+ curl -fsSL https://downloads.gemarcade.com/sdk/v10.3.1/gem-web-sdk.tgz.sri
85
85
  openssl dgst -sha384 -binary gem-web-sdk.tgz | openssl base64 -A
86
86
  ```
87
87
 
@@ -702,53 +702,49 @@ the `var()` above, or read `gem.viewport`. The release checklist looks for the b
702
702
 
703
703
  ### The arcade's own controls: reserved areas
704
704
 
705
- On a phone your game is full-bleed, and the arcade keeps one row of its own over the top of it:
706
-
707
- - **The menu button**, in the **top-right corner**, always there. It opens
708
- [the Arcade's menu](#the-arcades-menu): Return to the Arcade, mute, the player's Arcade-wide
709
- settings and the rest. Not your settings: those are [your own button](#game-settings).
710
- - **The player's wallets** (Gems, Tickets, their achievement score), in the **middle of the row**,
711
- [there unless your game hides them](#the-arcades-wallet-shown-unless-you-hide-it-never-drawn),
712
- during play as well as on your menus. They are translucent, so your game shows through them — but they are still the Arcade's,
713
- and still taps the Arcade takes.
705
+ The Arcade keeps **one control of its own over every game**, on every device — a phone's full-bleed
706
+ game, a framed or full-window game on a desktop, a tablet or a TV in native fullscreen:
707
+
708
+ - **The Gem button**, the Gem Arcade's gem, in the **top-left corner**, always there (a touch target, about
709
+ 50px across). It opens [the Arcade's menu](#the-arcades-menu): Return to the Arcade, the player's Gems,
710
+ Tickets and achievement score, mute, the player's Arcade-wide settings and the rest. Not your
711
+ settings: those are [your own button](#game-settings).
712
+ - **Nothing else.** The player's wallets (Gems, Tickets, their achievement score) are **not** drawn
713
+ over your game: the player opens the Gem menu to see them, and every platform-currency payout
714
+ flies into the Gem button ([the Arcade's wallet](#the-arcades-wallet-in-the-gem-menu-never-drawn-by-you)).
715
+ When the player switches the frame-rate readout on, it sits beside the gem and is reserved the
716
+ same way.
714
717
 
715
718
  **The top of the screen has one layout, in every game:**
716
719
 
717
- | Where | Whose | What goes there |
718
- | -------------------------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
719
- | **Top-left** | yours | Your **Home / Back** buttons, drawn when a screen needs them, in the space to the left of the wallets. They move around _inside_ your game — back to your level select or title screen — and never leave it. |
720
- | **Middle and top-right** | the Arcade's | Its wallets and its menu button. Nothing of yours. |
721
- | **Centre and right, below the Arcade's row** | yours | Your **information**: score, moves, a timer, a level name. It starts under the bottom of the Arcade's row, never beside it or under it. |
722
-
723
- Keep the left for Home / Back even on a screen that has neither today: a player learns where "back"
724
- is once, across every game, and information that sits there on one screen teaches them the wrong
725
- thing on the next.
720
+ | Where | Whose | What goes there |
721
+ | ------------------------------------ | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
722
+ | **Top-left corner** | the Arcade's | Its Gem button. Nothing of yours under it. |
723
+ | **Top-left, right of the Gem** | yours | Your **Home / Back** buttons, drawn when a screen needs them, level with the Gem and just to its right. They move around _inside_ your game — back to your level select or title screen — and never leave it. |
724
+ | **Centre of the top row** | yours | Your **information**: score, moves, a timer, a level name. |
725
+ | **Top-right** | yours | Your **settings** button ([Game settings](#game-settings)). |
726
726
 
727
- **Your settings button goes top-right, clear of the Arcade's controls**: never under one, and below
728
- any the Arcade keeps in that corner. [Game settings](#game-settings) shows how to place it.
727
+ Keep the spot beside the Gem for Home / Back even on a screen that has neither today: a player
728
+ learns where "back" is once, across every game, and information that sits there on one screen
729
+ teaches them the wrong thing on the next.
729
730
 
730
- **How much room the top-left has.** The menu button is about 48px across — the size of a Home or
731
- Back button. With every wallet shown, the narrowest phones (360px wide) leave roughly 68px to the
732
- left of the wallets: room for **one** button. Two buttons, or a wide one, go on their own row below
733
- the Arcade's. Do not copy those numbers — read the space, as below.
731
+ **Your settings button goes top-right**, clear of any Arcade control: under the Gem Arcade there is
732
+ none in that corner, but another embedder may keep one there. [Game settings](#game-settings) shows
733
+ how to place it.
734
734
 
735
735
  Those rectangles of your frame are **reserved**: keep essential UI and every touch target out of
736
- them. **Never hard-code their size or height.** They differ by phone, and in native fullscreen the
737
- whole row may rise into the camera band — read them, as below.
736
+ them. **Never hard-code their size or position.** They differ by phone, and in native fullscreen the
737
+ gem may rise into the camera band — read them, as below.
738
738
 
739
- An inset cannot say that — as a top inset, a button a few dozen pixels wide would take your whole top
740
- strip. So `gem.viewport` also carries the rectangles, in the same CSS pixels of your frame, measured
741
- from its top-left corner — one per wallet shown, and one for the menu button:
739
+ An inset cannot say that — as a left or top inset, a button a few dozen pixels wide would take a whole
740
+ strip of your screen. So `gem.viewport` also carries the rectangles, in the same CSS pixels of your
741
+ frame, measured from its top-left corner — one for the Gem button, and one for the frame-rate
742
+ readout while the player shows it:
742
743
 
743
744
  ```json
744
745
  {
745
746
  "insets": { "top": 47, "right": 0, "bottom": 34, "left": 0 },
746
- "reserved": [
747
- { "x": 68, "y": 51, "width": 72, "height": 28 },
748
- { "x": 144, "y": 51, "width": 72, "height": 28 },
749
- { "x": 220, "y": 51, "width": 72, "height": 28 },
750
- { "x": 304, "y": 51, "width": 48, "height": 48 }
751
- ]
747
+ "reserved": [{ "x": 8, "y": 55, "width": 52, "height": 52 }]
752
748
  }
753
749
  ```
754
750
 
@@ -756,59 +752,44 @@ from its top-left corner — one per wallet shown, and one for the menu button:
756
752
  `--gem-safe-*` before anything else hears the push: `--gem-reserved-tl-width` and
757
753
  `--gem-reserved-tl-height`, and the same pair for `tr`, `bl` and `br` — how far that corner's
758
754
  reserved rectangles reach in from its two edges. A rectangle belongs to the corner its centre lies
759
- nearest to.
760
-
761
- ⚠️ **The wallets sit in the middle, so they count toward BOTH top corners.** A wallet left of
762
- centre is a top-left rectangle, one right of centre a top-right one. While wallets are shown,
763
- `--gem-reserved-tl-height` is the bottom of the wallets and `--gem-reserved-tl-width` reaches to the
764
- middle of the screen — even though the corner itself, left of the first wallet, is clear. So:
755
+ nearest to. Under the Gem Arcade the Gem button is a top-left rectangle, so:
765
756
 
766
757
  ```css
767
- /* your information — score, moves, a timer — below the WHOLE of the arcade's row: the taller of
768
- the two top corners. It moves up by itself when gameplay hides the wallets. */
769
- #info {
770
- top: max(
771
- var(--gem-safe-top, env(safe-area-inset-top, 0px)),
772
- var(--gem-reserved-tl-height, 0px),
773
- var(--gem-reserved-tr-height, 0px)
774
- );
775
- right: var(--gem-safe-right, 0px);
776
- }
777
- /* ONE Home or Back button, level with the arcade's row, in the clear corner to the wallets' left */
758
+ /* ONE Home or Back button, level with the Gem, just to its right */
778
759
  #back {
779
760
  top: var(--gem-safe-top, env(safe-area-inset-top, 0px));
780
- left: var(--gem-safe-left, 0px);
761
+ left: max(var(--gem-safe-left, 0px), var(--gem-reserved-tl-width, 0px));
781
762
  }
782
- /* a ROW of your own buttons does not fit beside the wallets: start it below the arcade's row,
783
- like your information */
784
- #nav {
763
+ /* your information — score, moves, a timer — clear of every top corner the arcade reserves */
764
+ #info {
785
765
  top: max(
786
766
  var(--gem-safe-top, env(safe-area-inset-top, 0px)),
787
- var(--gem-reserved-tl-height, 0px),
788
767
  var(--gem-reserved-tr-height, 0px)
789
768
  );
769
+ left: max(var(--gem-safe-left, 0px), var(--gem-reserved-tl-width, 0px));
770
+ right: var(--gem-safe-right, 0px);
790
771
  }
791
772
  ```
792
773
 
793
- The per-corner properties cannot say how wide the clear corner is — only that the corner's
794
- rectangles reach in to the middle. To know whether your button fits beside the wallets, read the
795
- rectangles from script: the clear width at the top-left is the smallest `x` among
796
- `gem.viewport.reserved` (the whole width when the list is empty).
774
+ The per-corner properties say how far a corner's rectangles reach, not how much room is left beside
775
+ them. To know whether a row of your own buttons fits beside the Gem, read the rectangles from
776
+ script: the room to the right of the top-left ones is the frame's width less the furthest right
777
+ edge among them.
797
778
 
798
779
  ```js
799
780
  const reserved = gem.viewport?.reserved ?? [];
800
- const clearLeft = reserved.length ? Math.min(...reserved.map((r) => r.x)) : window.innerWidth;
801
- nav.classList.toggle('below-arcade-row', clearLeft < nav.offsetWidth + 8);
781
+ const topLeft = reserved.filter((r) => r.x + r.width / 2 < window.innerWidth / 2);
782
+ const from = topLeft.length ? Math.max(...topLeft.map((r) => r.x + r.width)) : 0;
783
+ nav.classList.toggle('below-arcade-row', window.innerWidth - from < nav.offsetWidth + 8);
802
784
  ```
803
785
 
804
786
  All eight properties are written on every push, `0px` for a clear corner, so a rotation never leaves
805
787
  a stale value; they are never set under an embedder that sends no viewport, which is what the `0px`
806
788
  fallback is for. `gem.viewport.reserved` is `[]` when nothing is covered.
807
789
 
808
- **Lay out against it whenever it changes.** The wallets' rectangles are there for the whole
809
- session on the Arcade's phone layout, and their number and width can change as the player's
810
- balances and currencies do. Read every corner, not only the ones this page names today: a layout that honours
811
- all four is right under any embedder.
790
+ **Lay out against it whenever it changes.** The Gem button's rectangle is there for the whole
791
+ session, and it moves with a rotation, a resize or the frame-rate readout. Read every corner, not
792
+ only the one this page names today: a layout that honours all four is right under any embedder.
812
793
 
813
794
  **Older SDKs get it folded into the top inset.** A game on an SDK from before reserved areas cannot
814
795
  read the rectangles, so the arcade sends it none and instead raises `insets.top` — and so
@@ -1021,7 +1002,7 @@ gem.controls.declare({
1021
1002
  });
1022
1003
  ```
1023
1004
 
1024
- It is screen state, like [`gem.setWalletVisible`](#the-arcades-wallet-shown-unless-you-hide-it-never-drawn):
1005
+ It is screen state, like [`gem.setWalletVisible`](#the-arcades-wallet-in-the-gem-menu-never-drawn-by-you):
1025
1006
  each call is the whole answer, the latest wins, and the SDK holds it and sends it again after a
1026
1007
  reconnect. It returns `false` before the bridge is up (it is held and sent on connect) and under an
1027
1008
  embedder that does not show these settings; it never throws. A key or a value other than these is
@@ -1088,9 +1069,9 @@ function frame(dt) {
1088
1069
 
1089
1070
  ## The Arcade's menu
1090
1071
 
1091
- The Arcade keeps one menu button over every game, on every device. Its menu is how a player leaves
1092
- (**Return to the Arcade**), mutes, goes fullscreen, reports a problem and changes their Arcade-wide
1093
- settings — the ones that reach you as [`gem.prefs.recommended`](#game-settings). You can add up to
1072
+ The Arcade keeps one button over every game, on every device: the Gem, at the top-left. Its menu is
1073
+ how a player leaves (**Return to the Arcade**), sees their Gems, Tickets and achievement score, mutes,
1074
+ goes fullscreen, reports a problem and changes their Arcade-wide settings — the ones that reach you as [`gem.prefs.recommended`](#game-settings). You can add up to
1094
1075
  four entries of your own:
1095
1076
 
1096
1077
  ```js
@@ -1207,28 +1188,24 @@ its music out than cut it, say. The Arcade still shows its button for your game
1207
1188
  so this is a promise: your `onPrefs` handler must go quiet on `muted: true` and come back on `false`,
1208
1189
  and the release checklist checks that it does.
1209
1190
 
1210
- ## The Arcade's wallet: shown unless you hide it, never drawn
1191
+ ## The Arcade's wallet: in the Gem menu, never drawn by you
1211
1192
 
1212
1193
  The player's platform balances — Gems, Tickets (`ARCADE_TICKETS`) and their achievement score —
1213
1194
  belong to the Arcade. **Your game never draws one**, and never shows a pending state for one: the
1214
- Arcade takes every figure from the platform and draws the wallets itself, in the middle of the row
1215
- across the top of your frame on a phone, with its menu button at the right end.
1216
-
1217
- **By default the Arcade shows every wallet the whole time, during play too.** They are small,
1218
- translucent chips in the middle of the top row, and while shown they are
1219
- [reserved rectangles](#the-arcades-own-controls-reserved-areas): lay every screen out below both
1220
- `--gem-reserved-tl-height` and `--gem-reserved-tr-height`. A game that calls nothing keeps them.
1221
-
1222
- **A game may hide them for gameplay** (honoured again since 2026-10-08): call
1223
- `gem.setWalletVisible(false)` when play starts and `gem.setWalletVisible(true)` when a menu opens.
1224
- While hidden, their rectangles leave `gem.viewport.reserved` and the top row is the game's; the
1225
- Arcade still pops a wallet up for a moment when something happens to it (a reward you cued, a
1226
- spend, a landing), floating over the game without moving anything. This applies on a phone, where
1227
- the wallets sit over your game; where the Arcade docks them beside the frame it changes nothing.
1228
- Read the `--gem-reserved-*` properties rather than assuming either state.
1229
-
1230
- ⚠️ **The Arcade ignores the `only` option**: a shown wallet is every wallet. Do not build a store
1231
- screen that relies on narrowing them to one currency.
1195
+ Arcade takes every figure from the platform and shows them itself.
1196
+
1197
+ **The Gem Arcade draws no wallet over your game** (since 2026-10-11). Nothing of it sits in your top
1198
+ row, at rest or when a balance moves. The player opens the Gem menu — the Gem button at the
1199
+ top-left — to see their Gems, Tickets and achievement score, and every payout
1200
+ [`gem.cueReward`](inventory-and-catalogs.md#showing-the-reward-land-in-the-arcades-wallet) announces
1201
+ flies into the Gem button. A payout you do not cue flies too, from the middle of your frame, so cue
1202
+ the ones the player earns on screen and the flight starts where they are looking.
1203
+
1204
+ **`gem.setWalletVisible` changes nothing on the Gem Arcade.** It is still part of the contract, so a
1205
+ game that calls it keeps working, and it is the call to make for an embedder that draws wallets over
1206
+ games: hide them while you play, show them on your menus. Under the Gem Arcade there is no wallet to
1207
+ show or hide and no wallet rectangle in `gem.viewport.reserved`. The `only` option is ignored there
1208
+ as well.
1232
1209
 
1233
1210
  ## No accidental text selection
1234
1211
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indiegems/gem-web-sdk",
3
- "version": "10.3.0",
3
+ "version": "10.3.1",
4
4
  "description": "postMessage bridge contract between gem-web and browser-playable games",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -2437,9 +2437,10 @@
2437
2437
  "$comment": [
2438
2438
  "A platform-currency reward is on its way — the game's SERVER has just",
2439
2439
  "moved (or is about to move) a progression mapped onto a platform currency,",
2440
- "and the game would like the arcade's wallet to show it landing: a pending",
2441
- "state now and, when the platform confirms the grant, the currency flying",
2442
- "from `origin` into the wallet.",
2440
+ "and the game would like the arcade to show it landing: the currency flying",
2441
+ "from `origin` into the arcade's chrome — in the Gem Arcade, into its Gem",
2442
+ "button at the frame's top-left — and the total moving when the platform",
2443
+ "confirms the grant.",
2443
2444
  "",
2444
2445
  "A PRESENTATION CUE, NOT A CLAIM. Nothing here is trusted as a number. The",
2445
2446
  "amount that lands and the player's new total reach the parent from gem-api",
@@ -2452,7 +2453,8 @@
2452
2453
  "`origin` is where the flight starts, in CSS px of the frame's own",
2453
2454
  "coordinate space — the same space `gem.viewport` speaks — measured from",
2454
2455
  "the frame's top-left corner; the parent translates it into its own page.",
2455
- "Absent, the arcade animates at the wallet alone. Integers, like",
2456
+ "Absent, the Gem Arcade flies the confirmed grant from the middle of the",
2457
+ "frame, as it does a grant no cue announced. Integers, like",
2456
2458
  "`gem.viewport`'s insets: a fractional pixel is not a placement, and the",
2457
2459
  "SDK rounds and clamps on the way out. 16384 is a bound, not a size.",
2458
2460
  "",
@@ -2472,10 +2474,9 @@
2472
2474
  "other, `gem.cueReward` returns false and the game does NOTHING. There is",
2473
2475
  "no fallback celebration: Gems display belongs to the arcade (the",
2474
2476
  "creator's ruling, 2026-09-24), so a game draws no Gems flight, counter or",
2475
- "celebration of its own. The same holds for Tickets (`ARCADE_TICKETS`): the",
2476
- "arcade's wallet shows Gems and Tickets side by side and flies a payout",
2477
- "into the one `currencySlug` names. `origin` is the centre of the game's icon for",
2478
- "that currency — its gem, or its ticket."
2477
+ "celebration of its own. The same holds for Tickets (`ARCADE_TICKETS`):",
2478
+ "`currencySlug` decides what flies and which total moves. `origin` is the",
2479
+ "centre of the game's icon for that currency — its gem, or its ticket."
2479
2480
  ],
2480
2481
  "fields": {
2481
2482
  "currencySlug": { "kind": "string", "maxLength": 32 },
@@ -2531,6 +2532,12 @@
2531
2532
  "docks its wallets beside the frame rather than over it, this changes",
2532
2533
  "nothing.",
2533
2534
  "",
2535
+ "THE GEM ARCADE DRAWS NO WALLET OVER A GAME (since 2026-10-11): the player",
2536
+ "sees their balances in its Gem menu and payouts fly into its Gem button, so",
2537
+ "it advertises this message, accepts it, and changes nothing on screen — no",
2538
+ "wallet is shown, popped up or reserved whatever the game says. The rules",
2539
+ "above are for a parent that does draw wallets over the frame.",
2540
+ "",
2534
2541
  "A PRESENTATION REQUEST ONLY. Not an authorization control, and it carries no",
2535
2542
  "numbers: the parent takes every figure it shows from the platform. A game",
2536
2543
  "never draws a platform balance itself and never implements a pending state.",