JuanCS-Dev commited on
Commit
f679dc2
·
verified ·
1 Parent(s): 16773d9

feat: O6 Mah feminine Byte

Browse files
dashboard/features/streamer/mah.svg.js CHANGED
@@ -1,58 +1,46 @@
1
  // dashboard/features/streamer/mah.svg.js
2
- // O6 — Mah's avatar artwork. Pure, scalable SVG (sized by CSS), same viewBox
3
- // scale as Byte so the duo reads as a pair. HOMAGE to her signature motifs —
4
- // cow-print bucket hat (the "Mahmoojen = moo" pun), big round glasses, chibi
5
- // face with rosy cheeks — drawn fresh in our language. NOT a copy of her
6
- // commissioned emote (that art is the artist's IP).
7
 
8
- // Mouth shape per state (mirrors Byte's vocabulary so the pair feels coherent).
9
  export const MOUTH_PATHS = Object.freeze({
10
- unseen: "M20 38 h8",
11
- idle: "M20 38 h8",
12
- neutral: "M20 38 h8",
13
- happy: "M20 37 Q24 41 28 37",
14
- hype: "M19 36 Q24 43 29 36 Z",
15
- sad: "M20 40 Q24 36 28 40",
16
- talking: "M21 37 q3 4 6 0 q-3 2 -6 0 Z",
17
  });
18
 
19
  export const MAH_SVG = `
20
- <svg class="mah-figure" viewBox="0 0 48 52" role="img" aria-label="Mah">
21
- <!-- hair (frames the face) -->
22
- <path class="mah-hair" d="M10 30 Q9 14 24 13 Q39 14 38 30 L38 40 Q38 47 31 47 L17 47 Q10 47 10 40 Z" fill="#2b2440" />
23
- <!-- twin buns + red scrunchies (her red accent, from the cards) -->
24
- <circle class="mah-bun" cx="11" cy="20" r="4.5" fill="#2b2440" />
25
- <circle class="mah-bun" cx="37" cy="20" r="4.5" fill="#2b2440" />
26
- <circle class="mah-tie" cx="13" cy="23.5" r="2.2" fill="#e23b5a" />
27
- <circle class="mah-tie" cx="35" cy="23.5" r="2.2" fill="#e23b5a" />
28
- <!-- face -->
29
- <rect class="mah-face" x="13" y="20" width="22" height="24" rx="11" fill="#f1c9a4" />
30
- <!-- cow-print bucket hat (signature) -->
31
- <g class="mah-hat">
32
- <path class="mah-hat-brim" d="M7 19 Q24 13 41 19 Q41 23 24 23 Q7 23 7 19 Z" fill="#ffffff" stroke="#1e1430" stroke-width="0.8" />
33
- <path class="mah-hat-top" d="M11 19 Q11 7 24 7 Q37 7 37 19 Q24 16 11 19 Z" fill="#ffffff" stroke="#1e1430" stroke-width="0.8" />
34
- <ellipse class="mah-spot" cx="18" cy="13" rx="2.6" ry="2" fill="#1e1430" />
35
- <ellipse class="mah-spot" cx="30" cy="12" rx="2.1" ry="1.7" fill="#1e1430" />
36
- <ellipse class="mah-spot" cx="26" cy="17" rx="1.5" ry="1.2" fill="#1e1430" />
37
- <!-- tiny cow ears -->
38
- <ellipse cx="10" cy="14" rx="2.4" ry="1.6" fill="#f1c9a4" transform="rotate(-25 10 14)" />
39
- <ellipse cx="38" cy="14" rx="2.4" ry="1.6" fill="#f1c9a4" transform="rotate(25 38 14)" />
40
- <!-- little red bow on the hat (her accent) -->
41
- <path class="mah-bow" d="M24 19 l-3.5 -2.2 v4.4 Z M24 19 l3.5 -2.2 v4.4 Z" fill="#e23b5a" />
42
- <circle cx="24" cy="19" r="1.1" fill="#b5283f" />
43
  </g>
44
- <!-- rosy cheeks (revealed on happy/hype) -->
45
- <circle class="mah-cheek left" cx="16.5" cy="35" r="2.3" fill="#ff8fb6" />
46
- <circle class="mah-cheek right" cx="31.5" cy="35" r="2.3" fill="#ff8fb6" />
47
- <!-- round glasses -->
48
- <g class="mah-glasses" fill="#fbfcff" stroke="#1e1430" stroke-width="1.4">
49
- <circle cx="18.5" cy="31" r="5.2" />
50
- <circle cx="29.5" cy="31" r="5.2" />
51
- <line x1="23.7" y1="31" x2="24.3" y2="31" />
 
52
  </g>
53
- <!-- eyes (behind the lenses) -->
54
- <circle class="mah-eye left" cx="18.5" cy="31" r="1.7" fill="#2b2440" />
55
- <circle class="mah-eye right" cx="29.5" cy="31" r="1.7" fill="#2b2440" />
56
  <!-- mouth -->
57
- <path class="mah-mouth" d="${MOUTH_PATHS.idle}" stroke="#b5546e" stroke-width="2" fill="#b5546e" fill-opacity="0" stroke-linecap="round" stroke-linejoin="round" />
58
  </svg>`;
 
1
  // dashboard/features/streamer/mah.svg.js
2
+ // O6 — Mah's avatar: a FEMININE counterpart to Byte, same mascot language (no
3
+ // real-person traits). Same head/face/eyes so they read as siblings; feminine
4
+ // touches: a little bow, eyelashes, blush, a heart antenna, and her coral/red
5
+ // accent. Pure scalable SVG, same viewBox as Byte for the duo.
 
6
 
7
+ // Mouth shape per state (mirrors Byte's vocabulary).
8
  export const MOUTH_PATHS = Object.freeze({
9
+ unseen: "M19 30 h10",
10
+ idle: "M19 30 h10",
11
+ neutral: "M19 30 h10",
12
+ happy: "M19 29 Q24 34 29 29",
13
+ hype: "M18 28 Q24 37 30 28 Z",
14
+ sad: "M19 32 Q24 27 29 32",
15
+ talking: "M20 29 q4 5 8 0 q-4 2 -8 0 Z",
16
  });
17
 
18
  export const MAH_SVG = `
19
+ <svg class="mah-figure" viewBox="0 0 48 50" role="img" aria-label="Mah">
20
+ <!-- antenna with a heart tip (feminine touch) -->
21
+ <line class="mah-antenna" x1="24" y1="10" x2="24" y2="5.5" stroke="#ff7aa8" stroke-width="2" stroke-linecap="round" />
22
+ <path class="mah-heart" d="M24 3.4 q1.6 -2 3 0 q1.2 1.7 -3 4 q-4.2 -2.3 -3 -4 q1.4 -2 3 0 Z" fill="#e23b5a" />
23
+ <!-- head -->
24
+ <rect class="mah-head" x="8" y="10" width="32" height="30" rx="9" fill="#ff7aa8" />
25
+ <rect class="mah-face" x="13" y="15" width="22" height="20" rx="6" fill="#1e1430" />
26
+ <!-- side bow (her signature accent) -->
27
+ <g class="mah-bow">
28
+ <path d="M9 16 l-4 -3 v6 Z M9 16 l4 -3 v6 Z" fill="#e23b5a" />
29
+ <circle cx="9" cy="16" r="1.3" fill="#b5283f" />
 
 
 
 
 
 
 
 
 
 
 
 
30
  </g>
31
+ <!-- blush cheeks (revealed on happy/hype) -->
32
+ <circle class="mah-cheek left" cx="16" cy="29" r="2.3" fill="#ff5d86" />
33
+ <circle class="mah-cheek right" cx="32" cy="29" r="2.3" fill="#ff5d86" />
34
+ <!-- eyelashes (feminine) -->
35
+ <g class="mah-lashes" stroke="#8be9fd" stroke-width="1" stroke-linecap="round">
36
+ <line x1="17" y1="20.6" x2="15.4" y2="19.6" />
37
+ <line x1="17.6" y1="20" x2="16.6" y2="18.6" />
38
+ <line x1="31" y1="20.6" x2="32.6" y2="19.6" />
39
+ <line x1="30.4" y1="20" x2="31.4" y2="18.6" />
40
  </g>
41
+ <!-- eyes (same as Byte — sibling resemblance) -->
42
+ <rect class="mah-eye left" x="17" y="21" width="3.6" height="6.2" rx="1.8" fill="#8be9fd" />
43
+ <rect class="mah-eye right" x="27.4" y="21" width="3.6" height="6.2" rx="1.8" fill="#8be9fd" />
44
  <!-- mouth -->
45
+ <path class="mah-mouth" d="${MOUTH_PATHS.idle}" stroke="#ff9ab4" stroke-width="2" fill="#ff9ab4" fill-opacity="0" stroke-linecap="round" stroke-linejoin="round" />
46
  </svg>`;
dashboard/styles/mascot.css CHANGED
@@ -312,7 +312,7 @@
312
  .mah-avatar {
313
  --mah-size: 44px;
314
  width: var(--mah-size);
315
- height: calc(var(--mah-size) * 52 / 48);
316
  flex: 0 0 auto;
317
  display: inline-block;
318
  line-height: 0;
 
312
  .mah-avatar {
313
  --mah-size: 44px;
314
  width: var(--mah-size);
315
+ height: calc(var(--mah-size) * 50 / 48);
316
  flex: 0 0 auto;
317
  display: inline-block;
318
  line-height: 0;
dashboard/tests/mah_render.test.js CHANGED
@@ -48,15 +48,18 @@ test("Prove that the context/size class survives re-render", () => {
48
  });
49
 
50
  test("Prove the SVG carries her signature motifs (homage, not copy)", () => {
 
51
  for (const hook of [
52
  "mah-figure",
53
- "mah-hat", // cow-print bucket hat (the moo pun)
54
- "mah-spot", // cow spots
55
- "mah-glasses", // round glasses
56
- "mah-eye",
 
 
57
  "mah-cheek",
58
  "mah-mouth",
59
- 'viewBox="0 0 48 52"',
60
  ]) {
61
  assert.ok(MAH_SVG.includes(hook), `SVG must expose ${hook}`);
62
  }
 
48
  });
49
 
50
  test("Prove the SVG carries her signature motifs (homage, not copy)", () => {
51
+ // Feminine counterpart to Byte: same mascot hooks + feminine touches.
52
  for (const hook of [
53
  "mah-figure",
54
+ "mah-head",
55
+ "mah-face",
56
+ "mah-eye", // same eyes as Byte (sibling)
57
+ "mah-lashes", // feminine
58
+ "mah-bow", // feminine signature
59
+ "mah-heart", // heart antenna tip
60
  "mah-cheek",
61
  "mah-mouth",
62
+ 'viewBox="0 0 48 50"', // same scale as Byte for the duo
63
  ]) {
64
  assert.ok(MAH_SVG.includes(hook), `SVG must expose ${hook}`);
65
  }