@magicfeedback/popup-sdk 1.5.0 → 1.7.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.
@@ -178,11 +178,2096 @@ var init_font = __esm({
178
178
  }
179
179
  });
180
180
 
181
+ // src/i18n/labels.ts
182
+ function resolveLocale(lang) {
183
+ if (typeof lang !== "string") return "en";
184
+ const normalized = lang.trim().toLowerCase().replace(/_/g, "-");
185
+ if (!normalized) return "en";
186
+ if (normalized === "zh" || normalized.startsWith("zh-")) return "zh-CN";
187
+ const primary = normalized.split("-")[0];
188
+ switch (primary) {
189
+ case "en":
190
+ return "en";
191
+ case "es":
192
+ return "es";
193
+ case "da":
194
+ return "da";
195
+ case "no":
196
+ case "nb":
197
+ case "nn":
198
+ return "no";
199
+ case "sv":
200
+ return "sv";
201
+ case "fi":
202
+ return "fi";
203
+ case "de":
204
+ return "de";
205
+ case "fr":
206
+ return "fr";
207
+ case "pt":
208
+ return "pt";
209
+ case "ar":
210
+ return "ar";
211
+ case "bn":
212
+ return "bn";
213
+ default:
214
+ return "en";
215
+ }
216
+ }
217
+ function isRtlLanguage(lang) {
218
+ return RTL_LOCALES.includes(resolveLocale(lang));
219
+ }
220
+ function directionFor(lang) {
221
+ return isRtlLanguage(lang) ? "rtl" : "ltr";
222
+ }
223
+ function getLabels(lang) {
224
+ return LABELS[resolveLocale(lang)];
225
+ }
226
+ function resolveActionLabels(actions, lang) {
227
+ const labels = getLabels(lang);
228
+ const pick = (value, fallback) => {
229
+ const trimmed = typeof value === "string" ? value.trim() : "";
230
+ return trimmed ? value : fallback;
231
+ };
232
+ return {
233
+ accept: pick(actions?.accept?.label, labels.accept),
234
+ decline: pick(actions?.decline?.label, labels.decline),
235
+ start: pick(actions?.start?.label, labels.start),
236
+ complete: pick(actions?.complete?.label, labels.complete),
237
+ back: pick(actions?.back?.label, labels.back)
238
+ };
239
+ }
240
+ var EN, ES, DA, NO, SV, FI, DE, FR, PT, AR, BN, ZH_CN, LABELS, RTL_LOCALES, RESOLVE_LOCALE_JS;
241
+ var init_labels = __esm({
242
+ "src/i18n/labels.ts"() {
243
+ "use strict";
244
+ EN = {
245
+ accept: "Send",
246
+ decline: "Cancel",
247
+ start: "Start survey",
248
+ complete: "Complete survey",
249
+ back: "Back",
250
+ question: "Question",
251
+ of: "of",
252
+ followUp: "Follow-up",
253
+ closeAria: "Close popup",
254
+ loadingAria: "Loading survey",
255
+ errorRequired: "Please answer the required question to continue.",
256
+ errorSubmit: "An error occurred while submitting. Please try again or close the popup."
257
+ };
258
+ ES = {
259
+ accept: "Enviar",
260
+ decline: "Cancelar",
261
+ start: "Empezar encuesta",
262
+ complete: "Completar encuesta",
263
+ back: "Atr\xE1s",
264
+ question: "Pregunta",
265
+ of: "de",
266
+ followUp: "Seguimiento",
267
+ closeAria: "Cerrar ventana emergente",
268
+ loadingAria: "Cargando encuesta",
269
+ errorRequired: "Responde la pregunta obligatoria para continuar.",
270
+ errorSubmit: "Se produjo un error al enviar. Int\xE9ntalo de nuevo o cierra la ventana."
271
+ };
272
+ DA = {
273
+ accept: "Send",
274
+ decline: "Annuller",
275
+ start: "Start unders\xF8gelse",
276
+ complete: "Afslut unders\xF8gelse",
277
+ back: "Tilbage",
278
+ question: "Sp\xF8rgsm\xE5l",
279
+ of: "af",
280
+ followUp: "Opf\xF8lgning",
281
+ closeAria: "Luk pop op",
282
+ loadingAria: "Indl\xE6ser unders\xF8gelse",
283
+ errorRequired: "Besvar venligst det obligatoriske sp\xF8rgsm\xE5l for at forts\xE6tte.",
284
+ errorSubmit: "Der opstod en fejl under afsendelsen. Pr\xF8v igen, eller luk pop op-vinduet."
285
+ };
286
+ NO = {
287
+ accept: "Send",
288
+ decline: "Avbryt",
289
+ start: "Start unders\xF8kelse",
290
+ complete: "Fullf\xF8r unders\xF8kelse",
291
+ back: "Tilbake",
292
+ question: "Sp\xF8rsm\xE5l",
293
+ of: "av",
294
+ followUp: "Oppf\xF8lging",
295
+ closeAria: "Lukk popup",
296
+ loadingAria: "Laster unders\xF8kelse",
297
+ errorRequired: "Svar p\xE5 det obligatoriske sp\xF8rsm\xE5let for \xE5 fortsette.",
298
+ errorSubmit: "Det oppstod en feil under innsendingen. Pr\xF8v igjen, eller lukk popupen."
299
+ };
300
+ SV = {
301
+ accept: "Skicka",
302
+ decline: "Avbryt",
303
+ start: "Starta unders\xF6kning",
304
+ complete: "Slutf\xF6r unders\xF6kning",
305
+ back: "Tillbaka",
306
+ question: "Fr\xE5ga",
307
+ of: "av",
308
+ followUp: "Uppf\xF6ljning",
309
+ closeAria: "St\xE4ng popup",
310
+ loadingAria: "Laddar unders\xF6kning",
311
+ errorRequired: "Svara p\xE5 den obligatoriska fr\xE5gan f\xF6r att forts\xE4tta.",
312
+ errorSubmit: "Ett fel uppstod vid inskickningen. F\xF6rs\xF6k igen eller st\xE4ng popupen."
313
+ };
314
+ FI = {
315
+ accept: "L\xE4het\xE4",
316
+ decline: "Peruuta",
317
+ start: "Aloita kysely",
318
+ complete: "Viimeistele kysely",
319
+ back: "Takaisin",
320
+ question: "Kysymys",
321
+ of: "/",
322
+ followUp: "Jatkokysymys",
323
+ closeAria: "Sulje ponnahdusikkuna",
324
+ loadingAria: "Ladataan kysely\xE4",
325
+ errorRequired: "Vastaa pakolliseen kysymykseen jatkaaksesi.",
326
+ errorSubmit: "L\xE4hetyksess\xE4 tapahtui virhe. Yrit\xE4 uudelleen tai sulje ponnahdusikkuna."
327
+ };
328
+ DE = {
329
+ accept: "Senden",
330
+ decline: "Abbrechen",
331
+ start: "Umfrage starten",
332
+ complete: "Umfrage abschlie\xDFen",
333
+ back: "Zur\xFCck",
334
+ question: "Frage",
335
+ of: "von",
336
+ followUp: "Folgefrage",
337
+ closeAria: "Popup schlie\xDFen",
338
+ loadingAria: "Umfrage wird geladen",
339
+ errorRequired: "Bitte beantworte die Pflichtfrage, um fortzufahren.",
340
+ errorSubmit: "Beim Senden ist ein Fehler aufgetreten. Versuche es erneut oder schlie\xDFe das Popup."
341
+ };
342
+ FR = {
343
+ accept: "Envoyer",
344
+ decline: "Annuler",
345
+ start: "Commencer l'enqu\xEAte",
346
+ complete: "Terminer l'enqu\xEAte",
347
+ back: "Retour",
348
+ question: "Question",
349
+ of: "sur",
350
+ followUp: "Question compl\xE9mentaire",
351
+ closeAria: "Fermer la fen\xEAtre",
352
+ loadingAria: "Chargement de l'enqu\xEAte",
353
+ errorRequired: "Veuillez r\xE9pondre \xE0 la question obligatoire pour continuer.",
354
+ errorSubmit: "Une erreur s'est produite lors de l'envoi. R\xE9essayez ou fermez la fen\xEAtre."
355
+ };
356
+ PT = {
357
+ accept: "Enviar",
358
+ decline: "Cancelar",
359
+ start: "Iniciar question\xE1rio",
360
+ complete: "Concluir question\xE1rio",
361
+ back: "Voltar",
362
+ question: "Pergunta",
363
+ of: "de",
364
+ followUp: "Seguimento",
365
+ closeAria: "Fechar janela",
366
+ loadingAria: "A carregar question\xE1rio",
367
+ errorRequired: "Responda \xE0 pergunta obrigat\xF3ria para continuar.",
368
+ errorSubmit: "Ocorreu um erro ao enviar. Tente novamente ou feche a janela."
369
+ };
370
+ AR = {
371
+ accept: "\u0625\u0631\u0633\u0627\u0644",
372
+ decline: "\u0625\u0644\u063A\u0627\u0621",
373
+ start: "\u0627\u0628\u062F\u0623 \u0627\u0644\u0627\u0633\u062A\u0628\u064A\u0627\u0646",
374
+ complete: "\u0625\u0646\u0647\u0627\u0621 \u0627\u0644\u0627\u0633\u062A\u0628\u064A\u0627\u0646",
375
+ back: "\u0631\u062C\u0648\u0639",
376
+ question: "\u0633\u0624\u0627\u0644",
377
+ of: "\u0645\u0646",
378
+ followUp: "\u0633\u0624\u0627\u0644 \u0645\u062A\u0627\u0628\u0639\u0629",
379
+ closeAria: "\u0625\u063A\u0644\u0627\u0642 \u0627\u0644\u0646\u0627\u0641\u0630\u0629 \u0627\u0644\u0645\u0646\u0628\u062B\u0642\u0629",
380
+ loadingAria: "\u062C\u0627\u0631\u064D \u062A\u062D\u0645\u064A\u0644 \u0627\u0644\u0627\u0633\u062A\u0628\u064A\u0627\u0646",
381
+ errorRequired: "\u064A\u0631\u062C\u0649 \u0627\u0644\u0625\u062C\u0627\u0628\u0629 \u0639\u0644\u0649 \u0627\u0644\u0633\u0624\u0627\u0644 \u0627\u0644\u0645\u0637\u0644\u0648\u0628 \u0644\u0644\u0645\u062A\u0627\u0628\u0639\u0629.",
382
+ errorSubmit: "\u062D\u062F\u062B \u062E\u0637\u0623 \u0623\u062B\u0646\u0627\u0621 \u0627\u0644\u0625\u0631\u0633\u0627\u0644. \u064A\u0631\u062C\u0649 \u0627\u0644\u0645\u062D\u0627\u0648\u0644\u0629 \u0645\u0631\u0629 \u0623\u062E\u0631\u0649 \u0623\u0648 \u0625\u063A\u0644\u0627\u0642 \u0627\u0644\u0646\u0627\u0641\u0630\u0629."
383
+ };
384
+ BN = {
385
+ accept: "\u09AA\u09BE\u09A0\u09BE\u09A8",
386
+ decline: "\u09AC\u09BE\u09A4\u09BF\u09B2",
387
+ start: "\u099C\u09B0\u09BF\u09AA \u09B6\u09C1\u09B0\u09C1 \u0995\u09B0\u09C1\u09A8",
388
+ complete: "\u099C\u09B0\u09BF\u09AA \u09B8\u09AE\u09CD\u09AA\u09C2\u09B0\u09CD\u09A3 \u0995\u09B0\u09C1\u09A8",
389
+ back: "\u09AA\u09BF\u099B\u09A8\u09C7",
390
+ question: "\u09AA\u09CD\u09B0\u09B6\u09CD\u09A8",
391
+ of: "/",
392
+ followUp: "\u09AB\u09B2\u09CB-\u0986\u09AA",
393
+ closeAria: "\u09AA\u09AA\u0986\u09AA \u09AC\u09A8\u09CD\u09A7 \u0995\u09B0\u09C1\u09A8",
394
+ loadingAria: "\u099C\u09B0\u09BF\u09AA \u09B2\u09CB\u09A1 \u09B9\u099A\u09CD\u099B\u09C7",
395
+ errorRequired: "\u099A\u09BE\u09B2\u09BF\u09AF\u09BC\u09C7 \u09AF\u09C7\u09A4\u09C7 \u0986\u09AC\u09B6\u09CD\u09AF\u0995 \u09AA\u09CD\u09B0\u09B6\u09CD\u09A8\u09C7\u09B0 \u0989\u09A4\u09CD\u09A4\u09B0 \u09A6\u09BF\u09A8\u0964",
396
+ errorSubmit: "\u099C\u09AE\u09BE \u09A6\u09C7\u0993\u09AF\u09BC\u09BE\u09B0 \u09B8\u09AE\u09AF\u09BC \u098F\u0995\u099F\u09BF \u09A4\u09CD\u09B0\u09C1\u099F\u09BF \u0998\u099F\u09C7\u099B\u09C7\u0964 \u0986\u09AC\u09BE\u09B0 \u099A\u09C7\u09B7\u09CD\u099F\u09BE \u0995\u09B0\u09C1\u09A8 \u09AC\u09BE \u09AA\u09AA\u0986\u09AA \u09AC\u09A8\u09CD\u09A7 \u0995\u09B0\u09C1\u09A8\u0964"
397
+ };
398
+ ZH_CN = {
399
+ accept: "\u53D1\u9001",
400
+ decline: "\u53D6\u6D88",
401
+ start: "\u5F00\u59CB\u95EE\u5377",
402
+ complete: "\u5B8C\u6210\u95EE\u5377",
403
+ back: "\u8FD4\u56DE",
404
+ question: "\u95EE\u9898",
405
+ of: "/",
406
+ followUp: "\u8FFD\u95EE",
407
+ closeAria: "\u5173\u95ED\u5F39\u7A97",
408
+ loadingAria: "\u6B63\u5728\u52A0\u8F7D\u95EE\u5377",
409
+ errorRequired: "\u8BF7\u56DE\u7B54\u5FC5\u7B54\u9898\u540E\u7EE7\u7EED\u3002",
410
+ errorSubmit: "\u63D0\u4EA4\u65F6\u51FA\u9519\u3002\u8BF7\u91CD\u8BD5\u6216\u5173\u95ED\u5F39\u7A97\u3002"
411
+ };
412
+ LABELS = {
413
+ en: EN,
414
+ es: ES,
415
+ da: DA,
416
+ no: NO,
417
+ sv: SV,
418
+ fi: FI,
419
+ de: DE,
420
+ fr: FR,
421
+ pt: PT,
422
+ ar: AR,
423
+ bn: BN,
424
+ "zh-CN": ZH_CN
425
+ };
426
+ RTL_LOCALES = ["ar"];
427
+ RESOLVE_LOCALE_JS = `function ddResolveLocale(lang){
428
+ if(typeof lang!=='string') return 'en';
429
+ var n=lang.trim().toLowerCase().replace(/_/g,'-');
430
+ if(!n) return 'en';
431
+ if(n==='zh'||n.indexOf('zh-')===0) return 'zh-CN';
432
+ var p=n.split('-')[0];
433
+ if(p==='en') return 'en';
434
+ if(p==='es') return 'es';
435
+ if(p==='da') return 'da';
436
+ if(p==='no'||p==='nb'||p==='nn') return 'no';
437
+ if(p==='sv') return 'sv';
438
+ if(p==='fi') return 'fi';
439
+ if(p==='de') return 'de';
440
+ if(p==='fr') return 'fr';
441
+ if(p==='pt') return 'pt';
442
+ if(p==='ar') return 'ar';
443
+ if(p==='bn') return 'bn';
444
+ return 'en';
445
+ }`;
446
+ }
447
+ });
448
+
181
449
  // src/assets/style.css
182
450
  var style_default;
183
451
  var init_style = __esm({
184
452
  "src/assets/style.css"() {
185
- style_default = '.magicfeedback-container {\n width: 100%;\n}\n\n\n.magicfeedback-success-message,\n.magicfeedback-info-message,\n.magicfeedback-start-message,\n.magicfeedback-container{\n animation-duration: 0.5s;\n animation-name: animate-fade;\n animation-delay: 0.25s;\n animation-fill-mode: backwards;\n\n font-style: normal;\n text-align: justify;\n font-weight: 400;\n font-size: 1.2rem;\n color: #475569;\n line-height: 1.5;\n}\n\n@keyframes animate-fade {\n 0% { opacity: 0; }\n 100% { opacity: 1; }\n}\n\n.magicfeedback-form {\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n align-items: center;\n width: 100%;\n}\n.magicfeedback-questions {\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n align-items: flex-start;\n width: 100%;\n}\n\n.magicfeedback-div {\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n align-items: flex-start;\n margin-bottom: 10px;\n width: 100%;\n}\n\n.magicfeedback-label {\n margin-bottom: 25px;\n margin-top: 20px;\n font-weight: 400;\n font-family: inherit;\n font-size: 1.2rem;\n color: #212529;\n text-align: start;\n word-wrap: break-word;\n white-space: normal;\n\n}\n\n.magicfeedback-checkbox {\n display: flex;\n flex-direction: column;\n flex-wrap: wrap;\n width: 100%;\n}\n\n.magicfeedback-checkbox-container {\n display: flex;\n flex-direction: row;\n justify-content: flex-start;\n align-items: center;\n margin-bottom: 5px;\n margin-top: 5px;\n}\n\n/* Cualificado con `div`: @magicfeedback/native reutiliza la clase "magicfeedback-radio"\n tambi\xE9n en el <input> de cada opci\xF3n (rating), y sin el tag este selector lo capturaba\n tambi\xE9n, rompiendo su tama\xF1o (el input pasaba a display:flex; width:100%). */\ndiv.magicfeedback-radio {\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n flex-wrap: wrap;\n width: 100%;\n margin-right: 5px;\n padding: 5px;\n box-sizing: border-box;\n}\n\n.magicfeedback-checkbox-container,\n.magicfeedback-radio-container {\n display: flex;\n flex-direction: row;\n justify-content: flex-start;\n align-items: center;\n margin: 5px;\n padding: 5px 0;\n background-color: #fff;\n border-radius: 5px;\n box-shadow: 0 0 3px #ccc;\n}\n\n.deepdots-popup input::-webkit-outer-spin-button,\n.deepdots-popup input::-webkit-inner-spin-button {\n -webkit-appearance: none;\n -moz-appearance: textfield;\n}\n\n.magicfeedback-checkbox input[type="checkbox"] {\n margin-right: 5px;\n margin-left: 5px;\n width: 20px;\n height: 20px;\n cursor: pointer;\n}\n\n\n.magicfeedback-checkbox label,\n.magicfeedback-radio-container label {\n margin-left: 5px;\n font-weight: 400;\n font-family: inherit;\n font-size: 16px;\n color: #212529;\n text-align: start;\n width: 100%;\n}\n\n.deepdots-popup p {\n margin-bottom: 0px;\n font-size: 12px;\n}\n\n.deepdots-popup h2 {\n line-height: 1.66;\n margin: 0;\n padding: 0;\n font-weight: 900;\n color: #222;\n font-family: var(--deepdots-font, \'Montserrat\');\n font-size: 18px;\n text-transform: uppercase;\n text-align: center;\n margin-bottom: 40px;\n}\n\n/* Los controles de formulario no heredan font-family por defecto: cuando hay\n fuente custom (clase deepdots-has-font), los forzamos a usar la del contenedor. */\n.deepdots-popup.deepdots-has-font button,\n.deepdots-popup.deepdots-has-font input,\n.deepdots-popup.deepdots-has-font textarea,\n.deepdots-popup.deepdots-has-font select {\n font-family: var(--deepdots-font, inherit);\n}\n\n.deepdots-popup h6 {\n margin-bottom: 1rem;\n}\n\n.deepdots-popup input[type="date"],\n.deepdots-popup input[type="text"],\n.deepdots-popup input[type="number"],\n.deepdots-popup input[type="email"],\n.deepdots-popup input[type="password"],\n.deepdots-popup textarea,\n.deepdots-popup select {\n box-sizing: border-box;\n padding: 10px;\n margin: 10px 0;\n width: 100%;\n border: 2px solid #ccc; /* Default border color - you can customize this */\n border-radius: 5px;\n font-size: 18px;\n outline: none;\n transition: border-color 0.3s ease;\n min-height: 50px;\n font-family: inherit;\n -webkit-appearance: none;\n}\n\n.deepdots-popup select {\n background-image: linear-gradient(45deg, transparent 50%, gray 50%),\n linear-gradient(135deg, gray 50%, transparent 50%),\n linear-gradient(to right, #ccc, #ccc);\n background-position: calc(100% - 20px) calc(1em + 2px),\n calc(100% - 15px) calc(1em + 2px),\n calc(100% - 2.5em) 0.5em;\n background-size: 5px 5px,\n 5px 5px,\n 1px 1.5em;\n background-repeat: no-repeat;\n}\n\n.magicfeedback-boolean-container {\n display: flex;\n flex-direction: row;\n justify-content: flex-start;\n align-items: center;\n margin: 10px 0;\n width: 100%;\n}\n\n.magicfeedback-boolean-container label {\n margin-left: 10px;\n font-weight: 400;\n font-size: 16px;\n width: 100%;\n padding-top: 5px;\n}\n\n.magicfeedback-boolean-option {\n margin-right: 10px;\n margin-left: 10px;\n width: 100%;\n height: 38px;\n border-radius: 8px;\n font-size: 16px;\n cursor: pointer;\n border: 1px solid #ced4da !important;\n}\n\n.magicfeedback-boolean-option label {\n font-weight: 400;\n font-size: 16px;\n color: #475569;\n cursor: pointer;\n width: 100%;\n height: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n border-radius: inherit;\n}\n\n.magicfeedback-boolean-option input[type=radio] + label:hover {\n color: #007bff;\n}\n\n.magicfeedback-boolean-option input[type=radio]:checked + label {\n color: #007bff;\n background-color: #cadff8;\n}\n\n/* Tama\xF1o expl\xEDcito y sin padding: un radio nativo con `padding: 20px` y solo `width` (sin\n `height`) se dibujaba enorme en WebKit, que s\xED aplica el padding al control. Se ve\xEDa en\n iOS (WebView de React Native y Safari) y no en Chrome. `flex: 0 0 auto` evita que el\n contenedor flex de la opci\xF3n lo estire. */\n.deepdots-popup input[type="radio"] {\n padding: 0;\n margin: 10px 0 10px 15px;\n width: 20px;\n height: 20px;\n min-width: 20px;\n flex: 0 0 auto;\n background-color: #fff;\n box-shadow: none;\n}\n\n/* Style for focused input/select */\n.deepdots-popup input:focus, .deepdots-popup select:focus {\n border-color: #4CAF50; /* Highlight color when focused - you can customize this */\n}\n\n/* Style for invalid input (example: validation error) */\n.deepdots-popup input.error, .deepdots-popup select.error {\n border-color: #ff3333; /* Red color for error state - you can customize this */\n}\n\n.magicfeedback-action-container {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n align-items: center;\n margin-top: 10px;\n width: 100%;\n}\n\n.magicfeedback-action-container .magicfeedback-submit {\n cursor: pointer;\n padding: 10px;\n margin: 10px 0;\n width: 100px;\n border-radius: 8px;\n font-size: 16px;\n outline: none;\n transition: border-color 0.3s ease;\n background-color: #1E293B;\n color: white;\n}\n\n.magicfeedback-action-container .magicfeedback-back {\n cursor: pointer;\n padding: 10px;\n margin: 10px 0;\n width: 100px;\n border: 0;\n border-radius: 8px;\n font-size: 16px;\n outline: none;\n transition: border-color 0.3s ease;\n background-color: transparent;\n color: #212529;\n}\n\n\n\n/* Rating styles */\n.magicfeedback-rating {\n width: 100%;\n}\n\n.magicfeedback-rating-container {\n display: flex;\n flex-direction: row;\n justify-content: space-around;\n flex-wrap: wrap;\n align-items: center;\n\n margin: 15px 5px;\n padding: 0;\n\n list-style: none;\n font-size: 1.5rem;\n cursor: pointer;\n user-select: none;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n}\n\n.magicfeedback-rating-placeholder-value,\n.magicfeedback-rating-placeholder{\n text-align: center;\n align-content: center;\n justify-content: center;\n text-wrap: wrap;\n}\n\n.magicfeedback-rating-option {\n margin: 0 0.5rem;\n padding: 0;\n}\n\n@media (max-width: 1024px) {\n .magicfeedback-rating-option {\n margin: 10px 0;\n padding: 0;\n width: 20%;\n display: flex;\n justify-content: center;\n }\n\n .magicfeedback-rating-placeholder-value {\n font-size: 0.75rem;\n margin-bottom: 1px;\n }\n .magicfeedback-rating-placeholder{\n justify-content: center;\n }\n\n .magicfeedback-rating-container {\n flex-wrap: wrap;\n justify-content: flex-start;\n }\n}\n\n\n.magicfeedback-rating-option-label-container {\n display: flex;\n flex-direction: column;\n}\n\n\n.magicfeedback-rating-option-label-container label {\n display: inline-block;\n text-align: center;\n margin-bottom: 0;\n font-weight: 600;\n font-size: 18px;\n color: #475569;\n}\n\n.magicfeedback-rating-option-label-container input[type=radio] {\n position: absolute;\n opacity: 0;\n width: 0;\n height: 0;\n}\n\n/* IMAGE STYLES */\n.magicfeedback-rating-option-label-container input[type=radio] + img {\n cursor: pointer;\n height: 48px;\n width: 48px;\n}\n\n/* LABEL STYLES */\n.magicfeedback-rating-option-label-container input[type=radio] + label {\n cursor: pointer;\n}\n\n/* CHECKED STYLES */\n.magicfeedback-rating-option-label-container input[type=radio]:checked + img {\n box-shadow: #007bff 0px 1px 4px, #007BFFA0 0px 0px 0px 2px;\n border-radius: 50%;\n}\n\n.magicfeedback-rating-number {\n width: 100%;\n}\n.magicfeedback-rating-container,\n.magicfeedback-rating-number-container {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n align-items: center;\n\n margin: 15px 0;\n padding: 0;\n\n list-style: none;\n font-size: 1.5rem;\n cursor: pointer;\n user-select: none;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n}\n\n/* Cuando hay placeholders (Very bad / Very good), el placeholder ocupa\n el 100% de la primera l\xEDnea y los boxes bajan a la siguiente */\n.magicfeedback-rating-number-container--with-placeholder {\n flex-wrap: wrap;\n align-items: flex-start;\n}\n\n.magicfeedback-rating-number-container--with-placeholder .magicfeedback-rating-placeholder {\n width: 100%;\n margin-bottom: 8px;\n}\n\n.magicfeedback-rating-number-container--with-placeholder .magicfeedback-rating-number-option {\n width: auto;\n flex: 1;\n}\n\n.magicfeedback-rating-number-option {\n display: flex;\n flex-direction: row;\n justify-content: flex-start;\n align-items: center;\n margin: 5px;\n padding: 0;\n list-style: none;\n font-size: 1.5rem;\n cursor: pointer;\n user-select: none;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n width: 100%;\n}\n\n.magicfeedback-rating-number-option-row{\n max-width: 100% !important;\n}\n\n.magicfeedback-rating-number-top-placeholder,\n.magicfeedback-rating-number-bottom-placeholder{\n text-align: center !important;\n align-content: center;\n justify-content: center;\n text-wrap: wrap;\n\n font-size: 15px;\n color: #475569;\n\n width: 100%;\n margin: auto;\n}\n\n@media (min-width: 650px) {\n .magicfeedback-rating-number-option-row +.magicfeedback-rating-number-container-ltr:first-child,\n .magicfeedback-rating-number-option-row + +.magicfeedback-rating-number-container-rtl:last-child {\n margin-left: 0;\n width: calc(100% - 10px);\n }\n\n .magicfeedback-rating-number-option-row +.magicfeedback-rating-number-container-rtl:first-child,\n .magicfeedback-rating-number-option-row + +.magicfeedback-rating-number-container-ltr:last-child {\n margin-right: 0;\n width: calc(100% - 10px);\n }\n}\n\n\n.magicfeedback-rating-number-option-label-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n}\n\n.magicfeedback-rating-number-option-label-container label {\n display: flex;\n align-items: center;\n justify-content: center;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n margin: 0 10px;\n font-weight: 600;\n font-size: 14px;\n color: #475569;\n cursor: pointer;\n width: 100%;\n height: 100%;\n min-height: 50px;\n text-align: center;\n padding: 0;\n border-radius: 4px;\n border: 1px solid #ced4da;\n background-color: rgba(246, 246, 246, 0.3);\n transition: background-color 0.15s ease-in-out;\n}\n\n.magicfeedback-rating-number-option-label-container input[type=radio] {\n position: absolute;\n opacity: 0;\n width: 0;\n height: 0;\n}\n\n.magicfeedback-rating-number-option-label-container input[type=radio] + label {\n cursor: pointer;\n}\n\n.magicfeedback-rating-number-option-label-container input[type=radio] + label:hover,\n.magicfeedback-rating-number-option-label-container input[type=radio]:checked + label {\n color: #007bff;\n border: 1px solid #007bff;\n background-color: rgba(86, 168, 253, 0.29);\n}\n\n.magicfeedback-rating-number-container-column{\n align-items: flex-start !important;\n}\n\n@media (max-width: 650px) {\n .magicfeedback-rating-number-container-ltr {\n justify-content: center;\n flex-wrap: wrap;\n }\n\n .magicfeedback-rating-number-container-rtl {\n justify-content: center;\n flex-wrap: wrap-reverse;\n }\n\n .magicfeedback-rating-number-option {\n max-width: 100%;\n height: 55px;\n margin: 5px 0;\n }\n}\n\n.magicfeedback-rating-star {\n width: 100%;\n}\n\n.magicfeedback-rating-star-container {\n display: flex !important;\n flex-direction: row !important;\n justify-content: center !important;\n align-items: center !important;\n flex-wrap: wrap;\n margin: 15px 5px;\n padding: 0;\n list-style: none;\n font-size: 1.5rem;\n cursor: pointer;\n user-select: none;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n}\n\n.magicfeedback-rating-star-option:not(:checked) > .rating__star {\n float: right;\n width: 1em;\n overflow: hidden;\n white-space: nowrap;\n cursor: pointer;\n font-size: 30px;\n color: #ccc;\n margin: 0 10px;\n}\n\n.magicfeedback-rating-star-option:not(:checked) > .rating__star:hover,\n.magicfeedback-rating-star-option:not(:checked) > .rating__star:hover ~ span {\n color: #deb217 !important;\n}\n\n.magicfeedback-rating-star-selected {\n color: #ffc700 !important;\n}\n\n\n/* Style for multiple choice image */\n.magicfeedback-image-option-label-container:hover {\n cursor: pointer;\n border: 0 !important;\n}\n\n.magicfeedback-image-option-label-container input[type=radio]:checked + img,\n.magicfeedback-image-option-label-container input[type=checkbox]:checked + img {\n border: 1px solid #007bff !important;\n box-shadow: 0 0 3px #007bff !important;\n}\n\n.magicfeedback-image-option-label-container input[type=radio] + img,\n.magicfeedback-image-option-label-container input[type=checkbox] + img {\n border: 1px solid transparent !important;\n}\n\n.magicfeedback-image-option-label-container{\n margin: 10px !important;\n height: calc(100% - 20px) !important;\n width: calc(100% - 20px) !important;\n}\n\n.magicfeedback-multiple-choice-image-option {\n display: flex;\n height: auto !important;\n box-shadow: 0 0 3px #ccc;\n}\n\n.magicfeedback-multiple-choice-image-label {\n font-size: 1rem;\n}\n\n.magicfeedback-consent-container {\n display: flex;\n flex-direction: row;\n justify-content: flex-start;\n align-items: center;\n margin: 10px 0;\n width: 100%;\n}\n\n.magicfeedback-consent-container label {\n margin-left: 10px;\n}\n\n.magicfeedback-start-message-container {\n /* ... add your start message container styles here ... */\n}\n\n.magicfeedback-success-message,\n.magicfeedback-info-message,\n.magicfeedback-start-message {\n margin: 35px 5px;\n}\n\n.magicfeedback-success-message p,\n.magicfeedback-info-message p,\n.magicfeedback-start-message p {\n font-style: normal;\n text-align: start;\n font-weight: 400;\n font-size: 16px;\n color: #475569;\n line-height: 1.5;\n}\n\n.magicfeedback-success-message img,\n.magicfeedback-info-message img,\n.magicfeedback-start-message img {\n width: 400px;\n max-width: 80%;\n height: auto;\n margin: 10px auto;\n}\n\n.magicfeedback-counter,\n.magicfeedback-point-system-total {\n margin: 10px 0 0 0 !important;\n display: flex !important;\n justify-content: right !important;\n align-items: center !important;\n width: 100%;\n}\n\n.magicfeedback-skip-container {\n background-color: transparent !important;\n border: 0 !important;\n color: #999999FF !important;\n padding: 0 !important;\n margin: 0 !important;\n cursor: pointer !important;\n font-size: 0.5em !important;\n font-weight: 400 !important;\n box-shadow: 0 0 0 !important;\n\n &:hover {\n color: #0066ff;\n }\n}\n\n.magicfeedback-skip-container input[type=checkbox] {\n border-color: #999999FF !important;\n border: 0 !important;\n cursor: pointer !important;\n\n}\n\n.magicfeedback-multi-question-matrix,\n.magicfeedback-point-system,\n.magicfeedback-priority-list {\n width: 100% !important;\n}\n\n.magicfeedback-multi-question-matrix-container,\n.magicfeedback-point-system-container,\n.magicfeedback-priority-list-container {\n width: 100% !important;\n overflow-x: auto;\n}\n\n.magicfeedback-point-system-list,\n.magicfeedback-priority-list-list,\n.magicfeedback-multi-question-matrix-table {\n width: 100% !important;\n padding: 0 !important;\n overflow-x: auto;\n}\n\n.magicfeedback-multi-question-matrix {\n position: relative !important;\n}\n\n.magicfeedback-multi-question-matrix-container {\n overflow: auto !important;\n padding-bottom: 10px;\n}\n\n.magicfeedback-multi-question-matrix-label{\n text-align: left !important;\n}\n.magicfeedback-priority-list-item {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n align-items: center;\n padding: 10px 0 10px 10px;\n\n border: 1px solid #ced4da;\n border-radius: 5px;\n margin: 10px 0 !important;\n}\n\n.magicfeedback-point-system-item {\n height: 45px;\n margin: 5px 0 !important;\n}\n\n.magicfeedback-point-system-item label,\n.magicfeedback-priority-list-item-label {\n font-family: inherit;\n font-size: 18px !important;\n color: #212529;\n text-align: start;\n word-wrap: break-word;\n white-space: normal;\n padding: 0 10px 0 0;\n}\n\n.magicfeedback-point-system-input-container {\n padding: 0 10px 0 0;\n border-radius: 5px;\n font-size: 14px;\n border: 1px solid #ced4da;\n height: 42px;\n margin: auto 0;\n}\n\n.magicfeedback-multi-question-matrix-table thead {\n margin-bottom: 20px;\n}\n\n.magicfeedback-multi-question-matrix-table th{\n text-align: center;\n font-weight: 400 !important;\n font-size: 1rem !important;\n padding: 0 10px !important;\n}\n\n.magicfeedback-multi-question-matrix-table th,\n.magicfeedback-multi-question-matrix-table td label,\n.magicfeedback-priority-list-arrow-up,\n.magicfeedback-priority-list-arrow-down {\n font-style: normal !important;\n font-weight: 400 !important;\n font-size: 1rem !important;\n color: #475569 !important;\n cursor: pointer !important;\n margin: 0 !important;\n line-height: inherit;\n}\n\n.magicfeedback-multi-question-matrix-table tr {\n align-items: center;\n margin: 5px 0;\n}\n\n.magicfeedback-multi-question-matrix-row-tr{\n border-radius: 5px;\n margin: 10px 0 !important;\n}\n\n.magicfeedback-multi-question-matrix-row-tr:nth-child(odd) {\n background-color: #f1f6f6; /* Light gray background for odd rows */\n}\n\n.magicfeedback-multi-question-matrix-row-tr:nth-child(even) {\n background-color: #ffffff; /* White background for even rows */\n}\n\n.magicfeedback-multi-question-matrix-row-label {\n text-align: left !important;\n}\n\n.magicfeedback-point-system-item span {\n color: #475569 !important;\n}\n\n.magicfeedback-point-system-item input {\n padding: 0;\n margin: 0 !important;\n width: auto !important;\n min-width: 100px !important;\n height: auto !important;\n min-height: 42px;\n cursor: pointer;\n font-size: 14px;\n text-align: center !important;\n}\n\n.magicfeedback-multi-question-matrix-table input {\n margin: auto !important;\n padding: 20px !important;\n width: 100% !important;\n height: 15px;\n border: 1px solid #ced4da;\n cursor: pointer;\n}\n\n.magicfeedback-image{\n max-height: 400px !important;\n height: auto !important;\n max-width: 100% !important;\n margin: 10px auto !important;\n}\n\n.magicfeedback-error{\n margin-top: 5px;\n}';
453
+ style_default = `/**
454
+ * NO EDITAR A MANO \u2014 generado por scripts/vendor-survey-css.mjs
455
+ *
456
+ * Copia de @magicfeedback/native@2.2.22 \u2192 dist/styles/magicfeedback-default.css
457
+ * (la hoja can\xF3nica del paquete, la que apunta su campo "style"), con estos cambios locales:
458
+ *
459
+ * 1. Sin el @import de Google Fonts (Nunito): no queremos una petici\xF3n externa desde la
460
+ * p\xE1gina del host, y la tipograf\xEDa la decide el popup.
461
+ * 2. .magicfeedback-container hereda la fuente del popup (var(--deepdots-font, inherit)).
462
+ * 3. Los selectores desnudos (h2, p, input, textarea, select, ::placeholder, .error) van
463
+ * acotados a .deepdots-popup: este CSS se inyecta en el <head> del host y sin acotar
464
+ * repintar\xEDa su web.
465
+ * 4. El grupo .magicfeedback-radio se cualifica como div.magicfeedback-radio (la clase acaba
466
+ * tambi\xE9n en el <input> del boolean).
467
+ * 5. Al final, un bloque de reglas propias del popup (fuente en los controles y padding del
468
+ * radio nativo).
469
+ *
470
+ * Las variables --mf-* se dejan en :root a prop\xF3sito: el modal del priority-list se portea a
471
+ * <body>, fuera de .deepdots-popup, y ah\xED las necesita.
472
+ *
473
+ * Para subir de versi\xF3n: npm i @magicfeedback/native@<v> && node scripts/vendor-survey-css.mjs
474
+ */
475
+
476
+ /**
477
+ * @magicfeedback/native - Default Styles
478
+ * Clean, minimal, and elegant survey rendering
479
+ */
480
+
481
+ /* @import de Google Fonts (Nunito) eliminado al vendorizar: la fuente la pone el popup. */
482
+
483
+ /* ========================================
484
+ CSS VARIABLES - Design SYSTEM
485
+ ======================================== */
486
+ :root {
487
+ /* Colors - Minimal Pastel */
488
+ /* --mf-primary is the one source of truth for brand/accent color \u2014
489
+ every token below derives from it via color-mix() (or references
490
+ it directly) so changing this single value, here or via a
491
+ per-integration override, keeps hover/light/border states in
492
+ sync automatically instead of going stale independently. Scoped
493
+ to genuinely interactive/accent surfaces (buttons, selected
494
+ chips, focus rings) \u2014 general body text stays on its own neutral
495
+ scale below, not tied to the brand color. */
496
+ --mf-primary: #5d7bad;
497
+ --mf-primary-hover: color-mix(in srgb, var(--mf-primary) 85%, black);
498
+ --mf-primary-light: color-mix(in srgb, var(--mf-primary) 15%, white);
499
+ /* a translucent tint \u2014 mixed with transparent (opacity), not white,
500
+ so it reads as a soft shadow of the brand color rather than a
501
+ pastel of it. */
502
+ --mf-primary-border: color-mix(in srgb, var(--mf-primary) 35%, transparent);
503
+
504
+ --mf-text-primary: #1E293B;
505
+ --mf-text-secondary: #475569;
506
+ --mf-text-muted: #94A3B8;
507
+
508
+ --mf-bg-primary: #F8FAFC;
509
+ --mf-bg-secondary: #FFFFFF;
510
+ --mf-bg-hover: #EEF2F6;
511
+
512
+ --mf-border: #E2E8F0;
513
+ --mf-border-focus: var(--mf-primary);
514
+
515
+ --mf-success: #16A34A;
516
+ --mf-error: #EF4444;
517
+ --mf-warning: #F59E0B;
518
+
519
+ --mf-surface: #FFFFFF;
520
+ --mf-surface-alt: #F1F5F9;
521
+ --mf-accent: #38BDF8;
522
+
523
+ /* Spacing */
524
+ --mf-space-xs: 0.25rem;
525
+ --mf-space-sm: 0.5rem;
526
+ --mf-space-md: 0.75rem;
527
+ --mf-space-lg: 1rem;
528
+ --mf-space-xl: 1.5rem;
529
+
530
+ /* Border Radius */
531
+ --mf-radius-sm: 0.5rem;
532
+ --mf-radius-md: 0.75rem;
533
+ --mf-radius-lg: 1.25rem;
534
+ --mf-radius-full: 9999px;
535
+
536
+ /* Shadows */
537
+ --mf-shadow-sm: 0 1px 2px 0 rgba(15, 23, 42, 0.06);
538
+ --mf-shadow-md: 0 8px 20px rgba(15, 23, 42, 0.08);
539
+ --mf-shadow-lg: 0 16px 30px rgba(15, 23, 42, 0.12);
540
+ --mf-shadow-focus: 0 0 0 3px rgba(30, 41, 59, 0.15);
541
+ --mf-shadow-card: 0 18px 40px rgba(15, 23, 42, 0.08);
542
+
543
+ /* Typography */
544
+ --mf-font-sans: "Nunito", "Quicksand", "Avenir Next", "Trebuchet MS", sans-serif;
545
+ --mf-font-size-sm: 0.875rem;
546
+ --mf-font-size-base: 1rem;
547
+ --mf-font-size-lg: 1.125rem;
548
+ --mf-font-size-xl: 1.25rem;
549
+ --mf-line-height: 1.6;
550
+
551
+ /* Font Weights */
552
+ --mf-font-weight-normal: 400;
553
+ --mf-font-weight-medium: 500;
554
+ --mf-font-weight-semibold: 600;
555
+ --mf-font-weight-bold: 700;
556
+ --mf-font-weight-extrabold: 800;
557
+
558
+ /* Transitions */
559
+ --mf-transition: all 0.2s ease;
560
+ --mf-transition-fast: all 0.15s ease;
561
+ }
562
+
563
+ /* ========================================
564
+ ANIMATIONS
565
+ ======================================== */
566
+ @keyframes mf-fade-in {
567
+ from {
568
+ opacity: 0;
569
+ transform: translateY(8px);
570
+ }
571
+ to {
572
+ opacity: 1;
573
+ transform: translateY(0);
574
+ }
575
+ }
576
+
577
+ @keyframes mf-slide-in {
578
+ from {
579
+ opacity: 0;
580
+ transform: translateX(-16px);
581
+ }
582
+ to {
583
+ opacity: 1;
584
+ transform: translateX(0);
585
+ }
586
+ }
587
+
588
+ @keyframes mf-scale-in {
589
+ from {
590
+ opacity: 0;
591
+ transform: scale(0.95);
592
+ }
593
+ to {
594
+ opacity: 1;
595
+ transform: scale(1);
596
+ }
597
+ }
598
+
599
+ @keyframes mf-pulse {
600
+ 0%,
601
+ 100% {
602
+ opacity: 1;
603
+ }
604
+ 50% {
605
+ opacity: 0.8;
606
+ }
607
+ }
608
+
609
+ /* ========================================
610
+ BASE CONTAINER
611
+ ======================================== */
612
+ .magicfeedback-container {
613
+ /* Local: hereda la fuente del popup; --deepdots-font viene de PopupStyle.font. */
614
+ font-family: var(--deepdots-font, inherit);
615
+ color: var(--mf-text-primary);
616
+ line-height: var(--mf-line-height);
617
+ animation: mf-fade-in 0.4s ease-out;
618
+ border-radius: var(--mf-radius-lg);
619
+ }
620
+
621
+ /* ========================================
622
+ MESSAGES
623
+ ======================================== */
624
+ .magicfeedback-success-message,
625
+ .magicfeedback-info-message,
626
+ .magicfeedback-start-message {
627
+ padding: var(--mf-space-lg);
628
+ margin: var(--mf-space-lg) 0;
629
+ animation: mf-scale-in 0.3s ease-out;
630
+ }
631
+
632
+ /* .magicfeedback-info-message/-start-message are set via innerHTML (see
633
+ renderInfoPage.ts / questions.service.ts's renderStartMessage) \u2014 whatever
634
+ rich text a survey author writes lands here as real HTML, not just the
635
+ <p>/<img> pair this used to style. Covering the rest of what a rich-text
636
+ editor commonly outputs (headings, lists, links, emphasis, quotes, code,
637
+ rules) keeps that content on the same type scale and palette as the rest
638
+ of the widget instead of falling back to unstyled browser defaults. */
639
+ .magicfeedback-success-message > :first-child,
640
+ .magicfeedback-info-message > :first-child,
641
+ .magicfeedback-start-message > :first-child {
642
+ margin-top: 0;
643
+ }
644
+
645
+ .magicfeedback-success-message > :last-child,
646
+ .magicfeedback-info-message > :last-child,
647
+ .magicfeedback-start-message > :last-child {
648
+ margin-bottom: 0;
649
+ }
650
+
651
+ .magicfeedback-success-message p,
652
+ .magicfeedback-info-message p,
653
+ .magicfeedback-start-message p {
654
+ font-size: var(--mf-font-size-base);
655
+ color: var(--mf-text-secondary);
656
+ margin: 0 0 var(--mf-space-md);
657
+ line-height: var(--mf-line-height);
658
+ }
659
+
660
+ .magicfeedback-info-message h1,
661
+ .magicfeedback-info-message h2,
662
+ .magicfeedback-info-message h3,
663
+ .magicfeedback-info-message h4,
664
+ .magicfeedback-info-message h5,
665
+ .magicfeedback-info-message h6,
666
+ .magicfeedback-start-message h1,
667
+ .magicfeedback-start-message h2,
668
+ .magicfeedback-start-message h3,
669
+ .magicfeedback-start-message h4,
670
+ .magicfeedback-start-message h5,
671
+ .magicfeedback-start-message h6 {
672
+ color: var(--mf-text-primary);
673
+ font-weight: var(--mf-font-weight-bold);
674
+ line-height: 1.3;
675
+ margin: var(--mf-space-lg) 0 var(--mf-space-sm);
676
+ text-align: start;
677
+ }
678
+
679
+ .magicfeedback-info-message h1, .magicfeedback-start-message h1 { font-size: var(--mf-font-size-xl); }
680
+ .magicfeedback-info-message h2, .magicfeedback-start-message h2 { font-size: var(--mf-font-size-lg); }
681
+ .magicfeedback-info-message h3,
682
+ .magicfeedback-info-message h4,
683
+ .magicfeedback-info-message h5,
684
+ .magicfeedback-info-message h6,
685
+ .magicfeedback-start-message h3,
686
+ .magicfeedback-start-message h4,
687
+ .magicfeedback-start-message h5,
688
+ .magicfeedback-start-message h6 { font-size: var(--mf-font-size-base); }
689
+
690
+ .magicfeedback-info-message strong,
691
+ .magicfeedback-info-message b,
692
+ .magicfeedback-start-message strong,
693
+ .magicfeedback-start-message b {
694
+ font-weight: var(--mf-font-weight-bold);
695
+ color: var(--mf-text-primary);
696
+ }
697
+
698
+ .magicfeedback-info-message a,
699
+ .magicfeedback-start-message a {
700
+ color: var(--mf-primary);
701
+ text-decoration: underline;
702
+ text-underline-offset: 2px;
703
+ }
704
+
705
+ .magicfeedback-info-message a:hover,
706
+ .magicfeedback-start-message a:hover {
707
+ color: var(--mf-primary-hover);
708
+ }
709
+
710
+ .magicfeedback-info-message ul,
711
+ .magicfeedback-info-message ol,
712
+ .magicfeedback-start-message ul,
713
+ .magicfeedback-start-message ol {
714
+ margin: 0 0 var(--mf-space-md);
715
+ padding-inline-start: var(--mf-space-xl);
716
+ color: var(--mf-text-secondary);
717
+ line-height: var(--mf-line-height);
718
+ }
719
+
720
+ .magicfeedback-info-message li + li,
721
+ .magicfeedback-start-message li + li {
722
+ margin-top: var(--mf-space-xs);
723
+ }
724
+
725
+ .magicfeedback-info-message blockquote,
726
+ .magicfeedback-start-message blockquote {
727
+ margin: 0 0 var(--mf-space-md);
728
+ padding: var(--mf-space-sm) var(--mf-space-md);
729
+ border-inline-start: 3px solid var(--mf-primary-border);
730
+ color: var(--mf-text-secondary);
731
+ font-style: italic;
732
+ }
733
+
734
+ .magicfeedback-info-message code,
735
+ .magicfeedback-start-message code {
736
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
737
+ font-size: 0.9em;
738
+ background: var(--mf-bg-hover);
739
+ padding: 0.15em 0.4em;
740
+ border-radius: var(--mf-radius-sm);
741
+ }
742
+
743
+ .magicfeedback-info-message pre,
744
+ .magicfeedback-start-message pre {
745
+ margin: 0 0 var(--mf-space-md);
746
+ padding: var(--mf-space-md);
747
+ background: var(--mf-bg-hover);
748
+ border-radius: var(--mf-radius-md);
749
+ overflow-x: auto;
750
+ }
751
+
752
+ .magicfeedback-info-message pre code,
753
+ .magicfeedback-start-message pre code {
754
+ background: none;
755
+ padding: 0;
756
+ }
757
+
758
+ .magicfeedback-info-message hr,
759
+ .magicfeedback-start-message hr {
760
+ border: none;
761
+ border-top: 1px solid var(--mf-border);
762
+ margin: var(--mf-space-lg) 0;
763
+ }
764
+
765
+ .magicfeedback-success-message img,
766
+ .magicfeedback-info-message img,
767
+ .magicfeedback-start-message img {
768
+ max-width: 100%;
769
+ height: auto;
770
+ margin: var(--mf-space-lg) auto;
771
+ display: block;
772
+ border-radius: var(--mf-radius-md);
773
+ }
774
+
775
+ .magicfeedback-image {
776
+ max-height: 400px;
777
+ height: auto;
778
+ max-width: 100%;
779
+ margin: var(--mf-space-lg) auto;
780
+ display: block;
781
+ border-radius: var(--mf-radius-md);
782
+ }
783
+
784
+ /* ========================================
785
+ FORM STRUCTURE
786
+ ======================================== */
787
+ .magicfeedback-form {
788
+ display: flex;
789
+ flex-direction: column;
790
+ gap: var(--mf-space-lg);
791
+ padding: clamp(16px, 2.5vw, 28px);
792
+ }
793
+
794
+ .magicfeedback-questions {
795
+ display: flex;
796
+ flex-direction: column;
797
+ gap: var(--mf-space-xl);
798
+ width: 100%;
799
+ }
800
+
801
+ .magicfeedback-div {
802
+ display: flex;
803
+ flex-direction: column;
804
+ gap: var(--mf-space-sm);
805
+ animation: mf-slide-in 0.3s ease-out;
806
+ background: var(--mf-bg-secondary);
807
+ border-radius: var(--mf-radius-md);
808
+ }
809
+
810
+ /* ========================================
811
+ LABELS & TYPOGRAPHY
812
+ ======================================== */
813
+ .magicfeedback-label {
814
+ font-size: var(--mf-font-size-lg);
815
+ font-weight: var(--mf-font-weight-bold);
816
+ color: var(--mf-text-primary);
817
+ line-height: var(--mf-line-height);
818
+ text-align: start;
819
+ letter-spacing: -0.01em;
820
+ }
821
+
822
+ .magicfeedback-sublabel {
823
+ font-size: var(--mf-font-size-base);
824
+ font-weight: var(--mf-font-weight-normal);
825
+ color: var(--mf-text-secondary);
826
+ margin-bottom: var(--mf-space-sm);
827
+ }
828
+
829
+ .deepdots-popup h2 {
830
+ font-size: var(--mf-font-size-xl);
831
+ font-weight: 600;
832
+ color: var(--mf-text-primary);
833
+ margin: 0 0 var(--mf-space-xl) 0;
834
+ text-align: center;
835
+ letter-spacing: -0.01em;
836
+ }
837
+
838
+ .deepdots-popup p {
839
+ margin: 0;
840
+ font-size: var(--mf-font-size-sm);
841
+ color: var(--mf-text-secondary);
842
+ }
843
+
844
+ /* ========================================
845
+ FORM INPUTS
846
+ ======================================== */
847
+ .deepdots-popup input[type="date"],
848
+ .deepdots-popup input[type="text"],
849
+ .deepdots-popup input[type="number"],
850
+ .deepdots-popup input[type="email"],
851
+ .deepdots-popup input[type="password"],
852
+ .deepdots-popup textarea,
853
+ .deepdots-popup select {
854
+ padding: 0.75rem 0.9rem;
855
+ font-size: var(--mf-font-size-base);
856
+ font-family: inherit;
857
+ color: var(--mf-text-primary);
858
+ background-color: var(--mf-surface);
859
+ border: 2px solid var(--mf-border);
860
+ border-radius: var(--mf-radius-md);
861
+ outline: none;
862
+ transition: var(--mf-transition);
863
+ -webkit-appearance: none;
864
+ appearance: none;
865
+ box-shadow: var(--mf-shadow-sm);
866
+ }
867
+
868
+ .deepdots-popup textarea {
869
+ min-height: 100px;
870
+ resize: vertical;
871
+ }
872
+
873
+ .deepdots-popup input::placeholder,
874
+ .deepdots-popup textarea::placeholder {
875
+ color: var(--mf-text-muted);
876
+ }
877
+
878
+ /* Remove number input spinners */
879
+ .deepdots-popup input::-webkit-outer-spin-button,
880
+ .deepdots-popup input::-webkit-inner-spin-button {
881
+ -webkit-appearance: none;
882
+ margin: 0;
883
+ }
884
+
885
+ .deepdots-popup input[type="number"] {
886
+ /* -moz-appearance: textfield; removed for lint compatibility */
887
+ }
888
+
889
+ /* Custom Select Arrow */
890
+ .deepdots-popup select {
891
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%2364748b' d='M6 9L1 4h10z'/%3E%3C/svg%3E");
892
+ background-repeat: no-repeat;
893
+ background-position: right var(--mf-space-md) center;
894
+ padding-inline-end: var(--mf-space-xl);
895
+ }
896
+
897
+ /* Error State */
898
+ .deepdots-popup input.error,
899
+ .deepdots-popup select.error,
900
+ .deepdots-popup textarea.error {
901
+ border-color: var(--mf-error);
902
+ }
903
+
904
+ .magicfeedback-error {
905
+ margin-top: var(--mf-space-xs);
906
+ font-size: var(--mf-font-size-sm);
907
+ color: var(--mf-error);
908
+ }
909
+
910
+ /* ========================================
911
+ CHECKBOX & RADIO OPTIONS
912
+ ======================================== */
913
+ .magicfeedback-checkbox,
914
+ div.magicfeedback-radio {
915
+ display: flex;
916
+ flex-direction: column;
917
+ gap: var(--mf-space-sm);
918
+ width: 100%;
919
+ }
920
+
921
+ .magicfeedback-checkbox-container,
922
+ .magicfeedback-radio-container {
923
+ display: flex;
924
+ align-items: center;
925
+ gap: var(--mf-space-sm);
926
+ padding: var(--mf-space-md);
927
+ border: 1.5px solid var(--mf-border);
928
+ border-radius: var(--mf-radius-md);
929
+ cursor: pointer;
930
+ transition: var(--mf-transition-fast);
931
+ }
932
+
933
+ .magicfeedback-checkbox-container:hover,
934
+ .magicfeedback-radio-container:hover {
935
+ background-color: var(--mf-bg-hover);
936
+ border-color: var(--mf-primary);
937
+ }
938
+
939
+ .magicfeedback-checkbox-container:has(input:checked),
940
+ .magicfeedback-radio-container:has(input:checked) {
941
+ background-color: var(--mf-primary-light);
942
+ border-color: var(--mf-primary);
943
+ }
944
+
945
+ .magicfeedback-checkbox input[type="checkbox"],
946
+ .magicfeedback-radio-container input[type="radio"] {
947
+ width: 18px;
948
+ height: 18px;
949
+ margin: 0;
950
+ cursor: pointer;
951
+ flex-shrink: 0;
952
+ accent-color: var(--mf-primary);
953
+ }
954
+
955
+ .magicfeedback-checkbox label,
956
+ .magicfeedback-radio-container label {
957
+ font-size: var(--mf-font-size-base);
958
+ text-align: start;
959
+ color: var(--mf-text-primary);
960
+ cursor: pointer;
961
+ margin: 0;
962
+ flex: 1;
963
+ }
964
+
965
+ /* ========================================
966
+ BOOLEAN OPTIONS
967
+ ======================================== */
968
+ .magicfeedback-boolean-container {
969
+ display: flex;
970
+ gap: var(--mf-space-md);
971
+ width: 100%;
972
+ }
973
+
974
+ .magicfeedback-boolean-option {
975
+ flex: 1;
976
+ position: relative;
977
+ }
978
+
979
+ .magicfeedback-boolean-option input[type="radio"] {
980
+ position: absolute;
981
+ opacity: 0;
982
+ width: 0;
983
+ height: 0;
984
+ }
985
+
986
+ .magicfeedback-boolean-option label {
987
+ display: flex;
988
+ align-items: center;
989
+ justify-content: center;
990
+ padding: var(--mf-space-md);
991
+ font-size: var(--mf-font-size-base);
992
+ font-weight: 500;
993
+ color: var(--mf-text-secondary);
994
+ border: 1.5px solid var(--mf-border);
995
+ border-radius: var(--mf-radius-md);
996
+ cursor: pointer;
997
+ transition: var(--mf-transition-fast);
998
+ margin: 0;
999
+ width: -webkit-fill-available;
1000
+ height: inherit;
1001
+ }
1002
+
1003
+ .magicfeedback-boolean-option label:hover {
1004
+ background-color: var(--mf-bg-hover);
1005
+ border-color: var(--mf-primary);
1006
+ }
1007
+
1008
+ .magicfeedback-boolean-option input[type="radio"]:checked + label {
1009
+ color: var(--mf-primary);
1010
+ background-color: var(--mf-primary-light);
1011
+ border-color: var(--mf-primary);
1012
+ font-weight: 600;
1013
+ }
1014
+
1015
+ /* ========================================
1016
+ RATING SYSTEMS
1017
+ ======================================== */
1018
+ .magicfeedback-rating,
1019
+ .magicfeedback-rating-number,
1020
+ .magicfeedback-rating-star {
1021
+ width: 100%;
1022
+ }
1023
+
1024
+ .magicfeedback-rating-container,
1025
+ .magicfeedback-rating-number-container,
1026
+ .magicfeedback-rating-star-container {
1027
+ display: flex;
1028
+ flex-wrap: wrap;
1029
+ gap: var(--mf-space-sm);
1030
+ justify-content: center;
1031
+ align-items: center;
1032
+ padding: var(--mf-space-md) 0;
1033
+ list-style: none;
1034
+ margin: 0;
1035
+ }
1036
+
1037
+ /* Caption line below the row \u2014 min on one side, max on the other (swapped
1038
+ for order: "rtl") \u2014 same simple, non-responsive pattern as the
1039
+ rating-number row caption. Used by rating-star and rating-emoji. */
1040
+ .magicfeedback-rating-placeholder {
1041
+ display: flex;
1042
+ justify-content: space-between;
1043
+ gap: var(--mf-space-md);
1044
+ width: 100%;
1045
+ margin-top: var(--mf-space-sm);
1046
+ font-size: var(--mf-font-size-sm);
1047
+ font-weight: var(--mf-font-weight-semibold);
1048
+ color: var(--mf-text-secondary);
1049
+ }
1050
+
1051
+ .magicfeedback-rating-placeholder-value {
1052
+ overflow-wrap: anywhere;
1053
+ }
1054
+
1055
+ .magicfeedback-rating-placeholder-value:last-child {
1056
+ text-align: end;
1057
+ }
1058
+
1059
+ /* Rating with Images */
1060
+ .magicfeedback-rating-option-label-container input[type="radio"] {
1061
+ position: absolute;
1062
+ opacity: 0;
1063
+ width: 0;
1064
+ height: 0;
1065
+ }
1066
+
1067
+ .magicfeedback-rating-option-label-container img {
1068
+ width: 56px;
1069
+ height: 56px;
1070
+ cursor: pointer;
1071
+ transition: var(--mf-transition-fast);
1072
+ border-radius: var(--mf-radius-full);
1073
+ border: 2px solid transparent;
1074
+ }
1075
+
1076
+ .magicfeedback-rating-option-label-container img:hover {
1077
+ transform: scale(1.1);
1078
+ border-color: var(--mf-primary);
1079
+ }
1080
+
1081
+ .magicfeedback-rating-option-label-container input[type="radio"]:checked + img {
1082
+ border-color: var(--mf-primary);
1083
+ box-shadow: 0 0 0 3px var(--mf-primary-light);
1084
+ }
1085
+
1086
+ .magicfeedback-rating-option-label-container label {
1087
+ display: block;
1088
+ text-align: center;
1089
+ font-size: var(--mf-font-size-sm);
1090
+ color: var(--mf-text-secondary);
1091
+ margin-top: var(--mf-space-xs);
1092
+ cursor: pointer;
1093
+ }
1094
+
1095
+ /* Rating Numbers \u2014 each option is its own outlined chip in the survey's
1096
+ primary color, with a gap between them. Row and column use the same
1097
+ chip; column additionally has room to show each option's own text
1098
+ plainly next to its number. */
1099
+
1100
+ /* Every size here is width:100%/flex:1 combined with the chip's own
1101
+ padding and border. Without border-box, the browser's default
1102
+ content-box adds that padding/border on TOP of the declared size, so
1103
+ the chip quietly overflows past its flex slot \u2014 reading as "not quite
1104
+ full width" or, worse, pushing into the next chip. */
1105
+ .magicfeedback-rating-number-container,
1106
+ .magicfeedback-rating-number-option,
1107
+ .magicfeedback-rating-number-option-label-container,
1108
+ .magicfeedback-rating-number-value {
1109
+ box-sizing: border-box;
1110
+ }
1111
+
1112
+ /* The shared rating-container rule (above, reused by star rating) sets
1113
+ align-items:center for its row-of-chips layout \u2014 in a stacked column
1114
+ that still nudges a 100%-wide chip inward instead of a true 0 offset.
1115
+ Force stretch so every chip fills the exact same width, flush on
1116
+ both sides. */
1117
+ .magicfeedback-rating-number-container-column,
1118
+ .magicfeedback-rating-number-container-column-reverse {
1119
+ align-items: stretch;
1120
+ }
1121
+
1122
+ /* Caption line below the row \u2014 the single place min/max labels live
1123
+ for row mode, shared by mobile and desktop. */
1124
+ .magicfeedback-rating-number-scale-labels {
1125
+ display: flex;
1126
+ justify-content: space-between;
1127
+ gap: var(--mf-space-md);
1128
+ margin-top: var(--mf-space-sm);
1129
+ font-size: var(--mf-font-size-sm);
1130
+ font-weight: var(--mf-font-weight-semibold);
1131
+ color: var(--mf-text-secondary);
1132
+ }
1133
+
1134
+ .magicfeedback-rating-number-scale-label {
1135
+ overflow-wrap: anywhere;
1136
+ }
1137
+
1138
+ .magicfeedback-rating-number-scale-label:last-child {
1139
+ text-align: end;
1140
+ }
1141
+
1142
+ /* Column, no per-option text: each row is its own separated chip, so
1143
+ the min/max labels bookend the stack from outside it \u2014 one line
1144
+ above the first chip, one below the last. Margin goes on whichever
1145
+ side actually faces the list \u2014 the "before" label (always the first
1146
+ child) gets space below it, the "after" one (always right after the
1147
+ container, extra option row or not) gets space above it \u2014 so both
1148
+ sit the same distance from the chips regardless of which one it is. */
1149
+ .magicfeedback-rating-number-scale-label-block {
1150
+ font-size: var(--mf-font-size-sm);
1151
+ font-weight: var(--mf-font-weight-semibold);
1152
+ color: var(--mf-text-secondary);
1153
+ text-align: center;
1154
+ }
1155
+
1156
+ .magicfeedback-rating-number-scale-label-block:first-child {
1157
+ margin-bottom: var(--mf-space-sm);
1158
+ }
1159
+
1160
+ .magicfeedback-rating-number-container + .magicfeedback-rating-number-scale-label-block {
1161
+ margin-top: var(--mf-space-sm);
1162
+ }
1163
+
1164
+ .magicfeedback-rating-number-option {
1165
+ display: flex;
1166
+ }
1167
+
1168
+ .magicfeedback-rating-number-option-label-container {
1169
+ position: relative;
1170
+ width: 100%;
1171
+ display: flex;
1172
+ cursor: pointer;
1173
+ }
1174
+
1175
+ .magicfeedback-rating-number-option-label-container input[type="radio"] {
1176
+ position: absolute;
1177
+ opacity: 0;
1178
+ width: 0;
1179
+ height: 0;
1180
+ }
1181
+
1182
+ .magicfeedback-rating-number-value {
1183
+ display: flex;
1184
+ align-items: center;
1185
+ justify-content: center;
1186
+ width: 100%;
1187
+ transition: var(--mf-transition-fast);
1188
+ color: var(--mf-text-secondary);
1189
+ font-weight: var(--mf-font-weight-semibold);
1190
+ }
1191
+
1192
+ /* Row: individual outlined chips in the survey's own primary color \u2014
1193
+ var(--mf-primary) so whatever brand color a given survey sets carries
1194
+ through automatically, no color hardcoded here. */
1195
+ .magicfeedback-rating-number-container-row,
1196
+ .magicfeedback-rating-number-container-row-reverse {
1197
+ flex-wrap: nowrap;
1198
+ gap: var(--mf-space-sm);
1199
+ }
1200
+
1201
+ .magicfeedback-rating-number-option-row,
1202
+ .magicfeedback-rating-number-option-row-reverse {
1203
+ flex: 1 1 0;
1204
+ min-width: 0;
1205
+ }
1206
+
1207
+ .magicfeedback-rating-number-option-row .magicfeedback-rating-number-value,
1208
+ .magicfeedback-rating-number-option-row-reverse .magicfeedback-rating-number-value {
1209
+ min-height: 56px;
1210
+ padding: var(--mf-space-sm);
1211
+ border: 2px solid var(--mf-primary-border);
1212
+ border-radius: var(--mf-radius-md);
1213
+ background: var(--mf-bg-secondary);
1214
+ color: var(--mf-primary);
1215
+ font-size: var(--mf-font-size-lg);
1216
+ font-weight: var(--mf-font-weight-bold);
1217
+ }
1218
+
1219
+ /* More than 6 options (e.g. a 0-10 NPS scale): still one row, never
1220
+ wraps \u2014 but scaled down on purpose, so it reads as a compact chip
1221
+ rather than the same 56px button stretched thin. */
1222
+ .magicfeedback-rating-number-container-row--dense .magicfeedback-rating-number-option-row .magicfeedback-rating-number-value,
1223
+ .magicfeedback-rating-number-container-row--dense .magicfeedback-rating-number-option-row-reverse .magicfeedback-rating-number-value {
1224
+ min-height: 36px;
1225
+ padding: var(--mf-space-xs);
1226
+ border-radius: var(--mf-radius-sm);
1227
+ font-size: 0.8rem;
1228
+ }
1229
+
1230
+ .magicfeedback-rating-number-option-row .magicfeedback-rating-number-option-label-container:hover .magicfeedback-rating-number-value,
1231
+ .magicfeedback-rating-number-option-row-reverse .magicfeedback-rating-number-option-label-container:hover .magicfeedback-rating-number-value {
1232
+ background: var(--mf-primary-light);
1233
+ }
1234
+
1235
+ .magicfeedback-rating-number-option-row .magicfeedback-rating-number-option-label-container input[type="radio"]:checked + .magicfeedback-rating-number-value,
1236
+ .magicfeedback-rating-number-option-row-reverse .magicfeedback-rating-number-option-label-container input[type="radio"]:checked + .magicfeedback-rating-number-value {
1237
+ color: #fff;
1238
+ background-color: var(--mf-primary);
1239
+ box-shadow: var(--mf-shadow-md);
1240
+ }
1241
+
1242
+ /* Extra option: always its own row below the scale, and styled like every
1243
+ other chip now \u2014 "doesn't apply" is still not a point on the 1..N
1244
+ continuum, but it no longer needs a different border style to say so. */
1245
+ .magicfeedback-rating-number-extra-row {
1246
+ display: flex;
1247
+ justify-content: center;
1248
+ margin-top: var(--mf-space-sm);
1249
+ }
1250
+
1251
+ .magicfeedback-rating-number-option--extra {
1252
+ flex: 0 1 auto;
1253
+ }
1254
+
1255
+ .magicfeedback-rating-number-option--extra .magicfeedback-rating-number-option-label-container {
1256
+ width: auto;
1257
+ }
1258
+
1259
+ .magicfeedback-rating-number-option--extra .magicfeedback-rating-number-value {
1260
+ min-height: 36px;
1261
+ padding: 0 var(--mf-space-md);
1262
+ border: 2px solid var(--mf-primary-border);
1263
+ border-radius: var(--mf-radius-md);
1264
+ background: var(--mf-bg-secondary);
1265
+ color: var(--mf-primary);
1266
+ font-size: var(--mf-font-size-sm);
1267
+ }
1268
+
1269
+ .magicfeedback-rating-number-option--extra .magicfeedback-rating-number-option-label-container:hover .magicfeedback-rating-number-value {
1270
+ background: var(--mf-primary-light);
1271
+ }
1272
+
1273
+ .magicfeedback-rating-number-option--extra .magicfeedback-rating-number-option-label-container input[type="radio"]:checked + .magicfeedback-rating-number-value {
1274
+ color: #fff;
1275
+ background-color: var(--mf-primary);
1276
+ box-shadow: var(--mf-shadow-md);
1277
+ }
1278
+
1279
+ /* Column: the same separated chips as row, just stacked \u2014 each option is
1280
+ its own outlined chip with a gap between them, not one shared box. */
1281
+ .magicfeedback-rating-number-container-column,
1282
+ .magicfeedback-rating-number-container-column-reverse {
1283
+ gap: var(--mf-space-sm);
1284
+ }
1285
+
1286
+ .magicfeedback-rating-number-option-column,
1287
+ .magicfeedback-rating-number-option-column-reverse {
1288
+ width: 100%;
1289
+ }
1290
+
1291
+ .magicfeedback-rating-number-option-column .magicfeedback-rating-number-value,
1292
+ .magicfeedback-rating-number-option-column-reverse .magicfeedback-rating-number-value {
1293
+ justify-content: flex-start;
1294
+ gap: var(--mf-space-sm);
1295
+ min-height: 48px;
1296
+ padding: var(--mf-space-sm) var(--mf-space-md);
1297
+ border: 2px solid var(--mf-primary-border);
1298
+ border-radius: var(--mf-radius-md);
1299
+ background: var(--mf-bg-secondary);
1300
+ color: var(--mf-primary);
1301
+ }
1302
+
1303
+ .magicfeedback-rating-number-option-column .magicfeedback-rating-number-option-label-container:hover .magicfeedback-rating-number-value,
1304
+ .magicfeedback-rating-number-option-column-reverse .magicfeedback-rating-number-option-label-container:hover .magicfeedback-rating-number-value {
1305
+ background: var(--mf-primary-light);
1306
+ }
1307
+
1308
+ .magicfeedback-rating-number-option-column .magicfeedback-rating-number-option-label-container input[type="radio"]:checked + .magicfeedback-rating-number-value,
1309
+ .magicfeedback-rating-number-option-column-reverse .magicfeedback-rating-number-option-label-container input[type="radio"]:checked + .magicfeedback-rating-number-value {
1310
+ color: #fff;
1311
+ background-color: var(--mf-primary);
1312
+ box-shadow: var(--mf-shadow-md);
1313
+ }
1314
+
1315
+ .magicfeedback-rating-number-value-num {
1316
+ font-weight: var(--mf-font-weight-bold);
1317
+ }
1318
+
1319
+ /* Column with per-option text: a min-width so "1".."9" and "10" line up,
1320
+ with the label text starting at the same x. Skipped entirely when the
1321
+ column has no per-option text at all (--bare below) \u2014 with nothing to
1322
+ align against, the same left-shift bug from row mode would resurface. */
1323
+ .magicfeedback-rating-number-container-column:not(.magicfeedback-rating-number-container-column--bare) .magicfeedback-rating-number-value-num,
1324
+ .magicfeedback-rating-number-container-column-reverse:not(.magicfeedback-rating-number-container-column--bare) .magicfeedback-rating-number-value-num {
1325
+ flex: none;
1326
+ min-width: 1.4em;
1327
+ }
1328
+
1329
+ /* Column, no per-option text at all (only min/max, or nothing): a bare
1330
+ numbered list has nothing to left-align against, so center each
1331
+ number instead of stranding it on the left with blank space beside it. */
1332
+ .magicfeedback-rating-number-container-column--bare .magicfeedback-rating-number-value {
1333
+ justify-content: center;
1334
+ }
1335
+
1336
+ .magicfeedback-rating-number-value-label {
1337
+ font-weight: var(--mf-font-weight-medium);
1338
+ }
1339
+
1340
+ .magicfeedback-rating-number-option-column .magicfeedback-rating-number-option-label-container input[type="radio"]:checked + .magicfeedback-rating-number-value,
1341
+ .magicfeedback-rating-number-option-column-reverse .magicfeedback-rating-number-option-label-container input[type="radio"]:checked + .magicfeedback-rating-number-value {
1342
+ color: #fff;
1343
+ background-color: var(--mf-primary);
1344
+ }
1345
+
1346
+ /* Star Rating */
1347
+ .magicfeedback-rating-star-container {
1348
+ justify-content: center;
1349
+ }
1350
+
1351
+ .magicfeedback-rating-star-option:not(:checked) > .rating__star {
1352
+ font-size: 40px;
1353
+ color: var(--mf-border);
1354
+ cursor: pointer;
1355
+ margin: 0 var(--mf-space-xs);
1356
+ transition: var(--mf-transition-fast);
1357
+ }
1358
+
1359
+ .magicfeedback-rating-star-option:not(:checked) > .rating__star:hover,
1360
+ .magicfeedback-rating-star-option:not(:checked) > .rating__star:hover ~ span {
1361
+ color: #fbbf24;
1362
+ transform: scale(1.1);
1363
+ }
1364
+
1365
+ .magicfeedback-rating-star-selected {
1366
+ color: #fbbf24 !important;
1367
+ }
1368
+
1369
+ /* ========================================
1370
+ MULTIPLE CHOICE WITH IMAGES
1371
+ ======================================== */
1372
+ .magicfeedback-multiple-choice-image-option {
1373
+ display: flex;
1374
+ border-radius: var(--mf-radius-md);
1375
+ overflow: hidden;
1376
+ transition: var(--mf-transition-fast);
1377
+ }
1378
+
1379
+ .magicfeedback-image-option-label-container {
1380
+ cursor: pointer;
1381
+ border-radius: var(--mf-radius-md);
1382
+ overflow: hidden;
1383
+ transition: var(--mf-transition-fast);
1384
+ }
1385
+
1386
+ .magicfeedback-image-option-label-container input[type="radio"],
1387
+ .magicfeedback-image-option-label-container input[type="checkbox"] {
1388
+ position: absolute;
1389
+ opacity: 0;
1390
+ width: 0;
1391
+ height: 0;
1392
+ }
1393
+
1394
+ .magicfeedback-image-option-label-container img {
1395
+ width: 100%;
1396
+ height: auto;
1397
+ display: block;
1398
+ border: 2px solid var(--mf-border);
1399
+ border-radius: var(--mf-radius-md);
1400
+ transition: var(--mf-transition-fast);
1401
+ }
1402
+
1403
+ .magicfeedback-image-option-label-container:hover img {
1404
+ border-color: var(--mf-primary);
1405
+ box-shadow: var(--mf-shadow-md);
1406
+ }
1407
+
1408
+ .magicfeedback-image-option-label-container input:checked + img {
1409
+ border-color: var(--mf-primary);
1410
+ box-shadow: 0 0 0 3px var(--mf-primary-light);
1411
+ }
1412
+
1413
+ /* ========================================
1414
+ MATRIX QUESTIONS
1415
+ ======================================== */
1416
+ .magicfeedback-multi-question-matrix-container {
1417
+ width: 100%;
1418
+ overflow-x: auto;
1419
+ border-radius: var(--mf-radius-md);
1420
+ }
1421
+
1422
+ .magicfeedback-multi-question-matrix-table {
1423
+ width: 100%;
1424
+ border-collapse: separate;
1425
+ border-spacing: 0 var(--mf-space-xs);
1426
+ }
1427
+
1428
+ .magicfeedback-multi-question-matrix-table th {
1429
+ padding: var(--mf-space-md);
1430
+ text-align: center;
1431
+ font-size: var(--mf-font-size-sm);
1432
+ font-weight: 500;
1433
+ color: var(--mf-text-secondary);
1434
+ }
1435
+
1436
+ .magicfeedback-multi-question-matrix-row-tr {
1437
+ background-color: var(--mf-bg-primary);
1438
+ border-radius: var(--mf-radius-md);
1439
+ transition: var(--mf-transition-fast);
1440
+ }
1441
+
1442
+ .magicfeedback-multi-question-matrix-row-tr:nth-child(even) {
1443
+ background-color: var(--mf-bg-secondary);
1444
+ }
1445
+
1446
+ .magicfeedback-multi-question-matrix-row-tr:hover {
1447
+ background-color: var(--mf-bg-hover);
1448
+ box-shadow: var(--mf-shadow-sm);
1449
+ }
1450
+
1451
+ .magicfeedback-multi-question-matrix-table td {
1452
+ padding: var(--mf-space-md);
1453
+ text-align: center;
1454
+ }
1455
+
1456
+ .magicfeedback-multi-question-matrix-label {
1457
+ text-align: start;
1458
+ font-size: var(--mf-font-size-base);
1459
+ color: var(--mf-text-primary);
1460
+ }
1461
+
1462
+ .magicfeedback-multi-question-matrix-table input[type="radio"] {
1463
+ width: 20px;
1464
+ height: 20px;
1465
+ cursor: pointer;
1466
+ accent-color: var(--mf-primary);
1467
+ }
1468
+
1469
+ /* ========================================
1470
+ PRIORITY LIST
1471
+ ======================================== */
1472
+ .magicfeedback-priority-list-item {
1473
+ display: flex;
1474
+ align-items: center;
1475
+ justify-content: space-between;
1476
+ padding: var(--mf-space-md);
1477
+ margin: var(--mf-space-sm) 0;
1478
+ background-color: var(--mf-bg-primary);
1479
+ border: 1.5px solid var(--mf-border);
1480
+ border-radius: var(--mf-radius-md);
1481
+ transition: var(--mf-transition-fast);
1482
+ }
1483
+
1484
+ .magicfeedback-priority-list-item:hover {
1485
+ box-shadow: var(--mf-shadow-sm);
1486
+ border-color: var(--mf-primary);
1487
+ }
1488
+
1489
+ .magicfeedback-priority-list-item-label {
1490
+ flex: 1;
1491
+ font-size: var(--mf-font-size-base);
1492
+ text-align: start;
1493
+ color: var(--mf-text-primary);
1494
+ margin: 0;
1495
+ }
1496
+
1497
+ .magicfeedback-priority-list-arrow-up,
1498
+ .magicfeedback-priority-list-arrow-down {
1499
+ padding: var(--mf-space-xs);
1500
+ font-size: var(--mf-font-size-lg);
1501
+ color: var(--mf-text-secondary);
1502
+ cursor: pointer;
1503
+ transition: var(--mf-transition-fast);
1504
+ user-select: none;
1505
+ }
1506
+
1507
+ .magicfeedback-priority-list-arrow-up:hover,
1508
+ .magicfeedback-priority-list-arrow-down:hover {
1509
+ color: var(--mf-primary);
1510
+ transform: scale(1.2);
1511
+ }
1512
+
1513
+ /* ========================================
1514
+ POINT SYSTEM
1515
+ ======================================== */
1516
+ .magicfeedback-point-system-item {
1517
+ display: flex;
1518
+ align-items: center;
1519
+ justify-content: space-between;
1520
+ padding: var(--mf-space-md);
1521
+ margin: var(--mf-space-sm) 0;
1522
+ background-color: var(--mf-bg-primary);
1523
+ border: 1.5px solid var(--mf-border);
1524
+ border-radius: var(--mf-radius-md);
1525
+ min-height: 45px;
1526
+ }
1527
+
1528
+ .magicfeedback-point-system-item label {
1529
+ flex: 1;
1530
+ font-size: var(--mf-font-size-base);
1531
+ color: var(--mf-text-primary);
1532
+ margin: 0;
1533
+ }
1534
+
1535
+ .magicfeedback-point-system-input-container {
1536
+ display: flex;
1537
+ align-items: center;
1538
+ gap: var(--mf-space-sm);
1539
+ }
1540
+
1541
+ .magicfeedback-point-system-item input {
1542
+ width: 80px;
1543
+ min-width: 80px;
1544
+ padding: var(--mf-space-sm);
1545
+ text-align: center;
1546
+ font-size: var(--mf-font-size-base);
1547
+ border: 1.5px solid var(--mf-border);
1548
+ border-radius: var(--mf-radius-md);
1549
+ margin: 0;
1550
+ }
1551
+
1552
+ .magicfeedback-point-system-total {
1553
+ display: flex;
1554
+ justify-content: flex-end;
1555
+ margin-top: var(--mf-space-md);
1556
+ font-size: var(--mf-font-size-base);
1557
+ font-weight: 600;
1558
+ color: var(--mf-text-primary);
1559
+ }
1560
+
1561
+ /* ========================================
1562
+ CONSENT
1563
+ ======================================== */
1564
+ .magicfeedback-consent-container {
1565
+ display: flex;
1566
+ flex-direction: row;
1567
+ align-items: center;
1568
+ gap: var(--mf-space-sm);
1569
+ padding: var(--mf-space-md);
1570
+ background-color: var(--mf-bg-secondary);
1571
+ border-radius: var(--mf-radius-md);
1572
+ margin: var(--mf-space-md) 0;
1573
+ }
1574
+
1575
+ .magicfeedback-consent-container input[type="checkbox"] {
1576
+ margin-top: 2px;
1577
+ flex-shrink: 0;
1578
+ accent-color: var(--mf-primary);
1579
+ }
1580
+
1581
+ .magicfeedback-consent-container label {
1582
+ flex: 1;
1583
+ font-size: var(--mf-font-size-sm);
1584
+ text-align: start;
1585
+ color: var(--mf-text-secondary);
1586
+ line-height: var(--mf-line-height);
1587
+ cursor: pointer;
1588
+ margin-bottom: 0;
1589
+ }
1590
+
1591
+ /* ========================================
1592
+ ACTION BUTTONS
1593
+ ======================================== */
1594
+ .magicfeedback-action-container {
1595
+ display: flex;
1596
+ align-items: center;
1597
+ justify-content: space-between;
1598
+ gap: var(--mf-space-md);
1599
+ margin-top: var(--mf-space-xl);
1600
+ padding-top: var(--mf-space-lg);
1601
+ border-top: 1px solid var(--mf-border);
1602
+ }
1603
+
1604
+ .magicfeedback-submit {
1605
+ padding: 0.8rem 1.6rem;
1606
+ font-size: var(--mf-font-size-base);
1607
+ font-weight: 800;
1608
+ color: #FFFFFF;
1609
+ background-color: var(--mf-primary);
1610
+ border: 2px solid var(--mf-primary);
1611
+ border-radius: var(--mf-radius-full);
1612
+ cursor: pointer;
1613
+ transition: var(--mf-transition-fast);
1614
+ box-shadow: var(--mf-shadow-md);
1615
+ }
1616
+
1617
+ .magicfeedback-submit:hover {
1618
+ background-color: var(--mf-primary-hover);
1619
+ box-shadow: var(--mf-shadow-lg);
1620
+ transform: translateY(-2px);
1621
+ }
1622
+
1623
+ .magicfeedback-submit:active {
1624
+ transform: translateY(0);
1625
+ box-shadow: var(--mf-shadow-sm);
1626
+ }
1627
+
1628
+ .magicfeedback-submit:disabled {
1629
+ opacity: 0.5;
1630
+ cursor: not-allowed;
1631
+ transform: none;
1632
+ }
1633
+
1634
+ .magicfeedback-back {
1635
+ padding: 0.65rem 1rem;
1636
+ font-size: var(--mf-font-size-base);
1637
+ font-weight: 700;
1638
+ color: var(--mf-primary);
1639
+ background-color: var(--mf-bg-secondary);
1640
+ border: 2px solid var(--mf-border);
1641
+ border-radius: var(--mf-radius-full);
1642
+ cursor: pointer;
1643
+ transition: var(--mf-transition-fast);
1644
+ }
1645
+
1646
+ .magicfeedback-back:hover {
1647
+ border-color: var(--mf-primary);
1648
+ background-color: var(--mf-bg-hover);
1649
+ }
1650
+
1651
+ /* ========================================
1652
+ SKIP & COUNTER
1653
+ ======================================== */
1654
+ .magicfeedback-skip-container {
1655
+ display: flex;
1656
+ align-items: center;
1657
+ gap: var(--mf-space-xs);
1658
+ padding: 0;
1659
+ margin: 0;
1660
+ font-size: var(--mf-font-size-sm);
1661
+ color: var(--mf-text-muted);
1662
+ background: transparent;
1663
+ border: none;
1664
+ cursor: pointer;
1665
+ transition: var(--mf-transition-fast);
1666
+ }
1667
+
1668
+ .magicfeedback-skip-container:hover {
1669
+ color: var(--mf-primary);
1670
+ }
1671
+
1672
+ .magicfeedback-skip-container input[type="checkbox"] {
1673
+ margin: 0;
1674
+ cursor: pointer;
1675
+ accent-color: var(--mf-primary);
1676
+ }
1677
+
1678
+ .magicfeedback-counter {
1679
+ display: flex;
1680
+ justify-content: flex-end;
1681
+ margin-top: var(--mf-space-md);
1682
+ font-size: var(--mf-font-size-sm);
1683
+ color: var(--mf-text-muted);
1684
+ }
1685
+
1686
+ /* ========================================
1687
+ MODAL STYLES
1688
+ ======================================== */
1689
+ /* Modal backdrop */
1690
+ .magicfeedback-modal-backdrop {
1691
+ position: fixed;
1692
+ top: 0;
1693
+ left: 0;
1694
+ width: 100vw;
1695
+ height: 100vh;
1696
+ background: rgba(0,0,0,0.4);
1697
+ display: none; /* toggled to flex when open */
1698
+ align-items: center;
1699
+ justify-content: center;
1700
+ z-index: 9999;
1701
+ }
1702
+
1703
+ /* Modal container */
1704
+ .magicfeedback-modal {
1705
+ background: #fff;
1706
+ border-radius: 8px;
1707
+ box-shadow: 0 8px 24px rgba(0,0,0,0.2);
1708
+ max-width: 520px;
1709
+ width: 90%;
1710
+ max-height: 80vh;
1711
+ /* Flex column so the options list scrolls while the actions footer
1712
+ (counter + confirm button) stays pinned and always visible. */
1713
+ display: flex;
1714
+ flex-direction: column;
1715
+ overflow: hidden;
1716
+ padding: 16px;
1717
+ position: relative;
1718
+ /* Portalled to document.body (see renderPriorityList.ts) to escape the
1719
+ host page's overflow/z-index \u2014 so it never inherits
1720
+ .magicfeedback-container's neutral text color and instead inherits
1721
+ whatever color the host page's own <body> happens to set. Needs its
1722
+ own explicit baseline rather than relying on that inheritance. */
1723
+ color: var(--mf-text-primary);
1724
+ }
1725
+
1726
+ /* Modal actions */
1727
+ .magicfeedback-modal-actions {
1728
+ display: flex;
1729
+ justify-content: flex-end;
1730
+ gap: 8px;
1731
+ margin-top: 12px;
1732
+ flex-shrink: 0;
1733
+ }
1734
+
1735
+ .magicfeedback-modal-counter {
1736
+ margin-inline-end: auto;
1737
+ display: flex;
1738
+ align-items: center;
1739
+ font-size: 14px;
1740
+ color: var(--mf-text-secondary);
1741
+ }
1742
+
1743
+ /* Modal list */
1744
+ .magicfeedback-modal-list {
1745
+ display: flex;
1746
+ flex-direction: column;
1747
+ gap: 8px;
1748
+ /* Scrollable area; footer stays fixed below it. */
1749
+ flex: 1 1 auto;
1750
+ overflow-y: auto;
1751
+ min-height: 0;
1752
+ }
1753
+
1754
+ .magicfeedback-modal-row {
1755
+ display: flex;
1756
+ align-items: center;
1757
+ gap: 10px;
1758
+ cursor: pointer;
1759
+ }
1760
+
1761
+ /* Priority list header */
1762
+ .magicfeedback-priority-list-header {
1763
+ display: flex;
1764
+ align-items: center;
1765
+ justify-content: space-between;
1766
+ gap: 12px;
1767
+ margin-bottom: 8px;
1768
+ }
1769
+
1770
+ .magicfeedback-priority-list-reorder {
1771
+ margin-top: 8px;
1772
+ }
1773
+
1774
+ .magicfeedback-priority-list-list {
1775
+ padding: 0;
1776
+ list-style: none;
1777
+ }
1778
+
1779
+ .magicfeedback-priority-list-item {
1780
+ display: flex;
1781
+ justify-content: space-between;
1782
+ align-items: center;
1783
+ margin: 5px 0;
1784
+ }
1785
+
1786
+ .magicfeedback-priority-list-item-label {
1787
+ font-size: 15px;
1788
+ }
1789
+
1790
+ .magicfeedback-priority-list-arrows {
1791
+ display: flex;
1792
+ align-items: center;
1793
+ gap: 6px;
1794
+ }
1795
+
1796
+ /* Buttons */
1797
+ .magicfeedback-button {
1798
+ appearance: none;
1799
+ border: 2px solid var(--mf-border);
1800
+ border-radius: var(--mf-radius-full);
1801
+ background: var(--mf-bg-secondary);
1802
+ color: var(--mf-text-primary);
1803
+ padding: 0.6rem 1rem;
1804
+ font-size: 14px;
1805
+ font-weight: 700;
1806
+ cursor: pointer;
1807
+ box-shadow: var(--mf-shadow-sm);
1808
+ }
1809
+
1810
+ .magicfeedback-button:hover {
1811
+ background: var(--mf-bg-hover);
1812
+ border-color: var(--mf-primary);
1813
+ }
1814
+
1815
+ .magicfeedback-button:active {
1816
+ transform: translateY(1px);
1817
+ }
1818
+
1819
+ .magicfeedback-button-primary {
1820
+ border-color: var(--mf-primary);
1821
+ background: var(--mf-primary);
1822
+ color: #fff;
1823
+ box-shadow: var(--mf-shadow-md);
1824
+ }
1825
+
1826
+ .magicfeedback-button-primary:hover {
1827
+ background: var(--mf-primary-hover);
1828
+ }
1829
+
1830
+ .magicfeedback-button-primary:active {
1831
+ background: var(--mf-primary-hover);
1832
+ }
1833
+
1834
+ /* Warning flash */
1835
+ .magicfeedback-warning {
1836
+ color: #C70039;
1837
+ }
1838
+
1839
+ /* Start message button */
1840
+ .magicfeedback-start-message-button {
1841
+ appearance: none;
1842
+ border: 2px solid var(--mf-primary);
1843
+ border-radius: var(--mf-radius-full);
1844
+ background: var(--mf-primary);
1845
+ color: #fff;
1846
+ padding: 0.8rem 1.4rem;
1847
+ font-size: 15px;
1848
+ font-weight: 800;
1849
+ cursor: pointer;
1850
+ box-shadow: var(--mf-shadow-md);
1851
+ }
1852
+
1853
+ .magicfeedback-start-message-button:hover {
1854
+ background: var(--mf-primary-hover);
1855
+ }
1856
+
1857
+ /* ========================================
1858
+ RESPONSIVE DESIGN
1859
+ ======================================== */
1860
+ @media (max-width: 768px) {
1861
+ :root {
1862
+ --mf-space-lg: 1.25rem;
1863
+ --mf-space-xl: 1.5rem;
1864
+ }
1865
+
1866
+ .magicfeedback-container {
1867
+ padding: 12px;
1868
+ border-radius: var(--mf-radius-md);
1869
+ }
1870
+
1871
+ .magicfeedback-form {
1872
+ padding: 14px;
1873
+ border-radius: var(--mf-radius-md);
1874
+ }
1875
+
1876
+ .magicfeedback-div {
1877
+ padding: 12px;
1878
+ gap: var(--mf-space-lg)
1879
+ }
1880
+
1881
+ .magicfeedback-label {
1882
+ font-size: var(--mf-font-size-base);
1883
+ }
1884
+
1885
+ .deepdots-popup input[type="date"],
1886
+ .deepdots-popup input[type="text"],
1887
+ .deepdots-popup input[type="number"],
1888
+ .deepdots-popup input[type="email"],
1889
+ .deepdots-popup input[type="password"],
1890
+ .deepdots-popup textarea,
1891
+ .deepdots-popup select {
1892
+ padding: 0.85rem 0.95rem;
1893
+ font-size: 1rem;
1894
+ min-height: 46px;
1895
+ }
1896
+
1897
+ /*
1898
+ .magicfeedback-radio-container,
1899
+ .magicfeedback-checkbox-container,
1900
+ .magicfeedback-boolean-container,
1901
+ .magicfeedback-consent-container {
1902
+ width: 100%;
1903
+ }
1904
+ */
1905
+
1906
+ .magicfeedback-radio-container,
1907
+ .magicfeedback-checkbox-container {
1908
+ padding: 10px 12px;
1909
+ border-radius: var(--mf-radius-md);
1910
+ border: 1px solid var(--mf-border);
1911
+ gap: 10px;
1912
+ }
1913
+
1914
+ .magicfeedback-rating-container,
1915
+ .magicfeedback-rating-number-container,
1916
+ .magicfeedback-rating-star-container {
1917
+ gap: 10px;
1918
+ }
1919
+
1920
+ .magicfeedback-boolean-container {
1921
+ flex-direction: column;
1922
+ gap: 10px;
1923
+ }
1924
+
1925
+ .magicfeedback-rating-number-container-row,
1926
+ .magicfeedback-rating-number-container-row-reverse {
1927
+ gap: 6px;
1928
+ }
1929
+
1930
+ .magicfeedback-rating-number-option-row .magicfeedback-rating-number-value,
1931
+ .magicfeedback-rating-number-option-row-reverse .magicfeedback-rating-number-value {
1932
+ min-height: 44px;
1933
+ padding: var(--mf-space-xs);
1934
+ font-size: 0.9rem;
1935
+ }
1936
+
1937
+ .magicfeedback-action-container {
1938
+ flex-direction: column-reverse;
1939
+ }
1940
+
1941
+ .magicfeedback-submit,
1942
+ .magicfeedback-back {
1943
+ width: 100%;
1944
+ text-align: center;
1945
+ min-height: 48px;
1946
+ }
1947
+ }
1948
+
1949
+ /* ========================================
1950
+ ACCESSIBILITY
1951
+ ======================================== */
1952
+ @media (prefers-reduced-motion: reduce) {
1953
+ *,
1954
+ *::before,
1955
+ *::after {
1956
+ animation-duration: 0.01ms !important;
1957
+ animation-iteration-count: 1 !important;
1958
+ transition-duration: 0.01ms !important;
1959
+ }
1960
+ }
1961
+
1962
+
1963
+ /* ========================================
1964
+ UTILITY CLASSES
1965
+ ======================================== */
1966
+ .magicfeedback-visually-hidden {
1967
+ position: absolute;
1968
+ width: 1px;
1969
+ height: 1px;
1970
+ padding: 0;
1971
+ margin: -1px;
1972
+ overflow: hidden;
1973
+ clip: rect(0, 0, 0, 0);
1974
+ white-space: nowrap;
1975
+ border-width: 0;
1976
+ }
1977
+
1978
+ .magicfeedback-modal-close {
1979
+ position: absolute;
1980
+ top: 8px;
1981
+ inset-inline-end: 8px;
1982
+ background: transparent;
1983
+ border: none;
1984
+ font-size: 20px;
1985
+ line-height: 1;
1986
+ cursor: pointer;
1987
+ color: #666;
1988
+ }
1989
+
1990
+ .magicfeedback-modal-close:hover,
1991
+ .magicfeedback-modal-close:focus {
1992
+ color: #000;
1993
+ outline: none;
1994
+ }
1995
+
1996
+ /* ========================================
1997
+ FILE / IMAGE UPLOAD
1998
+ ======================================== */
1999
+ .magicfeedback-upload {
2000
+ display: flex;
2001
+ flex-direction: column;
2002
+ gap: var(--mf-space-md);
2003
+ width: 100%;
2004
+ margin: 10px 0;
2005
+ }
2006
+
2007
+ /* The native input is an invisible, focusable overlay covering the dropzone. */
2008
+ .magicfeedback-upload-native {
2009
+ position: absolute;
2010
+ inset: 0;
2011
+ width: 100%;
2012
+ height: 100%;
2013
+ margin: 0;
2014
+ padding: 0;
2015
+ opacity: 0;
2016
+ cursor: pointer;
2017
+ z-index: 2;
2018
+ }
2019
+
2020
+ .magicfeedback-upload-dropzone {
2021
+ position: relative;
2022
+ display: flex;
2023
+ flex-direction: column;
2024
+ align-items: center;
2025
+ justify-content: center;
2026
+ gap: var(--mf-space-sm);
2027
+ box-sizing: border-box;
2028
+ width: 100%;
2029
+ min-height: 150px;
2030
+ padding: var(--mf-space-xl);
2031
+ text-align: center;
2032
+ border: 2px dashed var(--mf-border);
2033
+ border-radius: var(--mf-radius-md);
2034
+ background-color: var(--mf-surface-alt);
2035
+ cursor: pointer;
2036
+ transition: var(--mf-transition);
2037
+ }
2038
+
2039
+ .magicfeedback-upload-dropzone:hover {
2040
+ border-color: var(--mf-primary);
2041
+ background-color: var(--mf-bg-hover);
2042
+ }
2043
+
2044
+ .magicfeedback-upload-dropzone:focus-within {
2045
+ border-color: var(--mf-primary);
2046
+ box-shadow: var(--mf-shadow-focus);
2047
+ }
2048
+
2049
+ .magicfeedback-upload-dropzone.is-dragover {
2050
+ border-color: var(--mf-primary);
2051
+ border-style: solid;
2052
+ background-color: var(--mf-primary-light);
2053
+ box-shadow: var(--mf-shadow-focus);
2054
+ }
2055
+
2056
+ .magicfeedback-upload-icon {
2057
+ display: inline-flex;
2058
+ align-items: center;
2059
+ justify-content: center;
2060
+ width: 46px;
2061
+ height: 46px;
2062
+ color: var(--mf-primary);
2063
+ background-color: var(--mf-surface);
2064
+ border-radius: var(--mf-radius-full);
2065
+ box-shadow: var(--mf-shadow-sm);
2066
+ pointer-events: none;
2067
+ }
2068
+
2069
+ .magicfeedback-upload-icon svg {
2070
+ width: 24px;
2071
+ height: 24px;
2072
+ }
2073
+
2074
+ .magicfeedback-upload-cta {
2075
+ font-family: inherit;
2076
+ font-weight: var(--mf-font-weight-semibold);
2077
+ font-size: var(--mf-font-size-base);
2078
+ color: var(--mf-text-primary);
2079
+ pointer-events: none;
2080
+ }
2081
+
2082
+ .magicfeedback-upload-hint {
2083
+ font-family: inherit;
2084
+ font-size: var(--mf-font-size-sm);
2085
+ color: var(--mf-text-muted);
2086
+ pointer-events: none;
2087
+ }
2088
+
2089
+ .magicfeedback-upload-list {
2090
+ display: flex;
2091
+ flex-direction: column;
2092
+ gap: var(--mf-space-sm);
2093
+ width: 100%;
2094
+ margin: 0;
2095
+ padding: 0;
2096
+ list-style: none;
2097
+ }
2098
+
2099
+ .magicfeedback-upload-list:empty {
2100
+ display: none;
2101
+ }
2102
+
2103
+ .magicfeedback-upload-file-item {
2104
+ display: flex;
2105
+ align-items: center;
2106
+ gap: var(--mf-space-md);
2107
+ padding: var(--mf-space-sm) var(--mf-space-md);
2108
+ background-color: var(--mf-surface);
2109
+ border: 1px solid var(--mf-border);
2110
+ border-radius: var(--mf-radius-sm);
2111
+ box-shadow: var(--mf-shadow-sm);
2112
+ animation: mf-scale-in 0.2s ease-out;
2113
+ }
2114
+
2115
+ .magicfeedback-upload-thumb {
2116
+ flex: 0 0 auto;
2117
+ display: inline-flex;
2118
+ align-items: center;
2119
+ justify-content: center;
2120
+ width: 40px;
2121
+ height: 40px;
2122
+ overflow: hidden;
2123
+ color: var(--mf-text-secondary);
2124
+ background-color: var(--mf-surface-alt);
2125
+ border-radius: var(--mf-radius-sm);
2126
+ }
2127
+
2128
+ .magicfeedback-upload-thumb img {
2129
+ width: 100%;
2130
+ height: 100%;
2131
+ object-fit: cover;
2132
+ }
2133
+
2134
+ .magicfeedback-upload-thumb svg {
2135
+ width: 20px;
2136
+ height: 20px;
2137
+ }
2138
+
2139
+ .magicfeedback-upload-file-info {
2140
+ display: flex;
2141
+ flex-direction: column;
2142
+ flex: 1 1 auto;
2143
+ min-width: 0;
2144
+ text-align: start;
2145
+ }
2146
+
2147
+ .magicfeedback-upload-file-name {
2148
+ font-family: inherit;
2149
+ font-size: var(--mf-font-size-sm);
2150
+ font-weight: var(--mf-font-weight-semibold);
2151
+ color: var(--mf-text-primary);
2152
+ white-space: nowrap;
2153
+ overflow: hidden;
2154
+ text-overflow: ellipsis;
2155
+ }
2156
+
2157
+ .magicfeedback-upload-file-size {
2158
+ font-family: inherit;
2159
+ font-size: 0.75rem;
2160
+ color: var(--mf-text-muted);
2161
+ }
2162
+
2163
+ .magicfeedback-upload-remove {
2164
+ flex: 0 0 auto;
2165
+ display: inline-flex;
2166
+ align-items: center;
2167
+ justify-content: center;
2168
+ width: 30px;
2169
+ height: 30px;
2170
+ padding: 0;
2171
+ color: var(--mf-text-muted);
2172
+ background-color: transparent;
2173
+ border: none;
2174
+ border-radius: var(--mf-radius-full);
2175
+ cursor: pointer;
2176
+ transition: var(--mf-transition-fast);
2177
+ }
2178
+
2179
+ .magicfeedback-upload-remove:hover,
2180
+ .magicfeedback-upload-remove:focus-visible {
2181
+ color: var(--mf-error);
2182
+ background-color: var(--mf-primary-light);
2183
+ outline: none;
2184
+ }
2185
+
2186
+ .magicfeedback-upload-remove svg {
2187
+ width: 16px;
2188
+ height: 16px;
2189
+ }
2190
+
2191
+ .magicfeedback-upload-error {
2192
+ display: none;
2193
+ font-family: inherit;
2194
+ font-size: var(--mf-font-size-sm);
2195
+ color: var(--mf-error);
2196
+ }
2197
+
2198
+ .magicfeedback-upload-error.is-visible {
2199
+ display: block;
2200
+ }
2201
+
2202
+ /* ========================================
2203
+ RTL (Arabic)
2204
+ ========================================
2205
+ The SDK stamps dir="rtl" (and .magicfeedback-rtl) on the survey container
2206
+ for right-to-left languages. Everything else in this stylesheet uses logical
2207
+ properties (text-align: start, padding-inline-*, inset-inline-*), so it
2208
+ mirrors on its own; only the handful of rules that cannot be expressed
2209
+ logically live here.
2210
+
2211
+ Rules are scoped to [dir="rtl"] inside our own subtree so a host page that is
2212
+ itself RTL, or one that embeds an Arabic survey in an LTR page, both render
2213
+ correctly. */
2214
+
2215
+ /* background-position has no logical form: move the select caret to the
2216
+ left edge, opposite the padding that inset-inline-end already mirrored. */
2217
+ [dir="rtl"] select {
2218
+ background-position: left var(--mf-space-md) center;
2219
+ }
2220
+
2221
+ /* Emails, URLs, numbers, dates and phone numbers are latin/numeric content
2222
+ even in an Arabic survey: keep their own direction LTR so punctuation
2223
+ (@, ., +, /) lands where the user expects, but align them to the start of
2224
+ the RTL line so they still read as part of the form. */
2225
+ [dir="rtl"] input[type="email"],
2226
+ [dir="rtl"] input[type="url"],
2227
+ [dir="rtl"] input[type="number"],
2228
+ [dir="rtl"] input[type="tel"],
2229
+ [dir="rtl"] input[type="date"],
2230
+ [dir="rtl"] input[type="time"] {
2231
+ direction: ltr;
2232
+ text-align: right;
2233
+ }
2234
+
2235
+ /* Mirror of mf-slide-in: questions enter from the reading edge. */
2236
+ @keyframes mf-slide-in-rtl {
2237
+ from {
2238
+ opacity: 0;
2239
+ transform: translateX(16px);
2240
+ }
2241
+ to {
2242
+ opacity: 1;
2243
+ transform: translateX(0);
2244
+ }
2245
+ }
2246
+
2247
+ [dir="rtl"] .magicfeedback-div {
2248
+ animation-name: mf-slide-in-rtl;
2249
+ }
2250
+
2251
+ /* ========================================
2252
+ LOCAL \u2014 reglas del popup, no vienen del paquete
2253
+ ======================================== */
2254
+
2255
+ /* Los controles de formulario no heredan font-family: cuando el popup trae fuente propia
2256
+ (clase deepdots-has-font), se les fuerza la del contenedor. */
2257
+ .deepdots-popup.deepdots-has-font button,
2258
+ .deepdots-popup.deepdots-has-font input,
2259
+ .deepdots-popup.deepdots-has-font textarea,
2260
+ .deepdots-popup.deepdots-has-font select {
2261
+ font-family: var(--deepdots-font, inherit);
2262
+ }
2263
+
2264
+ /* WebKit s\xED aplica el padding al radio nativo: con padding el control se dibuja enorme (se vio
2265
+ en iOS, WebView de RN y Safari, no en Chrome). El paquete ya no lo pone, pero la regla es
2266
+ barata y evita que vuelva. */
2267
+ .deepdots-popup input[type="radio"] {
2268
+ padding: 0;
2269
+ }
2270
+ `;
186
2271
  }
187
2272
  });
188
2273
 
@@ -207,6 +2292,49 @@ var init_logger = __esm({
207
2292
  }
208
2293
  });
209
2294
 
2295
+ // src/ui/logo.ts
2296
+ function insertPopupLogo(parent, anchor, style, id) {
2297
+ if (!style?.logo) return null;
2298
+ if (parent.ownerDocument.getElementById(id)) return null;
2299
+ const img = parent.ownerDocument.createElement("img");
2300
+ img.id = id;
2301
+ img.src = style.logo;
2302
+ img.alt = "Logo";
2303
+ img.style.cssText = BASE_CSS;
2304
+ if (style.logoSize && MAX_HEIGHT[style.logoSize]) {
2305
+ img.style.maxHeight = MAX_HEIGHT[style.logoSize];
2306
+ }
2307
+ switch (style.logoPosition) {
2308
+ case "left":
2309
+ img.style.margin = "12px 0 0 0";
2310
+ img.style.setProperty("margin-inline-start", "0");
2311
+ img.style.setProperty("margin-inline-end", "16px");
2312
+ break;
2313
+ case "right":
2314
+ img.style.margin = "12px 0 0 0";
2315
+ img.style.setProperty("margin-inline-start", "auto");
2316
+ img.style.setProperty("margin-inline-end", "0");
2317
+ break;
2318
+ case "center":
2319
+ img.style.margin = "12px auto 0 auto";
2320
+ break;
2321
+ }
2322
+ parent.insertBefore(img, anchor);
2323
+ return img;
2324
+ }
2325
+ var BASE_CSS, MAX_HEIGHT;
2326
+ var init_logo = __esm({
2327
+ "src/ui/logo.ts"() {
2328
+ "use strict";
2329
+ BASE_CSS = "max-height:40px; max-width:100%; object-fit:contain; display:block; margin:12px 0 0 0;";
2330
+ MAX_HEIGHT = {
2331
+ small: "30px",
2332
+ medium: "50px",
2333
+ large: "70px"
2334
+ };
2335
+ }
2336
+ });
2337
+
210
2338
  // src/ui/renderPopup.ts
211
2339
  var renderPopup_exports = {};
212
2340
  __export(renderPopup_exports, {
@@ -304,6 +2432,9 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
304
2432
  let stylesInjected = false;
305
2433
  let pageDepth = 0;
306
2434
  let onStartPage = false;
2435
+ let labels = getLabels(options?.language);
2436
+ let actionLabels = resolveActionLabels(actions, options?.language);
2437
+ let direction = directionFor(options?.language);
307
2438
  const isDark = style?.theme === "dark";
308
2439
  const theme = {
309
2440
  popupBg: isDark ? "#1e1e1e" : "#fff",
@@ -313,7 +2444,6 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
313
2444
  // oscuros con texto blanco sobre el fondo claro del popup.
314
2445
  colorScheme: isDark ? "dark" : "light",
315
2446
  textPrimary: isDark ? "#f0f0f0" : "#111",
316
- closeBtnHoverBg: isDark ? "rgba(255,255,255,0.10)" : "rgba(0,0,0,0.06)",
317
2447
  closeBtnHoverColor: isDark ? "#fff" : "#000000",
318
2448
  textMuted: isDark ? "#9ca3af" : "#6b7280",
319
2449
  progressTrack: isDark ? "#3f3f46" : "#e5e7eb"
@@ -331,6 +2461,7 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
331
2461
  const popup = document.createElement("div");
332
2462
  popup.id = "dd-popup";
333
2463
  popup.className = "deepdots-popup";
2464
+ popup.setAttribute("dir", direction);
334
2465
  popup.style.cssText = `
335
2466
  position: relative;
336
2467
  display: flex;
@@ -360,7 +2491,7 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
360
2491
  const titleEl = document.createElement("h2");
361
2492
  titleEl.id = "dd-title";
362
2493
  titleEl.className = "deepdots-popup-title";
363
- titleEl.style.cssText = `margin:0; font-size:17px; font-weight:600; line-height:1.3; color:${theme.textPrimary}; text-transform:none; text-align:left; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;`;
2494
+ titleEl.style.cssText = `margin:0; font-size:17px; font-weight:600; line-height:1.3; color:${theme.textPrimary}; text-transform:none; text-align:start; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;`;
364
2495
  titleEl.hidden = true;
365
2496
  const setTitle = (value) => {
366
2497
  if (!value) return;
@@ -372,10 +2503,10 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
372
2503
  const closeBtn = document.createElement("button");
373
2504
  closeBtn.id = "dd-close";
374
2505
  closeBtn.type = "button";
375
- closeBtn.setAttribute("aria-label", "Close popup");
2506
+ closeBtn.setAttribute("aria-label", labels.closeAria);
376
2507
  closeBtn.innerHTML = `
377
- <svg width="28" height="28" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
378
- <path d="M6 6L18 18M6 18L18 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
2508
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2509
+ <path d="M5 5L19 19M5 19L19 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="butt"/>
379
2510
  </svg>
380
2511
  `;
381
2512
  closeBtn.style.cssText = `
@@ -390,17 +2521,15 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
390
2521
  cursor:pointer;
391
2522
  color:${theme.textPrimary};
392
2523
  padding:4px;
393
- transition: color .15s ease, transform .15s ease, background .15s ease;
2524
+ transition: color .15s ease, transform .15s ease;
394
2525
  box-shadow: none !important;
395
2526
  `;
396
2527
  closeBtn.onmouseenter = () => {
397
2528
  closeBtn.style.color = theme.closeBtnHoverColor;
398
- closeBtn.style.background = theme.closeBtnHoverBg;
399
2529
  closeBtn.style.transform = "scale(1.06)";
400
2530
  };
401
2531
  closeBtn.onmouseleave = () => {
402
2532
  closeBtn.style.color = theme.textPrimary;
403
- closeBtn.style.background = "transparent";
404
2533
  closeBtn.style.transform = "scale(1)";
405
2534
  };
406
2535
  closeBtn.onclick = () => {
@@ -433,7 +2562,7 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
433
2562
  progressLabel.appendChild(progressTotal);
434
2563
  const progressFollowUp = document.createElement("span");
435
2564
  progressFollowUp.id = "dd-progress-followup";
436
- progressFollowUp.textContent = "Follow-up";
2565
+ progressFollowUp.textContent = labels.followUp;
437
2566
  progressFollowUp.style.cssText = "display:none; font-size:12px; font-weight:600; color:#fff; background:rgba(59,130,246,0.44); border-radius:999px; padding:2px 10px;";
438
2567
  progressHead.appendChild(progressLabel);
439
2568
  progressHead.appendChild(progressFollowUp);
@@ -465,8 +2594,8 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
465
2594
  progressCurrent.textContent = `${Math.round(pct)}%`;
466
2595
  progressTotal.textContent = "";
467
2596
  } else {
468
- progressCurrent.textContent = `Question ${label}`;
469
- progressTotal.textContent = ` of ${total}`;
2597
+ progressCurrent.textContent = `${labels.question} ${label}`;
2598
+ progressTotal.textContent = ` ${labels.of} ${total}`;
470
2599
  }
471
2600
  progressFollowUp.style.display = p.followup ? "inline-block" : "none";
472
2601
  }
@@ -503,7 +2632,7 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
503
2632
  const spinnerEl = document.createElement("div");
504
2633
  spinnerEl.className = "mf-spinner";
505
2634
  spinnerEl.setAttribute("role", "status");
506
- spinnerEl.setAttribute("aria-label", "Loading survey");
2635
+ spinnerEl.setAttribute("aria-label", labels.loadingAria);
507
2636
  spinnerEl.innerHTML = '<div class="mf-spinner-circle"></div>';
508
2637
  spinnerEl.style.cssText = "position:absolute; top:50%; left:50%; transform:translate(-50%,-50%);";
509
2638
  const formDivId = `magicfeedback-form-${surveyId}`;
@@ -522,7 +2651,7 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
522
2651
  const backButton = document.createElement("button");
523
2652
  backButton.id = "dd-back";
524
2653
  backButton.className = "dd-nav-btn";
525
- backButton.textContent = actions?.back ? actions.back.label : "Back";
2654
+ backButton.textContent = actionLabels.back;
526
2655
  backButton.style.cssText = `
527
2656
  background: transparent;
528
2657
  color: ${theme.textMuted};
@@ -552,7 +2681,7 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
552
2681
  const startButton = document.createElement("button");
553
2682
  startButton.id = "dd-start";
554
2683
  startButton.className = "dd-nav-btn";
555
- startButton.textContent = actions?.start ? actions.start.label : "Start survey";
2684
+ startButton.textContent = actionLabels.start;
556
2685
  startButton.style.cssText = `
557
2686
  background: #1E293B;
558
2687
  color: #fff;
@@ -579,7 +2708,7 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
579
2708
  const closeButton = document.createElement("button");
580
2709
  closeButton.id = "dd-complete";
581
2710
  closeButton.className = "dd-nav-btn";
582
- closeButton.textContent = actions?.complete ? actions.complete.label : "Complete survey";
2711
+ closeButton.textContent = actionLabels.complete;
583
2712
  closeButton.style.cssText = `
584
2713
  background: #1E293B;
585
2714
  color: #fff;
@@ -610,7 +2739,7 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
610
2739
  const submitButton = document.createElement("button");
611
2740
  submitButton.id = "dd-submit";
612
2741
  submitButton.className = "dd-nav-btn";
613
- submitButton.textContent = actions?.accept ? actions.accept.label : "Send";
2742
+ submitButton.textContent = actionLabels.accept;
614
2743
  submitButton.style.cssText = `
615
2744
  background: #1E293B;
616
2745
  color: #fff;
@@ -634,6 +2763,19 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
634
2763
  formInstance?.send?.();
635
2764
  }
636
2765
  };
2766
+ function applyLabels(lang) {
2767
+ labels = getLabels(lang);
2768
+ actionLabels = resolveActionLabels(actions, lang);
2769
+ backButton.textContent = actionLabels.back;
2770
+ startButton.textContent = actionLabels.start;
2771
+ closeButton.textContent = actionLabels.complete;
2772
+ submitButton.textContent = actionLabels.accept;
2773
+ closeBtn.setAttribute("aria-label", labels.closeAria);
2774
+ spinnerEl.setAttribute("aria-label", labels.loadingAria);
2775
+ progressFollowUp.textContent = labels.followUp;
2776
+ direction = directionFor(lang);
2777
+ popup.setAttribute("dir", direction);
2778
+ }
637
2779
  backButton.style.display = "none";
638
2780
  startButton.style.display = "none";
639
2781
  submitButton.style.display = "none";
@@ -754,6 +2896,8 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
754
2896
  addSuccessScreen: false
755
2897
  };
756
2898
  generateOptions.onLoadedEvent = ({ formData }) => {
2899
+ const surveyLang = Array.isArray(formData?.lang) ? formData.lang.find((l) => typeof l === "string" && l.trim().length > 0) : void 0;
2900
+ if (surveyLang) applyLabels(surveyLang);
757
2901
  try {
758
2902
  } catch {
759
2903
  }
@@ -790,47 +2934,7 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
790
2934
  backButton.style.color = s.buttonSecondaryColor;
791
2935
  backButton.style.border = "none";
792
2936
  }
793
- if (s.logo) {
794
- if (!document.getElementById("deepdots-popup-logo")) {
795
- const logoImg = document.createElement("img");
796
- logoImg.id = "deepdots-popup-logo";
797
- logoImg.src = s.logo;
798
- logoImg.alt = "Logo";
799
- logoImg.style.cssText = "max-height:40px; max-width:100%; object-fit:contain;";
800
- if (s.logoSize) {
801
- switch (s.logoSize) {
802
- case "small":
803
- logoImg.style.maxHeight = "30px";
804
- break;
805
- case "medium":
806
- logoImg.style.maxHeight = "50px";
807
- break;
808
- case "large":
809
- logoImg.style.maxHeight = "70px";
810
- break;
811
- }
812
- }
813
- if (s.logoPosition) {
814
- switch (s.logoPosition) {
815
- case "left":
816
- logoImg.style.margin = "0 16px 42px 0";
817
- logoImg.style.display = "block";
818
- logoImg.style.marginLeft = "0";
819
- break;
820
- case "right":
821
- logoImg.style.margin = "0 0 42px 16px";
822
- logoImg.style.display = "block";
823
- logoImg.style.marginLeft = "auto";
824
- break;
825
- case "center":
826
- logoImg.style.margin = "0 auto 42px auto";
827
- logoImg.style.display = "block";
828
- break;
829
- }
830
- }
831
- containerContent.insertBefore(logoImg, main);
832
- }
833
- }
2937
+ insertPopupLogo(popup, progressEl, s, "deepdots-popup-logo");
834
2938
  if (s.startMessage && s.startMessage !== "") {
835
2939
  sdkLog(s.startMessage);
836
2940
  onStartPage = true;
@@ -854,13 +2958,13 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
854
2958
  if (errText) {
855
2959
  setLoading(false);
856
2960
  if (errText.toLowerCase().includes("no response")) {
857
- errorHint.textContent = "Please answer the required question to continue.";
2961
+ errorHint.textContent = labels.errorRequired;
858
2962
  errorHint.style.display = "block";
859
2963
  emit("popup_clicked", surveyId, { action: "validation_error_required" });
860
2964
  updateNavButtons();
861
2965
  return;
862
2966
  }
863
- errorHint.textContent = "An error occurred while submitting. Please try again or close the popup.";
2967
+ errorHint.textContent = labels.errorSubmit;
864
2968
  errorHint.style.display = "block";
865
2969
  emit("popup_clicked", surveyId, { action: "submit_error", error: errText });
866
2970
  return;
@@ -901,7 +3005,9 @@ var init_renderPopup = __esm({
901
3005
  "use strict";
902
3006
  init_tracking_manager();
903
3007
  init_font();
3008
+ init_logo();
904
3009
  init_logger();
3010
+ init_labels();
905
3011
  import_native = __toESM(require("@magicfeedback/native"));
906
3012
  init_style();
907
3013
  }
@@ -1113,6 +3219,7 @@ init_tracking_manager();
1113
3219
 
1114
3220
  // src/ui/surveyHtml.ts
1115
3221
  init_font();
3222
+ init_labels();
1116
3223
  init_style();
1117
3224
  var POSITION_MAP = {
1118
3225
  center: { justifyContent: "center", alignItems: "center", padding: "0", background: "rgba(0,0,0,0.5)" },
@@ -1126,9 +3233,13 @@ var POSITION_MAP = {
1126
3233
  function jsonForScript(value) {
1127
3234
  return JSON.stringify(value ?? null).replace(/</g, "\\u003C").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
1128
3235
  }
3236
+ function trimmedOrNull(value) {
3237
+ const trimmed = typeof value === "string" ? value.trim() : "";
3238
+ return trimmed ? value : null;
3239
+ }
1129
3240
  function buildSurveyHtml(opts) {
1130
3241
  const env = opts.env === "development" ? "dev" : "prod";
1131
- const version = opts.version ?? "2.2.4";
3242
+ const version = opts.version ?? "2.2.22";
1132
3243
  const cdn = `https://cdn.jsdelivr.net/npm/@magicfeedback/native@${version}/dist/magicfeedback-sdk.browser.js`;
1133
3244
  const sid = jsonForScript(opts.surveyId);
1134
3245
  const pid = jsonForScript(opts.productId);
@@ -1160,10 +3271,22 @@ function buildSurveyHtml(opts) {
1160
3271
  const titleJson = jsonForScript(opts.title ?? "");
1161
3272
  const customCss = (opts.surveyCss ?? "").replace(/<\/\s*style/gi, "<\\/style");
1162
3273
  const progressPref = opts.showProgressBar === void 0 ? "null" : String(opts.showProgressBar);
1163
- const backLabel = jsonForScript(opts.actions?.back?.label ?? "Back");
1164
- const startLabel = jsonForScript(opts.actions?.start?.label ?? "Start survey");
1165
- const completeLabel = jsonForScript(opts.actions?.complete?.label ?? "Complete survey");
1166
- const submitLabel = jsonForScript(opts.actions?.accept?.label ?? "Send");
3274
+ const initLabels = getLabels(opts.language);
3275
+ const initActionLabels = resolveActionLabels(opts.actions, opts.language);
3276
+ const backLabel = jsonForScript(initActionLabels.back);
3277
+ const startLabel = jsonForScript(initActionLabels.start);
3278
+ const completeLabel = jsonForScript(initActionLabels.complete);
3279
+ const submitLabel = jsonForScript(initActionLabels.accept);
3280
+ const labelsTableJson = jsonForScript(LABELS);
3281
+ const actionOverridesJson = jsonForScript({
3282
+ accept: trimmedOrNull(opts.actions?.accept?.label),
3283
+ start: trimmedOrNull(opts.actions?.start?.label),
3284
+ complete: trimmedOrNull(opts.actions?.complete?.label),
3285
+ back: trimmedOrNull(opts.actions?.back?.label)
3286
+ });
3287
+ const initLangJson = jsonForScript(opts.language ?? "");
3288
+ const initDirection = directionFor(opts.language);
3289
+ const rtlLocalesJson = jsonForScript(RTL_LOCALES);
1167
3290
  return `<!DOCTYPE html><html><head>
1168
3291
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
1169
3292
  <meta name="color-scheme" content="${colorScheme}"/>
@@ -1176,8 +3299,8 @@ body{display:${bodyDisplay};justify-content:${pos.justifyContent};align-items:${
1176
3299
  .deepdots-popup-header{display:flex;justify-content:space-between;align-items:center;gap:12px;width:100%;flex:0 0 auto}
1177
3300
  /* Neutraliza la regla \`.deepdots-popup h2\` del CSS del survey (uppercase, centrado y
1178
3301
  margin-bottom 40px), pensada para los enunciados y no para el t\xEDtulo de la cabecera. */
1179
- #dd-title{margin:0;font-family:var(--deepdots-font,'Montserrat',inherit);font-size:17px;font-weight:600;line-height:1.3;color:${textPrimary};text-transform:none;text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
1180
- #dd-close{background:transparent;border:none;width:32px;height:32px;display:flex;align-items:center;justify-content:center;border-radius:8px;cursor:pointer;color:${textPrimary};padding:4px;flex:0 0 auto;margin-left:auto}
3302
+ #dd-title{margin:0;font-family:var(--deepdots-font,'Montserrat',inherit);font-size:17px;font-weight:600;line-height:1.3;color:${textPrimary};text-transform:none;text-align:start;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
3303
+ #dd-close{background:transparent;border:none;width:32px;height:32px;display:flex;align-items:center;justify-content:center;border-radius:8px;cursor:pointer;color:${textPrimary};padding:4px;flex:0 0 auto;margin-inline-start:auto}
1181
3304
  /* Progreso alineado con la cabecera: sin padding horizontal propio, lo marca la tarjeta.
1182
3305
  El vertical es el mismo arriba y abajo, y del mismo valor que el padding de la tarjeta. */
1183
3306
  .deepdots-progress{display:none;flex-direction:column;gap:8px;width:100%;flex:0 0 auto;padding:16px 0;box-sizing:border-box}
@@ -1205,7 +3328,7 @@ body{display:${bodyDisplay};justify-content:${pos.justifyContent};align-items:${
1205
3328
  #dd-form-wrapper{width:100%;flex:1 1 auto}
1206
3329
  #mf{width:100%;box-sizing:border-box;visibility:hidden}
1207
3330
  .deepdots-popup-main *{max-width:100%;box-sizing:border-box}
1208
- #dd-logo{max-height:40px;max-width:100%;object-fit:contain}
3331
+ #dd-logo{max-height:40px;max-width:100%;object-fit:contain;display:block;margin:12px 0 0 0}
1209
3332
  .deepdots-error-hint{display:none;margin:12px 0 0 0;padding:10px 12px;border-radius:6px;background:#FEF3C7;color:#92400E;border:1px solid #FCD34D;font-size:13px}
1210
3333
  /* Pantalla final: el HTML del editor de la plataforma (imagen + texto), centrado. */
1211
3334
  .deepdots-success{display:none;width:100%;text-align:center;padding:24px 0;color:${textPrimary}}
@@ -1234,35 +3357,35 @@ body{display:${bodyDisplay};justify-content:${pos.justifyContent};align-items:${
1234
3357
  ${customCss}
1235
3358
  </style>
1236
3359
  </head><body>
1237
- <div class="${popupClass}" id="dd-popup">
3360
+ <div class="${popupClass}" id="dd-popup" dir="${initDirection}">
1238
3361
  <div class="deepdots-popup-header">
1239
3362
  <h2 id="dd-title" class="deepdots-popup-title" hidden></h2>
1240
- <button type="button" id="dd-close" aria-label="Close popup">
1241
- <svg width="28" height="28" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
1242
- <path d="M6 6L18 18M6 18L18 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3363
+ <button type="button" id="dd-close" aria-label="${initLabels.closeAria}">
3364
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
3365
+ <path d="M5 5L19 19M5 19L19 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="butt"/>
1243
3366
  </svg>
1244
3367
  </button>
1245
3368
  </div>
1246
3369
  <div class="deepdots-progress" id="dd-progress">
1247
3370
  <div class="deepdots-progress-head">
1248
3371
  <span id="dd-progress-label"><span id="dd-progress-current"></span><span id="dd-progress-total"></span></span>
1249
- <span id="dd-progress-followup">Follow-up</span>
3372
+ <span id="dd-progress-followup">${initLabels.followUp}</span>
1250
3373
  </div>
1251
3374
  <div class="deepdots-progress-track"><div id="dd-progress-bar"></div></div>
1252
3375
  </div>
1253
3376
  <div class="deepdots-popup-container-content" id="dd-content">
1254
3377
  <div class="deepdots-popup-main" id="dd-main">
1255
3378
  <div id="dd-form-wrapper">
1256
- <div class="mf-spinner" id="dd-spinner" role="status" aria-label="Loading survey"><div class="mf-spinner-circle"></div></div>
3379
+ <div class="mf-spinner" id="dd-spinner" role="status" aria-label="${initLabels.loadingAria}"><div class="mf-spinner-circle"></div></div>
1257
3380
  <div id="mf"></div>
1258
3381
  </div>
1259
3382
  <div class="deepdots-error-hint" id="dd-error" role="alert" aria-live="polite"></div>
1260
3383
  </div>
1261
3384
  <div class="deepdots-popup-footer" id="dd-footer">
1262
- <button type="button" class="dd-nav-btn" id="dd-submit">Send</button>
1263
- <button type="button" class="dd-nav-btn" id="dd-back">Back</button>
1264
- <button type="button" class="dd-nav-btn" id="dd-complete">Complete survey</button>
1265
- <button type="button" class="dd-nav-btn" id="dd-start">Start survey</button>
3385
+ <button type="button" class="dd-nav-btn" id="dd-submit"></button>
3386
+ <button type="button" class="dd-nav-btn" id="dd-back"></button>
3387
+ <button type="button" class="dd-nav-btn" id="dd-complete"></button>
3388
+ <button type="button" class="dd-nav-btn" id="dd-start"></button>
1266
3389
  </div>
1267
3390
  </div>
1268
3391
  </div>
@@ -1291,6 +3414,32 @@ ${customCss}
1291
3414
  var progressTotal=document.getElementById('dd-progress-total');
1292
3415
  var progressFollowUp=document.getElementById('dd-progress-followup');
1293
3416
  var progressBar=document.getElementById('dd-progress-bar');
3417
+ var closeEl=document.getElementById('dd-close');
3418
+
3419
+ // --- i18n del chrome -------------------------------------------------------------------
3420
+ // La tabla completa viaja embebida porque el idioma del survey (\`formData.lang[0]\`) solo se
3421
+ // conoce ya dentro del WebView. \`ddResolveLocale\` es el espejo del \`resolveLocale\` de TS
3422
+ // (paridad cubierta por test).
3423
+ var DD_LABELS=${labelsTableJson};
3424
+ var DD_ACTION_OVERRIDES=${actionOverridesJson};
3425
+ ${RESOLVE_LOCALE_JS}
3426
+ var DD_LABELS_ACTIVE=DD_LABELS[ddResolveLocale(${initLangJson})];
3427
+ var DD_RTL=${rtlLocalesJson};
3428
+ function ddIsRtl(lang){ return DD_RTL.indexOf(ddResolveLocale(lang))!==-1; }
3429
+ function ddApplyLabels(lang){
3430
+ var next=DD_LABELS[ddResolveLocale(lang)];
3431
+ if(!next) return;
3432
+ DD_LABELS_ACTIVE=next;
3433
+ // El survey ya se ha volteado a s\xED mismo: el chrome tiene que acompa\xF1arlo.
3434
+ popup.setAttribute('dir', ddIsRtl(lang) ? 'rtl' : 'ltr');
3435
+ backBtn.textContent=DD_ACTION_OVERRIDES.back||next.back;
3436
+ startBtn.textContent=DD_ACTION_OVERRIDES.start||next.start;
3437
+ completeBtn.textContent=DD_ACTION_OVERRIDES.complete||next.complete;
3438
+ submitBtn.textContent=DD_ACTION_OVERRIDES.accept||next.accept;
3439
+ if(closeEl){ closeEl.setAttribute('aria-label',next.closeAria); }
3440
+ if(spinner){ spinner.setAttribute('aria-label',next.loadingAria); }
3441
+ progressFollowUp.textContent=next.followUp;
3442
+ }
1294
3443
 
1295
3444
  function setTitle(t){
1296
3445
  if(!t) return;
@@ -1331,8 +3480,8 @@ ${customCss}
1331
3480
  progressCurrent.textContent=Math.round(pct)+'%';
1332
3481
  progressTotal.textContent='';
1333
3482
  } else {
1334
- progressCurrent.textContent='Question '+label;
1335
- progressTotal.textContent=' of '+total;
3483
+ progressCurrent.textContent=DD_LABELS_ACTIVE.question+' '+label;
3484
+ progressTotal.textContent=' '+DD_LABELS_ACTIVE.of+' '+total;
1336
3485
  }
1337
3486
  progressFollowUp.style.display=p&&p.followup?'inline-block':'none';
1338
3487
  }
@@ -1342,7 +3491,7 @@ ${customCss}
1342
3491
  completeBtn.textContent=${completeLabel};
1343
3492
  submitBtn.textContent=${submitLabel};
1344
3493
 
1345
- document.getElementById('dd-close').onclick=function(){ emitJSON('popup_close'); };
3494
+ closeEl.onclick=function(){ emitJSON('popup_close'); };
1346
3495
  backBtn.onclick=function(){ if(window.DeepdotsForm && window.DeepdotsForm.back){ window.DeepdotsForm.back(); } };
1347
3496
  startBtn.onclick=function(){
1348
3497
  if(window.DeepdotsForm && window.DeepdotsForm.startForm){
@@ -1437,6 +3586,14 @@ ${customCss}
1437
3586
  // fallback es un literal gen\xE9rico que ignora style.successMessage.
1438
3587
  addSuccessScreen:false,
1439
3588
  onLoadedEvent:function(args){
3589
+ // Idioma del survey: manda sobre el del init para que el chrome no se quede en
3590
+ // ingl\xE9s delante de un survey traducido.
3591
+ var langs=args && args.formData ? args.formData.lang : null;
3592
+ if(langs && langs.length){
3593
+ for(var li=0;li<langs.length;li++){
3594
+ if(typeof langs[li]==='string' && langs[li].trim()){ ddApplyLabels(langs[li]); break; }
3595
+ }
3596
+ }
1440
3597
  var s=args && args.formData ? args.formData.style : null;
1441
3598
  if(s && !stylesInjected){
1442
3599
  stylesInjected=true;
@@ -1463,10 +3620,14 @@ ${customCss}
1463
3620
  if(s.logoSize==='small'){ logoImg.style.maxHeight='30px'; }
1464
3621
  else if(s.logoSize==='medium'){ logoImg.style.maxHeight='50px'; }
1465
3622
  else if(s.logoSize==='large'){ logoImg.style.maxHeight='70px'; }
1466
- if(s.logoPosition==='left'){ logoImg.style.margin='0 16px 20px 0'; logoImg.style.display='block'; logoImg.style.marginLeft='0'; }
1467
- else if(s.logoPosition==='right'){ logoImg.style.margin='0 0 20px 16px'; logoImg.style.display='block'; logoImg.style.marginLeft='auto'; }
1468
- else if(s.logoPosition==='center'){ logoImg.style.margin='0 auto 20px auto'; logoImg.style.display='block'; }
1469
- main.insertBefore(logoImg, document.getElementById('dd-form-wrapper'));
3623
+ // M\xE1rgenes l\xF3gicos: con un survey RTL el popup va con dir="rtl" y el logo
3624
+ // tiene que acompa\xF1ar al chrome. En LTR el resultado es el mismo de antes.
3625
+ if(s.logoPosition==='left'){ logoImg.style.margin='12px 0 0 0'; logoImg.style.setProperty('margin-inline-start','0'); logoImg.style.setProperty('margin-inline-end','16px'); }
3626
+ else if(s.logoPosition==='right'){ logoImg.style.margin='12px 0 0 0'; logoImg.style.setProperty('margin-inline-start','auto'); logoImg.style.setProperty('margin-inline-end','0'); }
3627
+ else if(s.logoPosition==='center'){ logoImg.style.margin='12px auto 0 auto'; }
3628
+ // Encima de la barra de progreso, como hermano del header (espejo de ui/logo.ts en
3629
+ // web). Fuera de #dd-main, as\xED el logo no se va con el scroll del formulario.
3630
+ popup.insertBefore(logoImg, progressEl);
1470
3631
  }
1471
3632
  if(s.startMessage && s.startMessage!==''){ onStartPage=true; updateButtons('start'); }
1472
3633
  else { updateButtons('in_progress_first'); }
@@ -1488,12 +3649,12 @@ ${customCss}
1488
3649
  setLoading(false);
1489
3650
  if(error.toLowerCase().indexOf('no response')!==-1){
1490
3651
  // La p\xE1gina no ha cambiado: el estado de navegaci\xF3n se queda como estaba.
1491
- errorHint.textContent='Please answer the required question to continue.';
3652
+ errorHint.textContent=DD_LABELS_ACTIVE.errorRequired;
1492
3653
  errorHint.style.display='block';
1493
3654
  updateNavButtons();
1494
3655
  return;
1495
3656
  }
1496
- errorHint.textContent='An error occurred while submitting. Please try again or close the popup.';
3657
+ errorHint.textContent=DD_LABELS_ACTIVE.errorSubmit;
1497
3658
  errorHint.style.display='block';
1498
3659
  return;
1499
3660
  }
@@ -1566,7 +3727,8 @@ var ReactNativePopupRenderer = class {
1566
3727
  chrome: renderChrome,
1567
3728
  title: options?.title,
1568
3729
  showProgressBar: options?.showProgressBar,
1569
- surveyCss: options?.surveyCss
3730
+ surveyCss: options?.surveyCss,
3731
+ language: options?.language
1570
3732
  });
1571
3733
  if (this.options.onShow) {
1572
3734
  this.options.onShow({ surveyId, productId, html });
@@ -3379,7 +5541,7 @@ var DeepdotsPopups = class {
3379
5541
  miniService,
3380
5542
  analyticsFeedbackSessionId,
3381
5543
  this.renderChrome,
3382
- { title, showProgressBar: this.showProgressBar, surveyCss: this.surveyCss }
5544
+ { title, showProgressBar: this.showProgressBar, surveyCss: this.surveyCss, language: this.language }
3383
5545
  );
3384
5546
  return;
3385
5547
  }
@@ -3399,7 +5561,7 @@ var DeepdotsPopups = class {
3399
5561
  sessionId,
3400
5562
  miniService,
3401
5563
  analyticsFeedbackSessionId,
3402
- { title, showProgressBar: this.showProgressBar, surveyCss: this.surveyCss }
5564
+ { title, showProgressBar: this.showProgressBar, surveyCss: this.surveyCss, language: this.language }
3403
5565
  );
3404
5566
  });
3405
5567
  }