@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.
@@ -0,0 +1,2302 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __commonJS = (cb, mod) => function __require() {
8
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
19
+ // If the importer is in node compatibility mode or this is not an ESM
20
+ // file that has been converted to a CommonJS file using a Babel-
21
+ // compatible transform (i.e. "__esModule" has not been set), then set
22
+ // "default" to the CommonJS "module.exports" for node compatibility.
23
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
24
+ mod
25
+ ));
26
+
27
+ // src/tracking/tracking-manager.ts
28
+ var InMemoryStorage = class {
29
+ constructor() {
30
+ this.map = /* @__PURE__ */ new Map();
31
+ }
32
+ getItem(key) {
33
+ return this.map.has(key) ? this.map.get(key) : null;
34
+ }
35
+ setItem(key, value) {
36
+ this.map.set(key, value);
37
+ }
38
+ removeItem(key) {
39
+ this.map.delete(key);
40
+ }
41
+ };
42
+ function createDefaultStorage() {
43
+ try {
44
+ if (typeof window !== "undefined" && window.localStorage) {
45
+ const ls = window.localStorage;
46
+ const probe = "__deepdots_probe__";
47
+ ls.setItem(probe, "1");
48
+ ls.removeItem(probe);
49
+ return {
50
+ getItem: (k) => ls.getItem(k),
51
+ setItem: (k, v) => ls.setItem(k, v),
52
+ removeItem: (k) => ls.removeItem(k)
53
+ };
54
+ }
55
+ } catch {
56
+ }
57
+ return new InMemoryStorage();
58
+ }
59
+ var STORAGE_KEYS = {
60
+ userId: "deepdots.user_id",
61
+ firstSeen: "deepdots.user.first_seen",
62
+ contactAttributes: "deepdots.contact.attributes"
63
+ };
64
+ function buildSurveyIdentity(userId, sessionId, miniService = null, analyticsFeedbackSessionId = null) {
65
+ const profile = userId ? [{ key: "external-user-id", value: [userId] }] : [];
66
+ const metadata = [];
67
+ if (sessionId) metadata.push({ key: "session_id", value: [sessionId] });
68
+ if (userId) metadata.push({ key: "user_id", value: [userId] });
69
+ if (miniService) metadata.push({ key: "mini_service", value: [miniService] });
70
+ if (analyticsFeedbackSessionId) metadata.push({ key: "deepdots_analytics_feedback_session_id", value: [analyticsFeedbackSessionId] });
71
+ return { profile, metadata };
72
+ }
73
+ function defaultUuid() {
74
+ const g = typeof globalThis !== "undefined" ? globalThis : {};
75
+ if (g.crypto?.randomUUID) return g.crypto.randomUUID();
76
+ const bytes = new Uint8Array(16);
77
+ if (g.crypto?.getRandomValues) {
78
+ g.crypto.getRandomValues(bytes);
79
+ } else {
80
+ for (let i = 0; i < 16; i++) bytes[i] = Math.floor(Math.random() * 256);
81
+ }
82
+ bytes[6] = bytes[6] & 15 | 64;
83
+ bytes[8] = bytes[8] & 63 | 128;
84
+ const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0"));
85
+ return `${hex.slice(0, 4).join("")}-${hex.slice(4, 6).join("")}-${hex.slice(6, 8).join("")}-${hex.slice(8, 10).join("")}-${hex.slice(10, 16).join("")}`;
86
+ }
87
+ var TrackingManager = class {
88
+ constructor(options) {
89
+ /** session_id cacheado, provisto por el backend (no se genera ni se persiste). */
90
+ this.sessionId = null;
91
+ this.userWasJustCreated = false;
92
+ this.storage = options.storage;
93
+ this.clientUserId = options.clientUserId;
94
+ this.now = options.now ?? (() => Date.now());
95
+ this.uuid = options.uuid ?? defaultUuid;
96
+ this.enabled = options.enabled ?? true;
97
+ }
98
+ isTrackingEnabled() {
99
+ return this.enabled;
100
+ }
101
+ setTrackingEnabled(enabled) {
102
+ this.enabled = enabled;
103
+ }
104
+ /** Resuelve el user_id según la regla: cliente > persistido > generar+persistir. */
105
+ getUserId() {
106
+ if (!this.enabled) return null;
107
+ if (this.clientUserId) return this.clientUserId;
108
+ const persisted = this.storage.getItem(STORAGE_KEYS.userId);
109
+ if (persisted) return persisted;
110
+ const id = this.uuid();
111
+ this.storage.setItem(STORAGE_KEYS.userId, id);
112
+ this.storage.setItem(STORAGE_KEYS.firstSeen, String(this.now()));
113
+ this.userWasJustCreated = true;
114
+ return id;
115
+ }
116
+ /** `true` solo en la primera sesión tras crear el user_id propio del SDK. */
117
+ isNewUser() {
118
+ return this.userWasJustCreated;
119
+ }
120
+ /** session_id actual provisto por el backend, o null si aún no llegó. */
121
+ getSessionId() {
122
+ if (!this.enabled) return null;
123
+ return this.sessionId;
124
+ }
125
+ /** Cachea el session_id devuelto por el backend (respuesta de POST /sdk/popups). */
126
+ setSessionId(sessionId) {
127
+ if (!this.enabled) return;
128
+ this.sessionId = sessionId;
129
+ }
130
+ };
131
+
132
+ // src/ui/font.ts
133
+ var FORMAT_BY_EXT = {
134
+ woff2: "woff2",
135
+ woff: "woff",
136
+ ttf: "truetype",
137
+ otf: "opentype"
138
+ };
139
+ function fontFormatFromUrl(url) {
140
+ const clean = url.split("?")[0].split("#")[0];
141
+ const ext = clean.slice(clean.lastIndexOf(".") + 1).toLowerCase();
142
+ return FORMAT_BY_EXT[ext];
143
+ }
144
+ function sanitizeFamily(family) {
145
+ return family.replace(/[^A-Za-z0-9 ._-]/g, "").trim();
146
+ }
147
+ function isSafeFontUrl(url) {
148
+ if (!/^(https?:|data:)/i.test(url)) return false;
149
+ return !/[\x00-\x20"<>\\]/.test(url);
150
+ }
151
+ function buildFontFamilyValue(family) {
152
+ const safe = sanitizeFamily(family);
153
+ return `"${safe}", -apple-system, system-ui, sans-serif`;
154
+ }
155
+ function buildFontFaceCss(family, url) {
156
+ if (!url || !isSafeFontUrl(url)) return "";
157
+ const safe = sanitizeFamily(family);
158
+ const fmt = fontFormatFromUrl(url);
159
+ const src = fmt ? `url("${url}") format("${fmt}")` : `url("${url}")`;
160
+ return `@font-face{font-family:"${safe}";src:${src};font-display:swap;}`;
161
+ }
162
+
163
+ // src/i18n/labels.ts
164
+ var EN = {
165
+ accept: "Send",
166
+ decline: "Cancel",
167
+ start: "Start survey",
168
+ complete: "Complete survey",
169
+ back: "Back",
170
+ question: "Question",
171
+ of: "of",
172
+ followUp: "Follow-up",
173
+ closeAria: "Close popup",
174
+ loadingAria: "Loading survey",
175
+ errorRequired: "Please answer the required question to continue.",
176
+ errorSubmit: "An error occurred while submitting. Please try again or close the popup."
177
+ };
178
+ var ES = {
179
+ accept: "Enviar",
180
+ decline: "Cancelar",
181
+ start: "Empezar encuesta",
182
+ complete: "Completar encuesta",
183
+ back: "Atr\xE1s",
184
+ question: "Pregunta",
185
+ of: "de",
186
+ followUp: "Seguimiento",
187
+ closeAria: "Cerrar ventana emergente",
188
+ loadingAria: "Cargando encuesta",
189
+ errorRequired: "Responde la pregunta obligatoria para continuar.",
190
+ errorSubmit: "Se produjo un error al enviar. Int\xE9ntalo de nuevo o cierra la ventana."
191
+ };
192
+ var DA = {
193
+ accept: "Send",
194
+ decline: "Annuller",
195
+ start: "Start unders\xF8gelse",
196
+ complete: "Afslut unders\xF8gelse",
197
+ back: "Tilbage",
198
+ question: "Sp\xF8rgsm\xE5l",
199
+ of: "af",
200
+ followUp: "Opf\xF8lgning",
201
+ closeAria: "Luk pop op",
202
+ loadingAria: "Indl\xE6ser unders\xF8gelse",
203
+ errorRequired: "Besvar venligst det obligatoriske sp\xF8rgsm\xE5l for at forts\xE6tte.",
204
+ errorSubmit: "Der opstod en fejl under afsendelsen. Pr\xF8v igen, eller luk pop op-vinduet."
205
+ };
206
+ var NO = {
207
+ accept: "Send",
208
+ decline: "Avbryt",
209
+ start: "Start unders\xF8kelse",
210
+ complete: "Fullf\xF8r unders\xF8kelse",
211
+ back: "Tilbake",
212
+ question: "Sp\xF8rsm\xE5l",
213
+ of: "av",
214
+ followUp: "Oppf\xF8lging",
215
+ closeAria: "Lukk popup",
216
+ loadingAria: "Laster unders\xF8kelse",
217
+ errorRequired: "Svar p\xE5 det obligatoriske sp\xF8rsm\xE5let for \xE5 fortsette.",
218
+ errorSubmit: "Det oppstod en feil under innsendingen. Pr\xF8v igjen, eller lukk popupen."
219
+ };
220
+ var SV = {
221
+ accept: "Skicka",
222
+ decline: "Avbryt",
223
+ start: "Starta unders\xF6kning",
224
+ complete: "Slutf\xF6r unders\xF6kning",
225
+ back: "Tillbaka",
226
+ question: "Fr\xE5ga",
227
+ of: "av",
228
+ followUp: "Uppf\xF6ljning",
229
+ closeAria: "St\xE4ng popup",
230
+ loadingAria: "Laddar unders\xF6kning",
231
+ errorRequired: "Svara p\xE5 den obligatoriska fr\xE5gan f\xF6r att forts\xE4tta.",
232
+ errorSubmit: "Ett fel uppstod vid inskickningen. F\xF6rs\xF6k igen eller st\xE4ng popupen."
233
+ };
234
+ var FI = {
235
+ accept: "L\xE4het\xE4",
236
+ decline: "Peruuta",
237
+ start: "Aloita kysely",
238
+ complete: "Viimeistele kysely",
239
+ back: "Takaisin",
240
+ question: "Kysymys",
241
+ of: "/",
242
+ followUp: "Jatkokysymys",
243
+ closeAria: "Sulje ponnahdusikkuna",
244
+ loadingAria: "Ladataan kysely\xE4",
245
+ errorRequired: "Vastaa pakolliseen kysymykseen jatkaaksesi.",
246
+ errorSubmit: "L\xE4hetyksess\xE4 tapahtui virhe. Yrit\xE4 uudelleen tai sulje ponnahdusikkuna."
247
+ };
248
+ var DE = {
249
+ accept: "Senden",
250
+ decline: "Abbrechen",
251
+ start: "Umfrage starten",
252
+ complete: "Umfrage abschlie\xDFen",
253
+ back: "Zur\xFCck",
254
+ question: "Frage",
255
+ of: "von",
256
+ followUp: "Folgefrage",
257
+ closeAria: "Popup schlie\xDFen",
258
+ loadingAria: "Umfrage wird geladen",
259
+ errorRequired: "Bitte beantworte die Pflichtfrage, um fortzufahren.",
260
+ errorSubmit: "Beim Senden ist ein Fehler aufgetreten. Versuche es erneut oder schlie\xDFe das Popup."
261
+ };
262
+ var FR = {
263
+ accept: "Envoyer",
264
+ decline: "Annuler",
265
+ start: "Commencer l'enqu\xEAte",
266
+ complete: "Terminer l'enqu\xEAte",
267
+ back: "Retour",
268
+ question: "Question",
269
+ of: "sur",
270
+ followUp: "Question compl\xE9mentaire",
271
+ closeAria: "Fermer la fen\xEAtre",
272
+ loadingAria: "Chargement de l'enqu\xEAte",
273
+ errorRequired: "Veuillez r\xE9pondre \xE0 la question obligatoire pour continuer.",
274
+ errorSubmit: "Une erreur s'est produite lors de l'envoi. R\xE9essayez ou fermez la fen\xEAtre."
275
+ };
276
+ var PT = {
277
+ accept: "Enviar",
278
+ decline: "Cancelar",
279
+ start: "Iniciar question\xE1rio",
280
+ complete: "Concluir question\xE1rio",
281
+ back: "Voltar",
282
+ question: "Pergunta",
283
+ of: "de",
284
+ followUp: "Seguimento",
285
+ closeAria: "Fechar janela",
286
+ loadingAria: "A carregar question\xE1rio",
287
+ errorRequired: "Responda \xE0 pergunta obrigat\xF3ria para continuar.",
288
+ errorSubmit: "Ocorreu um erro ao enviar. Tente novamente ou feche a janela."
289
+ };
290
+ var AR = {
291
+ accept: "\u0625\u0631\u0633\u0627\u0644",
292
+ decline: "\u0625\u0644\u063A\u0627\u0621",
293
+ start: "\u0627\u0628\u062F\u0623 \u0627\u0644\u0627\u0633\u062A\u0628\u064A\u0627\u0646",
294
+ complete: "\u0625\u0646\u0647\u0627\u0621 \u0627\u0644\u0627\u0633\u062A\u0628\u064A\u0627\u0646",
295
+ back: "\u0631\u062C\u0648\u0639",
296
+ question: "\u0633\u0624\u0627\u0644",
297
+ of: "\u0645\u0646",
298
+ followUp: "\u0633\u0624\u0627\u0644 \u0645\u062A\u0627\u0628\u0639\u0629",
299
+ closeAria: "\u0625\u063A\u0644\u0627\u0642 \u0627\u0644\u0646\u0627\u0641\u0630\u0629 \u0627\u0644\u0645\u0646\u0628\u062B\u0642\u0629",
300
+ loadingAria: "\u062C\u0627\u0631\u064D \u062A\u062D\u0645\u064A\u0644 \u0627\u0644\u0627\u0633\u062A\u0628\u064A\u0627\u0646",
301
+ 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.",
302
+ 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."
303
+ };
304
+ var BN = {
305
+ accept: "\u09AA\u09BE\u09A0\u09BE\u09A8",
306
+ decline: "\u09AC\u09BE\u09A4\u09BF\u09B2",
307
+ start: "\u099C\u09B0\u09BF\u09AA \u09B6\u09C1\u09B0\u09C1 \u0995\u09B0\u09C1\u09A8",
308
+ complete: "\u099C\u09B0\u09BF\u09AA \u09B8\u09AE\u09CD\u09AA\u09C2\u09B0\u09CD\u09A3 \u0995\u09B0\u09C1\u09A8",
309
+ back: "\u09AA\u09BF\u099B\u09A8\u09C7",
310
+ question: "\u09AA\u09CD\u09B0\u09B6\u09CD\u09A8",
311
+ of: "/",
312
+ followUp: "\u09AB\u09B2\u09CB-\u0986\u09AA",
313
+ closeAria: "\u09AA\u09AA\u0986\u09AA \u09AC\u09A8\u09CD\u09A7 \u0995\u09B0\u09C1\u09A8",
314
+ loadingAria: "\u099C\u09B0\u09BF\u09AA \u09B2\u09CB\u09A1 \u09B9\u099A\u09CD\u099B\u09C7",
315
+ 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",
316
+ 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"
317
+ };
318
+ var ZH_CN = {
319
+ accept: "\u53D1\u9001",
320
+ decline: "\u53D6\u6D88",
321
+ start: "\u5F00\u59CB\u95EE\u5377",
322
+ complete: "\u5B8C\u6210\u95EE\u5377",
323
+ back: "\u8FD4\u56DE",
324
+ question: "\u95EE\u9898",
325
+ of: "/",
326
+ followUp: "\u8FFD\u95EE",
327
+ closeAria: "\u5173\u95ED\u5F39\u7A97",
328
+ loadingAria: "\u6B63\u5728\u52A0\u8F7D\u95EE\u5377",
329
+ errorRequired: "\u8BF7\u56DE\u7B54\u5FC5\u7B54\u9898\u540E\u7EE7\u7EED\u3002",
330
+ errorSubmit: "\u63D0\u4EA4\u65F6\u51FA\u9519\u3002\u8BF7\u91CD\u8BD5\u6216\u5173\u95ED\u5F39\u7A97\u3002"
331
+ };
332
+ var LABELS = {
333
+ en: EN,
334
+ es: ES,
335
+ da: DA,
336
+ no: NO,
337
+ sv: SV,
338
+ fi: FI,
339
+ de: DE,
340
+ fr: FR,
341
+ pt: PT,
342
+ ar: AR,
343
+ bn: BN,
344
+ "zh-CN": ZH_CN
345
+ };
346
+ var SUPPORTED_LANGUAGES = [
347
+ // Los 11 idiomas que la plataforma ofrece para un survey, más zh-CN (que el SDK nativo ya
348
+ // traía). Si la plataforma añade uno nuevo, hay que añadirlo aquí o el chrome saldrá en
349
+ // inglés bajo un survey traducido.
350
+ "en",
351
+ "es",
352
+ "da",
353
+ "no",
354
+ "sv",
355
+ "fi",
356
+ "de",
357
+ "fr",
358
+ "pt",
359
+ "ar",
360
+ "bn",
361
+ "zh-CN"
362
+ ];
363
+ function resolveLocale(lang) {
364
+ if (typeof lang !== "string") return "en";
365
+ const normalized = lang.trim().toLowerCase().replace(/_/g, "-");
366
+ if (!normalized) return "en";
367
+ if (normalized === "zh" || normalized.startsWith("zh-")) return "zh-CN";
368
+ const primary = normalized.split("-")[0];
369
+ switch (primary) {
370
+ case "en":
371
+ return "en";
372
+ case "es":
373
+ return "es";
374
+ case "da":
375
+ return "da";
376
+ case "no":
377
+ case "nb":
378
+ case "nn":
379
+ return "no";
380
+ case "sv":
381
+ return "sv";
382
+ case "fi":
383
+ return "fi";
384
+ case "de":
385
+ return "de";
386
+ case "fr":
387
+ return "fr";
388
+ case "pt":
389
+ return "pt";
390
+ case "ar":
391
+ return "ar";
392
+ case "bn":
393
+ return "bn";
394
+ default:
395
+ return "en";
396
+ }
397
+ }
398
+ var RTL_LOCALES = ["ar"];
399
+ function isRtlLanguage(lang) {
400
+ return RTL_LOCALES.includes(resolveLocale(lang));
401
+ }
402
+ function directionFor(lang) {
403
+ return isRtlLanguage(lang) ? "rtl" : "ltr";
404
+ }
405
+ function getLabels(lang) {
406
+ return LABELS[resolveLocale(lang)];
407
+ }
408
+ function resolveActionLabels(actions, lang) {
409
+ const labels = getLabels(lang);
410
+ const pick = (value, fallback) => {
411
+ const trimmed = typeof value === "string" ? value.trim() : "";
412
+ return trimmed ? value : fallback;
413
+ };
414
+ return {
415
+ accept: pick(actions?.accept?.label, labels.accept),
416
+ decline: pick(actions?.decline?.label, labels.decline),
417
+ start: pick(actions?.start?.label, labels.start),
418
+ complete: pick(actions?.complete?.label, labels.complete),
419
+ back: pick(actions?.back?.label, labels.back)
420
+ };
421
+ }
422
+ var RESOLVE_LOCALE_JS = `function ddResolveLocale(lang){
423
+ if(typeof lang!=='string') return 'en';
424
+ var n=lang.trim().toLowerCase().replace(/_/g,'-');
425
+ if(!n) return 'en';
426
+ if(n==='zh'||n.indexOf('zh-')===0) return 'zh-CN';
427
+ var p=n.split('-')[0];
428
+ if(p==='en') return 'en';
429
+ if(p==='es') return 'es';
430
+ if(p==='da') return 'da';
431
+ if(p==='no'||p==='nb'||p==='nn') return 'no';
432
+ if(p==='sv') return 'sv';
433
+ if(p==='fi') return 'fi';
434
+ if(p==='de') return 'de';
435
+ if(p==='fr') return 'fr';
436
+ if(p==='pt') return 'pt';
437
+ if(p==='ar') return 'ar';
438
+ if(p==='bn') return 'bn';
439
+ return 'en';
440
+ }`;
441
+
442
+ // src/assets/style.css
443
+ var style_default = `/**
444
+ * NO EDITAR A MANO \u2014 generado por scripts/vendor-survey-css.mjs
445
+ *
446
+ * Copia de @magicfeedback/native@2.2.22 \u2192 dist/styles/magicfeedback-default.css
447
+ * (la hoja can\xF3nica del paquete, la que apunta su campo "style"), con estos cambios locales:
448
+ *
449
+ * 1. Sin el @import de Google Fonts (Nunito): no queremos una petici\xF3n externa desde la
450
+ * p\xE1gina del host, y la tipograf\xEDa la decide el popup.
451
+ * 2. .magicfeedback-container hereda la fuente del popup (var(--deepdots-font, inherit)).
452
+ * 3. Los selectores desnudos (h2, p, input, textarea, select, ::placeholder, .error) van
453
+ * acotados a .deepdots-popup: este CSS se inyecta en el <head> del host y sin acotar
454
+ * repintar\xEDa su web.
455
+ * 4. El grupo .magicfeedback-radio se cualifica como div.magicfeedback-radio (la clase acaba
456
+ * tambi\xE9n en el <input> del boolean).
457
+ * 5. Al final, un bloque de reglas propias del popup (fuente en los controles y padding del
458
+ * radio nativo).
459
+ *
460
+ * Las variables --mf-* se dejan en :root a prop\xF3sito: el modal del priority-list se portea a
461
+ * <body>, fuera de .deepdots-popup, y ah\xED las necesita.
462
+ *
463
+ * Para subir de versi\xF3n: npm i @magicfeedback/native@<v> && node scripts/vendor-survey-css.mjs
464
+ */
465
+
466
+ /**
467
+ * @magicfeedback/native - Default Styles
468
+ * Clean, minimal, and elegant survey rendering
469
+ */
470
+
471
+ /* @import de Google Fonts (Nunito) eliminado al vendorizar: la fuente la pone el popup. */
472
+
473
+ /* ========================================
474
+ CSS VARIABLES - Design SYSTEM
475
+ ======================================== */
476
+ :root {
477
+ /* Colors - Minimal Pastel */
478
+ /* --mf-primary is the one source of truth for brand/accent color \u2014
479
+ every token below derives from it via color-mix() (or references
480
+ it directly) so changing this single value, here or via a
481
+ per-integration override, keeps hover/light/border states in
482
+ sync automatically instead of going stale independently. Scoped
483
+ to genuinely interactive/accent surfaces (buttons, selected
484
+ chips, focus rings) \u2014 general body text stays on its own neutral
485
+ scale below, not tied to the brand color. */
486
+ --mf-primary: #5d7bad;
487
+ --mf-primary-hover: color-mix(in srgb, var(--mf-primary) 85%, black);
488
+ --mf-primary-light: color-mix(in srgb, var(--mf-primary) 15%, white);
489
+ /* a translucent tint \u2014 mixed with transparent (opacity), not white,
490
+ so it reads as a soft shadow of the brand color rather than a
491
+ pastel of it. */
492
+ --mf-primary-border: color-mix(in srgb, var(--mf-primary) 35%, transparent);
493
+
494
+ --mf-text-primary: #1E293B;
495
+ --mf-text-secondary: #475569;
496
+ --mf-text-muted: #94A3B8;
497
+
498
+ --mf-bg-primary: #F8FAFC;
499
+ --mf-bg-secondary: #FFFFFF;
500
+ --mf-bg-hover: #EEF2F6;
501
+
502
+ --mf-border: #E2E8F0;
503
+ --mf-border-focus: var(--mf-primary);
504
+
505
+ --mf-success: #16A34A;
506
+ --mf-error: #EF4444;
507
+ --mf-warning: #F59E0B;
508
+
509
+ --mf-surface: #FFFFFF;
510
+ --mf-surface-alt: #F1F5F9;
511
+ --mf-accent: #38BDF8;
512
+
513
+ /* Spacing */
514
+ --mf-space-xs: 0.25rem;
515
+ --mf-space-sm: 0.5rem;
516
+ --mf-space-md: 0.75rem;
517
+ --mf-space-lg: 1rem;
518
+ --mf-space-xl: 1.5rem;
519
+
520
+ /* Border Radius */
521
+ --mf-radius-sm: 0.5rem;
522
+ --mf-radius-md: 0.75rem;
523
+ --mf-radius-lg: 1.25rem;
524
+ --mf-radius-full: 9999px;
525
+
526
+ /* Shadows */
527
+ --mf-shadow-sm: 0 1px 2px 0 rgba(15, 23, 42, 0.06);
528
+ --mf-shadow-md: 0 8px 20px rgba(15, 23, 42, 0.08);
529
+ --mf-shadow-lg: 0 16px 30px rgba(15, 23, 42, 0.12);
530
+ --mf-shadow-focus: 0 0 0 3px rgba(30, 41, 59, 0.15);
531
+ --mf-shadow-card: 0 18px 40px rgba(15, 23, 42, 0.08);
532
+
533
+ /* Typography */
534
+ --mf-font-sans: "Nunito", "Quicksand", "Avenir Next", "Trebuchet MS", sans-serif;
535
+ --mf-font-size-sm: 0.875rem;
536
+ --mf-font-size-base: 1rem;
537
+ --mf-font-size-lg: 1.125rem;
538
+ --mf-font-size-xl: 1.25rem;
539
+ --mf-line-height: 1.6;
540
+
541
+ /* Font Weights */
542
+ --mf-font-weight-normal: 400;
543
+ --mf-font-weight-medium: 500;
544
+ --mf-font-weight-semibold: 600;
545
+ --mf-font-weight-bold: 700;
546
+ --mf-font-weight-extrabold: 800;
547
+
548
+ /* Transitions */
549
+ --mf-transition: all 0.2s ease;
550
+ --mf-transition-fast: all 0.15s ease;
551
+ }
552
+
553
+ /* ========================================
554
+ ANIMATIONS
555
+ ======================================== */
556
+ @keyframes mf-fade-in {
557
+ from {
558
+ opacity: 0;
559
+ transform: translateY(8px);
560
+ }
561
+ to {
562
+ opacity: 1;
563
+ transform: translateY(0);
564
+ }
565
+ }
566
+
567
+ @keyframes mf-slide-in {
568
+ from {
569
+ opacity: 0;
570
+ transform: translateX(-16px);
571
+ }
572
+ to {
573
+ opacity: 1;
574
+ transform: translateX(0);
575
+ }
576
+ }
577
+
578
+ @keyframes mf-scale-in {
579
+ from {
580
+ opacity: 0;
581
+ transform: scale(0.95);
582
+ }
583
+ to {
584
+ opacity: 1;
585
+ transform: scale(1);
586
+ }
587
+ }
588
+
589
+ @keyframes mf-pulse {
590
+ 0%,
591
+ 100% {
592
+ opacity: 1;
593
+ }
594
+ 50% {
595
+ opacity: 0.8;
596
+ }
597
+ }
598
+
599
+ /* ========================================
600
+ BASE CONTAINER
601
+ ======================================== */
602
+ .magicfeedback-container {
603
+ /* Local: hereda la fuente del popup; --deepdots-font viene de PopupStyle.font. */
604
+ font-family: var(--deepdots-font, inherit);
605
+ color: var(--mf-text-primary);
606
+ line-height: var(--mf-line-height);
607
+ animation: mf-fade-in 0.4s ease-out;
608
+ border-radius: var(--mf-radius-lg);
609
+ }
610
+
611
+ /* ========================================
612
+ MESSAGES
613
+ ======================================== */
614
+ .magicfeedback-success-message,
615
+ .magicfeedback-info-message,
616
+ .magicfeedback-start-message {
617
+ padding: var(--mf-space-lg);
618
+ margin: var(--mf-space-lg) 0;
619
+ animation: mf-scale-in 0.3s ease-out;
620
+ }
621
+
622
+ /* .magicfeedback-info-message/-start-message are set via innerHTML (see
623
+ renderInfoPage.ts / questions.service.ts's renderStartMessage) \u2014 whatever
624
+ rich text a survey author writes lands here as real HTML, not just the
625
+ <p>/<img> pair this used to style. Covering the rest of what a rich-text
626
+ editor commonly outputs (headings, lists, links, emphasis, quotes, code,
627
+ rules) keeps that content on the same type scale and palette as the rest
628
+ of the widget instead of falling back to unstyled browser defaults. */
629
+ .magicfeedback-success-message > :first-child,
630
+ .magicfeedback-info-message > :first-child,
631
+ .magicfeedback-start-message > :first-child {
632
+ margin-top: 0;
633
+ }
634
+
635
+ .magicfeedback-success-message > :last-child,
636
+ .magicfeedback-info-message > :last-child,
637
+ .magicfeedback-start-message > :last-child {
638
+ margin-bottom: 0;
639
+ }
640
+
641
+ .magicfeedback-success-message p,
642
+ .magicfeedback-info-message p,
643
+ .magicfeedback-start-message p {
644
+ font-size: var(--mf-font-size-base);
645
+ color: var(--mf-text-secondary);
646
+ margin: 0 0 var(--mf-space-md);
647
+ line-height: var(--mf-line-height);
648
+ }
649
+
650
+ .magicfeedback-info-message h1,
651
+ .magicfeedback-info-message h2,
652
+ .magicfeedback-info-message h3,
653
+ .magicfeedback-info-message h4,
654
+ .magicfeedback-info-message h5,
655
+ .magicfeedback-info-message h6,
656
+ .magicfeedback-start-message h1,
657
+ .magicfeedback-start-message h2,
658
+ .magicfeedback-start-message h3,
659
+ .magicfeedback-start-message h4,
660
+ .magicfeedback-start-message h5,
661
+ .magicfeedback-start-message h6 {
662
+ color: var(--mf-text-primary);
663
+ font-weight: var(--mf-font-weight-bold);
664
+ line-height: 1.3;
665
+ margin: var(--mf-space-lg) 0 var(--mf-space-sm);
666
+ text-align: start;
667
+ }
668
+
669
+ .magicfeedback-info-message h1, .magicfeedback-start-message h1 { font-size: var(--mf-font-size-xl); }
670
+ .magicfeedback-info-message h2, .magicfeedback-start-message h2 { font-size: var(--mf-font-size-lg); }
671
+ .magicfeedback-info-message h3,
672
+ .magicfeedback-info-message h4,
673
+ .magicfeedback-info-message h5,
674
+ .magicfeedback-info-message h6,
675
+ .magicfeedback-start-message h3,
676
+ .magicfeedback-start-message h4,
677
+ .magicfeedback-start-message h5,
678
+ .magicfeedback-start-message h6 { font-size: var(--mf-font-size-base); }
679
+
680
+ .magicfeedback-info-message strong,
681
+ .magicfeedback-info-message b,
682
+ .magicfeedback-start-message strong,
683
+ .magicfeedback-start-message b {
684
+ font-weight: var(--mf-font-weight-bold);
685
+ color: var(--mf-text-primary);
686
+ }
687
+
688
+ .magicfeedback-info-message a,
689
+ .magicfeedback-start-message a {
690
+ color: var(--mf-primary);
691
+ text-decoration: underline;
692
+ text-underline-offset: 2px;
693
+ }
694
+
695
+ .magicfeedback-info-message a:hover,
696
+ .magicfeedback-start-message a:hover {
697
+ color: var(--mf-primary-hover);
698
+ }
699
+
700
+ .magicfeedback-info-message ul,
701
+ .magicfeedback-info-message ol,
702
+ .magicfeedback-start-message ul,
703
+ .magicfeedback-start-message ol {
704
+ margin: 0 0 var(--mf-space-md);
705
+ padding-inline-start: var(--mf-space-xl);
706
+ color: var(--mf-text-secondary);
707
+ line-height: var(--mf-line-height);
708
+ }
709
+
710
+ .magicfeedback-info-message li + li,
711
+ .magicfeedback-start-message li + li {
712
+ margin-top: var(--mf-space-xs);
713
+ }
714
+
715
+ .magicfeedback-info-message blockquote,
716
+ .magicfeedback-start-message blockquote {
717
+ margin: 0 0 var(--mf-space-md);
718
+ padding: var(--mf-space-sm) var(--mf-space-md);
719
+ border-inline-start: 3px solid var(--mf-primary-border);
720
+ color: var(--mf-text-secondary);
721
+ font-style: italic;
722
+ }
723
+
724
+ .magicfeedback-info-message code,
725
+ .magicfeedback-start-message code {
726
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
727
+ font-size: 0.9em;
728
+ background: var(--mf-bg-hover);
729
+ padding: 0.15em 0.4em;
730
+ border-radius: var(--mf-radius-sm);
731
+ }
732
+
733
+ .magicfeedback-info-message pre,
734
+ .magicfeedback-start-message pre {
735
+ margin: 0 0 var(--mf-space-md);
736
+ padding: var(--mf-space-md);
737
+ background: var(--mf-bg-hover);
738
+ border-radius: var(--mf-radius-md);
739
+ overflow-x: auto;
740
+ }
741
+
742
+ .magicfeedback-info-message pre code,
743
+ .magicfeedback-start-message pre code {
744
+ background: none;
745
+ padding: 0;
746
+ }
747
+
748
+ .magicfeedback-info-message hr,
749
+ .magicfeedback-start-message hr {
750
+ border: none;
751
+ border-top: 1px solid var(--mf-border);
752
+ margin: var(--mf-space-lg) 0;
753
+ }
754
+
755
+ .magicfeedback-success-message img,
756
+ .magicfeedback-info-message img,
757
+ .magicfeedback-start-message img {
758
+ max-width: 100%;
759
+ height: auto;
760
+ margin: var(--mf-space-lg) auto;
761
+ display: block;
762
+ border-radius: var(--mf-radius-md);
763
+ }
764
+
765
+ .magicfeedback-image {
766
+ max-height: 400px;
767
+ height: auto;
768
+ max-width: 100%;
769
+ margin: var(--mf-space-lg) auto;
770
+ display: block;
771
+ border-radius: var(--mf-radius-md);
772
+ }
773
+
774
+ /* ========================================
775
+ FORM STRUCTURE
776
+ ======================================== */
777
+ .magicfeedback-form {
778
+ display: flex;
779
+ flex-direction: column;
780
+ gap: var(--mf-space-lg);
781
+ padding: clamp(16px, 2.5vw, 28px);
782
+ }
783
+
784
+ .magicfeedback-questions {
785
+ display: flex;
786
+ flex-direction: column;
787
+ gap: var(--mf-space-xl);
788
+ width: 100%;
789
+ }
790
+
791
+ .magicfeedback-div {
792
+ display: flex;
793
+ flex-direction: column;
794
+ gap: var(--mf-space-sm);
795
+ animation: mf-slide-in 0.3s ease-out;
796
+ background: var(--mf-bg-secondary);
797
+ border-radius: var(--mf-radius-md);
798
+ }
799
+
800
+ /* ========================================
801
+ LABELS & TYPOGRAPHY
802
+ ======================================== */
803
+ .magicfeedback-label {
804
+ font-size: var(--mf-font-size-lg);
805
+ font-weight: var(--mf-font-weight-bold);
806
+ color: var(--mf-text-primary);
807
+ line-height: var(--mf-line-height);
808
+ text-align: start;
809
+ letter-spacing: -0.01em;
810
+ }
811
+
812
+ .magicfeedback-sublabel {
813
+ font-size: var(--mf-font-size-base);
814
+ font-weight: var(--mf-font-weight-normal);
815
+ color: var(--mf-text-secondary);
816
+ margin-bottom: var(--mf-space-sm);
817
+ }
818
+
819
+ .deepdots-popup h2 {
820
+ font-size: var(--mf-font-size-xl);
821
+ font-weight: 600;
822
+ color: var(--mf-text-primary);
823
+ margin: 0 0 var(--mf-space-xl) 0;
824
+ text-align: center;
825
+ letter-spacing: -0.01em;
826
+ }
827
+
828
+ .deepdots-popup p {
829
+ margin: 0;
830
+ font-size: var(--mf-font-size-sm);
831
+ color: var(--mf-text-secondary);
832
+ }
833
+
834
+ /* ========================================
835
+ FORM INPUTS
836
+ ======================================== */
837
+ .deepdots-popup input[type="date"],
838
+ .deepdots-popup input[type="text"],
839
+ .deepdots-popup input[type="number"],
840
+ .deepdots-popup input[type="email"],
841
+ .deepdots-popup input[type="password"],
842
+ .deepdots-popup textarea,
843
+ .deepdots-popup select {
844
+ padding: 0.75rem 0.9rem;
845
+ font-size: var(--mf-font-size-base);
846
+ font-family: inherit;
847
+ color: var(--mf-text-primary);
848
+ background-color: var(--mf-surface);
849
+ border: 2px solid var(--mf-border);
850
+ border-radius: var(--mf-radius-md);
851
+ outline: none;
852
+ transition: var(--mf-transition);
853
+ -webkit-appearance: none;
854
+ appearance: none;
855
+ box-shadow: var(--mf-shadow-sm);
856
+ }
857
+
858
+ .deepdots-popup textarea {
859
+ min-height: 100px;
860
+ resize: vertical;
861
+ }
862
+
863
+ .deepdots-popup input::placeholder,
864
+ .deepdots-popup textarea::placeholder {
865
+ color: var(--mf-text-muted);
866
+ }
867
+
868
+ /* Remove number input spinners */
869
+ .deepdots-popup input::-webkit-outer-spin-button,
870
+ .deepdots-popup input::-webkit-inner-spin-button {
871
+ -webkit-appearance: none;
872
+ margin: 0;
873
+ }
874
+
875
+ .deepdots-popup input[type="number"] {
876
+ /* -moz-appearance: textfield; removed for lint compatibility */
877
+ }
878
+
879
+ /* Custom Select Arrow */
880
+ .deepdots-popup select {
881
+ 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");
882
+ background-repeat: no-repeat;
883
+ background-position: right var(--mf-space-md) center;
884
+ padding-inline-end: var(--mf-space-xl);
885
+ }
886
+
887
+ /* Error State */
888
+ .deepdots-popup input.error,
889
+ .deepdots-popup select.error,
890
+ .deepdots-popup textarea.error {
891
+ border-color: var(--mf-error);
892
+ }
893
+
894
+ .magicfeedback-error {
895
+ margin-top: var(--mf-space-xs);
896
+ font-size: var(--mf-font-size-sm);
897
+ color: var(--mf-error);
898
+ }
899
+
900
+ /* ========================================
901
+ CHECKBOX & RADIO OPTIONS
902
+ ======================================== */
903
+ .magicfeedback-checkbox,
904
+ div.magicfeedback-radio {
905
+ display: flex;
906
+ flex-direction: column;
907
+ gap: var(--mf-space-sm);
908
+ width: 100%;
909
+ }
910
+
911
+ .magicfeedback-checkbox-container,
912
+ .magicfeedback-radio-container {
913
+ display: flex;
914
+ align-items: center;
915
+ gap: var(--mf-space-sm);
916
+ padding: var(--mf-space-md);
917
+ border: 1.5px solid var(--mf-border);
918
+ border-radius: var(--mf-radius-md);
919
+ cursor: pointer;
920
+ transition: var(--mf-transition-fast);
921
+ }
922
+
923
+ .magicfeedback-checkbox-container:hover,
924
+ .magicfeedback-radio-container:hover {
925
+ background-color: var(--mf-bg-hover);
926
+ border-color: var(--mf-primary);
927
+ }
928
+
929
+ .magicfeedback-checkbox-container:has(input:checked),
930
+ .magicfeedback-radio-container:has(input:checked) {
931
+ background-color: var(--mf-primary-light);
932
+ border-color: var(--mf-primary);
933
+ }
934
+
935
+ .magicfeedback-checkbox input[type="checkbox"],
936
+ .magicfeedback-radio-container input[type="radio"] {
937
+ width: 18px;
938
+ height: 18px;
939
+ margin: 0;
940
+ cursor: pointer;
941
+ flex-shrink: 0;
942
+ accent-color: var(--mf-primary);
943
+ }
944
+
945
+ .magicfeedback-checkbox label,
946
+ .magicfeedback-radio-container label {
947
+ font-size: var(--mf-font-size-base);
948
+ text-align: start;
949
+ color: var(--mf-text-primary);
950
+ cursor: pointer;
951
+ margin: 0;
952
+ flex: 1;
953
+ }
954
+
955
+ /* ========================================
956
+ BOOLEAN OPTIONS
957
+ ======================================== */
958
+ .magicfeedback-boolean-container {
959
+ display: flex;
960
+ gap: var(--mf-space-md);
961
+ width: 100%;
962
+ }
963
+
964
+ .magicfeedback-boolean-option {
965
+ flex: 1;
966
+ position: relative;
967
+ }
968
+
969
+ .magicfeedback-boolean-option input[type="radio"] {
970
+ position: absolute;
971
+ opacity: 0;
972
+ width: 0;
973
+ height: 0;
974
+ }
975
+
976
+ .magicfeedback-boolean-option label {
977
+ display: flex;
978
+ align-items: center;
979
+ justify-content: center;
980
+ padding: var(--mf-space-md);
981
+ font-size: var(--mf-font-size-base);
982
+ font-weight: 500;
983
+ color: var(--mf-text-secondary);
984
+ border: 1.5px solid var(--mf-border);
985
+ border-radius: var(--mf-radius-md);
986
+ cursor: pointer;
987
+ transition: var(--mf-transition-fast);
988
+ margin: 0;
989
+ width: -webkit-fill-available;
990
+ height: inherit;
991
+ }
992
+
993
+ .magicfeedback-boolean-option label:hover {
994
+ background-color: var(--mf-bg-hover);
995
+ border-color: var(--mf-primary);
996
+ }
997
+
998
+ .magicfeedback-boolean-option input[type="radio"]:checked + label {
999
+ color: var(--mf-primary);
1000
+ background-color: var(--mf-primary-light);
1001
+ border-color: var(--mf-primary);
1002
+ font-weight: 600;
1003
+ }
1004
+
1005
+ /* ========================================
1006
+ RATING SYSTEMS
1007
+ ======================================== */
1008
+ .magicfeedback-rating,
1009
+ .magicfeedback-rating-number,
1010
+ .magicfeedback-rating-star {
1011
+ width: 100%;
1012
+ }
1013
+
1014
+ .magicfeedback-rating-container,
1015
+ .magicfeedback-rating-number-container,
1016
+ .magicfeedback-rating-star-container {
1017
+ display: flex;
1018
+ flex-wrap: wrap;
1019
+ gap: var(--mf-space-sm);
1020
+ justify-content: center;
1021
+ align-items: center;
1022
+ padding: var(--mf-space-md) 0;
1023
+ list-style: none;
1024
+ margin: 0;
1025
+ }
1026
+
1027
+ /* Caption line below the row \u2014 min on one side, max on the other (swapped
1028
+ for order: "rtl") \u2014 same simple, non-responsive pattern as the
1029
+ rating-number row caption. Used by rating-star and rating-emoji. */
1030
+ .magicfeedback-rating-placeholder {
1031
+ display: flex;
1032
+ justify-content: space-between;
1033
+ gap: var(--mf-space-md);
1034
+ width: 100%;
1035
+ margin-top: var(--mf-space-sm);
1036
+ font-size: var(--mf-font-size-sm);
1037
+ font-weight: var(--mf-font-weight-semibold);
1038
+ color: var(--mf-text-secondary);
1039
+ }
1040
+
1041
+ .magicfeedback-rating-placeholder-value {
1042
+ overflow-wrap: anywhere;
1043
+ }
1044
+
1045
+ .magicfeedback-rating-placeholder-value:last-child {
1046
+ text-align: end;
1047
+ }
1048
+
1049
+ /* Rating with Images */
1050
+ .magicfeedback-rating-option-label-container input[type="radio"] {
1051
+ position: absolute;
1052
+ opacity: 0;
1053
+ width: 0;
1054
+ height: 0;
1055
+ }
1056
+
1057
+ .magicfeedback-rating-option-label-container img {
1058
+ width: 56px;
1059
+ height: 56px;
1060
+ cursor: pointer;
1061
+ transition: var(--mf-transition-fast);
1062
+ border-radius: var(--mf-radius-full);
1063
+ border: 2px solid transparent;
1064
+ }
1065
+
1066
+ .magicfeedback-rating-option-label-container img:hover {
1067
+ transform: scale(1.1);
1068
+ border-color: var(--mf-primary);
1069
+ }
1070
+
1071
+ .magicfeedback-rating-option-label-container input[type="radio"]:checked + img {
1072
+ border-color: var(--mf-primary);
1073
+ box-shadow: 0 0 0 3px var(--mf-primary-light);
1074
+ }
1075
+
1076
+ .magicfeedback-rating-option-label-container label {
1077
+ display: block;
1078
+ text-align: center;
1079
+ font-size: var(--mf-font-size-sm);
1080
+ color: var(--mf-text-secondary);
1081
+ margin-top: var(--mf-space-xs);
1082
+ cursor: pointer;
1083
+ }
1084
+
1085
+ /* Rating Numbers \u2014 each option is its own outlined chip in the survey's
1086
+ primary color, with a gap between them. Row and column use the same
1087
+ chip; column additionally has room to show each option's own text
1088
+ plainly next to its number. */
1089
+
1090
+ /* Every size here is width:100%/flex:1 combined with the chip's own
1091
+ padding and border. Without border-box, the browser's default
1092
+ content-box adds that padding/border on TOP of the declared size, so
1093
+ the chip quietly overflows past its flex slot \u2014 reading as "not quite
1094
+ full width" or, worse, pushing into the next chip. */
1095
+ .magicfeedback-rating-number-container,
1096
+ .magicfeedback-rating-number-option,
1097
+ .magicfeedback-rating-number-option-label-container,
1098
+ .magicfeedback-rating-number-value {
1099
+ box-sizing: border-box;
1100
+ }
1101
+
1102
+ /* The shared rating-container rule (above, reused by star rating) sets
1103
+ align-items:center for its row-of-chips layout \u2014 in a stacked column
1104
+ that still nudges a 100%-wide chip inward instead of a true 0 offset.
1105
+ Force stretch so every chip fills the exact same width, flush on
1106
+ both sides. */
1107
+ .magicfeedback-rating-number-container-column,
1108
+ .magicfeedback-rating-number-container-column-reverse {
1109
+ align-items: stretch;
1110
+ }
1111
+
1112
+ /* Caption line below the row \u2014 the single place min/max labels live
1113
+ for row mode, shared by mobile and desktop. */
1114
+ .magicfeedback-rating-number-scale-labels {
1115
+ display: flex;
1116
+ justify-content: space-between;
1117
+ gap: var(--mf-space-md);
1118
+ margin-top: var(--mf-space-sm);
1119
+ font-size: var(--mf-font-size-sm);
1120
+ font-weight: var(--mf-font-weight-semibold);
1121
+ color: var(--mf-text-secondary);
1122
+ }
1123
+
1124
+ .magicfeedback-rating-number-scale-label {
1125
+ overflow-wrap: anywhere;
1126
+ }
1127
+
1128
+ .magicfeedback-rating-number-scale-label:last-child {
1129
+ text-align: end;
1130
+ }
1131
+
1132
+ /* Column, no per-option text: each row is its own separated chip, so
1133
+ the min/max labels bookend the stack from outside it \u2014 one line
1134
+ above the first chip, one below the last. Margin goes on whichever
1135
+ side actually faces the list \u2014 the "before" label (always the first
1136
+ child) gets space below it, the "after" one (always right after the
1137
+ container, extra option row or not) gets space above it \u2014 so both
1138
+ sit the same distance from the chips regardless of which one it is. */
1139
+ .magicfeedback-rating-number-scale-label-block {
1140
+ font-size: var(--mf-font-size-sm);
1141
+ font-weight: var(--mf-font-weight-semibold);
1142
+ color: var(--mf-text-secondary);
1143
+ text-align: center;
1144
+ }
1145
+
1146
+ .magicfeedback-rating-number-scale-label-block:first-child {
1147
+ margin-bottom: var(--mf-space-sm);
1148
+ }
1149
+
1150
+ .magicfeedback-rating-number-container + .magicfeedback-rating-number-scale-label-block {
1151
+ margin-top: var(--mf-space-sm);
1152
+ }
1153
+
1154
+ .magicfeedback-rating-number-option {
1155
+ display: flex;
1156
+ }
1157
+
1158
+ .magicfeedback-rating-number-option-label-container {
1159
+ position: relative;
1160
+ width: 100%;
1161
+ display: flex;
1162
+ cursor: pointer;
1163
+ }
1164
+
1165
+ .magicfeedback-rating-number-option-label-container input[type="radio"] {
1166
+ position: absolute;
1167
+ opacity: 0;
1168
+ width: 0;
1169
+ height: 0;
1170
+ }
1171
+
1172
+ .magicfeedback-rating-number-value {
1173
+ display: flex;
1174
+ align-items: center;
1175
+ justify-content: center;
1176
+ width: 100%;
1177
+ transition: var(--mf-transition-fast);
1178
+ color: var(--mf-text-secondary);
1179
+ font-weight: var(--mf-font-weight-semibold);
1180
+ }
1181
+
1182
+ /* Row: individual outlined chips in the survey's own primary color \u2014
1183
+ var(--mf-primary) so whatever brand color a given survey sets carries
1184
+ through automatically, no color hardcoded here. */
1185
+ .magicfeedback-rating-number-container-row,
1186
+ .magicfeedback-rating-number-container-row-reverse {
1187
+ flex-wrap: nowrap;
1188
+ gap: var(--mf-space-sm);
1189
+ }
1190
+
1191
+ .magicfeedback-rating-number-option-row,
1192
+ .magicfeedback-rating-number-option-row-reverse {
1193
+ flex: 1 1 0;
1194
+ min-width: 0;
1195
+ }
1196
+
1197
+ .magicfeedback-rating-number-option-row .magicfeedback-rating-number-value,
1198
+ .magicfeedback-rating-number-option-row-reverse .magicfeedback-rating-number-value {
1199
+ min-height: 56px;
1200
+ padding: var(--mf-space-sm);
1201
+ border: 2px solid var(--mf-primary-border);
1202
+ border-radius: var(--mf-radius-md);
1203
+ background: var(--mf-bg-secondary);
1204
+ color: var(--mf-primary);
1205
+ font-size: var(--mf-font-size-lg);
1206
+ font-weight: var(--mf-font-weight-bold);
1207
+ }
1208
+
1209
+ /* More than 6 options (e.g. a 0-10 NPS scale): still one row, never
1210
+ wraps \u2014 but scaled down on purpose, so it reads as a compact chip
1211
+ rather than the same 56px button stretched thin. */
1212
+ .magicfeedback-rating-number-container-row--dense .magicfeedback-rating-number-option-row .magicfeedback-rating-number-value,
1213
+ .magicfeedback-rating-number-container-row--dense .magicfeedback-rating-number-option-row-reverse .magicfeedback-rating-number-value {
1214
+ min-height: 36px;
1215
+ padding: var(--mf-space-xs);
1216
+ border-radius: var(--mf-radius-sm);
1217
+ font-size: 0.8rem;
1218
+ }
1219
+
1220
+ .magicfeedback-rating-number-option-row .magicfeedback-rating-number-option-label-container:hover .magicfeedback-rating-number-value,
1221
+ .magicfeedback-rating-number-option-row-reverse .magicfeedback-rating-number-option-label-container:hover .magicfeedback-rating-number-value {
1222
+ background: var(--mf-primary-light);
1223
+ }
1224
+
1225
+ .magicfeedback-rating-number-option-row .magicfeedback-rating-number-option-label-container input[type="radio"]:checked + .magicfeedback-rating-number-value,
1226
+ .magicfeedback-rating-number-option-row-reverse .magicfeedback-rating-number-option-label-container input[type="radio"]:checked + .magicfeedback-rating-number-value {
1227
+ color: #fff;
1228
+ background-color: var(--mf-primary);
1229
+ box-shadow: var(--mf-shadow-md);
1230
+ }
1231
+
1232
+ /* Extra option: always its own row below the scale, and styled like every
1233
+ other chip now \u2014 "doesn't apply" is still not a point on the 1..N
1234
+ continuum, but it no longer needs a different border style to say so. */
1235
+ .magicfeedback-rating-number-extra-row {
1236
+ display: flex;
1237
+ justify-content: center;
1238
+ margin-top: var(--mf-space-sm);
1239
+ }
1240
+
1241
+ .magicfeedback-rating-number-option--extra {
1242
+ flex: 0 1 auto;
1243
+ }
1244
+
1245
+ .magicfeedback-rating-number-option--extra .magicfeedback-rating-number-option-label-container {
1246
+ width: auto;
1247
+ }
1248
+
1249
+ .magicfeedback-rating-number-option--extra .magicfeedback-rating-number-value {
1250
+ min-height: 36px;
1251
+ padding: 0 var(--mf-space-md);
1252
+ border: 2px solid var(--mf-primary-border);
1253
+ border-radius: var(--mf-radius-md);
1254
+ background: var(--mf-bg-secondary);
1255
+ color: var(--mf-primary);
1256
+ font-size: var(--mf-font-size-sm);
1257
+ }
1258
+
1259
+ .magicfeedback-rating-number-option--extra .magicfeedback-rating-number-option-label-container:hover .magicfeedback-rating-number-value {
1260
+ background: var(--mf-primary-light);
1261
+ }
1262
+
1263
+ .magicfeedback-rating-number-option--extra .magicfeedback-rating-number-option-label-container input[type="radio"]:checked + .magicfeedback-rating-number-value {
1264
+ color: #fff;
1265
+ background-color: var(--mf-primary);
1266
+ box-shadow: var(--mf-shadow-md);
1267
+ }
1268
+
1269
+ /* Column: the same separated chips as row, just stacked \u2014 each option is
1270
+ its own outlined chip with a gap between them, not one shared box. */
1271
+ .magicfeedback-rating-number-container-column,
1272
+ .magicfeedback-rating-number-container-column-reverse {
1273
+ gap: var(--mf-space-sm);
1274
+ }
1275
+
1276
+ .magicfeedback-rating-number-option-column,
1277
+ .magicfeedback-rating-number-option-column-reverse {
1278
+ width: 100%;
1279
+ }
1280
+
1281
+ .magicfeedback-rating-number-option-column .magicfeedback-rating-number-value,
1282
+ .magicfeedback-rating-number-option-column-reverse .magicfeedback-rating-number-value {
1283
+ justify-content: flex-start;
1284
+ gap: var(--mf-space-sm);
1285
+ min-height: 48px;
1286
+ padding: var(--mf-space-sm) var(--mf-space-md);
1287
+ border: 2px solid var(--mf-primary-border);
1288
+ border-radius: var(--mf-radius-md);
1289
+ background: var(--mf-bg-secondary);
1290
+ color: var(--mf-primary);
1291
+ }
1292
+
1293
+ .magicfeedback-rating-number-option-column .magicfeedback-rating-number-option-label-container:hover .magicfeedback-rating-number-value,
1294
+ .magicfeedback-rating-number-option-column-reverse .magicfeedback-rating-number-option-label-container:hover .magicfeedback-rating-number-value {
1295
+ background: var(--mf-primary-light);
1296
+ }
1297
+
1298
+ .magicfeedback-rating-number-option-column .magicfeedback-rating-number-option-label-container input[type="radio"]:checked + .magicfeedback-rating-number-value,
1299
+ .magicfeedback-rating-number-option-column-reverse .magicfeedback-rating-number-option-label-container input[type="radio"]:checked + .magicfeedback-rating-number-value {
1300
+ color: #fff;
1301
+ background-color: var(--mf-primary);
1302
+ box-shadow: var(--mf-shadow-md);
1303
+ }
1304
+
1305
+ .magicfeedback-rating-number-value-num {
1306
+ font-weight: var(--mf-font-weight-bold);
1307
+ }
1308
+
1309
+ /* Column with per-option text: a min-width so "1".."9" and "10" line up,
1310
+ with the label text starting at the same x. Skipped entirely when the
1311
+ column has no per-option text at all (--bare below) \u2014 with nothing to
1312
+ align against, the same left-shift bug from row mode would resurface. */
1313
+ .magicfeedback-rating-number-container-column:not(.magicfeedback-rating-number-container-column--bare) .magicfeedback-rating-number-value-num,
1314
+ .magicfeedback-rating-number-container-column-reverse:not(.magicfeedback-rating-number-container-column--bare) .magicfeedback-rating-number-value-num {
1315
+ flex: none;
1316
+ min-width: 1.4em;
1317
+ }
1318
+
1319
+ /* Column, no per-option text at all (only min/max, or nothing): a bare
1320
+ numbered list has nothing to left-align against, so center each
1321
+ number instead of stranding it on the left with blank space beside it. */
1322
+ .magicfeedback-rating-number-container-column--bare .magicfeedback-rating-number-value {
1323
+ justify-content: center;
1324
+ }
1325
+
1326
+ .magicfeedback-rating-number-value-label {
1327
+ font-weight: var(--mf-font-weight-medium);
1328
+ }
1329
+
1330
+ .magicfeedback-rating-number-option-column .magicfeedback-rating-number-option-label-container input[type="radio"]:checked + .magicfeedback-rating-number-value,
1331
+ .magicfeedback-rating-number-option-column-reverse .magicfeedback-rating-number-option-label-container input[type="radio"]:checked + .magicfeedback-rating-number-value {
1332
+ color: #fff;
1333
+ background-color: var(--mf-primary);
1334
+ }
1335
+
1336
+ /* Star Rating */
1337
+ .magicfeedback-rating-star-container {
1338
+ justify-content: center;
1339
+ }
1340
+
1341
+ .magicfeedback-rating-star-option:not(:checked) > .rating__star {
1342
+ font-size: 40px;
1343
+ color: var(--mf-border);
1344
+ cursor: pointer;
1345
+ margin: 0 var(--mf-space-xs);
1346
+ transition: var(--mf-transition-fast);
1347
+ }
1348
+
1349
+ .magicfeedback-rating-star-option:not(:checked) > .rating__star:hover,
1350
+ .magicfeedback-rating-star-option:not(:checked) > .rating__star:hover ~ span {
1351
+ color: #fbbf24;
1352
+ transform: scale(1.1);
1353
+ }
1354
+
1355
+ .magicfeedback-rating-star-selected {
1356
+ color: #fbbf24 !important;
1357
+ }
1358
+
1359
+ /* ========================================
1360
+ MULTIPLE CHOICE WITH IMAGES
1361
+ ======================================== */
1362
+ .magicfeedback-multiple-choice-image-option {
1363
+ display: flex;
1364
+ border-radius: var(--mf-radius-md);
1365
+ overflow: hidden;
1366
+ transition: var(--mf-transition-fast);
1367
+ }
1368
+
1369
+ .magicfeedback-image-option-label-container {
1370
+ cursor: pointer;
1371
+ border-radius: var(--mf-radius-md);
1372
+ overflow: hidden;
1373
+ transition: var(--mf-transition-fast);
1374
+ }
1375
+
1376
+ .magicfeedback-image-option-label-container input[type="radio"],
1377
+ .magicfeedback-image-option-label-container input[type="checkbox"] {
1378
+ position: absolute;
1379
+ opacity: 0;
1380
+ width: 0;
1381
+ height: 0;
1382
+ }
1383
+
1384
+ .magicfeedback-image-option-label-container img {
1385
+ width: 100%;
1386
+ height: auto;
1387
+ display: block;
1388
+ border: 2px solid var(--mf-border);
1389
+ border-radius: var(--mf-radius-md);
1390
+ transition: var(--mf-transition-fast);
1391
+ }
1392
+
1393
+ .magicfeedback-image-option-label-container:hover img {
1394
+ border-color: var(--mf-primary);
1395
+ box-shadow: var(--mf-shadow-md);
1396
+ }
1397
+
1398
+ .magicfeedback-image-option-label-container input:checked + img {
1399
+ border-color: var(--mf-primary);
1400
+ box-shadow: 0 0 0 3px var(--mf-primary-light);
1401
+ }
1402
+
1403
+ /* ========================================
1404
+ MATRIX QUESTIONS
1405
+ ======================================== */
1406
+ .magicfeedback-multi-question-matrix-container {
1407
+ width: 100%;
1408
+ overflow-x: auto;
1409
+ border-radius: var(--mf-radius-md);
1410
+ }
1411
+
1412
+ .magicfeedback-multi-question-matrix-table {
1413
+ width: 100%;
1414
+ border-collapse: separate;
1415
+ border-spacing: 0 var(--mf-space-xs);
1416
+ }
1417
+
1418
+ .magicfeedback-multi-question-matrix-table th {
1419
+ padding: var(--mf-space-md);
1420
+ text-align: center;
1421
+ font-size: var(--mf-font-size-sm);
1422
+ font-weight: 500;
1423
+ color: var(--mf-text-secondary);
1424
+ }
1425
+
1426
+ .magicfeedback-multi-question-matrix-row-tr {
1427
+ background-color: var(--mf-bg-primary);
1428
+ border-radius: var(--mf-radius-md);
1429
+ transition: var(--mf-transition-fast);
1430
+ }
1431
+
1432
+ .magicfeedback-multi-question-matrix-row-tr:nth-child(even) {
1433
+ background-color: var(--mf-bg-secondary);
1434
+ }
1435
+
1436
+ .magicfeedback-multi-question-matrix-row-tr:hover {
1437
+ background-color: var(--mf-bg-hover);
1438
+ box-shadow: var(--mf-shadow-sm);
1439
+ }
1440
+
1441
+ .magicfeedback-multi-question-matrix-table td {
1442
+ padding: var(--mf-space-md);
1443
+ text-align: center;
1444
+ }
1445
+
1446
+ .magicfeedback-multi-question-matrix-label {
1447
+ text-align: start;
1448
+ font-size: var(--mf-font-size-base);
1449
+ color: var(--mf-text-primary);
1450
+ }
1451
+
1452
+ .magicfeedback-multi-question-matrix-table input[type="radio"] {
1453
+ width: 20px;
1454
+ height: 20px;
1455
+ cursor: pointer;
1456
+ accent-color: var(--mf-primary);
1457
+ }
1458
+
1459
+ /* ========================================
1460
+ PRIORITY LIST
1461
+ ======================================== */
1462
+ .magicfeedback-priority-list-item {
1463
+ display: flex;
1464
+ align-items: center;
1465
+ justify-content: space-between;
1466
+ padding: var(--mf-space-md);
1467
+ margin: var(--mf-space-sm) 0;
1468
+ background-color: var(--mf-bg-primary);
1469
+ border: 1.5px solid var(--mf-border);
1470
+ border-radius: var(--mf-radius-md);
1471
+ transition: var(--mf-transition-fast);
1472
+ }
1473
+
1474
+ .magicfeedback-priority-list-item:hover {
1475
+ box-shadow: var(--mf-shadow-sm);
1476
+ border-color: var(--mf-primary);
1477
+ }
1478
+
1479
+ .magicfeedback-priority-list-item-label {
1480
+ flex: 1;
1481
+ font-size: var(--mf-font-size-base);
1482
+ text-align: start;
1483
+ color: var(--mf-text-primary);
1484
+ margin: 0;
1485
+ }
1486
+
1487
+ .magicfeedback-priority-list-arrow-up,
1488
+ .magicfeedback-priority-list-arrow-down {
1489
+ padding: var(--mf-space-xs);
1490
+ font-size: var(--mf-font-size-lg);
1491
+ color: var(--mf-text-secondary);
1492
+ cursor: pointer;
1493
+ transition: var(--mf-transition-fast);
1494
+ user-select: none;
1495
+ }
1496
+
1497
+ .magicfeedback-priority-list-arrow-up:hover,
1498
+ .magicfeedback-priority-list-arrow-down:hover {
1499
+ color: var(--mf-primary);
1500
+ transform: scale(1.2);
1501
+ }
1502
+
1503
+ /* ========================================
1504
+ POINT SYSTEM
1505
+ ======================================== */
1506
+ .magicfeedback-point-system-item {
1507
+ display: flex;
1508
+ align-items: center;
1509
+ justify-content: space-between;
1510
+ padding: var(--mf-space-md);
1511
+ margin: var(--mf-space-sm) 0;
1512
+ background-color: var(--mf-bg-primary);
1513
+ border: 1.5px solid var(--mf-border);
1514
+ border-radius: var(--mf-radius-md);
1515
+ min-height: 45px;
1516
+ }
1517
+
1518
+ .magicfeedback-point-system-item label {
1519
+ flex: 1;
1520
+ font-size: var(--mf-font-size-base);
1521
+ color: var(--mf-text-primary);
1522
+ margin: 0;
1523
+ }
1524
+
1525
+ .magicfeedback-point-system-input-container {
1526
+ display: flex;
1527
+ align-items: center;
1528
+ gap: var(--mf-space-sm);
1529
+ }
1530
+
1531
+ .magicfeedback-point-system-item input {
1532
+ width: 80px;
1533
+ min-width: 80px;
1534
+ padding: var(--mf-space-sm);
1535
+ text-align: center;
1536
+ font-size: var(--mf-font-size-base);
1537
+ border: 1.5px solid var(--mf-border);
1538
+ border-radius: var(--mf-radius-md);
1539
+ margin: 0;
1540
+ }
1541
+
1542
+ .magicfeedback-point-system-total {
1543
+ display: flex;
1544
+ justify-content: flex-end;
1545
+ margin-top: var(--mf-space-md);
1546
+ font-size: var(--mf-font-size-base);
1547
+ font-weight: 600;
1548
+ color: var(--mf-text-primary);
1549
+ }
1550
+
1551
+ /* ========================================
1552
+ CONSENT
1553
+ ======================================== */
1554
+ .magicfeedback-consent-container {
1555
+ display: flex;
1556
+ flex-direction: row;
1557
+ align-items: center;
1558
+ gap: var(--mf-space-sm);
1559
+ padding: var(--mf-space-md);
1560
+ background-color: var(--mf-bg-secondary);
1561
+ border-radius: var(--mf-radius-md);
1562
+ margin: var(--mf-space-md) 0;
1563
+ }
1564
+
1565
+ .magicfeedback-consent-container input[type="checkbox"] {
1566
+ margin-top: 2px;
1567
+ flex-shrink: 0;
1568
+ accent-color: var(--mf-primary);
1569
+ }
1570
+
1571
+ .magicfeedback-consent-container label {
1572
+ flex: 1;
1573
+ font-size: var(--mf-font-size-sm);
1574
+ text-align: start;
1575
+ color: var(--mf-text-secondary);
1576
+ line-height: var(--mf-line-height);
1577
+ cursor: pointer;
1578
+ margin-bottom: 0;
1579
+ }
1580
+
1581
+ /* ========================================
1582
+ ACTION BUTTONS
1583
+ ======================================== */
1584
+ .magicfeedback-action-container {
1585
+ display: flex;
1586
+ align-items: center;
1587
+ justify-content: space-between;
1588
+ gap: var(--mf-space-md);
1589
+ margin-top: var(--mf-space-xl);
1590
+ padding-top: var(--mf-space-lg);
1591
+ border-top: 1px solid var(--mf-border);
1592
+ }
1593
+
1594
+ .magicfeedback-submit {
1595
+ padding: 0.8rem 1.6rem;
1596
+ font-size: var(--mf-font-size-base);
1597
+ font-weight: 800;
1598
+ color: #FFFFFF;
1599
+ background-color: var(--mf-primary);
1600
+ border: 2px solid var(--mf-primary);
1601
+ border-radius: var(--mf-radius-full);
1602
+ cursor: pointer;
1603
+ transition: var(--mf-transition-fast);
1604
+ box-shadow: var(--mf-shadow-md);
1605
+ }
1606
+
1607
+ .magicfeedback-submit:hover {
1608
+ background-color: var(--mf-primary-hover);
1609
+ box-shadow: var(--mf-shadow-lg);
1610
+ transform: translateY(-2px);
1611
+ }
1612
+
1613
+ .magicfeedback-submit:active {
1614
+ transform: translateY(0);
1615
+ box-shadow: var(--mf-shadow-sm);
1616
+ }
1617
+
1618
+ .magicfeedback-submit:disabled {
1619
+ opacity: 0.5;
1620
+ cursor: not-allowed;
1621
+ transform: none;
1622
+ }
1623
+
1624
+ .magicfeedback-back {
1625
+ padding: 0.65rem 1rem;
1626
+ font-size: var(--mf-font-size-base);
1627
+ font-weight: 700;
1628
+ color: var(--mf-primary);
1629
+ background-color: var(--mf-bg-secondary);
1630
+ border: 2px solid var(--mf-border);
1631
+ border-radius: var(--mf-radius-full);
1632
+ cursor: pointer;
1633
+ transition: var(--mf-transition-fast);
1634
+ }
1635
+
1636
+ .magicfeedback-back:hover {
1637
+ border-color: var(--mf-primary);
1638
+ background-color: var(--mf-bg-hover);
1639
+ }
1640
+
1641
+ /* ========================================
1642
+ SKIP & COUNTER
1643
+ ======================================== */
1644
+ .magicfeedback-skip-container {
1645
+ display: flex;
1646
+ align-items: center;
1647
+ gap: var(--mf-space-xs);
1648
+ padding: 0;
1649
+ margin: 0;
1650
+ font-size: var(--mf-font-size-sm);
1651
+ color: var(--mf-text-muted);
1652
+ background: transparent;
1653
+ border: none;
1654
+ cursor: pointer;
1655
+ transition: var(--mf-transition-fast);
1656
+ }
1657
+
1658
+ .magicfeedback-skip-container:hover {
1659
+ color: var(--mf-primary);
1660
+ }
1661
+
1662
+ .magicfeedback-skip-container input[type="checkbox"] {
1663
+ margin: 0;
1664
+ cursor: pointer;
1665
+ accent-color: var(--mf-primary);
1666
+ }
1667
+
1668
+ .magicfeedback-counter {
1669
+ display: flex;
1670
+ justify-content: flex-end;
1671
+ margin-top: var(--mf-space-md);
1672
+ font-size: var(--mf-font-size-sm);
1673
+ color: var(--mf-text-muted);
1674
+ }
1675
+
1676
+ /* ========================================
1677
+ MODAL STYLES
1678
+ ======================================== */
1679
+ /* Modal backdrop */
1680
+ .magicfeedback-modal-backdrop {
1681
+ position: fixed;
1682
+ top: 0;
1683
+ left: 0;
1684
+ width: 100vw;
1685
+ height: 100vh;
1686
+ background: rgba(0,0,0,0.4);
1687
+ display: none; /* toggled to flex when open */
1688
+ align-items: center;
1689
+ justify-content: center;
1690
+ z-index: 9999;
1691
+ }
1692
+
1693
+ /* Modal container */
1694
+ .magicfeedback-modal {
1695
+ background: #fff;
1696
+ border-radius: 8px;
1697
+ box-shadow: 0 8px 24px rgba(0,0,0,0.2);
1698
+ max-width: 520px;
1699
+ width: 90%;
1700
+ max-height: 80vh;
1701
+ /* Flex column so the options list scrolls while the actions footer
1702
+ (counter + confirm button) stays pinned and always visible. */
1703
+ display: flex;
1704
+ flex-direction: column;
1705
+ overflow: hidden;
1706
+ padding: 16px;
1707
+ position: relative;
1708
+ /* Portalled to document.body (see renderPriorityList.ts) to escape the
1709
+ host page's overflow/z-index \u2014 so it never inherits
1710
+ .magicfeedback-container's neutral text color and instead inherits
1711
+ whatever color the host page's own <body> happens to set. Needs its
1712
+ own explicit baseline rather than relying on that inheritance. */
1713
+ color: var(--mf-text-primary);
1714
+ }
1715
+
1716
+ /* Modal actions */
1717
+ .magicfeedback-modal-actions {
1718
+ display: flex;
1719
+ justify-content: flex-end;
1720
+ gap: 8px;
1721
+ margin-top: 12px;
1722
+ flex-shrink: 0;
1723
+ }
1724
+
1725
+ .magicfeedback-modal-counter {
1726
+ margin-inline-end: auto;
1727
+ display: flex;
1728
+ align-items: center;
1729
+ font-size: 14px;
1730
+ color: var(--mf-text-secondary);
1731
+ }
1732
+
1733
+ /* Modal list */
1734
+ .magicfeedback-modal-list {
1735
+ display: flex;
1736
+ flex-direction: column;
1737
+ gap: 8px;
1738
+ /* Scrollable area; footer stays fixed below it. */
1739
+ flex: 1 1 auto;
1740
+ overflow-y: auto;
1741
+ min-height: 0;
1742
+ }
1743
+
1744
+ .magicfeedback-modal-row {
1745
+ display: flex;
1746
+ align-items: center;
1747
+ gap: 10px;
1748
+ cursor: pointer;
1749
+ }
1750
+
1751
+ /* Priority list header */
1752
+ .magicfeedback-priority-list-header {
1753
+ display: flex;
1754
+ align-items: center;
1755
+ justify-content: space-between;
1756
+ gap: 12px;
1757
+ margin-bottom: 8px;
1758
+ }
1759
+
1760
+ .magicfeedback-priority-list-reorder {
1761
+ margin-top: 8px;
1762
+ }
1763
+
1764
+ .magicfeedback-priority-list-list {
1765
+ padding: 0;
1766
+ list-style: none;
1767
+ }
1768
+
1769
+ .magicfeedback-priority-list-item {
1770
+ display: flex;
1771
+ justify-content: space-between;
1772
+ align-items: center;
1773
+ margin: 5px 0;
1774
+ }
1775
+
1776
+ .magicfeedback-priority-list-item-label {
1777
+ font-size: 15px;
1778
+ }
1779
+
1780
+ .magicfeedback-priority-list-arrows {
1781
+ display: flex;
1782
+ align-items: center;
1783
+ gap: 6px;
1784
+ }
1785
+
1786
+ /* Buttons */
1787
+ .magicfeedback-button {
1788
+ appearance: none;
1789
+ border: 2px solid var(--mf-border);
1790
+ border-radius: var(--mf-radius-full);
1791
+ background: var(--mf-bg-secondary);
1792
+ color: var(--mf-text-primary);
1793
+ padding: 0.6rem 1rem;
1794
+ font-size: 14px;
1795
+ font-weight: 700;
1796
+ cursor: pointer;
1797
+ box-shadow: var(--mf-shadow-sm);
1798
+ }
1799
+
1800
+ .magicfeedback-button:hover {
1801
+ background: var(--mf-bg-hover);
1802
+ border-color: var(--mf-primary);
1803
+ }
1804
+
1805
+ .magicfeedback-button:active {
1806
+ transform: translateY(1px);
1807
+ }
1808
+
1809
+ .magicfeedback-button-primary {
1810
+ border-color: var(--mf-primary);
1811
+ background: var(--mf-primary);
1812
+ color: #fff;
1813
+ box-shadow: var(--mf-shadow-md);
1814
+ }
1815
+
1816
+ .magicfeedback-button-primary:hover {
1817
+ background: var(--mf-primary-hover);
1818
+ }
1819
+
1820
+ .magicfeedback-button-primary:active {
1821
+ background: var(--mf-primary-hover);
1822
+ }
1823
+
1824
+ /* Warning flash */
1825
+ .magicfeedback-warning {
1826
+ color: #C70039;
1827
+ }
1828
+
1829
+ /* Start message button */
1830
+ .magicfeedback-start-message-button {
1831
+ appearance: none;
1832
+ border: 2px solid var(--mf-primary);
1833
+ border-radius: var(--mf-radius-full);
1834
+ background: var(--mf-primary);
1835
+ color: #fff;
1836
+ padding: 0.8rem 1.4rem;
1837
+ font-size: 15px;
1838
+ font-weight: 800;
1839
+ cursor: pointer;
1840
+ box-shadow: var(--mf-shadow-md);
1841
+ }
1842
+
1843
+ .magicfeedback-start-message-button:hover {
1844
+ background: var(--mf-primary-hover);
1845
+ }
1846
+
1847
+ /* ========================================
1848
+ RESPONSIVE DESIGN
1849
+ ======================================== */
1850
+ @media (max-width: 768px) {
1851
+ :root {
1852
+ --mf-space-lg: 1.25rem;
1853
+ --mf-space-xl: 1.5rem;
1854
+ }
1855
+
1856
+ .magicfeedback-container {
1857
+ padding: 12px;
1858
+ border-radius: var(--mf-radius-md);
1859
+ }
1860
+
1861
+ .magicfeedback-form {
1862
+ padding: 14px;
1863
+ border-radius: var(--mf-radius-md);
1864
+ }
1865
+
1866
+ .magicfeedback-div {
1867
+ padding: 12px;
1868
+ gap: var(--mf-space-lg)
1869
+ }
1870
+
1871
+ .magicfeedback-label {
1872
+ font-size: var(--mf-font-size-base);
1873
+ }
1874
+
1875
+ .deepdots-popup input[type="date"],
1876
+ .deepdots-popup input[type="text"],
1877
+ .deepdots-popup input[type="number"],
1878
+ .deepdots-popup input[type="email"],
1879
+ .deepdots-popup input[type="password"],
1880
+ .deepdots-popup textarea,
1881
+ .deepdots-popup select {
1882
+ padding: 0.85rem 0.95rem;
1883
+ font-size: 1rem;
1884
+ min-height: 46px;
1885
+ }
1886
+
1887
+ /*
1888
+ .magicfeedback-radio-container,
1889
+ .magicfeedback-checkbox-container,
1890
+ .magicfeedback-boolean-container,
1891
+ .magicfeedback-consent-container {
1892
+ width: 100%;
1893
+ }
1894
+ */
1895
+
1896
+ .magicfeedback-radio-container,
1897
+ .magicfeedback-checkbox-container {
1898
+ padding: 10px 12px;
1899
+ border-radius: var(--mf-radius-md);
1900
+ border: 1px solid var(--mf-border);
1901
+ gap: 10px;
1902
+ }
1903
+
1904
+ .magicfeedback-rating-container,
1905
+ .magicfeedback-rating-number-container,
1906
+ .magicfeedback-rating-star-container {
1907
+ gap: 10px;
1908
+ }
1909
+
1910
+ .magicfeedback-boolean-container {
1911
+ flex-direction: column;
1912
+ gap: 10px;
1913
+ }
1914
+
1915
+ .magicfeedback-rating-number-container-row,
1916
+ .magicfeedback-rating-number-container-row-reverse {
1917
+ gap: 6px;
1918
+ }
1919
+
1920
+ .magicfeedback-rating-number-option-row .magicfeedback-rating-number-value,
1921
+ .magicfeedback-rating-number-option-row-reverse .magicfeedback-rating-number-value {
1922
+ min-height: 44px;
1923
+ padding: var(--mf-space-xs);
1924
+ font-size: 0.9rem;
1925
+ }
1926
+
1927
+ .magicfeedback-action-container {
1928
+ flex-direction: column-reverse;
1929
+ }
1930
+
1931
+ .magicfeedback-submit,
1932
+ .magicfeedback-back {
1933
+ width: 100%;
1934
+ text-align: center;
1935
+ min-height: 48px;
1936
+ }
1937
+ }
1938
+
1939
+ /* ========================================
1940
+ ACCESSIBILITY
1941
+ ======================================== */
1942
+ @media (prefers-reduced-motion: reduce) {
1943
+ *,
1944
+ *::before,
1945
+ *::after {
1946
+ animation-duration: 0.01ms !important;
1947
+ animation-iteration-count: 1 !important;
1948
+ transition-duration: 0.01ms !important;
1949
+ }
1950
+ }
1951
+
1952
+
1953
+ /* ========================================
1954
+ UTILITY CLASSES
1955
+ ======================================== */
1956
+ .magicfeedback-visually-hidden {
1957
+ position: absolute;
1958
+ width: 1px;
1959
+ height: 1px;
1960
+ padding: 0;
1961
+ margin: -1px;
1962
+ overflow: hidden;
1963
+ clip: rect(0, 0, 0, 0);
1964
+ white-space: nowrap;
1965
+ border-width: 0;
1966
+ }
1967
+
1968
+ .magicfeedback-modal-close {
1969
+ position: absolute;
1970
+ top: 8px;
1971
+ inset-inline-end: 8px;
1972
+ background: transparent;
1973
+ border: none;
1974
+ font-size: 20px;
1975
+ line-height: 1;
1976
+ cursor: pointer;
1977
+ color: #666;
1978
+ }
1979
+
1980
+ .magicfeedback-modal-close:hover,
1981
+ .magicfeedback-modal-close:focus {
1982
+ color: #000;
1983
+ outline: none;
1984
+ }
1985
+
1986
+ /* ========================================
1987
+ FILE / IMAGE UPLOAD
1988
+ ======================================== */
1989
+ .magicfeedback-upload {
1990
+ display: flex;
1991
+ flex-direction: column;
1992
+ gap: var(--mf-space-md);
1993
+ width: 100%;
1994
+ margin: 10px 0;
1995
+ }
1996
+
1997
+ /* The native input is an invisible, focusable overlay covering the dropzone. */
1998
+ .magicfeedback-upload-native {
1999
+ position: absolute;
2000
+ inset: 0;
2001
+ width: 100%;
2002
+ height: 100%;
2003
+ margin: 0;
2004
+ padding: 0;
2005
+ opacity: 0;
2006
+ cursor: pointer;
2007
+ z-index: 2;
2008
+ }
2009
+
2010
+ .magicfeedback-upload-dropzone {
2011
+ position: relative;
2012
+ display: flex;
2013
+ flex-direction: column;
2014
+ align-items: center;
2015
+ justify-content: center;
2016
+ gap: var(--mf-space-sm);
2017
+ box-sizing: border-box;
2018
+ width: 100%;
2019
+ min-height: 150px;
2020
+ padding: var(--mf-space-xl);
2021
+ text-align: center;
2022
+ border: 2px dashed var(--mf-border);
2023
+ border-radius: var(--mf-radius-md);
2024
+ background-color: var(--mf-surface-alt);
2025
+ cursor: pointer;
2026
+ transition: var(--mf-transition);
2027
+ }
2028
+
2029
+ .magicfeedback-upload-dropzone:hover {
2030
+ border-color: var(--mf-primary);
2031
+ background-color: var(--mf-bg-hover);
2032
+ }
2033
+
2034
+ .magicfeedback-upload-dropzone:focus-within {
2035
+ border-color: var(--mf-primary);
2036
+ box-shadow: var(--mf-shadow-focus);
2037
+ }
2038
+
2039
+ .magicfeedback-upload-dropzone.is-dragover {
2040
+ border-color: var(--mf-primary);
2041
+ border-style: solid;
2042
+ background-color: var(--mf-primary-light);
2043
+ box-shadow: var(--mf-shadow-focus);
2044
+ }
2045
+
2046
+ .magicfeedback-upload-icon {
2047
+ display: inline-flex;
2048
+ align-items: center;
2049
+ justify-content: center;
2050
+ width: 46px;
2051
+ height: 46px;
2052
+ color: var(--mf-primary);
2053
+ background-color: var(--mf-surface);
2054
+ border-radius: var(--mf-radius-full);
2055
+ box-shadow: var(--mf-shadow-sm);
2056
+ pointer-events: none;
2057
+ }
2058
+
2059
+ .magicfeedback-upload-icon svg {
2060
+ width: 24px;
2061
+ height: 24px;
2062
+ }
2063
+
2064
+ .magicfeedback-upload-cta {
2065
+ font-family: inherit;
2066
+ font-weight: var(--mf-font-weight-semibold);
2067
+ font-size: var(--mf-font-size-base);
2068
+ color: var(--mf-text-primary);
2069
+ pointer-events: none;
2070
+ }
2071
+
2072
+ .magicfeedback-upload-hint {
2073
+ font-family: inherit;
2074
+ font-size: var(--mf-font-size-sm);
2075
+ color: var(--mf-text-muted);
2076
+ pointer-events: none;
2077
+ }
2078
+
2079
+ .magicfeedback-upload-list {
2080
+ display: flex;
2081
+ flex-direction: column;
2082
+ gap: var(--mf-space-sm);
2083
+ width: 100%;
2084
+ margin: 0;
2085
+ padding: 0;
2086
+ list-style: none;
2087
+ }
2088
+
2089
+ .magicfeedback-upload-list:empty {
2090
+ display: none;
2091
+ }
2092
+
2093
+ .magicfeedback-upload-file-item {
2094
+ display: flex;
2095
+ align-items: center;
2096
+ gap: var(--mf-space-md);
2097
+ padding: var(--mf-space-sm) var(--mf-space-md);
2098
+ background-color: var(--mf-surface);
2099
+ border: 1px solid var(--mf-border);
2100
+ border-radius: var(--mf-radius-sm);
2101
+ box-shadow: var(--mf-shadow-sm);
2102
+ animation: mf-scale-in 0.2s ease-out;
2103
+ }
2104
+
2105
+ .magicfeedback-upload-thumb {
2106
+ flex: 0 0 auto;
2107
+ display: inline-flex;
2108
+ align-items: center;
2109
+ justify-content: center;
2110
+ width: 40px;
2111
+ height: 40px;
2112
+ overflow: hidden;
2113
+ color: var(--mf-text-secondary);
2114
+ background-color: var(--mf-surface-alt);
2115
+ border-radius: var(--mf-radius-sm);
2116
+ }
2117
+
2118
+ .magicfeedback-upload-thumb img {
2119
+ width: 100%;
2120
+ height: 100%;
2121
+ object-fit: cover;
2122
+ }
2123
+
2124
+ .magicfeedback-upload-thumb svg {
2125
+ width: 20px;
2126
+ height: 20px;
2127
+ }
2128
+
2129
+ .magicfeedback-upload-file-info {
2130
+ display: flex;
2131
+ flex-direction: column;
2132
+ flex: 1 1 auto;
2133
+ min-width: 0;
2134
+ text-align: start;
2135
+ }
2136
+
2137
+ .magicfeedback-upload-file-name {
2138
+ font-family: inherit;
2139
+ font-size: var(--mf-font-size-sm);
2140
+ font-weight: var(--mf-font-weight-semibold);
2141
+ color: var(--mf-text-primary);
2142
+ white-space: nowrap;
2143
+ overflow: hidden;
2144
+ text-overflow: ellipsis;
2145
+ }
2146
+
2147
+ .magicfeedback-upload-file-size {
2148
+ font-family: inherit;
2149
+ font-size: 0.75rem;
2150
+ color: var(--mf-text-muted);
2151
+ }
2152
+
2153
+ .magicfeedback-upload-remove {
2154
+ flex: 0 0 auto;
2155
+ display: inline-flex;
2156
+ align-items: center;
2157
+ justify-content: center;
2158
+ width: 30px;
2159
+ height: 30px;
2160
+ padding: 0;
2161
+ color: var(--mf-text-muted);
2162
+ background-color: transparent;
2163
+ border: none;
2164
+ border-radius: var(--mf-radius-full);
2165
+ cursor: pointer;
2166
+ transition: var(--mf-transition-fast);
2167
+ }
2168
+
2169
+ .magicfeedback-upload-remove:hover,
2170
+ .magicfeedback-upload-remove:focus-visible {
2171
+ color: var(--mf-error);
2172
+ background-color: var(--mf-primary-light);
2173
+ outline: none;
2174
+ }
2175
+
2176
+ .magicfeedback-upload-remove svg {
2177
+ width: 16px;
2178
+ height: 16px;
2179
+ }
2180
+
2181
+ .magicfeedback-upload-error {
2182
+ display: none;
2183
+ font-family: inherit;
2184
+ font-size: var(--mf-font-size-sm);
2185
+ color: var(--mf-error);
2186
+ }
2187
+
2188
+ .magicfeedback-upload-error.is-visible {
2189
+ display: block;
2190
+ }
2191
+
2192
+ /* ========================================
2193
+ RTL (Arabic)
2194
+ ========================================
2195
+ The SDK stamps dir="rtl" (and .magicfeedback-rtl) on the survey container
2196
+ for right-to-left languages. Everything else in this stylesheet uses logical
2197
+ properties (text-align: start, padding-inline-*, inset-inline-*), so it
2198
+ mirrors on its own; only the handful of rules that cannot be expressed
2199
+ logically live here.
2200
+
2201
+ Rules are scoped to [dir="rtl"] inside our own subtree so a host page that is
2202
+ itself RTL, or one that embeds an Arabic survey in an LTR page, both render
2203
+ correctly. */
2204
+
2205
+ /* background-position has no logical form: move the select caret to the
2206
+ left edge, opposite the padding that inset-inline-end already mirrored. */
2207
+ [dir="rtl"] select {
2208
+ background-position: left var(--mf-space-md) center;
2209
+ }
2210
+
2211
+ /* Emails, URLs, numbers, dates and phone numbers are latin/numeric content
2212
+ even in an Arabic survey: keep their own direction LTR so punctuation
2213
+ (@, ., +, /) lands where the user expects, but align them to the start of
2214
+ the RTL line so they still read as part of the form. */
2215
+ [dir="rtl"] input[type="email"],
2216
+ [dir="rtl"] input[type="url"],
2217
+ [dir="rtl"] input[type="number"],
2218
+ [dir="rtl"] input[type="tel"],
2219
+ [dir="rtl"] input[type="date"],
2220
+ [dir="rtl"] input[type="time"] {
2221
+ direction: ltr;
2222
+ text-align: right;
2223
+ }
2224
+
2225
+ /* Mirror of mf-slide-in: questions enter from the reading edge. */
2226
+ @keyframes mf-slide-in-rtl {
2227
+ from {
2228
+ opacity: 0;
2229
+ transform: translateX(16px);
2230
+ }
2231
+ to {
2232
+ opacity: 1;
2233
+ transform: translateX(0);
2234
+ }
2235
+ }
2236
+
2237
+ [dir="rtl"] .magicfeedback-div {
2238
+ animation-name: mf-slide-in-rtl;
2239
+ }
2240
+
2241
+ /* ========================================
2242
+ LOCAL \u2014 reglas del popup, no vienen del paquete
2243
+ ======================================== */
2244
+
2245
+ /* Los controles de formulario no heredan font-family: cuando el popup trae fuente propia
2246
+ (clase deepdots-has-font), se les fuerza la del contenedor. */
2247
+ .deepdots-popup.deepdots-has-font button,
2248
+ .deepdots-popup.deepdots-has-font input,
2249
+ .deepdots-popup.deepdots-has-font textarea,
2250
+ .deepdots-popup.deepdots-has-font select {
2251
+ font-family: var(--deepdots-font, inherit);
2252
+ }
2253
+
2254
+ /* WebKit s\xED aplica el padding al radio nativo: con padding el control se dibuja enorme (se vio
2255
+ en iOS, WebView de RN y Safari, no en Chrome). El paquete ya no lo pone, pero la regla es
2256
+ barata y evita que vuelva. */
2257
+ .deepdots-popup input[type="radio"] {
2258
+ padding: 0;
2259
+ }
2260
+ `;
2261
+
2262
+ // src/util/logger.ts
2263
+ var active = console;
2264
+ function setLogger(logger) {
2265
+ active = logger ?? console;
2266
+ }
2267
+ function sdkLog(...args) {
2268
+ active.log(...args);
2269
+ }
2270
+ function sdkWarn(...args) {
2271
+ (active.warn ?? active.log)(...args);
2272
+ }
2273
+ function sdkError(...args) {
2274
+ (active.error ?? active.log)(...args);
2275
+ }
2276
+
2277
+ export {
2278
+ __commonJS,
2279
+ __toESM,
2280
+ InMemoryStorage,
2281
+ createDefaultStorage,
2282
+ STORAGE_KEYS,
2283
+ buildSurveyIdentity,
2284
+ TrackingManager,
2285
+ buildFontFamilyValue,
2286
+ buildFontFaceCss,
2287
+ LABELS,
2288
+ SUPPORTED_LANGUAGES,
2289
+ resolveLocale,
2290
+ RTL_LOCALES,
2291
+ isRtlLanguage,
2292
+ directionFor,
2293
+ getLabels,
2294
+ resolveActionLabels,
2295
+ RESOLVE_LOCALE_JS,
2296
+ style_default,
2297
+ setLogger,
2298
+ sdkLog,
2299
+ sdkWarn,
2300
+ sdkError
2301
+ };
2302
+ //# sourceMappingURL=chunk-W6MPSWMS.mjs.map