@baravak/risloo-profile-cli 4.46.3 → 4.75.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.
Files changed (101) hide show
  1. package/.agents/skills/create-profile/SKILL.md +14 -0
  2. package/.claude/settings.local.json +1 -3
  3. package/.claude/skills/create-profile/SKILL.md +203 -0
  4. package/AGENTS.md +413 -0
  5. package/CLAUDE.md +2 -185
  6. package/package.json +1 -1
  7. package/src/cli-commands/Executor.js +8 -2
  8. package/src/cli-commands/ExtractExecutor.js +55 -21
  9. package/src/cli-commands/GiftExecutor.js +1 -0
  10. package/src/handlebars/importPartials.js +10 -44
  11. package/src/handlebars/init.js +17 -11
  12. package/src/publish/json/profiles/BSSI93.json +392 -0
  13. package/src/publish/json/profiles/FRHPT93.json +2 -2
  14. package/src/publish/json/profiles/ISKS93.json +288 -0
  15. package/src/publish/json/profiles/MCMI9A.json +1540 -0
  16. package/src/publish/json/profiles/NEO93.json +3858 -0
  17. package/src/publish/json/profiles/NEO9A.json +1159 -1
  18. package/src/publish/json/profiles/NEO9Q.json +3856 -0
  19. package/src/publish/json/profiles/NEO9V.json +1157 -0
  20. package/src/publish/json/profiles/RIASEC9A.json +2775 -0
  21. package/src/publish/json/profiles/RSI93.json +359 -0
  22. package/src/samples/AEQ93.js +1 -1
  23. package/src/samples/AMS93.js +1 -1
  24. package/src/samples/AMS9A.js +3 -1
  25. package/src/samples/BAOMEIS93.js +1 -1
  26. package/src/samples/BEQI93.js +1 -1
  27. package/src/samples/BSCT93.js +5 -0
  28. package/src/samples/BSSI93.js +93 -0
  29. package/src/samples/CAATS93.js +1 -1
  30. package/src/samples/CERQ93.js +1 -1
  31. package/src/samples/CRAAS93.js +1 -1
  32. package/src/samples/DSWLS93.js +1 -1
  33. package/src/samples/EMSS93.js +1 -1
  34. package/src/samples/EPQ9A.js +6 -1
  35. package/src/samples/FACES93.js +6 -0
  36. package/src/samples/FRHPT93.js +41 -13
  37. package/src/samples/GMIT93.js +1 -1
  38. package/src/samples/HPL93.js +1 -1
  39. package/src/samples/ISKS93.js +62 -0
  40. package/src/samples/IUS93.js +1 -1
  41. package/src/samples/JCSI93.js +1 -1
  42. package/src/samples/JPFQ93.js +5 -0
  43. package/src/samples/KJGI93.js +1 -1
  44. package/src/samples/LMIQ93.js +1 -1
  45. package/src/samples/MCMI9A.js +530 -0
  46. package/src/samples/MMFAD93.js +1 -1
  47. package/src/samples/MOCI93.js +1 -1
  48. package/src/samples/NEO93.js +279 -0
  49. package/src/samples/NEO9A.js +93 -60
  50. package/src/samples/NEO9Q.js +281 -0
  51. package/src/samples/NEO9V.js +218 -0
  52. package/src/samples/OBQ4493.js +1 -1
  53. package/src/samples/PIES93.js +1 -1
  54. package/src/samples/PIES9A.js +4 -0
  55. package/src/samples/PMCIEF93.js +7 -1
  56. package/src/samples/PSWQ93.js +1 -1
  57. package/src/samples/RIASEC93.js +1 -1
  58. package/src/samples/RIASEC9A.js +256 -0
  59. package/src/samples/RSI93.js +89 -0
  60. package/src/samples/SASQ93.js +1 -1
  61. package/src/samples/SDCAQ93.js +1 -1
  62. package/src/samples/STAIY93.js +1 -1
  63. package/src/samples/WAQ93.js +1 -1
  64. package/src/samples/YBOCS93.js +1 -1
  65. package/src/samples/YPI93.js +5 -1
  66. package/views/profiles/MCMI9A_facets_partial.hbs +96 -0
  67. package/views/profiles/MCMI9A_main_partial.hbs +262 -0
  68. package/views/profiles/MCMI9A_noteworthy_partial.hbs +66 -0
  69. package/views/profiles/MCMI9A_vertical_label_partial.hbs +8 -0
  70. package/views/profiles/NEO_long_facets.hbs +125 -0
  71. package/views/profiles/NEO_main.hbs +152 -0
  72. package/views/profiles/NEO_short_facets.hbs +82 -0
  73. package/views/profiles/samples/BSCT93.hbs +17 -17
  74. package/views/profiles/samples/BSSI93.hbs +102 -0
  75. package/views/profiles/samples/FRHPT93_1.hbs +568 -87
  76. package/views/profiles/samples/FRHPT93_2.hbs +90 -76
  77. package/views/profiles/samples/FRHPT93_3.hbs +2 -2
  78. package/views/profiles/samples/FRHPT93_4.hbs +2 -2
  79. package/views/profiles/samples/FRHPT93_5.hbs +103 -0
  80. package/views/profiles/samples/FRHPT9A.hbs +7 -7
  81. package/views/profiles/samples/ISKS93.hbs +38 -0
  82. package/views/profiles/samples/MCMI9A_1.hbs +3 -0
  83. package/views/profiles/samples/MCMI9A_2.hbs +3 -0
  84. package/views/profiles/samples/MCMI9A_3.hbs +3 -0
  85. package/views/profiles/samples/MCMI9A_4.hbs +3 -0
  86. package/views/profiles/samples/NEO93_1.hbs +14 -0
  87. package/views/profiles/samples/NEO93_2.hbs +15 -0
  88. package/views/profiles/samples/NEO93_3.hbs +15 -0
  89. package/views/profiles/samples/NEO9A.hbs +14 -29
  90. package/views/profiles/samples/NEO9Q_1.hbs +13 -0
  91. package/views/profiles/samples/NEO9Q_2.hbs +14 -0
  92. package/views/profiles/samples/NEO9Q_3.hbs +14 -0
  93. package/views/profiles/samples/NEO9V_1.hbs +13 -0
  94. package/views/profiles/samples/NEO9V_2.hbs +3 -0
  95. package/views/profiles/samples/RIASEC9A_1.hbs +38 -0
  96. package/views/profiles/samples/RIASEC9A_2.hbs +67 -0
  97. package/views/profiles/samples/RIASEC9A_3.hbs +93 -0
  98. package/views/profiles/samples/RSI93.hbs +101 -0
  99. package/a.json +0 -4805
  100. package/src/publish/json/profiles/BSCT93_t1.json +0 -512
  101. package/src/publish/json/profiles/BSCT93_t2.json +0 -512
@@ -0,0 +1,38 @@
1
+ {{#> layout}}
2
+
3
+ <g transform="translate({{spec.profile.padding.[0].x}}, {{spec.profile.padding.[0].y}})">
4
+ <g transform="translate(100, 20)">
5
+ <line x1="0" y1="-10" x2="0" y2="214" stroke="#D4D4D8" stroke-width="2" stroke-linecap="round" />
6
+ {{#each items as | item index |}}
7
+ {{#with @root.spec.items as | itemsSpec |}}
8
+ <g transform="translate(0, {{math index '*' itemsSpec.distanceY}})">
9
+ <text x="-12" y="8" font-size="14" font-weight="400" fill="#7E22CE" text-anchor="start">{{item.label.fr}} ({{item.label.short}})</text>
10
+ <rect x="0" y="{{math itemsSpec.rect.body.height '-' itemsSpec.rect.base.height}}" width="500" height="{{itemsSpec.rect.base.height}}" fill="#F4F4F5" />
11
+ {{#if (boolean item.mark '!==' 0)}}
12
+ {{bar item.width itemsSpec.rect.body.height itemsSpec.rect.body.brs 0 fill="#7E22CE" fill-opacity=item.opacity}}
13
+ {{/if}}
14
+ <text x="{{math item.width '+' (ternary (boolean item.mark '!==' 0) 0 7)}}" y="-6" font-size="14" font-weight="500" fill="#7E22CE" text-anchor="middle">{{item.mark}}</text>
15
+ </g>
16
+ {{/with}}
17
+ {{/each}}
18
+ <text x="500" y="235" font-size="12" font-weight="400" fill="#D4D4D8" text-anchor="middle">56</text>
19
+ </g>
20
+ <g transform="translate(398, 329)">
21
+ {{#each questionItems as | item index |}}
22
+ <g transform="translate(0, {{ math index '*' 56 }})">
23
+ <text x="64" y="25" font-size="14" font-weight="400" fill="#3F3F46" text-anchor="end">{{ item.label }}</text>
24
+ {{#each item.marks as | mark markIndex |}}
25
+ <g transform="translate({{math -1 '*' (math markIndex '*' 64)}}, 0)">
26
+ {{#if (boolean index '===' 0)}}
27
+ <text x="20" y="-21" font-size="14" font-weight="400" fill="#3F3F46" text-anchor="middle">{{lookup (array 'و' 'ج' 'ه' 'الف' 'م' 'ق') markIndex}}</text>
28
+ {{/if}}
29
+ <rect x="0" y="0" width="40" height="40" fill="#F4F4F5" rx="4" />
30
+ <text x="20" y="25" font-size="16" font-weight="500" fill="#312E81" text-anchor="middle">{{ mark }}</text>
31
+ </g>
32
+ {{/each}}
33
+ </g>
34
+ {{/each}}
35
+ </g>
36
+ </g>
37
+
38
+ {{/layout}}
@@ -0,0 +1,67 @@
1
+ {{#> layout}}
2
+
3
+ <g transform="translate({{spec.profile.padding.[1].x}}, {{spec.profile.padding.[1].y}})">
4
+ <g transform="translate(9, 0)">
5
+ <line x1="176.5" y1="54" x2="415.5" y2="468" stroke="#CBD5E1" stroke-width="1" />
6
+ <line x1="176.5" y1="468" x2="415.5" y2="54" stroke="#CBD5E1" stroke-width="1" />
7
+
8
+ <line x1="176.5" y1="468" x2="176.5" y2="54" stroke="#E2E8F0" stroke-width="1" stroke-dasharray="5,5" />
9
+ <line x1="415.5" y1="468" x2="415.5" y2="54" stroke="#E2E8F0" stroke-width="1" stroke-dasharray="5,5" />
10
+
11
+ <line x1="57" y1="261" x2="415.5" y2="54" stroke="#E2E8F0" stroke-width="1" stroke-dasharray="5,5" />
12
+ <line x1="57" y1="261" x2="415.5" y2="468" stroke="#E2E8F0" stroke-width="1" stroke-dasharray="5,5" />
13
+
14
+ <line x1="176.5" y1="54" x2="535" y2="261" stroke="#E2E8F0" stroke-width="1" stroke-dasharray="5,5" />
15
+ <line x1="176.5" y1="468" x2="535" y2="261" stroke="#E2E8F0" stroke-width="1" stroke-dasharray="5,5" />
16
+
17
+ <line x1="57" y1="261" x2="535" y2="261" stroke="#CBD5E1" stroke-width="1" />
18
+
19
+ <text x="296" y="42" text-anchor="middle" fill="#CBD5E1" font-size="14" font-weight="500">56</text>
20
+
21
+ <g transform="translate(568, 235)">
22
+ <text y="0" text-anchor="middle" fill="{{ternary itemRadians.[0].bold '#4F46E5' '#475569'}}" font-size="14" dy=".85em" font-weight="700">A</text>
23
+ <text y="16" text-anchor="middle" fill="{{ternary itemRadians.[0].bold '#4F46E5' '#475569'}}" font-size="14" dy=".85em" font-weight="500">هنری</text>
24
+ <text y="38" text-anchor="middle" fill="{{ternary itemRadians.[0].bold '#6366F1' '#64748B'}}" font-size="12" dy=".8em" font-weight="500">{{itemRadians.[0].percentageText}} ٪</text>
25
+ </g>
26
+
27
+ <g transform="translate(465, 475)">
28
+ <text y="0" text-anchor="middle" fill="{{ternary itemRadians.[1].bold '#4F46E5' '#475569'}}" font-size="14" dy=".85em" font-weight="700">S</text>
29
+ <text y="16" text-anchor="middle" fill="{{ternary itemRadians.[1].bold '#4F46E5' '#475569'}}" font-size="14" dy=".85em" font-weight="500">اجتماعی</text>
30
+ <text y="38" text-anchor="middle" fill="{{ternary itemRadians.[1].bold '#6366F1' '#64748B'}}" font-size="12" dy=".8em" font-weight="500">{{itemRadians.[1].percentageText}} ٪</text>
31
+ </g>
32
+
33
+ <g transform="translate(148, 475)">
34
+ <text y="0" text-anchor="middle" fill="{{ternary itemRadians.[2].bold '#4F46E5' '#475569'}}" font-size="14" dy=".85em" font-weight="700">E</text>
35
+ <text y="16" text-anchor="middle" fill="{{ternary itemRadians.[2].bold '#4F46E5' '#475569'}}" font-size="14" dy=".85em" font-weight="500">متهور</text>
36
+ <text y="38" text-anchor="middle" fill="{{ternary itemRadians.[2].bold '#6366F1' '#64748B'}}" font-size="12" dy=".8em" font-weight="500">{{itemRadians.[2].percentageText}} ٪</text>
37
+ </g>
38
+
39
+ <g transform="translate(16, 235)">
40
+ <text y="0" text-anchor="middle" fill="{{ternary itemRadians.[3].bold '#4F46E5' '#475569'}}" font-size="14" dy=".85em" font-weight="700">C</text>
41
+ <text y="16" text-anchor="middle" fill="{{ternary itemRadians.[3].bold '#4F46E5' '#475569'}}" font-size="14" dy=".85em" font-weight="500">قراردادی</text>
42
+ <text y="38" text-anchor="middle" fill="{{ternary itemRadians.[3].bold '#6366F1' '#64748B'}}" font-size="12" dy=".8em" font-weight="500">{{itemRadians.[3].percentageText}} ٪</text>
43
+ </g>
44
+
45
+ <g transform="translate(148, 0)">
46
+ <text y="0" text-anchor="middle" fill="{{ternary itemRadians.[4].bold '#4F46E5' '#475569'}}" font-size="14" dy=".85em" font-weight="700">R</text>
47
+ <text y="16" text-anchor="middle" fill="{{ternary itemRadians.[4].bold '#4F46E5' '#475569'}}" font-size="14" dy=".85em" font-weight="500">واقع‌گرا</text>
48
+ <text y="38" text-anchor="middle" fill="{{ternary itemRadians.[4].bold '#6366F1' '#64748B'}}" font-size="12" dy=".8em" font-weight="500">{{itemRadians.[4].percentageText}} ٪</text>
49
+ </g>
50
+ <g transform="translate(465, 0)">
51
+ <text y="0" text-anchor="middle" fill="{{ternary itemRadians.[5].bold '#4F46E5' '#475569'}}" font-size="14" dy=".85em" font-weight="700">I</text>
52
+ <text y="16" text-anchor="middle" fill="{{ternary itemRadians.[5].bold '#4F46E5' '#475569'}}" font-size="14" dy=".85em" font-weight="500">جستجوگر</text>
53
+ <text y="38" text-anchor="middle" fill="{{ternary itemRadians.[5].bold '#6366F1' '#64748B'}}" font-size="12" dy=".8em" font-weight="500">{{itemRadians.[5].percentageText}} ٪</text>
54
+ </g>
55
+
56
+ {{#each itemRadians as |item|}}
57
+ <line x1="{{item.rad.start.[0]}}" y1="{{item.rad.start.[1]}}" x2="{{item.rad.end.[0]}}" y2="{{item.rad.end.[1]}}" stroke="{{ternary item.bold '#4F46E5' '#475569'}}" stroke-width="3" />
58
+ <circle cx="{{item.rad.value.[0]}}" cy="{{item.rad.value.[1]}}" r="12" fill="{{ternary item.bold '#4F46E5' '#475569'}}" />
59
+ <text x="{{item.rad.value.[0]}}" y="{{item.rad.value.[1]}}" text-anchor="middle" fill="#FFFFFF" font-size="14" font-weight="700" dy=".30em">{{item.mark}}</text>
60
+ {{/each}}
61
+ <path transform="translate(56,53)" d="M359.654 0.753893L479.307 208L359.654 415.246L120.346 415.246L0.69283 208L120.346 0.753883L359.654 0.753893Z" stroke="#94A3B8" fill="none" stroke-width="1.2"/>
62
+ <path transform="translate(264,233)" d="M47.6536 0.887187L63.3072 28L47.6536 55.1128L16.3464 55.1128L0.69282 28L16.3464 0.887185L47.6536 0.887187Z" fill="white" stroke="#CBD5E1" stroke-width="1.2"/>
63
+ <text x="296" y="261.5" text-anchor="middle" fill="#CBD5E1" font-size="14" dy=".25em" font-weight="500">0</text>
64
+ </g>
65
+ </g>
66
+
67
+ {{/layout}}
@@ -0,0 +1,93 @@
1
+ {{#> layout}}
2
+ <defs>
3
+ <linearGradient id="l3" x1="130" y1="0" x2="13.9423" y2="86.67" gradientUnits="userSpaceOnUse">
4
+ <stop stop-color="#9333EA"/>
5
+ <stop offset="1" stop-color="#C084FC"/>
6
+ </linearGradient>
7
+ <linearGradient id="l2" x1="160" y1="0" x2="1.785" y2="106.559" gradientUnits="userSpaceOnUse">
8
+ <stop stop-color="#7C3AED"/>
9
+ <stop offset="1" stop-color="#A78BFA"/>
10
+ </linearGradient>
11
+ <linearGradient id="l1" x1="200" y1="-7.62939e-06" x2="27.289" y2="134.93" gradientUnits="userSpaceOnUse">
12
+ <stop stop-color="#4F46E5"/>
13
+ <stop offset="1" stop-color="#818CF8"/>
14
+ </linearGradient>
15
+ </defs>
16
+ <g transform="translate({{spec.profile.padding.[2].x}}, {{spec.profile.padding.[2].y}})">
17
+ <g transform="translate(24, 0)">
18
+ <g transform="translate(0, 16)">
19
+ <rect width="130" height="68" rx="8" fill="url(#l3)"/>
20
+ <text x="65" y="34" dy=".3em" text-anchor="middle" font-weight="600" font-size="24" fill="white">
21
+ {{reportMap.[0]}}
22
+ </text>
23
+ </g>
24
+ <g transform="translate(145, 8)">
25
+ <rect width="160" height="84" rx="8" fill="url(#l2)"/>
26
+ <text x="80" y="42" dy=".3em" text-anchor="middle" font-weight="600" font-size="28" fill="white">
27
+ {{reportMap.[1]}}
28
+ </text>
29
+ </g>
30
+ <g transform="translate(320, 0)">
31
+ <rect width="200" height="100" rx="8" fill="url(#l1)"/>
32
+ <text x="100" y="50" dy=".3em" text-anchor="middle" font-weight="600" font-size="40" fill="white">
33
+ {{reportMap.[2]}}
34
+ </text>
35
+ </g>
36
+ </g>
37
+ <g transform="translate(0, 140)">
38
+ <g>
39
+ <rect x="24" width="80" height="264" rx="12" fill="#F8FAFC"/>
40
+ <rect x="40" y="16" width="48" height="48" rx="8" fill="#E2E8F0"/>
41
+ <rect x="112" width="80" height="264" rx="12" fill="#F8FAFC"/>
42
+ <rect x="128" y="16" width="48" height="48" rx="8" fill="#E2E8F0"/>
43
+ <rect x="200" width="80" height="264" rx="12" fill="#F8FAFC"/>
44
+ <rect x="216" y="16" width="48" height="48" rx="8" fill="#E2E8F0"/>
45
+ <rect x="288" width="80" height="264" rx="12" fill="#F8FAFC"/>
46
+ <rect x="304" y="16" width="48" height="48" rx="8" fill="#E2E8F0"/>
47
+ <rect x="376" width="80" height="264" rx="12" fill="#F8FAFC"/>
48
+ <rect x="392" y="16" width="48" height="48" rx="8" fill="#E2E8F0"/>
49
+ <rect x="464" width="80" height="264" rx="12" fill="#F8FAFC"/>
50
+ <rect x="480" y="16" width="48" height="48" rx="8" fill="#E2E8F0"/>
51
+ <line x1="0" y1="119.5" x2="686" y2="119.5" stroke="#CBD5E1" />
52
+ <line x1="0" y1="167.5" x2="686" y2="167.5" stroke="#CBD5E1" />
53
+ <line x1="0" y1="215.5" x2="686" y2="215.5" stroke="#CBD5E1" />
54
+ <g transform="translate(678, 72)">
55
+ <text y="24" dy=".3em" text-anchor="start" font-weight="500" font-size="16" fill="#475569">
56
+ نمره رغبت (خام)
57
+ </text>
58
+ <text y="72" dy=".3em" text-anchor="start" font-weight="500" font-size="16" fill="#475569">
59
+ رتبه
60
+ </text>
61
+ <text y="120" dy=".3em" text-anchor="start" font-weight="500" font-size="16" fill="#475569">
62
+ هم‌خوانی
63
+ </text>
64
+ <text y="168" dy=".3em" text-anchor="start" font-weight="500" font-size="16" fill="#475569">
65
+ میزان‌شده
66
+ </text>
67
+ </g>
68
+ </g>
69
+ <g transform="translate(24, 0)">
70
+ {{#each items as | item index |}}
71
+ <g transform="translate({{math 88 '*' index}}, 0)">
72
+ <text x="40" y="40" dy=".3em" text-anchor="middle" font-weight="500" font-size="16" fill="#475569">
73
+ {{item.label.short}}
74
+ </text>
75
+ <text x="40" y="96" dy=".3em" text-anchor="middle" font-weight="500" font-size="16" fill="#475569">
76
+ {{item.mark}}
77
+ </text>
78
+ <text x="40" y="144" dy=".3em" text-anchor="middle" font-weight="500" font-size="16" fill="#475569">
79
+ {{item.rank}}
80
+ </text>
81
+ <text x="40" y="192" dy=".3em" text-anchor="middle" font-weight="500" font-size="16" fill="#475569">
82
+ {{item.congruence}}
83
+ </text>
84
+ <text x="40" y="240" dy=".3em" text-anchor="middle" font-weight="500" font-size="16" fill="#475569">
85
+ {{item.calibrated}}
86
+ </text>
87
+ </g>
88
+ {{/each}}
89
+ </g>
90
+ </g>
91
+ </g>
92
+
93
+ {{/layout}}
@@ -0,0 +1,101 @@
1
+ {{#> layout}}
2
+
3
+ <defs>
4
+ {{! Ring fills — userSpaceOnUse, coords local to each ring's centre group.
5
+ Light at the base (0,125) → deep toward the top of the fill. }}
6
+ <linearGradient id="ring1grad" x1="0" y1="125" x2="-91.81" y2="-84.83" gradientUnits="userSpaceOnUse">
7
+ <stop stop-color="#F472B6"/>
8
+ <stop offset="1" stop-color="#BE185D"/>
9
+ </linearGradient>
10
+ <linearGradient id="ring2grad" x1="0" y1="125" x2="91.81" y2="-84.83" gradientUnits="userSpaceOnUse">
11
+ <stop stop-color="#34D399"/>
12
+ <stop offset="1" stop-color="#047857"/>
13
+ </linearGradient>
14
+
15
+ {{! Bar fill — stretched per bar (objectBoundingBox): light-green start → deep-green end. }}
16
+ <linearGradient id="barfill">
17
+ <stop stop-color="#A7F3D0"/>
18
+ <stop offset="1" stop-color="#047857"/>
19
+ </linearGradient>
20
+
21
+ {{! Drop-shadow for the 0 % baseline separator (same as the FRHPT/BSCT vsp filter). }}
22
+ <filter id="rsiBaseline" x="475" y="72" width="7" height="126" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
23
+ <feFlood flood-opacity="0" result="BackgroundImageFix"/>
24
+ <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
25
+ <feOffset dx="1"/>
26
+ <feGaussianBlur stdDeviation="1.5"/>
27
+ <feComposite in2="hardAlpha" operator="out"/>
28
+ <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0"/>
29
+ <feBlend mode="normal" in2="BackgroundImageFix" result="effect1"/>
30
+ <feBlend mode="normal" in="SourceGraphic" in2="effect1" result="shape"/>
31
+ </filter>
32
+ </defs>
33
+
34
+ <g transform="translate({{spec.profile.padding.x}}, {{spec.profile.padding.y}})">
35
+
36
+ {{! ===================== LEFT: two mirrored donut-ring gauges ===================== }}
37
+ {{! Left ring — negative image (pink), fills clockwise up the LEFT (direction false). }}
38
+ <g transform="translate(125, 125)">
39
+ {{gauge 125 87.5 (object tl=6 tr=6 bl=6 br=6) (object start=(toRad 90) end=(toRad 270)) false fill="#F1F5F9"}}
40
+ {{#if neg.p}}{{gauge 125 87.5 (object tl=6 tr=6 bl=6 br=6) (object start=(toRad 90) end=neg.zeta) false fill="url(#ring1grad)"}}{{/if}}
41
+ </g>
42
+ {{! Right ring — positive image (green), fills counter-cw up the RIGHT (direction true). }}
43
+ <g transform="translate(205, 125)">
44
+ {{gauge 125 87.5 (object tl=6 tr=6 bl=6 br=6) (object start=(toRad 90) end=(toRad -90)) true fill="#F1F5F9"}}
45
+ {{#if pos.p}}{{gauge 125 87.5 (object tl=6 tr=6 bl=6 br=6) (object start=(toRad 90) end=pos.zeta) true fill="url(#ring2grad)"}}{{/if}}
46
+ </g>
47
+
48
+ {{! Shared axis labels (gap centre x=165): 100 % at the top, 0 at the bottom base. }}
49
+ <text x="165" y="22" text-anchor="middle" font-size="14" font-weight="500" fill="#64748B" direction="ltr">٪ 100</text>
50
+ <text x="165" y="233" text-anchor="middle" font-size="14" font-weight="500" fill="#64748B">0</text>
51
+
52
+ {{! Ring centres: big percentage + raw fraction }}
53
+ <text x="98" y="124" text-anchor="middle" font-size="28" font-weight="600" fill="#BE185D" direction="ltr">٪ {{neg.percentage}}</text>
54
+ <text x="98" y="151" text-anchor="middle" font-size="16" font-weight="500" fill="#475569">{{neg.mark}} از {{neg.max}}</text>
55
+ <text x="232" y="124" text-anchor="middle" font-size="28" font-weight="600" fill="#047857" direction="ltr">٪ {{pos.percentage}}</text>
56
+ <text x="232" y="151" text-anchor="middle" font-size="16" font-weight="500" fill="#475569">{{pos.mark}} از {{pos.max}}</text>
57
+
58
+ {{! Ring titles (below). Left grows leftward from x=122 (anchor start);
59
+ right grows rightward from x=208 (anchor end). }}
60
+ <text x="120" y="285" text-anchor="start" font-size="18" xml:space="preserve"><tspan font-weight="500" fill="#64748B">تصور </tspan><tspan font-weight="600" fill="#BE185D">منفی</tspan></text>
61
+ <text x="120" y="311" text-anchor="start" font-size="18" font-weight="500" fill="#94A3B8">از خدا</text>
62
+ <text x="210" y="285" text-anchor="end" font-size="18" xml:space="preserve"><tspan font-weight="500" fill="#64748B">تصور </tspan><tspan font-weight="600" fill="#047857">مثبت</tspan></text>
63
+ <text x="210" y="311" text-anchor="end" font-size="18" font-weight="500" fill="#94A3B8">از خدا</text>
64
+
65
+ {{! ===================== RIGHT: two horizontal bars ===================== }}
66
+ {{! Bar axis: 0 % at x=477.5, 100 % at x=677.5 (width 200). Dashed gridlines at 25/50/75/100 %. }}
67
+ <text x="477" y="60" text-anchor="middle" font-size="12" font-weight="400" fill="#94A3B8">0</text>
68
+ <text x="677" y="60" text-anchor="middle" font-size="12" font-weight="400" fill="#94A3B8" direction="ltr">٪ 100</text>
69
+
70
+ <line x1="527.5" y1="75.5" x2="527.5" y2="194.5" stroke="#E2E8F0" stroke-linecap="round" stroke-dasharray="6 6"/>
71
+ <line x1="577.5" y1="75.5" x2="577.5" y2="194.5" stroke="#E2E8F0" stroke-linecap="round" stroke-dasharray="6 6"/>
72
+ <line x1="627.5" y1="75.5" x2="627.5" y2="194.5" stroke="#E2E8F0" stroke-linecap="round" stroke-dasharray="6 6"/>
73
+ <line x1="677.5" y1="75.5" x2="677.5" y2="194.5" stroke="#E2E8F0" stroke-linecap="round" stroke-dasharray="6 6"/>
74
+
75
+ {{#each bars as |item index|}}
76
+ <g transform="translate(478, {{math 99 '+' (math 48 '*' index)}})">
77
+ {{! track }}
78
+ {{bar 200 24 (object tl=0 bl=0 tr=6 br=6) (toRad 0) fill="black" fill-opacity="0.04"}}
79
+ {{! fill }}
80
+ {{#if item.p}}{{bar (math 200 '*' item.p) 24 (object tl=0 bl=0 tr=6 br=6) (toRad 0) fill="url(#barfill)"}}{{/if}}
81
+ {{! category name (right-aligned, 10px left of the bar start) }}
82
+ <text x="-10" y="12" dy=".32em" text-anchor="start" font-size="14" font-weight="400" fill="#475569">{{item.label.title}}</text>
83
+ {{! percentage — inside the fill (≥25 %) or just outside it (≤24 %) }}
84
+ {{#if (boolean item.percentage '<=' 24)}}
85
+ <text x="{{math (math 200 '*' item.p) '+' 6}}" y="12" dy=".32em" text-anchor="start" font-size="14" font-weight="500" fill="#047857" direction="ltr">٪ {{item.percentage}}</text>
86
+ {{else}}
87
+ <text x="{{math (math 200 '*' item.p) '-' 8}}" y="12" dy=".32em" text-anchor="end" font-size="14" font-weight="500" fill="#FFFFFF" direction="ltr">٪ {{item.percentage}}</text>
88
+ {{/if}}
89
+ {{! raw / max fraction (green raw + gray total) }}
90
+ <text x="208" y="12" dy=".32em" text-anchor="start" direction="ltr"><tspan font-weight="700" font-size="18" fill="#047857">{{item.mark}}</tspan><tspan font-weight="300" font-size="12" fill="#64748B">/</tspan><tspan font-weight="400" font-size="13" fill="#64748B">{{item.max}}</tspan></text>
91
+ </g>
92
+ {{/each}}
93
+
94
+ {{! 0 % baseline separator (white, subtle drop-shadow), drawn on top. }}
95
+ <g opacity="0.5" filter="url(#rsiBaseline)">
96
+ <line x1="477.5" y1="75.5" x2="477.5" y2="194.5" stroke="white" stroke-linecap="round"/>
97
+ </g>
98
+
99
+ </g>
100
+
101
+ {{/layout}}