studio-engine 0.54.0 → 0.55.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3419d6ec43e811060b90f6e628feabc249bb6790f9b911c258512ca2fa13f87e
4
- data.tar.gz: e91ce80dcd5465ce9660091cb7570327322e1a9aff79d115f4ba0116a7da4a38
3
+ metadata.gz: 203b2f8cf1001d19c7ffb24c778ab0f1bdcb0b9aafa59762ded0ea5689eb2423
4
+ data.tar.gz: a6dbf4164a79cd6b5de2a9cbee178e5455e55c619dfa7197f0db08ba398aaf5b
5
5
  SHA512:
6
- metadata.gz: 308d06c9339512b02da78a7c5877134a91b38f20cb89f6e4692b1f734839250a03d15fd1cdea463255ffe49b2e7a675d8f95624cbaf1e4f275ae4ddc83e7b480
7
- data.tar.gz: f920799c11d5fdb4ad8757e4afedea52592dcce1d103e7a53f5e666cf62c386994fc9d2d0bb284ea3530840291c5e375fb2f5d279e537b4253c24a60838319e8
6
+ metadata.gz: 0bb5c9bebe4977fef13ab139729ebbc5c560b52f31e573d153e63a00a8a40b970519ac783ad51b45773661e182f5dc848e424b4922e5748117c29560fdfc2b20
7
+ data.tar.gz: 4e16f3663bb43a61139cac420af9a2c265f91c5c5a6f708c32edf1ad5d1e92c6a559b545b148b4e134afe90d614a81de527906988a122b8326b9ae9ef881e6be
data/CHANGELOG.md CHANGED
@@ -6,6 +6,68 @@ The format is [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). This pro
6
6
 
7
7
  ### Added
8
8
 
9
+ - **`.studio-team-glow` rings a host that paints its own background**, and can
10
+ carry **two colors**.
11
+
12
+ The ring previously needed an opaque CHILD in front to cover its middle,
13
+ because both wedge layers are pseudo-elements at `z-index: -1 / -2` and CSS
14
+ paints an element's background BEFORE its negative-z descendants. A live board
15
+ card cannot supply that child: Turbo targets the card element itself for
16
+ replace and remove, so a wrapper host is orphaned every time a card leaves the
17
+ board. The primitive now cuts the host's own box out of both layers
18
+ (`padding` + `mask-composite`, the trick §1's `.studio-border-glow` already
19
+ used), so the ring works on the card directly.
20
+
21
+ **No-op for the wrapper shape** — its child was already covering that
22
+ interior. Verified side by side against both live consumers
23
+ (`style/_modal_specimen` and the hub's release-phase-meter): pixel-equivalent
24
+ before and after.
25
+
26
+ `--studio-team-glow-color-b` colors the SECOND of the two opposed wedges and
27
+ defaults to the first, so one-color callers see no change and a caller with a
28
+ pair to show — a Pokémon's two types — gets one per wedge.
29
+
30
+ The bloom twin needed care: a mask applies AFTER a filter, so its box carries a
31
+ transparent border twice the blur radius and its wedges stop at the padding
32
+ box. Without that room the halo ends on a hard line at its own edge.
33
+
34
+ ### Fixed
35
+
36
+ - **`.conic-surface` keeps its wash inside its own box.** The wash was an
37
+ OVERSIZED pseudo (`inset: -50%`) spun by a `transform` keyframe, cut back to
38
+ the element by the host's `overflow: hidden`. That clip is not dependable: the
39
+ rotating child is composited, and a `backdrop-filter` in its compositing path
40
+ drops it. The `.surface-glass` specimen — a backdrop-filter child of the wash
41
+ itself — is exactly that path, and on admin/style in Chromium the wash escaped
42
+ as a rotated slab across BOTH conic specimens.
43
+
44
+ The element no longer moves. The pseudo sits at `inset: 0` with
45
+ `border-radius: inherit`, and the sweep animates a registered
46
+ `--conic-surface-angle` inside the gradient — the technique §9b already used.
47
+ Nothing extends past the box, the rounded corners come from the pseudo, and no
48
+ clip has to hold. Same picture, one fewer thing that can fail.
49
+ `overflow: hidden` stays for the host's CONTENT.
50
+
51
+ The trade, stated: a registered-property animation repaints on the main thread
52
+ where a transform rode the compositor. At the default 16s sweep that is cheap,
53
+ and §9b already pays it at 4s.
54
+
55
+ - **`.studio-team-glow` is demoed and documented as the wrapper it is.** Its two
56
+ wedge layers are pseudos at z-index -1/-2, and CSS paints an element's own
57
+ background BEFORE its negative-z descendants — so a background on the glow HOST
58
+ is covered BY the wedges, not the other way round, and the ring becomes a wash
59
+ across the whole card face. What covers the middle is an opaque CHILD, which
60
+ paints later; that is TM's `holo-wrap` / `holo-card` split, and what both real
61
+ consumers already ship.
62
+
63
+ The §9b comment claimed the opposite ("host needs an opaque background"), and
64
+ the Effects specimen followed it, so the style guide showed two washed slabs
65
+ where the selection ring belongs. The specimen, its copyable snippet, and the
66
+ contract comment now all state the same thing. The primitive's geometry is
67
+ unchanged — the consumers tuned against it are untouched.
68
+
69
+ ### Added
70
+
9
71
  - **`studio/fields/_date_of_birth`** — the engine's one date-of-birth field,
10
72
  three selects (Month / Day / Year). Rendered by
11
73
  `studio/modals/blocks/_age_verify` and by `/profile/edit`'s birthday row.
@@ -507,26 +507,56 @@
507
507
  }
508
508
 
509
509
  /* =============================================================================
510
- 9b. studio-team-glow — single-color rotating "selected card" ring glow
510
+ 9b. studio-team-glow — rotating "selected card" ring glow, one or two colors
511
511
  Ported from turf-monster's per-team selected-card glow (.holo-border-glow):
512
- a single-color conic-gradient ring rotates around the element's edge, with a
513
- blurred bloom twin behind it. DISTINCT from .studio-border-glow (an animated
514
- RAINBOW border) and .studio-glow (a static soft box-shadow halo) — this is the
515
- "this card is selected / live" ring, tinted one color.
512
+ a conic-gradient ring rotates around the element's edge, with a blurred bloom
513
+ twin behind it. DISTINCT from .studio-border-glow (an animated RAINBOW border)
514
+ and .studio-glow (a static soft box-shadow halo) — this is the "this card is
515
+ selected / live" ring.
516
516
 
517
517
  The color is a CSS var (default the CTA role, so purple on McRitchie Studio),
518
- just like TM's per-team --glow-c. The wedge is swept by animating a registered
518
+ just like TM's per-team --glow-c. TWO opposed wedges travel the edge, and they
519
+ can carry two colors: --studio-team-glow-color-b defaults to the first, so a
520
+ one-color caller sees no change, and a caller with a pair to show (a Pokémon's
521
+ two types) gets one per wedge. The wedges are swept by animating a registered
519
522
  @property angle (rotating the GRADIENT, not the element — so no oversized-child
520
523
  clipping trick is needed). Opacity is a var (--studio-team-glow-opacity) with a
521
524
  transition, so a consumer can fade the glow in/out (the living style guide
522
525
  slides it between step cards as a modal's step machine advances).
523
526
 
524
- Host needs an opaque background (the ring shows only around the edge) and must
525
- NOT be clipped by an overflow-hidden ancestor near its border.
527
+ THE HOST MAY CARRY ITS OWN BACKGROUND — the ring cuts the host's box out of
528
+ both wedge layers, so only the band around the edge paints. That hole is what
529
+ makes the primitive work in the two shapes its consumers need:
530
+
531
+ · the WRAPPER shape (TM's holo-wrap / holo-card split) — a bare host with an
532
+ opaque child in front. The engine's style/_modal_specimen and the hub's
533
+ release-phase-meter both ship this. Unchanged by the hole: the child was
534
+ already covering that interior.
535
+ · the CARD shape — the host IS the opaque surface. This is what a live board
536
+ card needs, because it cannot take a wrapper at all: Turbo targets the card
537
+ element for both replace and remove, so a wrapper is orphaned every time a
538
+ card leaves the board.
539
+
540
+ Without the hole the card shape is impossible, and not for a tunable reason:
541
+ both layers are pseudo-elements at z-index -1 / -2, and CSS paints an element's
542
+ own background FIRST, then its negative-z descendants ON TOP of it (CSS 2.1
543
+ Appendix E, steps 1 and 2) — so a background on the host is covered BY the
544
+ wedges, and the ring becomes a wash across the whole face. Only a child, or
545
+ this hole, can cover the middle.
546
+
547
+ The host must still NOT be clipped by an overflow-hidden ancestor near its
548
+ border, or the ring is cut off with it.
526
549
 
527
550
  Usage: <div class="studio-team-glow rounded-xl bg-surface p-5">Selected</div>
528
- red glow: style="--studio-team-glow-color: #E11D48"
529
- Tune: --studio-team-glow-color / -opacity / -speed / -thickness / -bloom
551
+ wrapper shape, when the face is its own element:
552
+ <div class="studio-team-glow rounded-xl">
553
+ <div class="rounded-xl bg-surface p-5">Selected</div>
554
+ </div>
555
+ red glow: style="--studio-team-glow-color: #E11D48"
556
+ two types: style="--studio-team-glow-color: #F08030;
557
+ --studio-team-glow-color-b: #6890F0"
558
+ Tune: --studio-team-glow-color / -color-b / -opacity / -speed / -thickness /
559
+ -bloom
530
560
  ========================================================================== */
531
561
  @property --studio-team-glow-angle {
532
562
  syntax: "<angle>";
@@ -535,6 +565,11 @@
535
565
  }
536
566
  .studio-team-glow {
537
567
  --studio-team-glow-color: var(--color-cta);
568
+ /* The SECOND wedge's color. Defaults to the first, so a one-color caller sees
569
+ no change; a caller with two colors to show (a Pokémon's two types, a pair of
570
+ brand colors) gets one per wedge. Resolved on this element, so an inline
571
+ --studio-team-glow-color override feeds this default too. */
572
+ --studio-team-glow-color-b: var(--studio-team-glow-color);
538
573
  --studio-team-glow-opacity: 1;
539
574
  --studio-team-glow-speed: 4s;
540
575
  --studio-team-glow-thickness: 4px;
@@ -559,14 +594,47 @@
559
594
  var(--studio-team-glow-color) 12%,
560
595
  transparent 33%,
561
596
  transparent 50%,
562
- var(--studio-team-glow-color) 62%,
597
+ var(--studio-team-glow-color-b) 62%,
563
598
  transparent 83%
564
599
  );
565
600
  animation: studio-team-glow-spin var(--studio-team-glow-speed) linear infinite;
601
+ /* THE HOST'S OWN BOX IS PUNCHED OUT of both wedge layers, so what paints is the
602
+ band around the edge and nothing else. `padding` makes each layer's CONTENT
603
+ box exactly the host's box; mask-composite then removes that box from the
604
+ layer — the same mask trick §1's .studio-border-glow uses.
605
+ Why it is here: an opaque child in front covers the middle only when the host
606
+ CAN take a child. A live board card cannot — Turbo targets the card element
607
+ itself for replace and remove, so a wrapper is orphaned on every remove. With
608
+ the hole cut here the ring rides the card directly. For a wrapper host this
609
+ changes nothing visible: the child was already covering that interior. */
610
+ padding: var(--studio-team-glow-thickness);
611
+ -webkit-mask:
612
+ linear-gradient(#000 0 0) content-box,
613
+ linear-gradient(#000 0 0);
614
+ -webkit-mask-composite: xor;
615
+ mask:
616
+ linear-gradient(#000 0 0) content-box,
617
+ linear-gradient(#000 0 0);
618
+ mask-composite: exclude;
566
619
  }
567
620
  .studio-team-glow::after {
568
- /* Blurred bloom twin, a touch larger. */
569
- inset: calc(-1 * (var(--studio-team-glow-thickness) + 4px));
621
+ /* Blurred bloom twin, a touch larger: its wedges reach 4px PAST the ring, which
622
+ is what makes the bloom read as a halo, not a soft edge on the ring. Drop the
623
+ 4px and every WRAPPER consumer's ring visibly lightens (measured: 26% of the
624
+ pixels on style/_modal_specimen, 13% on the hub's release-phase-meter). The
625
+ box then carries a transparent BORDER of bloom-reach on top of that, and the
626
+ mask still holes out the host's box — so the blur
627
+ spreads outward into that reach and is cut where it has already faded, while
628
+ the inward half is cut at the host's edge (invisible: that edge is either the
629
+ card's own or the wrapper child's). Mask applies AFTER filter, which is why
630
+ the reach has to out-measure the blur — without it the halo ends on a hard
631
+ line at the layer's own box. */
632
+ inset: calc(-1 * (var(--studio-team-glow-thickness) + 4px + var(--studio-team-glow-bloom) * 2));
633
+ padding: calc(var(--studio-team-glow-thickness) + 4px);
634
+ border: calc(var(--studio-team-glow-bloom) * 2) solid transparent;
635
+ /* The wedges stop at the padding box (host + ring + the 4px); the border is empty
636
+ room the blur is allowed to spread into. */
637
+ background-clip: padding-box;
570
638
  z-index: -2;
571
639
  filter: blur(var(--studio-team-glow-bloom)) saturate(1.35);
572
640
  }
@@ -604,12 +672,36 @@
604
672
  11. conic-surface — slow rotating conic-gradient wash (authored fresh)
605
673
  A subtle animated ambient background for hero panels / empty states: a conic
606
674
  gradient sweeps between two themed stops (CTA -> surface by default) on a slow
607
- rotation. The gradient lives on a ::before that rotates, so content kept above
608
- it stays crisp. The element's radius clips the wash; give it one.
675
+ rotation. The gradient lives on a ::before behind the content, so content kept
676
+ above it stays crisp.
677
+
678
+ THE WASH IS CONTAINED BY CONSTRUCTION, NOT BY A CLIP. The first cut rotated an
679
+ OVERSIZED child (`inset: -50%` + `transform: rotate`) and leaned on the host's
680
+ `overflow: hidden` to cut it back to the box. That clip is not dependable: the
681
+ rotating child is composited, and a `backdrop-filter` anywhere in its
682
+ compositing path (its OWN .surface-glass child on the style guide, or an
683
+ unrelated overlay elsewhere on the page) drops the clip — the wash then paints
684
+ outside the box as a rotated slab. Observed on admin/style in Chromium, on both
685
+ conic specimens, with the .surface-glass demo the reliable trigger.
686
+
687
+ So the element never moves. The ::before sits at `inset: 0` with
688
+ `border-radius: inherit`, and the sweep animates a registered @property angle
689
+ inside the gradient — the same technique §9b uses. Nothing extends past the
690
+ box, the rounded corners come from the pseudo itself, and no clip has to hold.
691
+ `overflow: hidden` stays for the host's CONTENT, not for the wash.
692
+
693
+ The cost of the trade, stated: a registered-property animation repaints the
694
+ gradient on the main thread each frame, where a transform rode the compositor.
695
+ At the default 16s sweep that is cheap, and §9b already pays it at 4s.
609
696
 
610
697
  Usage: <div class="conic-surface rounded-2xl p-8"> ...content... </div>
611
698
  Tune: --conic-surface-from / --conic-surface-to / --conic-surface-duration
612
699
  ========================================================================== */
700
+ @property --conic-surface-angle {
701
+ syntax: "<angle>";
702
+ inherits: false;
703
+ initial-value: 0deg;
704
+ }
613
705
  .conic-surface {
614
706
  position: relative;
615
707
  isolation: isolate;
@@ -619,10 +711,11 @@
619
711
  .conic-surface::before {
620
712
  content: "";
621
713
  position: absolute;
622
- inset: -50%;
714
+ inset: 0;
715
+ border-radius: inherit;
623
716
  z-index: -1;
624
717
  background: conic-gradient(
625
- from 0deg,
718
+ from var(--conic-surface-angle),
626
719
  var(--conic-surface-from, var(--color-cta)),
627
720
  var(--conic-surface-to, var(--color-surface)),
628
721
  var(--conic-surface-from, var(--color-cta))
@@ -631,7 +724,7 @@
631
724
  }
632
725
 
633
726
  @keyframes conic-surface-spin {
634
- to { transform: rotate(360deg); }
727
+ to { --conic-surface-angle: 360deg; }
635
728
  }
636
729
 
637
730
  /* =============================================================================
@@ -27,8 +27,11 @@
27
27
  JS — the three selects. `alpine` comes from the enclosing
28
28
  studioProfileForm and is true only once that component has booted.
29
29
  %>
30
- <label class="block text-sm text-secondary mb-2 font-medium" for="profile_birthday">Date of birth</label>
31
-
30
+ <%# NO FIELD LABEL HERE, deliberately (operator's call, 2026-08-15). The row is
31
+ already titled "Birthday" by the section wrapper, and the three selects carry
32
+ their own MONTH / DAY / YEAR labels — a "Date of birth" line between the two
33
+ said the same thing a third time. The no-JS <input type="date"> keeps its id
34
+ so a label elsewhere could still point at it. %>
32
35
  <%
33
36
  y = user.birth_year
34
37
  m = user.birth_month
@@ -48,8 +51,27 @@
48
51
  <template x-if="alpine">
49
52
  <div>
50
53
  <%# The value the form actually submits. The selects write here; nothing
51
- types into it. %>
52
- <input type="hidden" name="profile[birthday]" :value="isoValue">
54
+ types into it.
55
+
56
+ THE NAME IS BOUND, AND THAT IS THE WHOLE POINT. A partly-filled date
57
+ has no ISO value, and submitting a BLANK birthday is not "no change" to
58
+ this controller — it is DELETE, and it clears all three columns on
59
+ purpose (see #birthday_attributes: someone deleting their birthday
60
+ means it). Those two facts met in a data-loss bug: a stored Jan 31,
61
+ switch the month to February, onMonthChange blanks the 31st because
62
+ February has no 31st, and the form is now one Save away from wiping a
63
+ birthday the person never asked to delete.
64
+
65
+ On THIS path a blank is always an edit in progress and never an
66
+ intentional clear, because the selects offer no empty option — once a
67
+ part is set the user cannot unset it. The intentional clear lives on
68
+ the no-JS <input type="date"> above, where it is a real gesture.
69
+
70
+ So while the date is incomplete the field submits NOTHING: Alpine
71
+ removes an attribute bound to false, an input with no name is not
72
+ submitted, and the controller's `return {} if raw.nil?` makes an absent
73
+ param a no-op. The birthday is left exactly as it was. %>
74
+ <input type="hidden" :name="complete ? 'profile[birthday]' : false" :value="isoValue">
53
75
 
54
76
  <%= render "studio/fields/date_of_birth" %>
55
77
  </div>
@@ -82,12 +82,64 @@
82
82
  this.publish();
83
83
  },
84
84
 
85
- // `fields` belongs to the enclosing studioProfileForm. Alpine's scope chain
86
- // makes it reachable and it is the SAME object, so assigning through it is
87
- // what raises the save bar. Without this the field would set a value the
88
- // dirty check never notices.
85
+ // WHAT THE DIRTY CHECK IS SHOWN, and why it is not isoValue.
86
+ //
87
+ // isoValue is "" for EVERY incomplete date, so publishing it made a whole
88
+ // class of edit invisible: on an empty birthday, choosing a month wrote ""
89
+ // over "" and the save bar never appeared. The operator reported exactly
90
+ // that. Choosing a month IS a change — the form just had no way to see it.
91
+ //
92
+ // So the signal is the three parts, which differ whenever any one of them
93
+ // does. It stays equal to isoValue for a COMPLETE date (same string, same
94
+ // shape) so a finished edit compares correctly against the value the page
95
+ // loaded with, and Discard restores it to that same string.
96
+ //
97
+ // `fields` belongs to the enclosing studioProfileForm — Alpine's scope
98
+ // chain makes it reachable and it is the SAME object, so assigning through
99
+ // it is what raises the save bar.
100
+ // THE EMPTY CASE IS NOT A PARTIAL ONE, and conflating them makes the page
101
+ // arrive already dirty. studioProfileForm's initial.birthday is "" for a
102
+ // person with no birthday on file, so an untouched empty field must also
103
+ // read "" — joining three blanks gives "--", which compares as a change and
104
+ // would raise the save bar on load, before anyone touched anything.
105
+ get signature() {
106
+ if (this.complete) return this.isoValue;
107
+ if (!this.year && !this.month && !this.day) return "";
108
+ return [this.year, this.month, this.day].join("-");
109
+ },
110
+
89
111
  publish() {
90
- if (this.fields) this.fields.birthday = this.isoValue;
112
+ if (this.fields) this.fields.birthday = this.signature;
113
+ },
114
+
115
+ // DISCARD MUST REACH THE SELECTS. studioProfileForm#discard reassigns its
116
+ // `fields` object, which restores every input bound with x-model — and the
117
+ // three selects are not, because they are bound to THIS component's own
118
+ // month/day/year. So Discard used to leave them showing the abandoned edit
119
+ // while the bar disappeared, and the hidden input went on carrying it: the
120
+ // next save would write the change the user had just discarded.
121
+ //
122
+ // Watching `fields.birthday` is what joins them. Discard sets it back to
123
+ // the initial string, this fires, and the selects follow — and because the
124
+ // guard below returns early when the value already matches, the publish →
125
+ // watch → publish path cannot loop.
126
+ init() {
127
+ var self = this;
128
+ this.publish();
129
+ this.$watch("fields.birthday", function (value) {
130
+ if (value === self.signature) return;
131
+ self.adopt(value);
132
+ });
133
+ },
134
+
135
+ // Takes an ISO date (or a blank) and puts the selects on it. Anything that
136
+ // is not a full date empties all three, which is what an initial blank and
137
+ // a cleared birthday both mean.
138
+ adopt(value) {
139
+ var m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(String(value || ""));
140
+ this.year = m ? String(+m[1]) : "";
141
+ this.month = m ? String(+m[2]) : "";
142
+ this.day = m ? String(+m[3]) : "";
91
143
  }
92
144
  };
93
145
  };
@@ -272,7 +272,7 @@
272
272
  <h3 class="text-xl font-bold text-heading">Effects</h3>
273
273
  <p class="text-muted text-sm">
274
274
  The <code class="font-mono text-2xs">engine-motion.css</code> visual-effect primitives beyond motion -
275
- gradient text, a soft glow halo, a single-color rotating <strong>selection glow</strong>
275
+ gradient text, a soft glow halo, a one- or two-color rotating <strong>selection glow</strong>
276
276
  (ported from Turf Monster's selected-team-card ring), frosted glass, and a conic wash. Each is
277
277
  themed through the role tokens and tunable via CSS-var knobs.
278
278
  </p>
@@ -297,12 +297,18 @@
297
297
  </div>
298
298
  <% end %>
299
299
 
300
+ <%# The CARD shape: the host carries its own background and the ring still
301
+ rings, because the primitive punches the host's box out of both wedge
302
+ layers. The WRAPPER shape (bare host + opaque child) is staged by the
303
+ Modals section's glow cards — both are documented in engine-motion.css
304
+ §9b. Two wedges travel the edge, so a pair of colors reads as a pair. %>
300
305
  <%= render layout: "style/specimen",
301
- locals: { klass: ".studio-team-glow (knob: --studio-team-glow-color)",
302
- usage: %(<div class="studio-team-glow rounded-xl bg-surface p-5">Selected</div>\n<div class="studio-team-glow rounded-xl bg-surface p-5" style="--studio-team-glow-color: #E11D48">Ravens</div>) } do %>
306
+ locals: { klass: ".studio-team-glow (knobs: --studio-team-glow-color / -color-b)",
307
+ usage: %(<div class="studio-team-glow rounded-xl bg-surface p-5">Selected</div>\n<div class="studio-team-glow rounded-xl bg-surface p-5"\n style="--studio-team-glow-color: #F08030; --studio-team-glow-color-b: #6890F0">Fire / Flying</div>) } do %>
303
308
  <div class="flex flex-wrap items-center justify-center gap-6">
304
309
  <div class="studio-team-glow rounded-xl bg-surface border border-subtle px-5 py-4 text-sm font-semibold text-heading text-center">Selected</div>
305
- <div class="studio-team-glow rounded-xl bg-surface border border-subtle px-5 py-4 text-sm font-semibold text-heading text-center" style="--studio-team-glow-color: #E11D48">Ravens</div>
310
+ <div class="studio-team-glow rounded-xl bg-surface border border-subtle px-5 py-4 text-sm font-semibold text-heading text-center"
311
+ style="--studio-team-glow-color: #F08030; --studio-team-glow-color-b: #6890F0">Fire / Flying</div>
306
312
  </div>
307
313
  <% end %>
308
314
 
@@ -1,3 +1,3 @@
1
1
  module Studio
2
- VERSION = "0.54.0"
2
+ VERSION = "0.55.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: studio-engine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.54.0
4
+ version: 0.55.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex McRitchie