wagtail-enap-designsystem 1.2.1.129__py3-none-any.whl → 1.2.1.131__py3-none-any.whl

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.

Potentially problematic release.


This version of wagtail-enap-designsystem might be problematic. Click here for more details.

Files changed (35) hide show
  1. enap_designsystem/blocks/__init__.py +6 -0
  2. enap_designsystem/blocks/form.py +243 -2
  3. enap_designsystem/blocks/html_blocks.py +316 -6
  4. enap_designsystem/blocks/semana_inovacao.py +1 -0
  5. enap_designsystem/context_processors.py +30 -6
  6. enap_designsystem/migrations/0395_formulariopage_enable_scoring_and_more.py +106 -0
  7. enap_designsystem/migrations/0396_alter_areaaluno_body_alter_enapcomponentes_body_and_more.py +51263 -0
  8. enap_designsystem/migrations/0397_alter_areaaluno_body_alter_enapcomponentes_body_and_more.py +51718 -0
  9. enap_designsystem/migrations/0398_alter_areaaluno_body_alter_enapcomponentes_body_and_more.py +51718 -0
  10. enap_designsystem/migrations/0399_alter_areaaluno_body_alter_enapcomponentes_body_and_more.py +51718 -0
  11. enap_designsystem/migrations/0400_alter_areaaluno_body_alter_enapcomponentes_body_and_more.py +51718 -0
  12. enap_designsystem/migrations/0401_alter_areaaluno_body_alter_cursoeadpage_curso_and_more.py +52692 -0
  13. enap_designsystem/migrations/0402_alter_areaaluno_body_alter_enapcomponentes_body_and_more.py +52082 -0
  14. enap_designsystem/migrations/0403_alter_areaaluno_body_alter_enapcomponentes_body_and_more.py +52802 -0
  15. enap_designsystem/migrations/0404_sistemavotacaopage_conteudo_pagina.py +253 -0
  16. enap_designsystem/migrations/0405_sistemavotacaopage_exigir_recaptcha_and_more.py +41 -0
  17. enap_designsystem/models.py +94 -46
  18. enap_designsystem/settings.py +4 -0
  19. enap_designsystem/templates/enap_designsystem/blocks/apresentacao_simple_block.html +1 -1
  20. enap_designsystem/templates/enap_designsystem/blocks/cards_titles.html +309 -0
  21. enap_designsystem/templates/enap_designsystem/blocks/clientes_block.html +1 -1
  22. enap_designsystem/templates/enap_designsystem/blocks/cpnu_dashboard_block.html +5 -0
  23. enap_designsystem/templates/enap_designsystem/blocks/logos_simple_block.html +329 -0
  24. enap_designsystem/templates/enap_designsystem/blocks/numeros_block.html +195 -0
  25. enap_designsystem/templates/enap_designsystem/blocks/page/pagenoticias_block.html +6 -0
  26. enap_designsystem/templates/enap_designsystem/blocks/recaptcha.html +146 -126
  27. enap_designsystem/templates/enap_designsystem/form_templates/formulario_page.html +1 -0
  28. enap_designsystem/templates/enap_designsystem/sistema_votacao_page.html +583 -543
  29. enap_designsystem/views.py +1 -1
  30. enap_designsystem/wagtail_hooks.py +390 -9
  31. {wagtail_enap_designsystem-1.2.1.129.dist-info → wagtail_enap_designsystem-1.2.1.131.dist-info}/METADATA +1 -1
  32. {wagtail_enap_designsystem-1.2.1.129.dist-info → wagtail_enap_designsystem-1.2.1.131.dist-info}/RECORD +35 -21
  33. {wagtail_enap_designsystem-1.2.1.129.dist-info → wagtail_enap_designsystem-1.2.1.131.dist-info}/WHEEL +0 -0
  34. {wagtail_enap_designsystem-1.2.1.129.dist-info → wagtail_enap_designsystem-1.2.1.131.dist-info}/licenses/LICENSE +0 -0
  35. {wagtail_enap_designsystem-1.2.1.129.dist-info → wagtail_enap_designsystem-1.2.1.131.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,309 @@
1
+ <!-- enap_designsystem/blocks/cards_titles.html -->
2
+ {% load wagtailcore_tags wagtailimages_tags %}
3
+ <section class="secao-apresentacao-cards">
4
+ <!-- Background com imagem se fornecida -->
5
+ <div class="secao-background"
6
+ {% if value.background_image_fundo_bg %}
7
+ style="background-image: url('{{ value.background_image_fundo_bg.url }}'); background-size: cover; background-position: center; background-repeat: no-repeat;"
8
+ {% else %}
9
+ style="background: linear-gradient(135deg, #6A1B9A 0%, #4A148C 50%, #2E1065 100%);"
10
+ {% endif %}>
11
+
12
+ <!-- Overlay para garantir legibilidade -->
13
+ <div class="secao-overlay">
14
+
15
+ <!-- Container principal -->
16
+ <div class="container mx-auto px-4 py-16 lg:py-24">
17
+
18
+ <!-- Título centralizado -->
19
+ {% if value.titulo %}
20
+ <div class="text-center mb-12 lg:mb-16">
21
+ <h2 class="titulo-secao"
22
+ style="color: {{ value.cor_titulo|default:'#FFFFFF' }};">
23
+ {{ value.titulo }}
24
+ </h2>
25
+ </div>
26
+ {% endif %}
27
+
28
+ <!-- Grid de Cards -->
29
+ {% if value.cards %}
30
+ <div class="cards-container {{ value.layout_cards|default:'cards-3-colunas' }}">
31
+ {% for card in value.cards %}
32
+ {% if card.block_type == 'card' %}
33
+ <div class="card-item">
34
+ <div class="card-apresentacao">
35
+
36
+ <!-- Imagem do card -->
37
+ {% if card.value.image %}
38
+ <div class="card-imagem">
39
+ {% image card.value.image width-400 as card_img %}
40
+ <img src="{{ card_img.url }}"
41
+ alt="{{ card.value.title|default:'Card' }}"
42
+ class="card-img">
43
+ </div>
44
+ {% endif %}
45
+
46
+ <!-- Conteúdo do card -->
47
+ <div class="card-conteudo">
48
+
49
+ <!-- Título -->
50
+ {% if card.value.title %}
51
+ <h3 class="card-titulo">
52
+ {{ card.value.title }}
53
+ </h3>
54
+ {% endif %}
55
+
56
+ <!-- Subtítulo/Cargo -->
57
+ {% if card.value.subtitle %}
58
+ <p class="card-subtitulo">
59
+ {{ card.value.subtitle }}
60
+ </p>
61
+ {% endif %}
62
+
63
+ <!-- Descrição -->
64
+ {% if card.value.description %}
65
+ <div class="card-descricao">
66
+ {{ card.value.description|richtext }}
67
+ </div>
68
+ {% endif %}
69
+
70
+ <!-- Link/Botão -->
71
+ {% if card.value.link_url %}
72
+ <div class="card-acao">
73
+ <a href="{{ card.value.link_url }}"
74
+ class="card-link"
75
+ {% if card.value.link_target %}target="{{ card.value.link_target }}"{% endif %}>
76
+ {{ card.value.link_text|default:'Saiba mais' }}
77
+ <svg class="link-arrow" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
78
+ <path d="M5 12h14M12 5l7 7-7 7"/>
79
+ </svg>
80
+ </a>
81
+ </div>
82
+ {% endif %}
83
+
84
+ </div>
85
+
86
+ </div>
87
+ </div>
88
+ {% endif %}
89
+ {% endfor %}
90
+ </div>
91
+ {% endif %}
92
+
93
+ </div>
94
+ </div>
95
+ </div>
96
+ </section>
97
+
98
+ <style>
99
+ .secao-apresentacao-cards {
100
+ position: relative;
101
+ min-height: 600px;
102
+ }
103
+
104
+ .secao-background {
105
+ position: relative;
106
+ width: 100%;
107
+ min-height: 600px;
108
+ }
109
+
110
+ .secao-overlay {
111
+ position: absolute;
112
+ top: 0;
113
+ left: 0;
114
+ right: 0;
115
+ bottom: 0;
116
+ background: rgba(106, 27, 154, 0.15);
117
+ backdrop-filter: blur(0.5px);
118
+ }
119
+
120
+ .titulo-secao {
121
+ font-size: 2.5rem;
122
+ font-weight: 700;
123
+ line-height: 1.2;
124
+ text-align: center;
125
+ margin-bottom: 0;
126
+ text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
127
+ }
128
+
129
+ .cards-container {
130
+ display: grid;
131
+ gap: 2rem;
132
+ max-width: 1200px;
133
+ margin: 0 auto;
134
+ }
135
+
136
+ /* Layouts responsivos */
137
+ .cards-1-coluna {
138
+ grid-template-columns: 1fr;
139
+ }
140
+
141
+ .cards-2-colunas {
142
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
143
+ max-width: 800px;
144
+ }
145
+
146
+ .cards-3-colunas {
147
+ grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
148
+ max-width: 1000px;
149
+ }
150
+
151
+ .cards-4-colunas {
152
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
153
+ }
154
+
155
+ .cards-5-colunas {
156
+ grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
157
+ }
158
+
159
+ .card-apresentacao {
160
+ background: rgba(0, 0, 0, 0.6);
161
+ border-radius: 12px;
162
+ overflow: hidden;
163
+ transition: all 0.3s ease;
164
+ backdrop-filter: blur(10px);
165
+ border: 1px solid rgba(255, 255, 255, 0.1);
166
+ height: 100%;
167
+ display: flex;
168
+ flex-direction: column;
169
+ }
170
+
171
+ .card-apresentacao:hover {
172
+ transform: translateY(-8px);
173
+ background: rgba(0, 0, 0, 0.7);
174
+ border-color: rgba(255, 255, 255, 0.2);
175
+ box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
176
+ }
177
+
178
+ .card-imagem {
179
+ position: relative;
180
+ height: 200px;
181
+ overflow: hidden;
182
+ }
183
+
184
+ .card-img {
185
+ width: 100%;
186
+ height: 100%;
187
+ object-fit: cover;
188
+ transition: transform 0.3s ease;
189
+ }
190
+
191
+ .card-apresentacao:hover .card-img {
192
+ transform: scale(1.05);
193
+ }
194
+
195
+ .card-conteudo {
196
+ padding: 1.5rem;
197
+ flex: 1;
198
+ display: flex;
199
+ flex-direction: column;
200
+ }
201
+
202
+ .card-titulo {
203
+ font-size: 1.25rem;
204
+ font-weight: 600;
205
+ margin-bottom: 0.5rem;
206
+ line-height: 1.4;
207
+ color: #FFFFFF;
208
+ }
209
+
210
+ .card-subtitulo {
211
+ font-size: 0.9rem;
212
+ font-weight: 400;
213
+ color: rgba(255, 255, 255, 0.8);
214
+ margin-bottom: 1rem;
215
+ font-style: italic;
216
+ }
217
+
218
+ .card-descricao {
219
+ flex: 1;
220
+ font-size: 0.95rem;
221
+ line-height: 1.6;
222
+ margin-bottom: 1rem;
223
+ color: rgba(255, 255, 255, 0.9);
224
+ }
225
+
226
+ .card-descricao * {
227
+ color: inherit !important;
228
+ }
229
+
230
+ .card-acao {
231
+ margin-top: auto;
232
+ }
233
+
234
+ .card-link {
235
+ display: inline-flex;
236
+ align-items: center;
237
+ gap: 0.5rem;
238
+ font-size: 0.95rem;
239
+ font-weight: 500;
240
+ text-decoration: none;
241
+ color: #FFFFFF;
242
+ transition: all 0.3s ease;
243
+ }
244
+
245
+ .card-link:hover {
246
+ transform: translateX(4px);
247
+ color: #FFFFFF;
248
+ }
249
+
250
+ .link-arrow {
251
+ transition: transform 0.3s ease;
252
+ }
253
+
254
+ .card-link:hover .link-arrow {
255
+ transform: translateX(4px);
256
+ }
257
+
258
+ /* Responsividade */
259
+ @media (max-width: 768px) {
260
+ .titulo-secao {
261
+ font-size: 2rem;
262
+ }
263
+
264
+ .cards-container {
265
+ grid-template-columns: 1fr;
266
+ gap: 1.5rem;
267
+ }
268
+
269
+ .card-imagem {
270
+ height: 160px;
271
+ }
272
+
273
+ .card-conteudo {
274
+ padding: 1.25rem;
275
+ }
276
+
277
+ .card-titulo {
278
+ font-size: 1.1rem;
279
+ }
280
+
281
+ .card-subtitulo {
282
+ font-size: 0.85rem;
283
+ }
284
+ }
285
+
286
+ @media (max-width: 480px) {
287
+ .titulo-secao {
288
+ font-size: 1.75rem;
289
+ }
290
+
291
+ .container {
292
+ padding-left: 1rem;
293
+ padding-right: 1rem;
294
+ }
295
+
296
+ .card-imagem {
297
+ height: 140px;
298
+ }
299
+
300
+ .card-conteudo {
301
+ padding: 1rem;
302
+ }
303
+
304
+ .card-titulo {
305
+ font-size: 1rem;
306
+ }
307
+ }
308
+ </style></document_content>
309
+ </invoke>
@@ -43,7 +43,7 @@
43
43
  <style>
44
44
  .clientes-section {
45
45
  padding: 80px 0;
46
- background: #FFFFFF;
46
+ background: linear-gradient(0deg, #FFFFFF 88%, #F5F7FA 96%);
47
47
  position: relative;
48
48
  }
49
49
 
@@ -452,6 +452,11 @@
452
452
  box-shadow: 0 8px 16px rgba(0,0,0,0.2);
453
453
  }
454
454
 
455
+ .card-botao:active {
456
+ background: #025257;
457
+ box-shadow: 0 8px 16px rgba(0,0,0,0.2);
458
+ }
459
+
455
460
  /* Indicadores do carrossel */
456
461
  .carousel-indicators-dash {
457
462
  display: none;
@@ -0,0 +1,329 @@
1
+ {% load wagtailimages_tags %}
2
+
3
+ <!-- Template: enap_designsystem/blocks/logos_simple_block.html -->
4
+
5
+ <section class="logos-simple-block" style="background-color: {{ value.cor_fundo }};">
6
+ <div class="container">
7
+ <div class="">
8
+ <!-- Coluna do título -->
9
+ <div class=" align-items-center">
10
+ <h2 class="logos-titulo" style="color: {{ value.cor_titulo }};">
11
+ {{ value.titulo }}
12
+ </h2>
13
+ </div>
14
+
15
+ <!-- Coluna do grid de logos -->
16
+ <div class="container">
17
+ <div class="logos-conteudo" style="background-color: {{ value.cor_fundo_conteudo }};">
18
+ <!-- Grid de logos -->
19
+ <div class="logos-container {{ value.espacamento_logos }}">
20
+ <div class="logos-grid {{ value.tipo_grid_logos }} {{ value.tamanho_logos }}">
21
+ {% for logo_card in value.lista_logos %}
22
+ <div class="logo-card {% if value.centralizar_logos %}text-center{% endif %}">
23
+ <div class="logo-image-container">
24
+ {% image logo_card.logo fill-200x200 class="logo-image" alt="Logo" %}
25
+ </div>
26
+ </div>
27
+ {% endfor %}
28
+ </div>
29
+ </div>
30
+ </div>
31
+ </div>
32
+ </div>
33
+ </div>
34
+ </section>
35
+
36
+ <style>
37
+ /* Estilos do componente LogosSimpleBlock */
38
+ .logos-simple-block {
39
+ padding: 80px 0;
40
+ min-height: 500px;
41
+ }
42
+
43
+ .logos-titulo {
44
+ font-size: 3.5rem;
45
+ font-weight: 700;
46
+ margin-bottom: 0;
47
+ line-height: 1.1;
48
+ text-align: center;
49
+ word-break: break-word;
50
+ margin: auto;
51
+ margin-bottom: 40px;
52
+ max-width: 400px;
53
+
54
+ }
55
+
56
+ .logos-conteudo {
57
+ padding: 60px 40px;
58
+ border-radius: 16px;
59
+ min-height: 350px;
60
+ display: flex;
61
+ align-items: center;
62
+ justify-content: center;
63
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);
64
+ position: relative;
65
+ overflow: hidden;
66
+ }
67
+
68
+ /* Efeito sutil de gradiente nas bordas */
69
+ .logos-conteudo::before {
70
+ content: '';
71
+ position: absolute;
72
+ top: 0;
73
+ left: 0;
74
+ right: 0;
75
+ bottom: 0;
76
+ background: linear-gradient(135deg, rgba(255,255,255,0.1) 0%, transparent 50%);
77
+ pointer-events: none;
78
+ }
79
+
80
+ /* Grid de logos */
81
+ .logos-container {
82
+ width: 100%;
83
+ position: relative;
84
+ z-index: 1;
85
+ }
86
+
87
+ .logos-grid {
88
+ display: grid;
89
+ gap: 30px;
90
+ align-items: center;
91
+ justify-items: center;
92
+ width: 100%;
93
+ }
94
+
95
+ /* Layouts do grid */
96
+ .logos-grid-1 {
97
+ grid-template-columns: 1fr;
98
+ max-width: 300px;
99
+ margin: 0 auto;
100
+ }
101
+ .logos-grid-2 {
102
+ grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
103
+ max-width: 600px;
104
+ margin: 0 auto;
105
+ }
106
+ .logos-grid-3 {
107
+ grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
108
+ max-width: 700px;
109
+ margin: 0 auto;
110
+ }
111
+ .logos-grid-4 {
112
+ grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
113
+ max-width: 800px;
114
+ margin: 0 auto;
115
+ }
116
+ .logos-grid-5 {
117
+ grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
118
+ max-width: 900px;
119
+ margin: 0 auto;
120
+ }
121
+ .logos-grid-6 {
122
+ grid-template-columns: repeat(auto-fit, minmax(90px, 1fr));
123
+ max-width: 1000px;
124
+ margin: 0 auto;
125
+ }
126
+
127
+ /* Espaçamentos */
128
+ .spacing-sm .logos-grid { gap: 20px; }
129
+ .spacing-md .logos-grid { gap: 30px; }
130
+ .spacing-lg .logos-grid { gap: 40px; }
131
+
132
+ /* Tamanhos das logos */
133
+ .logo-sm .logo-image {
134
+ max-height: 50px;
135
+ max-width: 120px;
136
+ }
137
+ .logo-md .logo-image {
138
+ max-height: 70px;
139
+ max-width: 160px;
140
+ }
141
+ .logo-lg .logo-image {
142
+ max-height: 90px;
143
+ max-width: 200px;
144
+ }
145
+
146
+ /* Estilo do card de logo */
147
+ .logo-card {
148
+ padding: 20px;
149
+ border-radius: 12px;
150
+ transition: all 0.3s ease;
151
+ display: flex;
152
+ align-items: center;
153
+ justify-content: center;
154
+ background: rgba(255, 255, 255, 0.02);
155
+ cursor: pointer;
156
+ position: relative;
157
+ overflow: hidden;
158
+ }
159
+
160
+ .logo-card:hover {
161
+ transform: translateY(-3px) scale(1.02);
162
+ background: rgba(255, 255, 255, 0.08);
163
+ box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
164
+ }
165
+
166
+ .logo-image-container {
167
+ display: flex;
168
+ align-items: center;
169
+ justify-content: center;
170
+ height: 100%;
171
+ min-height: 60px;
172
+ position: relative;
173
+ z-index: 1;
174
+ }
175
+
176
+ .logo-image {
177
+ max-width: 100%;
178
+ height: auto;
179
+ object-fit: contain;
180
+ transition: all 0.3s ease;
181
+ filter: brightness(0.95) contrast(1.05);
182
+ }
183
+
184
+ .logo-card:hover .logo-image {
185
+ filter: brightness(1) contrast(1.1);
186
+ transform: scale(1.05);
187
+ }
188
+
189
+ /* Efeito shimmer sutil */
190
+ .logo-card::after {
191
+ content: '';
192
+ position: absolute;
193
+ top: 0;
194
+ left: -100%;
195
+ width: 100%;
196
+ height: 100%;
197
+ background: linear-gradient(
198
+ 90deg,
199
+ transparent,
200
+ rgba(255, 255, 255, 0.1),
201
+ transparent
202
+ );
203
+ transition: left 0.8s ease;
204
+ }
205
+
206
+ .logo-card:hover::after {
207
+ left: 100%;
208
+ }
209
+
210
+ /* Responsividade */
211
+ @media (max-width: 992px) {
212
+ .logos-titulo {
213
+ font-size: 2.8rem;
214
+ text-align: center;
215
+ margin-bottom: 30px;
216
+ }
217
+
218
+ .logos-simple-block {
219
+ padding: 60px 0;
220
+ }
221
+ }
222
+
223
+ @media (max-width: 768px) {
224
+ .logos-simple-block {
225
+ padding: 50px 0;
226
+ min-height: 400px;
227
+ }
228
+
229
+ .logos-titulo {
230
+ font-size: 2.2rem;
231
+ margin-bottom: 25px;
232
+ }
233
+
234
+ .logos-conteudo {
235
+ padding: 40px 25px;
236
+ min-height: 280px;
237
+ border-radius: 12px;
238
+ }
239
+
240
+ .logos-grid-2,
241
+ .logos-grid-3,
242
+ .logos-grid-4,
243
+ .logos-grid-5,
244
+ .logos-grid-6 {
245
+ grid-template-columns: repeat(3, 1fr);
246
+ max-width: 100%;
247
+ }
248
+
249
+ .spacing-sm .logos-grid { gap: 15px; }
250
+ .spacing-md .logos-grid { gap: 20px; }
251
+ .spacing-lg .logos-grid { gap: 25px; }
252
+ }
253
+
254
+ @media (max-width: 480px) {
255
+ .logos-titulo {
256
+ font-size: 1.8rem;
257
+ }
258
+
259
+ .logos-conteudo {
260
+ padding: 30px 20px;
261
+ min-height: 250px;
262
+ }
263
+
264
+ .logos-grid-2,
265
+ .logos-grid-3,
266
+ .logos-grid-4,
267
+ .logos-grid-5,
268
+ .logos-grid-6 {
269
+ grid-template-columns: repeat(2, 1fr);
270
+ }
271
+
272
+ .logo-card {
273
+ padding: 15px;
274
+ }
275
+
276
+ .logo-sm .logo-image { max-height: 40px; max-width: 100px; }
277
+ .logo-md .logo-image { max-height: 50px; max-width: 120px; }
278
+ .logo-lg .logo-image { max-height: 60px; max-width: 140px; }
279
+ }
280
+
281
+ @media (max-width: 360px) {
282
+ .logos-grid-2,
283
+ .logos-grid-3,
284
+ .logos-grid-4,
285
+ .logos-grid-5,
286
+ .logos-grid-6 {
287
+ grid-template-columns: 1fr;
288
+ }
289
+ }
290
+
291
+ /* Animações de entrada */
292
+ @keyframes fadeInUp {
293
+ from {
294
+ opacity: 0;
295
+ transform: translateY(30px);
296
+ }
297
+ to {
298
+ opacity: 1;
299
+ transform: translateY(0);
300
+ }
301
+ }
302
+
303
+ @keyframes fadeInScale {
304
+ from {
305
+ opacity: 0;
306
+ transform: scale(0.8);
307
+ }
308
+ to {
309
+ opacity: 1;
310
+ transform: scale(1);
311
+ }
312
+ }
313
+
314
+ .logos-titulo {
315
+ animation: fadeInUp 0.8s ease forwards;
316
+ }
317
+
318
+ .logos-conteudo {
319
+ animation: fadeInScale 0.8s ease forwards;
320
+ animation-delay: 0.2s;
321
+ opacity: 0;
322
+ }
323
+
324
+ .logo-card {
325
+ animation: fadeInUp 0.6s ease forwards;
326
+ opacity: 0;
327
+ }
328
+
329
+ </style>