Index: gc_core/js/helpers.js
==================================================================
--- gc_core/js/helpers.js
+++ gc_core/js/helpers.js
@@ -72,11 +72,10 @@
 
     // conversions
     objectToMap: function (obj) {
         let m = new Map();
         for (let param in obj) {
-            //console.log(param + " " + obj[param]);
             m.set(param, obj[param]);
         }
         return m;
     },
 

Index: gc_lang/fr/build.py
==================================================================
--- gc_lang/fr/build.py
+++ gc_lang/fr/build.py
@@ -31,11 +31,11 @@
     sLang = dVars['sDefaultUILang']
     for sSection, lOpt in dVars['lStructOpt']:
         sHTML += f'\n<div id="subsection_{sSection}" class="opt_subsection">\n  <h2 data-l10n-id="option_{sSection}">{dVars["dOptLabel"][sLang][sSection][0]}</h2>\n'
         for lLineOpt in lOpt:
             for sOpt in lLineOpt:
-                sHTML += f'  <p><input type="checkbox" id="option_{sOpt}" data-option="{sOpt}"/><label id="option_label_{sOpt}" for="option_{sOpt}" data-l10n-id="option_{sOpt}">{dVars["dOptLabel"][sLang][sOpt][0]}</label></p>\n'
+                sHTML += f'  <p><input type="checkbox" id="option_{sOpt}" class="gc_option" data-option="{sOpt}"/><label id="option_label_{sOpt}" for="option_{sOpt}" data-l10n-id="option_{sOpt}">{dVars["dOptLabel"][sLang][sOpt][0]}</label></p>\n'
         sHTML += '</div>\n'
     return sHTML
 
 
 def createFirefoxExtension (sLang, dVars):

Index: gc_lang/fr/data/phonet_simil.txt
==================================================================
--- gc_lang/fr/data/phonet_simil.txt
+++ gc_lang/fr/data/phonet_simil.txt
@@ -631,10 +631,11 @@
 reflux reflue reflues refluent
 régal régals régale régale régalent
 reine reines renne rennes rêne rênes
 relai relais relaie relaies relaient relaye relayes relayent
 remblai remblais remblaie remblaies remblaient
+remord remords
 renvoi renvois renvoie renvoies renvoient
 repaire repaires repère repères repèrent reperds reperd
 repli replis replie replies replient
 ressenti ressentis ressentit
 resserre resserres resserrent ressers ressert

Index: gc_lang/fr/modules-js/conj.js
==================================================================
--- gc_lang/fr/modules-js/conj.js
+++ gc_lang/fr/modules-js/conj.js
@@ -81,18 +81,18 @@
             return null;
         }
         return this._lVtyp[this._dVerb[sVerb][0]];
     },
 
-    getSimil: function (sWord, sMorph, sFilter=null) {
+    getSimil: function (sWord, sMorph, bSubst=false) {
         if (!sMorph.includes(":V")) {
             return new Set();
         }
         let sInfi = sMorph.slice(1, sMorph.indexOf(" "));
         let tTags = this._getTags(sInfi);
         let aSugg = new Set();
-        if (sMorph.includes(":Q") || sMorph.includes(":Y")) {
+        if (!bSubst) {
             // we suggest conjugated forms
             if (sMorph.includes(":V1")) {
                 aSugg.add(sInfi);
                 aSugg.add(this._getConjWithTags(sInfi, tTags, ":Ip", ":3s"));
                 aSugg.add(this._getConjWithTags(sInfi, tTags, ":Ip", ":2p"));
@@ -124,13 +124,10 @@
             aSugg.delete("");
             // if there is only one past participle (epi inv), unreliable.
             if (aSugg.size === 1) {
                 aSugg.clear();
             }
-            if (sMorph.includes(":V1")) {
-                aSugg.add(sInfi);
-            }
         }
         return aSugg;
     },
 
     _getTags: function (sVerb) {
@@ -485,16 +482,19 @@
 }
 
 
 // Initialization
 if (!conj.bInit && typeof(browser) !== 'undefined') {
-    // WebExtension (but not in Worker)
+    // WebExtension Standard (but not in Worker)
     conj.init(helpers.loadFile(browser.extension.getURL("grammalecte/fr/conj_data.json")));
+} else if (!conj.bInit && typeof(chrome) !== 'undefined') {
+    // WebExtension Chrome (but not in Worker)
+    conj.init(helpers.loadFile(chrome.extension.getURL("grammalecte/fr/conj_data.json")));
 } else if (!conj.bInit && typeof(require) !== 'undefined') {
     // Add-on SDK and Thunderbird
     conj.init(helpers.loadFile("resource://grammalecte/fr/conj_data.json"));
-} else if ( !conj.bInit && typeof(self) !== 'undefined' && typeof(self.port) !== 'undefined' && typeof(self.port.on) !== "undefined") {
+} else if (!conj.bInit && typeof(self) !== 'undefined' && typeof(self.port) !== 'undefined' && typeof(self.port.on) !== "undefined") {
     // used within Firefox content script (conjugation panel).
     // can’t load JSON from here, so we do it in ui.js and send it here.
     self.port.on("provideConjData", function (sJSONData) {
         conj.init(sJSONData);
     });    

Index: gc_lang/fr/modules-js/gce_suggestions.js
==================================================================
--- gc_lang/fr/modules-js/gce_suggestions.js
+++ gc_lang/fr/modules-js/gce_suggestions.js
@@ -488,16 +488,16 @@
 
 function hasSimil (sWord, sPattern=null) {
     return phonet.hasSimil(sWord, sPattern);
 }
 
-function suggSimil (sWord, sPattern) {
+function suggSimil (sWord, sPattern=null, bSubst=false) {
     // return list of words phonetically similar to sWord and whom POS is matching sPattern
     let aSugg = phonet.selectSimil(sWord, sPattern);
     for (let sMorph of _dAnalyses.gl_get(sWord, [])) {
-        for (let e of conj.getSimil(sWord, sMorph, sPattern)) {
-            aSugg.add(e); 
+        for (let e of conj.getSimil(sWord, sMorph, bSubst)) {
+            aSugg.add(e);
         }
     }
     if (aSugg.size > 0) {
         return Array.from(aSugg).join("|");
     }

Index: gc_lang/fr/modules-js/phonet.js
==================================================================
--- gc_lang/fr/modules-js/phonet.js
+++ gc_lang/fr/modules-js/phonet.js
@@ -64,11 +64,11 @@
         }
         return [];
     },
 
     selectSimil: function (sWord, sPattern) {
-        // return list of words phonetically similar to sWord and whom POS is matching sPattern
+        // return a set of words phonetically similar to sWord and whom POS is matching sPattern
         if (!sPattern) {
             return new Set(this.getSimil(sWord));
         }
         let aSelect = new Set();
         for (let sSimil of this.getSimil(sWord)) {

Index: gc_lang/fr/modules/conj.py
==================================================================
--- gc_lang/fr/modules/conj.py
+++ gc_lang/fr/modules/conj.py
@@ -53,17 +53,18 @@
     if sVerb not in _dVerb:
         return None
     return _lVtyp[_dVerb[sVerb][0]]
 
 
-def getSimil (sWord, sMorph, sFilter=None):
+def getSimil (sWord, sMorph, bSubst=False):
     if ":V" not in sMorph:
         return set()
     sInfi = sMorph[1:sMorph.find(" ")]
     tTags = _getTags(sInfi)
     aSugg = set()
-    if ":Q" in sMorph or ":Y" in sMorph:
+    #if ":Q" in sMorph or ":Y" in sMorph:
+    if not bSubst:
         # we suggest conjugated forms
         if ":V1" in sMorph:
             aSugg.add(sInfi)
             aSugg.add(_getConjWithTags(sInfi, tTags, ":Ip", ":3s"))
             aSugg.add(_getConjWithTags(sInfi, tTags, ":Ip", ":2p"))
@@ -93,12 +94,10 @@
         aSugg.add(_getConjWithTags(sInfi, tTags, ":PQ", ":Q4"))
         aSugg.discard("")
         # if there is only one past participle (epi inv), unreliable.
         if len(aSugg) == 1:
             aSugg.clear()
-        if ":V1" in sMorph:
-            aSugg.add(sInfi)
     return aSugg
 
 
 def getConjSimilInfiV1 (sInfi):
     if sInfi not in _dVerb:

Index: gc_lang/fr/modules/gce_suggestions.py
==================================================================
--- gc_lang/fr/modules/gce_suggestions.py
+++ gc_lang/fr/modules/gce_suggestions.py
@@ -371,18 +371,17 @@
 
 def hasSimil (sWord, sPattern=None):
     return phonet.hasSimil(sWord, sPattern)
 
 
-def suggSimil (sWord, sPattern=None):
+def suggSimil (sWord, sPattern=None, bSubst=False):
     "return list of words phonetically similar to sWord and whom POS is matching sPattern"
     # we don’t check if word exists in _dAnalyses, for it is assumed it has been done before
     aSugg = phonet.selectSimil(sWord, sPattern)
     for sMorph in _dAnalyses.get(sWord, []):
-        for e in conj.getSimil(sWord, sMorph, sPattern):
-            aSugg.add(e)
-        #aSugg = aSugg.union(conj.getSimil(sWord, sMorph))
+        aSugg.update(conj.getSimil(sWord, sMorph, bSubst))
+        break
     if aSugg:
         return "|".join(aSugg)
     return ""
 
 

Index: gc_lang/fr/modules/phonet.py
==================================================================
--- gc_lang/fr/modules/phonet.py
+++ gc_lang/fr/modules/phonet.py
@@ -37,11 +37,11 @@
             return _lSet[_dWord[sWord]]
     return []
 
 
 def selectSimil (sWord, sPattern):
-    "return list of words phonetically similar to sWord and whom POS is matching sPattern"
+    "return a set of words phonetically similar to sWord and whom POS is matching sPattern"
     if not sPattern:
         return set(getSimil(sWord))
     aSelect = set()
     for sSimil in getSimil(sWord):
         for sMorph in _dMorph.get(sSimil, []):

Index: gc_lang/fr/oxt/TextFormatter/tf_tabrep.py
==================================================================
--- gc_lang/fr/oxt/TextFormatter/tf_tabrep.py
+++ gc_lang/fr/oxt/TextFormatter/tf_tabrep.py
@@ -370,11 +370,11 @@
                     ("(?<=\\b[XVICL][XVICL][XVICL][XVICL])(i?[èe]me|è|ᵉ)\\b",   "e",    True, True),
                     ("(?<=\\b[XVICL][XVICL][XVICL])(i?[èe]me|è|ᵉ)\\b",          "e",    True, True),
                     ("(?<=\\b[XVICL][XVICL])(i?[èe]me|è|ᵉ)\\b",                 "e",    True, True),
                     ("(?<=\\b[XVICL])(i?[èe]me|è|ᵉ)\\b",                        "e",    True, True),
                     ("(?<=\\b[1I])ᵉʳ\\b",                                       "er",   True, True),
-                    ("(?<=\\b[1I])ʳᵉ\\b",                                       "er",   True, True)
+                    ("(?<=\\b[1I])ʳᵉ\\b",                                       "re",   True, True)
     ],
     "misc2": [
                     ("etc(…|[.][.][.]?)",                       "etc.",         True,   True),
                     ("(?<!,) etc[.]",                           ", etc.",       True,   True)
     ],

Index: gc_lang/fr/rules.grx
==================================================================
--- gc_lang/fr/rules.grx
+++ gc_lang/fr/rules.grx
@@ -2503,24 +2503,24 @@
 
 
 ### incohérences globales (attention à la casse du 2e mot, car beaucoup de sigles peuvent tromper)
 __[s](incohérences_globales1)__
     ([clmtsCLMTS]es|[nvNV]os) ([cdlmst]es|[nv]os|cettes?|[mts]a|mon|je|tu|ils?|elle?|[vn]ous|on)  @@0,$
-    <<- -2>> =suggSimil(\2, ":[NA].*:[pi]")         # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder.
+    <<- -2>> =suggSimil(\2, ":[NA].*:[pi]", True)                                                   # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder.
 __[s](incohérences_globales2)__
     ([cC]e(?:tte|t|)|[mtsMTS]a|[mM]on) ([cdlmst]es|[nv]os|cettes?|[mts]a|mon|je|tu|ils?|elle?|[vn]ous|on)  @@0,$
-    <<- -2>> =suggSimil(\2, ":[NA].*:[si]")         # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder.
+    <<- -2>> =suggSimil(\2, ":[NA].*:[si]", True)                                                   # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder.
 
 TEST: {{Ces}} {{cette}} canaille qui nous a donné tant de fil à retordre.
 TEST: Mon {{il}} est une merveille.
 
 
 __[s](incohérence_globale_au_qqch)__
     ([aA]u) ({w2})  @@0,$
     <<- not \2.isupper() >>>
     <<- morph(\2, ">(?:[cdlmst]es|[nv]os|cettes?|[mts]a|mon|je|tu|ils?|elle?|[vn]ous|on|parce) ", False)
-    -2>> =suggSimil(\2, ":[NA].*:[si]")                                                             # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder.
+    -2>> =suggSimil(\2, ":[NA].*:[si]", True)                                                       # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder.
     <<- __else__ and morph(\2, ">quelle ", False) ->> auquel|auxquels|auxquelles                    # Incohérence. Soudez les deux mots.|https://fr.wiktionary.org/wiki/auquel
     <<- __else__ and \2 == "combien" and morph(word(1), ":[AY]", False) -1>> ô                      # Incohérence probable.|https://fr.wiktionary.org/wiki/%C3%B4_combien
 
 TEST: au {{nos}} enfants.
 TEST: {{Au quel}} faut-il s’adresser ?
@@ -2529,11 +2529,11 @@
 
 __[s](incohérence_globale_aux_qqch)__
     ([aA]ux) ({w2})  @@0,$
     <<- not \2.isupper() >>>
     <<- morph(\2, ">(?:[cdlmst]es|[nv]os|cettes?|[mts]a|mon|je|tu|ils?|elle?|[vn]ous|on|parce) ", False)
-    -2>> =suggSimil(\2, ":[NA].*:[pi]")                                                             # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder.
+    -2>> =suggSimil(\2, ":[NA].*:[pi]", True)                                                       # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder.
     <<- __else__ and morph(\2, ">quelle ", False) ->> auxquels|auxquelles                           # Incohérence. Soudez les deux mots.|https://fr.wiktionary.org/wiki/auquel
     <<- __else__ and \2 == "combien" and morph(word(1), ":[AY]", False) -1>> ô                      # Incohérence probable.|https://fr.wiktionary.org/wiki/%C3%B4_combien
 
 TEST: ils jouent aux {{des}}.
 TEST: {{Aux quels}} a-t-il adressé sa requête. ?
@@ -2540,12 +2540,12 @@
 TEST: Des individus {{aux}} combien sensibles aux usages.
 
 
 __[s](incohérences_globales3)__
     ([dD]es) ([cdlmst]es|[nv]os|cettes?|[mts]a|mon|je|tu|ils?|elle?|[vn]ous|on)  @@0,$
-    <<- -2>> =suggSimil(\2, ":[NA].*:[pi]")         # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder.
-    <<- -1>> de                                     # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder.
+    <<- -2>> =suggSimil(\2, ":[NA].*:[pi]", True)                                                   # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder.
+    <<- -1>> de                                                                                     # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder.
 
 TEST: je ne sais {{des}} {{ses}} choses.
 
 
 
@@ -2865,29 +2865,29 @@
 TEST: {{en n’}}{{envoient}} que peu.
 
 
 __[i]/conf(conf_malgré_le_la_les)__
     malgré l(?:es? +|a +|’)({w_3})  @@$
-    <<- morphex(\1, ":", ":[GNAWM]") -1>> =suggSimil(\1, ":[NA]")                                   # Incohérence : après “malgré”, on devrait trouver un groupe nominal.
+    <<- morphex(\1, ":", ":[GNAWM]") -1>> =suggSimil(\1, ":[NA]", True)                             # Incohérence : après “malgré”, on devrait trouver un groupe nominal.
 
 TEST: malgré l’{{arrête}} qui interdisait le port 
 
 
 __[i]/conf(conf_ma_ta_cette_verbe)__
     ([mt]a|cette) +({w_2})  @@0,$
     <<- morphex(\2, ":V.*:(?:Y|[123][sp])", ":[NAQ]") and \2[0].islower()
-    -2>> =suggSimil(\2, ":[NA]:[fe]:[si]")                                                          # Incohérence avec « \1 » : « \2 » est un verbe.
+    -2>> =suggSimil(\2, ":[NA]:[fe]:[si]", True)                                                    # Incohérence avec « \1 » : « \2 » est un verbe.
 
 TEST: Cette {{pèle}} est trop fragile.
 
 
 __[i]/conf(conf_sa_verbe)__
     (sa) ({w_2})  @@0,3
     <<- morphex(\2, ":V.*:(?:Y|[123][sp])", ":N.*:[fe]|:[AW]") and \2[0].islower() or \2 == "va"
     -1>> ça                                                                                         # Confusion : « \2 » est un verbe. Exemples : sa jambe, ça vient.
     <<- morphex(\2, ":V.*:(?:Y|[123][sp])", ":[NAQ]") and \2[0].islower() and hasSimil(\2)
-    -2>> =suggSimil(\2, ":[NA]:[fe]:[si]")                                                          # Incohérence avec « \1 » : « \2 » est un verbe.
+    -2>> =suggSimil(\2, ":[NA]:[fe]:[si]", True)                                                    # Incohérence avec « \1 » : « \2 » est un verbe.
 
 TEST: {{sa}} devient difficile.
 TEST: il me tendit {{sa}} {{pèche}}.
 
 
@@ -2898,67 +2898,67 @@
 
 
 __[i]/conf(conf_du_cet_au_verbe)__
     (du|cet|au) +({w_2})  @@0,$
     <<- morphex(\2, ":V.*:(?:Y|[123][sp])", ":[NAQ]") and \2[0].islower() and not (\2 == "sortir" and re.search(r"(?i)au", \1))
-    -2>> =suggSimil(\2, ":[NA]:[me]:[si]")                                                          # Incohérence avec « \1 » : « \2 » est un verbe.
+    -2>> =suggSimil(\2, ":[NA]:[me]:[si]", True)                                                    # Incohérence avec « \1 » : « \2 » est un verbe.
 
 TEST: cet {{plaît}} est infectée.
 
 
 __[i]/conf(conf_ce_verbe)__
     (ce) +(?!faire|peut)({w_2})  @@0,$
     <<- morphex(\2, ":V.*:(?:Y|[123][sp])", ":[NAQ]:.:[si]|:V0e.*:3[sp]|>devoir") and \2[0].islower() and hasSimil(\2)
-    -2>> =suggSimil(\2, ":[NA]:[me]:[si]")                                                          # Incohérence avec « \1 » : « \2 » est un verbe.
+    -2>> =suggSimil(\2, ":[NA]:[me]:[si]", True)                                                    # Incohérence avec « \1 » : « \2 » est un verbe.
 
 TEST: {{ce}} {{rappelle}} n’en finit pas.
 
 
 __[i]/conf(conf_mon_verbe)__
     (mon) +({w_2})  @@0,$
     <<- morphex(\2, ":V.*:(?:Y|[123][sp])", ":[NAQ]") and \2[0].islower()
-    -2>> =suggSimil(\2, ":[NA]:.:[si]")                                                             # Incohérence avec « \1 » : « \2 » est un verbe.
+    -2>> =suggSimil(\2, ":[NA]:.:[si]", True)                                                       # Incohérence avec « \1 » : « \2 » est un verbe.
 
 TEST: mon {{rackette}} n’a pas porté les fruits espérés.
 TEST: Belle qui tient mon vit captif entre tes doigts.
 
 
 __[i]/conf(conf_ton_son_verbe)__
     [st]on ({w_2})  @@4
     <<- morph(\1, ":V.*:(?:Y|[123][sp])") and \1[0].islower() and isStart()
-    -1>> =suggSimil(\1, ":[NA]:[me]:[si]")                                                          # Incohérence : « \1 » est un verbe.
+    -1>> =suggSimil(\1, ":[NA]:[me]:[si]", True)                                                    # Incohérence : « \1 » est un verbe.
 
 TEST: ton {{recèle}} a été dévoilé
 
 
 __[i]/conf(conf_det_plur_verbe)__
     ([dcmts]es|quelques|aux|[nv]os) +({w_2})  @@0,$
     <<- morphex(\2, ":V.*:(?:Y|[123][sp])", ":[NAQ]") and \2[0].islower() and not re.search(r"(?i)^quelques? soi(?:ent|t|s)\b", \0)
-    -2>> =suggSimil(\2, ":[NA]:.:[pi]")                                                             # Incohérence avec « \1 » : « \2 » est un verbe.
+    -2>> =suggSimil(\2, ":[NA]:.:[pi]", True)                                                       # Incohérence avec « \1 » : « \2 » est un verbe.
 
 TEST: la crainte des {{attentas}} fait feu de tout bois.
 
 
 __[i]/conf(conf_auxdits_verbe)__
     (auxdits) +({w_2})  @@0,$
     <<- morphex(\2, ":V.*:(?:Y|[123][sp])", ":[NAQ]") and \2[0].islower()
-    -2>> =suggSimil(\2, ":[NA]:[me]:[pi]")                                                          # Incohérence avec « \1 » : « \2 » est un verbe.
+    -2>> =suggSimil(\2, ":[NA]:[me]:[pi]", True)                                                    # Incohérence avec « \1 » : « \2 » est un verbe.
 
 TEST: elle se rendit auxdits {{jardinais}}
 
 
 __[i]/conf(conf_auxdites_verbe)__
     (auxdites) +({w_2})  @@0,$
     <<- morphex(\2, ":V.*:(?:Y|[123][sp])", ":[NAQ]") and \2[0].islower()
-    -2>> =suggSimil(\2, ":[NA]:[fe]:[pi]")                                                          # Incohérence avec « \1 » : « \2 » est un verbe.
+    -2>> =suggSimil(\2, ":[NA]:[fe]:[pi]", True)                                                    # Incohérence avec « \1 » : « \2 » est un verbe.
 
 TEST: auxdites {{scelles}}, il ne prêta pas attention.
 
 
 __[i]/conf(conf_de_la_vconj)__  de la ({w_2})  @@6
     <<- morphex(\1, ":[123][sp]", ":[NAQ]")
-    -1>> =suggSimil(\1, ":(?:[NA]:[fe]:[si])")                                                      # Incohérence : « \1 » est un verbe.
+    -1>> =suggSimil(\1, ":(?:[NA]:[fe]:[si])", True)                                                # Incohérence : « \1 » est un verbe.
 
 TEST: les petits esprits de la {{pensait}} religieuse
 
 
 TEST: pour les insulter au sortir du seul troquet dispensateur d’oubli liquide du coin
@@ -2966,78 +2966,78 @@
 
 
 __[i]/conf(conf_de_le_nom_ou_vconj)__
     (de le) ({w_2})  @@0,6
     <<- morphex(\2, ":[NAQ].*:[me]", ":[YG]") and \2[0].islower() -1>> du                           # Incohérence : « \2 » est un nom ou un adjectif.
-    <<- morph(\2, ":[123][sp]", False) -2>> =suggSimil(\2, ":Y")                                    # Incohérence : « \2 » est une forme verbale conjuguée.
+    <<- morph(\2, ":[123][sp]", False) -2>> =suggVerbInfi(\2)                                       # Incohérence : « \2 » est une forme verbale conjuguée.
 
 TEST: {{de le}} vin                                           ->> du
 TEST: il n’est pas interdit de le {{pensait}}
 
 
 __[i]/conf(conf_de_l_vconj)__
     de l’({w_2})  @@5
-    <<- morphex(\1, ":[123][sp]", ":[NAQ]") -1>> =suggSimil(\1, ":(?:[NA]:.:[si])")                 # Incohérence : « \1 » est une forme verbale conjuguée.
+    <<- morphex(\1, ":[123][sp]", ":[NAQ]") -1>> =suggSimil(\1, ":[NA]:.:[si]", True)               # Incohérence : « \1 » est une forme verbale conjuguée.
 
 TEST: de l’{{entra}}
 
 
 __[i]/conf(conf_un_verbe)__
     (?<!’)un ({w_2})  @@3
     <<- morph(\1, ":(?:Y|[123][sp])") and not before("(?i)(?:dont|sauf|un à) +$")
-    -1>> =suggSimil(\1, ":[NAQ]:[me]:[si]")                                                         # Incohérence : « \1 » est une forme verbale conjuguée.
+    -1>> =suggSimil(\1, ":[NAQ]:[me]:[si]", True)                                                   # Incohérence : « \1 » est une forme verbale conjuguée.
 
 TEST: un {{maintient}} difficile.
 
 
 __[i]/conf(conf_de_dès_par_vconj)__
     (?:d(?:e|ès)|par) ({w_2})  @@$
-    <<- \1[0].islower() and morph(\1, ":V.*:[123][sp]") -1>> =suggSimil(\1, ":[NA]")                # Incohérence : « \1 » est une forme verbale conjuguée.
+    <<- \1[0].islower() and morph(\1, ":V.*:[123][sp]") -1>> =suggSimil(\1, ":[NA]", True)          # Incohérence : « \1 » est une forme verbale conjuguée.
 
 TEST: par {{bloque}} de données
 TEST: il s’agit de {{mette}} en évidence.
 
 
 __[i]/conf(conf_d_une_vconj)__
     d’(?:une? +|)({w_2})  @@$
     <<- \1[0].islower() and morphex(\1, ":V.*:[123][sp]", ":[GNA]") and not before(r"(?i)\b(?:plus|moins) +$")
-    -1>> =suggSimil(\1, ":[NA]")    # Incohérence : « \1 » est une forme verbale conjuguée.
+    -1>> =suggSimil(\1, ":[NA]", True)                                                              # Incohérence : « \1 » est une forme verbale conjuguée.
 
 TEST: d’une {{habille}} femme
 TEST: plus d’un ont été traumatisés
 TEST: plus d’une sont parties aussi vite qu’elles étaient venues
 
 
 __[i]/conf(conf_il_on_pas_verbe)__
     (?<!t’)(?:il|on) (?:l’|l(?:es?|a|eur|ui) +|[nv]ous +|)({w_2}) @@$
     <<- morphex(\1, ":", ":(?:[123][sp]|O[onw]|X)|ou ") and morphex(word(-1), ":", ":3s", True)
-    -1>> =suggSimil(\1, ":(?:3s|Oo)")                                                               # Incohérence : « \1 » devrait être un verbe, un pronom objet, un adverbe de négation, etc.
+    -1>> =suggSimil(\1, ":(?:3s|Oo)", False)                                                        # Incohérence : « \1 » devrait être un verbe, un pronom objet, un adverbe de négation, etc.
 
 TEST: il {{et}} parti.
 
 
 __[i]/conf(conf_ils_pas_verbe)__
     (?<!t’)ils (?:l’|l(?:es?|a|eur|ui) +|[nv]ous +|)({w_2}) @@$
     <<- morphex(\1, ":", ":(?:[123][sp]|O[onw]|X)|ou ") and morphex(word(-1), ":", ":3p", True)
-    -1>> =suggSimil(\1, ":(?:3p|Oo)")                                                               # Incohérence avec « ils » : « \1 » devrait être un verbe, un pronom objet, un adverbe de négation, etc.
+    -1>> =suggSimil(\1, ":(?:3p|Oo)", False)                                                        # Incohérence avec « ils » : « \1 » devrait être un verbe, un pronom objet, un adverbe de négation, etc.
 
 TEST: ils {{son}} du même bois.
 TEST: Ils {{étai}} partie au {{restaurent}}
 
 
 __[i]/conf(conf_je_pas_verbe)__
     je (?!soussigné)(?:l’|l(?:es?|a|eur|ui) +|[nv]ous +|)({w_2}) @@$
     <<- morphex(\1, ":", ":(?:[123][sp]|O[onw]|X)") and morphex(word(-1), ":", ":1s", True)
-    -1>> =suggSimil(\1, ":(?:1s|Oo)")                                                               # Incohérence avec « je » : « \1 » devrait être un verbe, un pronom objet, un adverbe de négation, etc.
+    -1>> =suggSimil(\1, ":(?:1s|Oo)", False)                                                        # Incohérence avec « je » : « \1 » devrait être un verbe, un pronom objet, un adverbe de négation, etc.
 
 TEST: Je {{travail}}.
 
 
 __[i]/conf(conf_tu_pas_verbe)__
     tu (?:l’|l(?:es?|a|eur|ui) +|[nv]ous +|)({w_2}) @@$
     <<- morphex(\1, ":", ":(?:[123][sp]|O[onw]|X)") and morphex(word(-1), ":", ":(?:2s|V0e)", True)
-    -1>> =suggSimil(\1, ":(?:2s|Oo)")                                                               # Incohérence avec « tu » : « \1 » devrait être un verbe, un pronom objet, un adverbe de négation, etc.
+    -1>> =suggSimil(\1, ":(?:2s|Oo)", False)                                                        # Incohérence avec « tu » : « \1 » devrait être un verbe, un pronom objet, un adverbe de négation, etc.
 
 TEST: tu {{croix}} que tu sais quelque chose, mais tu ne sais rien.
 
 
 TEST: elles seules peuvent s’en sortir.
@@ -3064,11 +3064,11 @@
 #    # Incohérence avec « très » : « \2 » n’est ni un adjectif, ni un participe passé, ni un adverbe.
 
  
 __[i]/conf(conf_très_verbe)__
     très +(?!envie)({w_2})  @@$
-    <<- morphex(\1, ":(?:Y|[123][sp])", ":[AQW]") -1>> =suggSimil(\1, ":[AW]")                      # Incohérence avec « très » : « \1 » n’est ni un adjectif, ni un participe passé, ni un adverbe.
+    <<- morphex(\1, ":(?:Y|[123][sp])", ":[AQW]") -1>> =suggSimil(\1, ":[AW]", True)                # Incohérence avec « très » : « \1 » n’est ni un adjectif, ni un participe passé, ni un adverbe.
 
 TEST: Il est très {{cite}}.
 TEST: très {{suivit}} par ce détective
 TEST: il était très {{habille}}
 
@@ -3109,11 +3109,11 @@
 
 
 __[i]/conf(conf_si_vconj)__
     si +({w2})  @@$
     <<- morphex(\1, ":[123][sp]", ":[GNAQWMT]") and morphex(word(1), ":", ":D", True)
-    -1>> =suggSimil(\1, ":[AWGT]")                                                                  # Incohérence avec « si » : « \1 » ne devrait pas être une forme verbale conjuguée.
+    -1>> =suggSimil(\1, ":[AWGT]", True)                                                            # Incohérence avec « si » : « \1 » ne devrait pas être une forme verbale conjuguée.
 
 TEST: Ces gens sont si {{prit}} par leur travail qu’ils en oublient de vivre.
 TEST: Ça ira mieux demain, surtout si émerge une demande forte de la part des consommateurs.
 
 
@@ -3464,11 +3464,11 @@
 __[s]/conf(conf_c_est3)__
     ([scSC]es) (?:qu(?:lle|el?|)|comme|ce(?:t|tte|)|[nv]os|les?|eux|elles)  @@0
     <<- -1>> c’est                                                                          # Confusion probable. Écrivez « c’est » pour dire « ceci est… ».
 __[s]/conf(conf_c_est4)__
     ([scSC]es) ({w_1}) ({w_1}) @@0,w,$
-    <<- morph(\2, ":[WX]", False) and morph(\3, ":[RD]|>pire ", False) -1>> c’est           # Confusion probable. Écrivez « c’est » pour dire « ceci est… ».
+    <<- morph(\2, ":[WX]", ":N:.*:[pi]") and morph(\3, ":[RD]|>pire ", False) -1>> c’est           # Confusion probable. Écrivez « c’est » pour dire « ceci est… ».
 __[i]/conf(conf_ces_ses)__
     (c’est) ({w_2})  @@0,6 <<- morphex(\2, ":N.*:p", ":(?:G|W|M|A.*:[si])") -1>> ces|ses    # Confusion. Exemples : c’est facile ; ces chats (désignation) ; ses chats (possession)…
 
 TEST: {{ses}} au-dessus de ses forces.
 TEST: {{ces}} comme la peste
@@ -3475,10 +3475,11 @@
 TEST: car {{ses}} d’avance perdu
 TEST: {{ces}} qu’il y a tant de pertes
 TEST: {{ces}} jamais une bonne idée.
 TEST: {{c’est}} {{délires}} nous ennuient
 TEST: En 2015, c’est Paris et son agglomération qui…
+TEST: Ses pas de danse.
 
 
 # date / datte
 __[i]/conf(conf_date1)__
     dates
@@ -4045,44 +4046,44 @@
 __[i](p_m_enfin)__      m’enfin <<- ~>> *
 
 __[i]/conf(conf_j_y_en_qqch)__
     (j’(?:en +|y +|))({w_1})  @@0,$
     <<- morphex(\2, ":", ":(?:[123][sp]|O[onw])")
-    -2>> =suggSimil(\2, ":1s")                                                                      # Incohérence avec « \1 » : « \2 » devrait être un verbe.
+    -2>> =suggSimil(\2, ":1s", False)                                                               # Incohérence avec « \1 » : « \2 » devrait être un verbe.
 __[i]/conf(conf_ne_qqch)__
     (n(?:e +|’))({w_1})  @@0,$
     <<- morphex(\2, ":", ":(?:[123][sp]|Y|P|O[onw]|X)|>(?:[lmtsn]|surtout|guère|presque|même|tout|parfois|vraiment|réellement) ") and not re.search("(?i)-(?:ils?|elles?|[nv]ous|je|tu|on|ce)$", \2)
-    -2>> =suggSimil(\2, ":(?:[123][sp]|Oo|Y)")                                                      # Incohérence avec « \1 » : « \2 » devrait être un verbe ou un pronom personnel objet.
+    -2>> =suggSimil(\2, ":(?:[123][sp]|Oo|Y)", False)                                               # Incohérence avec « \1 » : « \2 » devrait être un verbe ou un pronom personnel objet.
 __[i]/conf(conf_n_y_en_qqch)__
     (n’(?:en|y)) ({w_1})  @@0,$
     <<- morphex(\2, ":", ":(?:[123][sp]|Y|P|O[onw]|X)") and not re.search("(?i)-(?:ils?|elles?|[nv]ous|je|tu|on|ce)$", \2)
-    -2>> =suggSimil(\2, ":(?:[123][sp]|Y)")                                                         # Incohérence avec « \1 » : « \2 » devrait être un verbe.
+    -2>> =suggSimil(\2, ":(?:[123][sp]|Y)", False)                                                  # Incohérence avec « \1 » : « \2 » devrait être un verbe.
 __[i]/conf(conf_ne_pronom_qqch)__
     (ne (?:l(?:es? +|eur +|a +|’)|[nv]ous))({w_1})  @@0,$
     <<- morphex(\2, ":", ":(?:[123][sp]|Y|P|O[onw]|X)") and not re.search("(?i)-(?:ils?|elles?|[nv]ous|je|tu|on|ce)$", \2)
-    -2>> =suggSimil(\2, ":(?:[123][sp]|Y)")                                                         # Incohérence avec « \1 » : « \2 » devrait être un verbe.
+    -2>> =suggSimil(\2, ":(?:[123][sp]|Y)", False)                                                  # Incohérence avec « \1 » : « \2 » devrait être un verbe.
 __[i]/conf(conf_me_te_se_qqch)__
     ([mts]e +(?:les? |la |l’|))(?!voi(?:là|ci))({w_1})  @@0,$
     <<- not re.search("(?i)^se que?", \0)
     and morphex(\2, ":", ":(?:[123][sp]|Y|P|Oo)|>[lmts] ") and not re.search("(?i)-(?:ils?|elles?|[nv]ous|je|tu|on|ce)$", \2)
-    -2>> =suggSimil(\2, ":(?:[123][sp]|Oo|Y)")                                                      # Incohérence avec « \1 » : « \2 » devrait être un verbe ou un pronom personnel objet.
+    -2>> =suggSimil(\2, ":(?:[123][sp]|Oo|Y)", False)                                               # Incohérence avec « \1 » : « \2 » devrait être un verbe ou un pronom personnel objet.
 __[i]/conf(conf_m_t_s_y_en_qqch)__
     ([mts]’(?:en|y)) (?!voilà)({w_1})  @@0,$
     <<- morphex(\2, ":", ":(?:[123][sp]|Y|P|Oo)") and not re.search("(?i)-(?:ils?|elles?|[nv]ous|je|tu|on|ce)$", \2)
-    -2>> =suggSimil(\2, ":(?:[123][sp]|Y)")                                                         # Incohérence avec « \1 » : « \2 » devrait être un verbe.
+    -2>> =suggSimil(\2, ":(?:[123][sp]|Y)", False)                                                  # Incohérence avec « \1 » : « \2 » devrait être un verbe.
 __[i]/conf(conf_m_s_qqch)__
     ([ms]’)({w_1})  @@0,2
     <<- morphex(\2, ":", ":(?:[123][sp]|Y|P)|>(?:en|y|ils?) ") and not re.search("(?i)-(?:ils?|elles?|[nv]ous|je|tu|on|ce)$", \2)
-    -2>> =suggSimil(\2, ":(?:[123][sp]|Y)")                                                         # Incohérence avec « \1 » : « \2 » devrait être un verbe.
+    -2>> =suggSimil(\2, ":(?:[123][sp]|Y)", False)                                                  # Incohérence avec « \1 » : « \2 » devrait être un verbe.
 __[i]/conf(conf_t_qqch)__
     (t’)({w_1})  @@0,2
     <<- morphex(\2, ":", ":(?:[123][sp]|Y|P)|>(?:en|y|ils?|elles?) ") and not re.search("(?i)-(?:ils?|elles?|[nv]ous|je|tu|on|ce)$", \2)
-    -2>> =suggSimil(\2, ":(?:[123][sp]|Y)")                                                         # Incohérence avec « \1 » : « \2 » devrait être un verbe.
+    -2>> =suggSimil(\2, ":(?:[123][sp]|Y)", False)                                                  # Incohérence avec « \1 » : « \2 » devrait être un verbe.
 __[i]/conf(conf_c_ç_qqch)__
     ([cç]’)({w_1})  @@0,2
     <<- morphex(\2, ":", ":[123][sp]|>(?:en|y|que?) ") and not re.search("(?i)-(?:ils?|elles?|[nv]ous|je|tu|on|dire)$", \2)
-    -2>> =suggSimil(\2, ":3s")                                                                      # Incohérence avec « \1 » : « \2 » devrait être un verbe.
+    -2>> =suggSimil(\2, ":3s", False)                                                               # Incohérence avec « \1 » : « \2 » devrait être un verbe.
 
 TEST: ne l’{{oubli}} pas
 TEST: elle ne la {{croix}} pas
 TEST: ils me les {{laissés}}.
 TEST: ne {{pensée}} rien, jamais
@@ -4742,10 +4743,11 @@
 __[i](p_chili_con_carne)__              chilis? (con carne) @@$ <<- ~1>> *
 __[i](p_chef_d_œuvre)__                 chefs?(-d’œuvre) @@$ <<- ~1>> *
 __[i](p_clair_comme)__                  claire?s? (comme (?:de l’eau de (?:boudin|roche|source)|du (?:cristal|jus de (?:boudin|chaussettes?|chique)))) @@$ <<- ~1>> *
 __[i](p_commis_d_office)__              commise?s? (d’office) @@$ <<- ~1>> *
 __[i](p_convention)__                   conventions? (récepteur|générateur) @@$ <<- ~1>> *
+__[i](p_con_comme)__                    con(?:ne|)s? (comme (?:un balai|une valise sans poignées?|la lune)) @@$ <<- ~1>> *
 __[i](p_coup_de)__
     coups? (de (?:balai|bol|cœur|foudre|fil|grâce|jarnac|théâtre|coude|genou|main|p(?:atte|ied|oing|oker|ouce)|tête)|d’(?:avance|éclat|État|œil|épaule)|du sort) @@$
     <<- ~1>> *
 __[i](p_course_contre_la_montre)__      courses? (contre la montre) @@$ <<- ~1>> *
 __[i](p_cousu_main)__                   cousue?s? +(main) @@$ <<- ~1>> *
@@ -4819,12 +4821,16 @@
     <<- ~1>> *
 __[i](p_oiseau_de)__                    oiseaux? (de (?:malheur|nuit|proie|mauvais augure)) @@$ <<- ~1>> * 
 __[i](p_onde_de_choc)__                 ondes? (de choc) @@$ <<- ~1>> *
 __[i](p_orge)__                         orge (perlé|mondé|carré) @@$ <<- ~1>> *
 __[i](p_noire_comme)__                  noire?s? (comme (?:la nuit|une nuit sans lune)) @@$ <<- ~1>> *
-__[i](p_pièce_de)__                     pièces? (de (?:théâtre|monnaie|\d+ (?:euros?|centimes?|cents?|livres? sterling|shillings?))) @@$ <<- ~1>> *
 __[i](p_partie_de_jambe_en_l_air)__     parties? (de jambes en l’air) @@$ <<- ~1>> *
+__[i](p_papier_à_lettre)__
+    papiers? (([àa]) lettres?) @@$,w
+    <<- \2 == "a" -2>> à                        # Confusion : “a” est une conjugaison du verbe “avoir”. Pour la préposition, écrivez “à”.
+    <<- ~1>> *
+__[i](p_pièce_de)__                     pièces? (de (?:théâtre|monnaie|\d+ (?:euros?|centimes?|cents?|livres? sterling|shillings?))) @@$ <<- ~1>> *
 __[i](p_porte_de)__                     portes? (de (?:service|garage)) @@$ <<- ~1>> *
 __[i](p_poudre_aux_yeux)__              poudres? (aux yeux) @@$ <<- ~1>> *
 __[i](p_preuve_du_contraire)__          preuves? +(?:suffisantes? +|)(du contraire) @@$ <<- ~1>> *
 __[i](p_quelqu_un_d_autre)__            quelqu un (d’autre) @@$ <<- ~1>> *
 __[i](loc_remire_à_plat)__
@@ -4894,10 +4900,11 @@
 TEST: cette fille {{a}} papa nous pourrit la vie.
 TEST: Les conséquences des gaz {{a}} effet de serre.
 TEST: devant la machine {{a}} café.
 TEST: Achète un moule {{a}} gaufres.
 TEST: Fais la mise {{a}} jour
+TEST: Amenez-moi du papier {{a}} lettres.
 TEST: Elle mit du rouge {{a}} lèvres.
 TEST: on a besoin d’une remise {{a}} plat.
 TEST: passe-moi mon sac {{a}} dos.
 TEST: dans le silo {{a}} grain.
 TEST: sa chambre, c’est une vraie soue {{a}} cochons.
@@ -5202,11 +5209,11 @@
 ## Simplication des locutions verbales
 __[i](p_donner_sens)__
     ((?:re|)donn\w+) +(sens) @@0,$
     <<- morph(\1, ">(?:re|)donner ", False) ~2>> *
 __[i](p_faire_qqch)__
-    (f[aiîeo]\w*) +(tous(?: deux| trois|) +|)(allusion|assaut|bonne figure|confiance|compliqué|chaud|débat|demi-tour|fausse route|froid|gr(?:ise mine|and cas)|h(?:alte|onte)|ma(?:chine|rche) arrière|p(?:art(?:ie(?: intégrante|)|)|eur|laisir|rofil bas)|rage|salle comble|sens|table rase|volte-face|ce que bon (?:me|te|lui|leur|nous|vous) semble) @@0,*,$
+    (f[aiîeo]\w*) +(tous(?: deux| trois|) +|)(allusion|assaut|bonne figure|confiance|compliqué|chaud|débat|demi-tour|fausse route|froid|gr(?:ise mine|and cas)|h(?:alte|onte)|illusion|ma(?:chine|rche) arrière|p(?:art(?:ie(?: intégrante|)|)|eur|laisir|rofil bas)|rage|salle comble|sens|table rase|volte-face|ce que bon (?:me|te|lui|leur|nous|vous) semble) @@0,*,$
     <<- morph(\1, ">faire ", False) ~2>> *
     <<- __also__ ~3>> *
 __[i](loc_mettre_à_qqch)__
     (m(?:et|[iî][mst])\w*) +(([àa]) (?:jour|niveau|plat|l’écart)) @@0,$,w
     <<- morph(\1, ">mettre ", False) >>>
@@ -5227,10 +5234,15 @@
     (rest\w+) (lettre morte) @@0,$
     <<- morph(\1, ">rester ", False) ~2>> *
 __[i](p_sembler_paraitre_être)__
     (sembl\w+|par[au]\w+) +(être|avoir été) +({w_2}) @@0,w,$
     <<- morph(\1, ">(?:sembler|para[îi]tre) ") and morphex(\3, ":A", ":G") ~2>> *
+__[i](loc_suivre_de_près)__
+    (suiv\w+) +((?:ça +|ce(?:ci|la) +|)de (pr[èé]s?|prêts?)) @@0,$,$
+    <<- morph(\1, ">suivre ", False) >>>
+    <<- \3 != "près" -3>> près                  # Confusion : écrivez “près” pour dire “proche de quelque chose”.|https://fr.wiktionary.org/wiki/pr%C3%A8s
+    <<- ~2>> *
 __[i](loc_tenir_à_distance)__
     (t[eiî]\w+) +(([àa]) distance) d(?:es?|u) @@0,$,w
     <<- morph(\1, ">tenir ", False) >>>
     <<- \3 == "a" -3>> à                        # Confusion : “a” est une conjugaison du verbe “avoir”. Pour la préposition, écrivez “à”.
     <<- ~2>> *
@@ -5245,10 +5257,11 @@
     (v[eiî]\w+) ((?:on ne sait|je ne sais) (?:pas |)(?:trop |)d’où) @@0,$
     <<- morph(\1, ">venir ", False) ~2>> *
 
 TEST: il faut tenir {{contes}} des faits au lieu de nos impressions.
 TEST: prendre {{a}} la légère ce test serait une erreur.
+TEST: on va suivre ça de {{prêt}}.
 TEST: il faut se tenir {{a}} distance de ces gens-là.
 
 
 # Autres tests contre les faux positifs
 TEST: pourquoi faire compliqué quand on peut faire simple
@@ -5309,11 +5322,11 @@
 TEST: ce que c’est : le signe évident d’une politique volontaire
 TEST: On aura carte blanche.
 TEST: La seule façon de redonner sens à des notions…
 TEST: Les longues tresses que j’ai pris l’habitude de porter depuis quelque temps et qu’il faut cinq heures pour parfaire.
 TEST: Il est pieds nus.
-TEST: des dossiers secrets {{défense}}
+TEST: des dossiers secrets défense
 
 
 #
 # //////////////////////////////////////// RÈGLES DE CONTRÔLE ////////////////////////////////////////
 #
@@ -11462,31 +11475,31 @@
 
 
 __[i]/inte(inte_je)__
     ({w1})-je  @@0
     <<- morphex(\1, ":V", ":1[sśŝ]") -1>> =suggVerb(@, ":1ś")                                       # Forme interrogative : « \1 » n’est pas un verbe à la 1ʳᵉ personne du singulier.
-    <<- not morph(\1, ":V", False) -1>> =suggSimil(\1, ":1[sśŝ]")                                   # Forme interrogative : « \1 » n’est pas un verbe à la 1ʳᵉ personne du singulier.
+    <<- not morph(\1, ":V", False) -1>> =suggSimil(\1, ":1[sśŝ]", False)                            # Forme interrogative : « \1 » n’est pas un verbe à la 1ʳᵉ personne du singulier.
 
 TEST: {{Vas}}-je                                            ->> Vais
 TEST: {{Prit}}-je                                           ->> Pris
 TEST: {{prix}}-je le temps d’y parvenir ? Oui.
 
 
 __[i]/inte(inte_tu)__
     ({w1})-tu  @@0
     <<- morphex(\1, ":V", ":[ISK].*:2s") -1>> =suggVerb(@, ":2s")                                   # Forme interrogative. « \1 » n’est pas un verbe à la 2ᵉ personne du singulier.
-    <<- not morph(\1, ":V", False) -1>> =suggSimil(\1, ":2s")                                       # Forme interrogative : « \1 » n’est pas un verbe à la 2ᵉ personne du singulier.
+    <<- not morph(\1, ":V", False) -1>> =suggSimil(\1, ":2s", False)                                # Forme interrogative : « \1 » n’est pas un verbe à la 2ᵉ personne du singulier.
 
 TEST: {{Peut}}-tu                                           ->> Peux
 TEST: {{peu}}-tu revenir chez moi ?
 
 
 __[i]/inte(inte_il_elle_on)__
     ({w1})-(?:t-|)(il|elle|on)  @@0,$
     <<- morphex(\1, ":V", ":3s") -1>> =suggVerb(@, ":3s")                                           # Forme interrogative : « \1 » n’est pas un verbe à la 3ᵉ personne du singulier.
     <<- \1 != "t" and (not \1.endswith("oilà") or \2 != "il") and morphex(\1, ":", ":V")
-    -1>> =suggSimil(\1, ":3s")                                                                      # Forme interrogative : « \1 » n’est pas un verbe à la 3ᵉ personne du singulier.
+    -1>> =suggSimil(\1, ":3s", False)                                                               # Forme interrogative : « \1 » n’est pas un verbe à la 3ᵉ personne du singulier.
     <<- not \2.endswith(("n", "N")) and morphex(\1, ":3p", ":3s") -2>> \2s                          # Forme interrogative : accordez “\2” avec le verbe à la 3ᵉ personne du pluriel.
 
 TEST: {{Peux}}-il                                           ->> Peut
 TEST: {{Attaques}}-t-on                                     ->> Attaque
 TEST: {{Prends}}-elle                                       ->> Prend
@@ -11496,11 +11509,11 @@
 
 
 __[s]/inte(inte_ce)__
     ({w_2})-([cs]e)  @@0,$
     <<- morphex(\1, ":V", ":(?:3s|V0e.*:3p)") -1>> =suggVerb(@, ":3s")      # Forme interrogative : « \1 » n’est pas un verbe à la 3ᵉ personne du singulier.|http://bdl.oqlf.gouv.qc.ca/bdl/gabarit_bdl.asp?id=4132
-    <<- morphex(\1, ":", ":V") -1>> =suggSimil(\1, ":3s")                   # Forme interrogative : « \1 » n’est pas un verbe à la 3ᵉ personne du singulier.|http://bdl.oqlf.gouv.qc.ca/bdl/gabarit_bdl.asp?id=4132
+    <<- morphex(\1, ":", ":V") -1>> =suggSimil(\1, ":3s", False)            # Forme interrogative : « \1 » n’est pas un verbe à la 3ᵉ personne du singulier.|http://bdl.oqlf.gouv.qc.ca/bdl/gabarit_bdl.asp?id=4132
     <<- \2 == "se" -2>> ce                                                  # Forme interrogative. Confusion.|http://bdl.oqlf.gouv.qc.ca/bdl/gabarit_bdl.asp?id=4132
 
 TEST: était-{{se}} cela, la vérité ineffable ?
 TEST: {{étai}}-ce notre destinée de souffrir ?
 TEST: étaient-{{se}} ces hommes-là qui allaient nous guider dans les montagnes ?
@@ -11509,20 +11522,20 @@
 
 
 __[i]/inte(inte_nous)__
     ({w1})-nous  @@0
     <<- morphex(\1, ":V", ":(?:1p|E:2[sp])") -1>> =suggVerb(@, ":1p")                               # Forme interrogative ou impérative incorrecte.
-    <<- morphex(\1, ":", ":V|>chez ") -1>> =suggSimil(\1, ":1p")                                    # Forme interrogative ou impérative incorrecte.
+    <<- morphex(\1, ":", ":V|>chez ") -1>> =suggSimil(\1, ":1p", False)                             # Forme interrogative ou impérative incorrecte.
 
 TEST: {{Prendront}}-nous                                    ->> Prendrons
 TEST: {{Attendront}}-nous le train                          ->> Attendrons
 
 
 __[i]/inte(inte_vous)__
     ({w1})-vous  @@0
     <<- morphex(\1, ":V", ":2p") -1>> =suggVerb(@, ":2p")                                           # Forme interrogative ou impérative incorrecte.
-    <<- not morph(\1, ":V|>chez ", False) -1>> =suggSimil(\1, ":2p")                                # Forme interrogative ou impérative incorrecte.
+    <<- not morph(\1, ":V|>chez ", False) -1>> =suggSimil(\1, ":2p", False)                         # Forme interrogative ou impérative incorrecte.
 
 TEST: {{Attaquait}}-vous                                    ->> Attaquiez
 TEST: Elle a de nombreux rendez-vous ce matin.
 TEST: êtes-vous là ?
 
@@ -11530,11 +11543,11 @@
 __[i]/inte(inte_ils_elles)__
     ({w1})-(?:ils|elles)  @@0
     <<- morphex(\1, ":V", ":3p") and spell(\1)
     -1>> =suggVerb(@, ":3p")                                                                        # Forme interrogative : « \1 » n’est pas un verbe à la 3ᵉ personne du pluriel.
     <<- \1 != "t" and not morph(\1, ":V", False) and spell(\1)
-    -1>> =suggSimil(\1, ":3p")                                                                      # Forme interrogative : « \1 » n’est pas un verbe à la 3ᵉ personne du pluriel.
+    -1>> =suggSimil(\1, ":3p", False)                                                               # Forme interrogative : « \1 » n’est pas un verbe à la 3ᵉ personne du pluriel.
 
 TEST: {{attaquant}}-ils                                     ->> attaquent
 TEST: {{prendrons}}-elles un verre avec moi ?
 
 

Index: gc_lang/fr/webext/background.js
==================================================================
--- gc_lang/fr/webext/background.js
+++ gc_lang/fr/webext/background.js
@@ -5,10 +5,18 @@
 
 function showError (e) {
     console.error(e.fileName + "\n" + e.name + "\nline: " + e.lineNumber + "\n" + e.message);
 }
 
+// Chrome don’t follow the W3C specification:
+// https://browserext.github.io/browserext/
+let bChrome = false;
+if (typeof(browser) !== "object") {
+    var browser = chrome;
+    bChrome = true;
+}
+
 
 /*
     Worker (separate thread to avoid freezing Firefox)
 */
 let xGCEWorker = new Worker("gce_worker.js");
@@ -17,11 +25,11 @@
     // https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent
     try {
         let {sActionDone, result, dInfo} = e.data;
         switch (sActionDone) {
             case "init":
-                browser.storage.local.set({"gc_options": result});
+                storeGCOptions(result);
                 break;
             case "parse":
             case "parseAndSpellcheck":
             case "parseAndSpellcheck1":
             case "getListOfTokens":
@@ -42,16 +50,19 @@
                 break;
             case "getOptions":
             case "getDefaultOptions":
             case "resetOptions":
                 // send result to panel
+                storeGCOptions(result);
+                if (bChrome) {
+                    e.data.result = helpers.mapToObject(e.data.result);
+                }
                 browser.runtime.sendMessage(e.data);
-                browser.storage.local.set({"gc_options": result});
                 break;
             case "setOptions":
             case "setOption":
-                browser.storage.local.set({"gc_options": result});
+                storeGCOptions(result);
                 break;
             default:
                 console.log("[background] Unknown command: " + sActionDone);
                 console.log(e.data);
         }
@@ -59,22 +70,27 @@
     catch (e) {
         showError(e);
     }
 };
 
+function initGrammarChecker (dSavedOptions) {
+    let dOptions = (dSavedOptions.hasOwnProperty("gc_options")) ? dSavedOptions.gc_options : null;
+    xGCEWorker.postMessage({
+        sCommand: "init",
+        dParam: {sExtensionPath: browser.extension.getURL(""), dOptions: dOptions, sContext: "Firefox"},
+        dInfo: {}
+    });
+}
 
 function init () {
+    if (bChrome) {
+        browser.storage.local.get("gc_options", initGrammarChecker);
+        return;
+    }
     let xPromise = browser.storage.local.get("gc_options");
     xPromise.then(
-        function (dSavedOptions) {
-            let dOptions = (dSavedOptions.hasOwnProperty("gc_options")) ? dSavedOptions.gc_options : null;
-            xGCEWorker.postMessage({
-                sCommand: "init",
-                dParam: {sExtensionPath: browser.extension.getURL("."), dOptions: dOptions, sContext: "Firefox"},
-                dInfo: {}
-            });
-        },
+        initGrammarChecker,
         function (e) {
             showError(e);
             xGCEWorker.postMessage({
                 sCommand: "init",
                 dParam: {sExtensionPath: browser.extension.getURL("."), dOptions: null, sContext: "Firefox"},
@@ -247,10 +263,19 @@
 
 
 /*
     Actions
 */
+
+function storeGCOptions (dOptions) {
+    if (bChrome) {
+        // JS crap again. Chrome can’t store Map object.
+        dOptions = helpers.mapToObject(dOptions);
+    }
+    browser.storage.local.set({"gc_options": dOptions});
+}
+
 function parseAndSpellcheckSelectedText (iTab, sText) {
     // send message to the tab
     let xTabPort = dConnx.get(iTab);
     xTabPort.postMessage({sActionDone: "openGCPanel", result: null, dInfo: null, bEnd: false, bError: false});
     // send command to the worker
@@ -272,20 +297,35 @@
         dInfo: {iReturnPort: iTab}
     });
 }
 
 function openConjugueurTab () {
+    if (bChrome) {
+        browser.tabs.create({
+            url: browser.extension.getURL("panel/conjugueur.html")
+        });
+        return;
+    }
     let xConjTab = browser.tabs.create({
         url: browser.extension.getURL("panel/conjugueur.html")
     });
     xConjTab.then(onCreated, onError);
 }
 
 function openConjugueurWindow () {
+    if (bChrome) {
+        browser.windows.create({
+            url: browser.extension.getURL("panel/conjugueur.html"),
+            type: "popup",
+            width: 710,
+            height: 980
+        });
+        return;
+    }
     let xConjWindow = browser.windows.create({
         url: browser.extension.getURL("panel/conjugueur.html"),
-        type: "detached_panel",
+        type: "popup",
         width: 710,
         height: 980
     });
     xConjWindow.then(onCreated, onError);
 }

Index: gc_lang/fr/webext/content_scripts/init.js
==================================================================
--- gc_lang/fr/webext/content_scripts/init.js
+++ gc_lang/fr/webext/content_scripts/init.js
@@ -12,23 +12,18 @@
 
 function showError (e) {
     console.error(e.fileName + "\n" + e.name + "\nline: " + e.lineNumber + "\n" + e.message);
 }
 
-function createNode (sType, oAttr, oDataset=null) {
-    try {
-        let xNode = document.createElement(sType);
-        Object.assign(xNode, oAttr);
-        if (oDataset) {
-            Object.assign(xNode.dataset, oDataset);
-        }
-        return xNode;
-    }
-    catch (e) {
-        showError(e);
-    }
-}
+// Chrome don’t follow the W3C specification:
+// https://browserext.github.io/browserext/
+let bChrome = false;
+if (typeof(browser) !== "object") {
+    var browser = chrome;
+    bChrome = true;
+}
+
 
 /*
 function loadImage (sContainerClass, sImagePath) {
     let xRequest = new XMLHttpRequest();
     xRequest.open('GET', browser.extension.getURL("")+sImagePath, false);
@@ -53,12 +48,14 @@
     oGCPanel: null,
 
     createMenus: function () {
         let lNode = document.getElementsByTagName("textarea");
         for (let xNode of lNode) {
-            this.lMenu.push(new GrammalecteMenu(this.nMenu, xNode));
-            this.nMenu += 1;
+            if (xNode.style.display !== "none" && xNode.style.visibility !== "hidden") {
+                this.lMenu.push(new GrammalecteMenu(this.nMenu, xNode));
+                this.nMenu += 1;
+            }
         }
     },
 
     createMenus2 () {
         let lNode = document.querySelectorAll("[contenteditable]");
@@ -98,10 +95,24 @@
     createGCPanel: function () {
         if (this.oGCPanel === null) {
             this.oGCPanel = new GrammalecteGrammarChecker("grammalecte_gc_panel", "Grammalecte", 500, 700);
             this.oGCPanel.insertIntoPage();
         }
+    },
+
+    createNode: function (sType, oAttr, oDataset=null) {
+        try {
+            let xNode = document.createElement(sType);
+            Object.assign(xNode, oAttr);
+            if (oDataset) {
+                Object.assign(xNode.dataset, oDataset);
+            }
+            return xNode;
+        }
+        catch (e) {
+            showError(e);
+        }
     }
 }
 
 
 /*

Index: gc_lang/fr/webext/content_scripts/menu.css
==================================================================
--- gc_lang/fr/webext/content_scripts/menu.css
+++ gc_lang/fr/webext/content_scripts/menu.css
@@ -18,11 +18,11 @@
     border-radius: 50%;
     text-align: center;
     cursor: pointer;
     box-shadow: 0 0 0 0 hsla(210, 50%, 50%, .5);
     z-index: 2147483640; /* maximum is 2147483647: https://stackoverflow.com/questions/491052/minimum-and-maximum-value-of-z-index */
-    animation: grammalecte-spin 2s ease infinite;
+    animation: grammalecte-spin 2s ease 3;
 }
 .grammalecte_menu_main_button:hover {
     border: 4px solid hsla(210, 80%, 35%, .5);
     background-color: hsla(210, 80%, 55%, .5);
     animation: grammalecte-spin .5s linear infinite;

Index: gc_lang/fr/webext/content_scripts/menu.js
==================================================================
--- gc_lang/fr/webext/content_scripts/menu.js
+++ gc_lang/fr/webext/content_scripts/menu.js
@@ -5,11 +5,11 @@
 
 class GrammalecteMenu {
 
     constructor (nMenu, xNode) {
         this.sMenuId = "grammalecte_menu" + nMenu;
-        this.xButton = createNode("div", {className: "grammalecte_menu_main_button", textContent: " "});
+        this.xButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_main_button", textContent: " "});
         this.xButton.onclick = () => { this.switchMenu(); };
         this.xMenu = this._createMenu(xNode);
         this._insertAfter(this.xButton, xNode);
         this._insertAfter(this.xMenu, xNode);
     }
@@ -19,25 +19,25 @@
     }
 
     _createMenu (xNode) {
         try {
             let sText = (xNode.tagName == "TEXTAREA") ? xNode.value : xNode.textContent;
-            let xMenu = createNode("div", {id: this.sMenuId, className: "grammalecte_menu"});
-            xMenu.appendChild(createNode("div", {className: "grammalecte_menu_header", textContent: "GRAMMALECTE"}));
+            let xMenu = oGrammalecte.createNode("div", {id: this.sMenuId, className: "grammalecte_menu"});
+            xMenu.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_menu_header", textContent: "GRAMMALECTE"}));
             // Text formatter
             if (xNode.tagName == "TEXTAREA") {
-                let xTFButton = createNode("div", {className: "grammalecte_menu_item", textContent: "Formateur de texte"});
+                let xTFButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_item", textContent: "Formateur de texte"});
                 xTFButton.onclick = () => {
                     this.switchMenu();
                     oGrammalecte.createTFPanel();
                     oGrammalecte.oTFPanel.start(xNode);
                     oGrammalecte.oTFPanel.show();
                 };
                 xMenu.appendChild(xTFButton);
             }
             // lexicographe
-            let xLxgButton = createNode("div", {className: "grammalecte_menu_item", textContent: "Lexicographe"});
+            let xLxgButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_item", textContent: "Lexicographe"});
             xLxgButton.onclick = () => {
                 this.switchMenu();
                 oGrammalecte.createLxgPanel();
                 oGrammalecte.oLxgPanel.clear();
                 oGrammalecte.oLxgPanel.show();
@@ -48,11 +48,11 @@
                     dInfo: {sTextAreaId: xNode.id}
                 });
             };
             xMenu.appendChild(xLxgButton);
             // Grammar checker
-            let xGCButton = createNode("div", {className: "grammalecte_menu_item", textContent: "Correction grammaticale"});
+            let xGCButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_item", textContent: "Correction grammaticale"});
             xGCButton.onclick = () => {
                 this.switchMenu();
                 oGrammalecte.createGCPanel();
                 oGrammalecte.oGCPanel.start(xNode);
                 oGrammalecte.oGCPanel.show();
@@ -63,27 +63,27 @@
                     dInfo: {sTextAreaId: xNode.id}
                 });
             };
             xMenu.appendChild(xGCButton);
             // Conjugation tool
-            let xConjButton = createNode("div", {className: "grammalecte_menu_item_block", textContent: "Conjugueur"});
-            let xConjButtonTab = createNode("div", {className: "grammalecte_menu_button", textContent: "Onglet"});
+            let xConjButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_item_block", textContent: "Conjugueur"});
+            let xConjButtonTab = oGrammalecte.createNode("div", {className: "grammalecte_menu_button", textContent: "Onglet"});
             xConjButtonTab.onclick = () => {
                 this.switchMenu();
                 xGrammalectePort.postMessage({sCommand: "openConjugueurTab", dParam: null, dInfo: null});
             };
-            let xConjButtonWin = createNode("div", {className: "grammalecte_menu_button", textContent: "Fenêtre"});
+            let xConjButtonWin = oGrammalecte.createNode("div", {className: "grammalecte_menu_button", textContent: "Fenêtre"});
             xConjButtonWin.onclick = () => {
                 this.switchMenu();
                 xGrammalectePort.postMessage({sCommand: "openConjugueurWindow", dParam: null, dInfo: null});
             };
             xConjButton.appendChild(xConjButtonTab);
             xConjButton.appendChild(xConjButtonWin);
             xMenu.appendChild(xConjButton);
-            //xMenu.appendChild(createNode("img", {scr: browser.extension.getURL("img/logo-16.png")}));
+            //xMenu.appendChild(oGrammalecte.createNode("img", {scr: browser.extension.getURL("img/logo-16.png")}));
             // can’t work, due to content-script policy: https://bugzilla.mozilla.org/show_bug.cgi?id=1267027
-            xMenu.appendChild(createNode("div", {className: "grammalecte_menu_footer"}));
+            xMenu.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_menu_footer"}));
             return xMenu;
         }
         catch (e) {
             showError(e);
         }

Index: gc_lang/fr/webext/content_scripts/panel.css
==================================================================
--- gc_lang/fr/webext/content_scripts/panel.css
+++ gc_lang/fr/webext/content_scripts/panel.css
@@ -94,40 +94,44 @@
     overflow: auto;
 }
 
 
 /*
-    CSS Spinner
-    Double bounce
-    http://tobiasahlin.com/spinkit/
+    Spinner
 */
 .grammalecte_spinner {
     visibility: hidden;
-    width: 40px;
-    height: 40px;
-    position: absolute;
-    top: 2px;
-    right: 180px;
-}
-.grammalecte_spinner .bounce1,
-.grammalecte_spinner .bounce2 {
-    width: 100%;
-    height: 100%;
-    border-radius: 50%;
-    background-color: hsl(0, 50%, 75%);
-    opacity: 0.6;
-    position: absolute;
-    top: 0;
-    left: 0;
-    animation: grammalecte-sk-bounce 2.0s infinite ease-in-out;
-}
-.grammalecte_spinner .bounce2 {
-    animation-delay: -1.0s;
-}
-
-@keyframes grammalecte-sk-bounce {
-    0%, 100% { 
-        transform: scale(0.0);
-    } 50% { 
-        transform: scale(1.0);
+    width: 20px;
+    height: 20px;
+    position: absolute;
+    top: 0px;
+    right: 200px;
+    background-color: hsla(210, 80%, 80%, .5);
+    border: 10px solid hsla(210, 80%, 60%, .5);
+    border-top: 10px solid hsla(210, 100%, 40%, .7);
+    border-bottom: 10px solid hsla(210, 100%, 40%, .7);
+    border-radius: 50%;
+    text-align: center;
+    cursor: pointer;
+    box-shadow: 0 0 0 0 hsla(210, 50%, 50%, .5);
+    animation: grammalecte-spin-big .5s linear infinite;
+}
+
+@keyframes grammalecte-spin-big {
+    0% {
+        transform: rotate(0deg) scale(1);
+        border-top: 10px solid hsla(210, 100%, 40%, .7);
+        border-bottom: 10px solid hsla(210, 100%, 40%, .7);
+    }
+    70% {
+        transform: rotate(180deg) scale(.8);
+        border-top: 10px solid hsla(0, 100%, 40%, .7);
+        border-bottom: 10px solid hsla(0, 100%, 40%, .7);
+        box-shadow: 0 0 0 20px hsla(210, 50%, 50%, 0);
+    }
+    100% {
+        transform: rotate(360deg) scale(1);
+        border-top: 10px solid hsla(210, 100%, 40%, .7);
+        border-bottom: 10px solid hsla(210, 100%, 40%, .7);
+        box-shadow: 0 0 0 0 hsla(210, 50%, 50%, 0);
     }
 }

Index: gc_lang/fr/webext/content_scripts/panel.js
==================================================================
--- gc_lang/fr/webext/content_scripts/panel.js
+++ gc_lang/fr/webext/content_scripts/panel.js
@@ -9,24 +9,24 @@
     constructor (sId, sTitle, nWidth, nHeight, bFlexible=true) {
         this.sId = sId;
         this.nWidth = nWidth;
         this.nHeight = nHeight;
         this.bFlexible = bFlexible;
-        this.xPanelBar = createNode("div", {className: "grammalecte_panel_bar"});
-        this.xPanelContent = createNode("div", {className: "grammalecte_panel_content"});
+        this.xPanelBar = oGrammalecte.createNode("div", {className: "grammalecte_panel_bar"});
+        this.xPanelContent = oGrammalecte.createNode("div", {className: "grammalecte_panel_content"});
         this.xWaitIcon = this._createWaitIcon();
         this.xPanel = this._createPanel(sTitle);
         this.center();
     }
 
     _createPanel (sTitle) {
         try {
-            let xPanel = createNode("div", {id: this.sId, className: "grammalecte_panel"});
+            let xPanel = oGrammalecte.createNode("div", {id: this.sId, className: "grammalecte_panel"});
             this.xPanelBar.appendChild(this._createButtons());
-            let xTitle = createNode("div", {className: "grammalecte_panel_title"});
+            let xTitle = oGrammalecte.createNode("div", {className: "grammalecte_panel_title"});
             xTitle.appendChild(this._createLogo());
-            xTitle.appendChild(createNode("div", {className: "grammalecte_panel_label", textContent: sTitle}));
+            xTitle.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_panel_label", textContent: sTitle}));
             this.xPanelBar.appendChild(xTitle);
             xPanel.appendChild(this.xPanelBar);
             xPanel.appendChild(this.xPanelContent);
             return xPanel;
         }
@@ -40,11 +40,11 @@
         xImg.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAC8UlEQVQ4jX3TbUgTcRwH8P89ddu5u9tt082aZmpFEU4tFz0QGTUwCi0heniR9MSUIKRaD0RvIlKigsooo+iNFa0XJYuwIjEK19OcDtPElsG0ktyp591t7u7+vUh7MPX3+vf5/n8/+P0BmKJIPUUVlh2rdVVeesWlzEybqg+bFOsoylnqPmNavGFfknV2Omu2Lvja3vxAURKJib3opHizu8riLK6gjRyuKgmoSoMRFENRUqfXTzvBGK62LC2uoFkOl4RhjQ8+qWt7dPNE3sbdp+2LXbsGe9qb4rIo/BfwFy6nWQ4ThWGNDzbcfu29dMDh2nHU7CypYNLmzTda0/L5cNuzmDQi/A4Y27k6eQxLI79wS/11D0AAMNvs6XT6ojVJjJEgTbMy2BT77xBMp09KcpaWV1uc41jQoi0NdUHfjeOO9WWn7AVF7s7n986SithPJGeupBh2PCSP/xxqxAp3eq6wuUV7Wc6MSZIEhA8vHjbfOe/OcW3zmAuKy+nUzAyD2bow8ODaEROFq8AyZ5WBYdEZXGqGxZ61HJV+9HYCJRbTNA0QBA40HWunaKN5dKg/DBKxeCIe09Th/m4MJwiMSZmLEzMQAABQRuNqgu8NYX3doTcMpvCkLbtQZ2AJkrPOZG1zlnY13T+Hy9EehY90h57eqcorcZ/lctZuMzAsOjLEqwNv66/6vZcPYRBC+C3cGaBxhSet2av1BpYgTTY7k5y2JPT41slIR6Axv8R9nnOs+4Pf+2r992uOxGVJwgAAAEINfgt3BGgsESWtWas1iGDyl+CT/u7WpvxNFRc4x7qtBoZFhSFejb7z1fq9NYfjsiT+cwcQavBruCOgU4SIGo18amuoq3Js3FNlynVtH385+s53ze+t8cRkURx3yMTTRBAEQVAUXbFlf3XystJKA2NExeFBdWASDAAA+MQACCEEmqbJ0b6PMC7JwhDU8YFHV5u9NZ64LErT/oW/63tPV6uJwmKoOND78u7Fg5NhAAD4CVbzY9cwrWQrAAAAAElFTkSuQmCC";
         return xImg;
     }
 
     _createButtons () {
-        let xButtonLine = createNode("div", {className: "grammalecte_panel_commands"});
+        let xButtonLine = oGrammalecte.createNode("div", {className: "grammalecte_panel_commands"});
         xButtonLine.appendChild(this.xWaitIcon);
         if (this.sId === "grammalecte_gc_panel") {
             xButtonLine.appendChild(this._createCopyButton());
         }
         xButtonLine.appendChild(this._createMoveButton("stickToTop", "¯", "Coller en haut"));
@@ -55,30 +55,30 @@
         xButtonLine.appendChild(this._createCloseButton());
         return xButtonLine;
     }
 
     _createWaitIcon () {
-        let xWaitIcon = createNode("div", {className: "grammalecte_spinner"});
-        xWaitIcon.appendChild(createNode("div", {className: "bounce1"}));
-        xWaitIcon.appendChild(createNode("div", {className: "bounce2"}));
+        let xWaitIcon = oGrammalecte.createNode("div", {className: "grammalecte_spinner"});
+        //xWaitIcon.appendChild(oGrammalecte.createNode("div", {className: "bounce1"}));
+        //xWaitIcon.appendChild(oGrammalecte.createNode("div", {className: "bounce2"}));
         return xWaitIcon;
     }
 
     _createCopyButton () {
-        let xButton = createNode("div", {id: "grammalecte_clipboard_button", className: "grammalecte_copy_button", textContent: "∑", title: "Copier dans le presse-papiers"});
+        let xButton = oGrammalecte.createNode("div", {id: "grammalecte_clipboard_button", className: "grammalecte_copy_button", textContent: "∑", title: "Copier dans le presse-papiers"});
         xButton.onclick = function () { this.copyTextToClipboard(); }.bind(this);
         return xButton;
     }
 
     _createMoveButton (sAction, sLabel, sTitle) {
-        let xButton = createNode("div", {className: "grammalecte_move_button", textContent: sLabel, title: sTitle});
+        let xButton = oGrammalecte.createNode("div", {className: "grammalecte_move_button", textContent: sLabel, title: sTitle});
         xButton.onclick = function () { this[sAction](); }.bind(this);
         return xButton;
     }
 
     _createCloseButton () {
-        let xButton = createNode("div", {className: "grammalecte_close_button", textContent: "×", title: "Fermer la fenêtre"});
+        let xButton = oGrammalecte.createNode("div", {className: "grammalecte_close_button", textContent: "×", title: "Fermer la fenêtre"});
         xButton.onclick = function () { this.hide(); }.bind(this);  // better than writing “let that = this;” before the function?
         return xButton;
     }
 
     insertIntoPage () {

Index: gc_lang/fr/webext/content_scripts/panel_gc.js
==================================================================
--- gc_lang/fr/webext/content_scripts/panel_gc.js
+++ gc_lang/fr/webext/content_scripts/panel_gc.js
@@ -44,12 +44,12 @@
     */
 
     constructor (...args) {
         super(...args);
         this.aIgnoredErrors = new Set();
-        this.xContentNode = createNode("div", {id: "grammalecte_gc_panel_content"});
-        this.xParagraphList = createNode("div", {id: "grammalecte_paragraph_list"});
+        this.xContentNode = oGrammalecte.createNode("div", {id: "grammalecte_gc_panel_content"});
+        this.xParagraphList = oGrammalecte.createNode("div", {id: "grammalecte_paragraph_list"});
         this.xContentNode.appendChild(this.xParagraphList);
         this.xPanelContent.addEventListener("click", onGrammalecteGCPanelClick, false);
         this.oTooltip = new GrammalecteTooltip(this.xContentNode);
         this.xPanelContent.appendChild(this.xContentNode);
         this.oTAC = new GrammalecteTextAreaControl();
@@ -76,17 +76,17 @@
     }
 
     addParagraphResult (oResult) {
         try {
             if (oResult && (oResult.sParagraph.trim() !== "" || oResult.aGrammErr.length > 0 || oResult.aSpellErr.length > 0)) {
-                let xNodeDiv = createNode("div", {className: "grammalecte_paragraph_block"});
+                let xNodeDiv = oGrammalecte.createNode("div", {className: "grammalecte_paragraph_block"});
                 // actions
-                let xActionsBar = createNode("div", {className: "grammalecte_paragraph_actions"});
-                xActionsBar.appendChild(createNode("div", {id: "grammalecte_check" + oResult.iParaNum, className: "grammalecte_paragraph_button grammalecte_green", textContent: "Réanalyser"}, {para_num: oResult.iParaNum}));
-                xActionsBar.appendChild(createNode("div", {id: "grammalecte_hide" + oResult.iParaNum, className: "grammalecte_paragraph_button grammalecte_red", textContent: "×", style: "font-weight: bold;"}));
+                let xActionsBar = oGrammalecte.createNode("div", {className: "grammalecte_paragraph_actions"});
+                xActionsBar.appendChild(oGrammalecte.createNode("div", {id: "grammalecte_check" + oResult.iParaNum, className: "grammalecte_paragraph_button grammalecte_green", textContent: "Réanalyser"}, {para_num: oResult.iParaNum}));
+                xActionsBar.appendChild(oGrammalecte.createNode("div", {id: "grammalecte_hide" + oResult.iParaNum, className: "grammalecte_paragraph_button grammalecte_red", textContent: "×", style: "font-weight: bold;"}));
                 // paragraph
-                let xParagraph = createNode("p", {id: "grammalecte_paragraph"+oResult.iParaNum, className: "grammalecte_paragraph", lang: "fr", contentEditable: "true"}, {para_num: oResult.iParaNum});
+                let xParagraph = oGrammalecte.createNode("p", {id: "grammalecte_paragraph"+oResult.iParaNum, className: "grammalecte_paragraph", lang: "fr", contentEditable: "true"}, {para_num: oResult.iParaNum});
                 xParagraph.setAttribute("spellcheck", "false"); // doesn’t seem possible to use “spellcheck” as a common attribute.
                 xParagraph.addEventListener("keyup", function (xEvent) {
                     this.oTAC.setParagraph(parseInt(xEvent.target.dataset.para_num), this.purgeText(xEvent.target.textContent));
                     this.oTAC.write();
                 }.bind(this)
@@ -235,11 +235,11 @@
     addSummary () {
         // todo
     }
 
     addMessage (sMessage) {
-        let xNode = createNode("div", {className: "grammalecte_gc_panel_message", textContent: sMessage});
+        let xNode = oGrammalecte.createNode("div", {className: "grammalecte_gc_panel_message", textContent: sMessage});
         this.xParagraphList.appendChild(xNode);
     }
 
     _copyToClipboard (sText)  {
         // recipe from https://github.com/mdn/webextensions-examples/blob/master/context-menu-copy-link-with-types/clipboard-helper.js
@@ -277,26 +277,26 @@
 
 class GrammalecteTooltip {
 
     constructor (xContentNode) {
         this.sErrorId = null;
-        this.xTooltip = createNode("div", {id: "grammalecte_tooltip"});
-        this.xTooltipArrow = createNode("img", {
+        this.xTooltip = oGrammalecte.createNode("div", {id: "grammalecte_tooltip"});
+        this.xTooltipArrow = oGrammalecte.createNode("img", {
             id: "grammalecte_tooltip_arrow",
             src: " data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwAAADsABataJCQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xNzNun2MAAAAnSURBVChTY/j//z8cq/kW/wdhZDEMSXRFWCVhGKwAmwQyHngFxf8B5fOGYfeFpYoAAAAASUVORK5CYII=",
             alt: "^",
         });
-        this.xTooltipSuggBlock = createNode("div", {id: "grammalecte_tooltip_sugg_block"});
-        let xMessageBlock = createNode("div", {id: "grammalecte_tooltip_message_block"});
-        xMessageBlock.appendChild(createNode("p", {id: "grammalecte_tooltip_rule_id"}));
-        xMessageBlock.appendChild(createNode("p", {id: "grammalecte_tooltip_message", textContent: "Erreur."}));
-        let xActions = xMessageBlock.appendChild(createNode("div", {id: "grammalecte_tooltip_actions"}));
-        xActions.appendChild(createNode("div", {id: "grammalecte_tooltip_ignore", textContent: "Ignorer"}));
-        xActions.appendChild(createNode("div", {id: "grammalecte_tooltip_url", textContent: "Voulez-vous en savoir plus ?…"}, {url: ""}));
+        this.xTooltipSuggBlock = oGrammalecte.createNode("div", {id: "grammalecte_tooltip_sugg_block"});
+        let xMessageBlock = oGrammalecte.createNode("div", {id: "grammalecte_tooltip_message_block"});
+        xMessageBlock.appendChild(oGrammalecte.createNode("p", {id: "grammalecte_tooltip_rule_id"}));
+        xMessageBlock.appendChild(oGrammalecte.createNode("p", {id: "grammalecte_tooltip_message", textContent: "Erreur."}));
+        let xActions = xMessageBlock.appendChild(oGrammalecte.createNode("div", {id: "grammalecte_tooltip_actions"}));
+        xActions.appendChild(oGrammalecte.createNode("div", {id: "grammalecte_tooltip_ignore", textContent: "Ignorer"}));
+        xActions.appendChild(oGrammalecte.createNode("div", {id: "grammalecte_tooltip_url", textContent: "Voulez-vous en savoir plus ?…"}, {url: ""}));
         xMessageBlock.appendChild(xActions);
         this.xTooltip.appendChild(xMessageBlock);
-        this.xTooltip.appendChild(createNode("div", {id: "grammalecte_tooltip_sugg_title", textContent: "SUGGESTIONS :"}));
+        this.xTooltip.appendChild(oGrammalecte.createNode("div", {id: "grammalecte_tooltip_sugg_title", textContent: "SUGGESTIONS :"}));
         this.xTooltip.appendChild(this.xTooltipSuggBlock);
         xContentNode.appendChild(this.xTooltip);
         xContentNode.appendChild(this.xTooltipArrow);
     }
 

Index: gc_lang/fr/webext/content_scripts/panel_lxg.js
==================================================================
--- gc_lang/fr/webext/content_scripts/panel_lxg.js
+++ gc_lang/fr/webext/content_scripts/panel_lxg.js
@@ -5,11 +5,11 @@
 class GrammalecteLexicographer extends GrammalectePanel {
 
     constructor (...args) {
         super(...args);
         this._nCount = 0;
-        this._xContentNode = createNode("div", {id: "grammalecte_lxg_panel_content"});
+        this._xContentNode = oGrammalecte.createNode("div", {id: "grammalecte_lxg_panel_content"});
         this.xPanelContent.appendChild(this._xContentNode);
     }
 
     clear () {
         this._nCount = 0;
@@ -18,24 +18,24 @@
         }
     }
 
     addSeparator (sText) {
         if (this._xContentNode.textContent !== "") {
-            this._xContentNode.appendChild(createNode("div", {className: "grammalecte_lxg_separator", textContent: sText}));
+            this._xContentNode.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_separator", textContent: sText}));
         }
     }
 
     addMessage (sClass, sText) {
-        this._xContentNode.appendChild(createNode("div", {className: sClass, textContent: sText}));
+        this._xContentNode.appendChild(oGrammalecte.createNode("div", {className: sClass, textContent: sText}));
     }
 
     addListOfTokens (lTokens) {
         try {
             if (lTokens) {
                 this._nCount += 1;
-                let xNodeDiv = createNode("div", {className: "grammalecte_lxg_list_of_tokens"});
-                xNodeDiv.appendChild(createNode("div", {className: "grammalecte_lxg_list_num", textContent: this._nCount}));
+                let xNodeDiv = oGrammalecte.createNode("div", {className: "grammalecte_lxg_list_of_tokens"});
+                xNodeDiv.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_list_num", textContent: this._nCount}));
                 for (let oToken of lTokens) {
                     xNodeDiv.appendChild(this._createTokenNode(oToken));
                 }
                 this._xContentNode.appendChild(xNodeDiv);
             }
@@ -44,19 +44,19 @@
             showError(e);
         }
     }
 
     _createTokenNode (oToken) {
-        let xTokenNode = createNode("div", {className: "grammalecte_lxg_token_block"});
-        xTokenNode.appendChild(createNode("div", {className: "grammalecte_lxg_token grammalecte_lxg_token_" + oToken.sType, textContent: oToken.sValue}));
-        xTokenNode.appendChild(createNode("div", {className: "grammalecte_lxg_token_colon", textContent: ":"}));
+        let xTokenNode = oGrammalecte.createNode("div", {className: "grammalecte_lxg_token_block"});
+        xTokenNode.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_token grammalecte_lxg_token_" + oToken.sType, textContent: oToken.sValue}));
+        xTokenNode.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_token_colon", textContent: ":"}));
         if (oToken.aLabel.length === 1) {
             xTokenNode.appendChild(document.createTextNode(oToken.aLabel[0]));
         } else {
-            let xTokenList = createNode("div", {className: "grammalecte_lxg_morph_list"});
+            let xTokenList = oGrammalecte.createNode("div", {className: "grammalecte_lxg_morph_list"});
             for (let sLabel of oToken.aLabel) {
-                xTokenList.appendChild(createNode("div", {className: "grammalecte_lxg_morph_elem", textContent: "• " + sLabel}));
+                xTokenList.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_morph_elem", textContent: "• " + sLabel}));
             }
             xTokenNode.appendChild(xTokenList);
         }
         return xTokenNode;
     }

Index: gc_lang/fr/webext/content_scripts/panel_tf.js
==================================================================
--- gc_lang/fr/webext/content_scripts/panel_tf.js
+++ gc_lang/fr/webext/content_scripts/panel_tf.js
@@ -15,12 +15,12 @@
 
     _createTextFormatter () {
         let xTFNode = document.createElement("div");
         try {
             // Options
-            let xOptions = createNode("div", {id: "grammalecte_tf_options"});
-            let xColumn1 = createNode("div", {className: "grammalecte_tf_column"});
+            let xOptions = oGrammalecte.createNode("div", {id: "grammalecte_tf_options"});
+            let xColumn1 = oGrammalecte.createNode("div", {className: "grammalecte_tf_column"});
             let xSSP = this._createFieldset("group_ssp", true, "Espaces surnuméraires");
             xSSP.appendChild(this._createBlockOption("o_start_of_paragraph", true, "En début de paragraphe"));
             xSSP.appendChild(this._createBlockOption("o_end_of_paragraph", true, "En fin de paragraphe"));
             xSSP.appendChild(this._createBlockOption("o_between_words", true, "Entre les mots"));
             xSSP.appendChild(this._createBlockOption("o_before_punctuation", true, "Avant les points (.), les virgules (,)"));
@@ -36,11 +36,11 @@
             xNBSP.appendChild(this._createBlockOption("o_nbsp_before_symbol", true, "Avant % ‰ € $ £ ¥ ˚C"));
             xNBSP.appendChild(this._createBlockOption("o_nbsp_within_numbers", true, "À l’intérieur des nombres"));
             xNBSP.appendChild(this._createBlockOption("o_nbsp_before_units", true, "Avant les unités de mesure"));
             let xDelete = this._createFieldset("group_delete", true, "Suppressions");
             xDelete.appendChild(this._createBlockOption("o_erase_non_breaking_hyphens", true, "Tirets conditionnels"));
-            let xColumn2 = createNode("div", {className: "grammalecte_tf_column"});
+            let xColumn2 = oGrammalecte.createNode("div", {className: "grammalecte_tf_column"});
             let xTypo = this._createFieldset("group_typo", true, "Signes typographiques");
             xTypo.appendChild(this._createBlockOption("o_ts_apostrophe", true, "Apostrophe (’)"));
             xTypo.appendChild(this._createBlockOption("o_ts_ellipsis", true, "Points de suspension (…)"));
             xTypo.appendChild(this._createBlockOption("o_ts_dash_middle", true, "Tirets d’incise :"));
             xTypo.appendChild(this._createRadioBoxHyphens("o_ts_m_dash_middle", "o_ts_n_dash_middle", false));
@@ -68,20 +68,20 @@
             xColumn2.appendChild(xMisc);
             xColumn2.appendChild(xStruct);
             xOptions.appendChild(xColumn1);
             xOptions.appendChild(xColumn2);
             // Actions
-            let xActions = createNode("div", {id: "grammalecte_tf_actions"});
-            let xDefaultButton = createNode("div", {id: "grammalecte_tf_reset", textContent: "Par défaut", className: "grammalecte_tf_button"});
+            let xActions = oGrammalecte.createNode("div", {id: "grammalecte_tf_actions"});
+            let xDefaultButton = oGrammalecte.createNode("div", {id: "grammalecte_tf_reset", textContent: "Par défaut", className: "grammalecte_tf_button"});
             xDefaultButton.addEventListener("click", () => { this.reset(); });
-            let xApplyButton = createNode("div", {id: "grammalecte_tf_apply", textContent: "Appliquer", className: "grammalecte_tf_button"});
+            let xApplyButton = oGrammalecte.createNode("div", {id: "grammalecte_tf_apply", textContent: "Appliquer", className: "grammalecte_tf_button"});
             xApplyButton.addEventListener("click", () => { this.saveOptions(); this.apply(); });
             xActions.appendChild(xDefaultButton);
-            xActions.appendChild(createNode("progress", {id: "grammalecte_tf_progressbar"}));
-            xActions.appendChild(createNode("span", {id: "grammalecte_tf_time_res", textContent: "…"}));
+            xActions.appendChild(oGrammalecte.createNode("progress", {id: "grammalecte_tf_progressbar"}));
+            xActions.appendChild(oGrammalecte.createNode("span", {id: "grammalecte_tf_time_res", textContent: "…"}));
             xActions.appendChild(xApplyButton);
-            //xActions.appendChild(createNode("div", {id: "grammalecte_infomsg", textContent: "blabla"}));
+            //xActions.appendChild(oGrammalecte.createNode("div", {id: "grammalecte_infomsg", textContent: "blabla"}));
             // create result
             xTFNode.appendChild(xOptions);
             xTFNode.appendChild(xActions);
         }
         catch (e) {
@@ -90,50 +90,50 @@
         return xTFNode;
     }
 
     // Common options
     _createFieldset (sId, bDefault, sLabel) {
-        let xFieldset = createNode("div", {id: sId, className: "grammalecte_tf_groupblock"});
-        let xGroupOption = createNode("div", {id: "o_"+sId, className: "grammalecte_tf_option grammalecte_tf_option_title_off", textContent: sLabel}, {selected: "false", default: bDefault, linked_ids: ""});
+        let xFieldset = oGrammalecte.createNode("div", {id: sId, className: "grammalecte_tf_groupblock"});
+        let xGroupOption = oGrammalecte.createNode("div", {id: "o_"+sId, className: "grammalecte_tf_option grammalecte_tf_option_title_off", textContent: sLabel}, {selected: "false", default: bDefault, linked_ids: ""});
         xGroupOption.addEventListener("click", (xEvent) => { this.switchOption(xEvent.target.id); this.switchGroup(xEvent.target.id); });
         xFieldset.appendChild(xGroupOption);
         return xFieldset;
     }
 
     _createBlockOption (sId, bDefault, sLabel) {
-        let xLine = createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_underline"});
+        let xLine = oGrammalecte.createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_underline"});
         xLine.appendChild(this._createOption(sId, bDefault, sLabel));
-        xLine.appendChild(createNode("div", {id: "res_"+sId, className: "grammalecte_tf_result", textContent: "·"}));
+        xLine.appendChild(oGrammalecte.createNode("div", {id: "res_"+sId, className: "grammalecte_tf_result", textContent: "·"}));
         return xLine;
     }
 
     _createOption (sId, bDefault, sLabel, sLinkedOptionsId="") {
-        let xOption = createNode("div", {id: sId, className: "grammalecte_tf_option grammalecte_tf_option_off", textContent: sLabel}, {selected: "false", default: bDefault, linked_ids: sLinkedOptionsId});
+        let xOption = oGrammalecte.createNode("div", {id: sId, className: "grammalecte_tf_option grammalecte_tf_option_off", textContent: sLabel}, {selected: "false", default: bDefault, linked_ids: sLinkedOptionsId});
         xOption.addEventListener("click", (xEvent) => { this.switchOption(xEvent.target.id); });
         return xOption;
     }
 
     // Hyphens
     _createRadioBoxHyphens (sIdEmDash, sIdEnDash, bDefaultEmDash) {
-        let xLine = createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_indent"});
+        let xLine = oGrammalecte.createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_indent"});
         xLine.appendChild(this._createOption(sIdEmDash, bDefaultEmDash, "cadratin (—)", sIdEnDash));
         xLine.appendChild(this._createOption(sIdEnDash, !bDefaultEmDash, "demi-cadratin (—)", sIdEmDash));
         return xLine;
     }
 
     // Ligatures
     _createRadioBoxLigatures () {
-        let xLine = createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_underline"});
+        let xLine = oGrammalecte.createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_underline"});
         xLine.appendChild(this._createOption("o_ts_ligature", true, "Ligatures"));
         xLine.appendChild(this._createOption("o_ts_ligature_do", false, "faire", "o_ts_ligature_undo"));
         xLine.appendChild(this._createOption("o_ts_ligature_undo", true, "défaire", "o_ts_ligature_do"));
-        xLine.appendChild(createNode("div", {id: "res_"+"o_ts_ligature", className: "grammalecte_tf_result", textContent: "·"}));
+        xLine.appendChild(oGrammalecte.createNode("div", {id: "res_"+"o_ts_ligature", className: "grammalecte_tf_result", textContent: "·"}));
         return xLine;
     }
 
     _createLigaturesSelection () {
-        let xLine = createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_indent"});
+        let xLine = oGrammalecte.createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_indent"});
         xLine.appendChild(this._createOption("o_ts_ligature_ff", true, "ff"));
         xLine.appendChild(this._createOption("o_ts_ligature_fi", true, "fi"));
         xLine.appendChild(this._createOption("o_ts_ligature_ffi", true, "ffi"));
         xLine.appendChild(this._createOption("o_ts_ligature_fl", true, "fl"));
         xLine.appendChild(this._createOption("o_ts_ligature_ffl", true, "ffl"));
@@ -142,32 +142,36 @@
         return xLine;
     }
 
     // Apostrophes
     _createSingleLetterOptions () {
-        let xLine = createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_indent"});
+        let xLine = oGrammalecte.createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_indent"});
         xLine.appendChild(this._createOption("o_ma_1letter_lowercase", false, "lettres isolées (j’ n’ m’ t’ s’ c’ d’ l’)"));
         xLine.appendChild(this._createOption("o_ma_1letter_uppercase", false, "Maj."));
         return xLine;
     }
 
     // Ordinals
     _createOrdinalOptions () {
-        let xLine = createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_underline"});
+        let xLine = oGrammalecte.createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_underline"});
         xLine.appendChild(this._createOption("o_ordinals_no_exponant", true, "Ordinaux (15e, XXIe…)"));
         xLine.appendChild(this._createOption("o_ordinals_exponant", true, "e → ᵉ"));
-        xLine.appendChild(createNode("div", {id: "res_"+"o_ordinals_no_exponant", className: "grammalecte_tf_result", textContent: "·"}));
+        xLine.appendChild(oGrammalecte.createNode("div", {id: "res_"+"o_ordinals_no_exponant", className: "grammalecte_tf_result", textContent: "·"}));
         return xLine;
     }
     
     /*
         Actions
     */
     start (xTextArea) {
         this.xTextArea = xTextArea;
-        let xPromise = browser.storage.local.get("tf_options");
-        xPromise.then(this.setOptions.bind(this), this.reset.bind(this));
+        if (bChrome) {
+            browser.storage.local.get("tf_options", this.setOptions.bind(this));
+        } else {
+            let xPromise = browser.storage.local.get("tf_options");
+            xPromise.then(this.setOptions.bind(this), this.reset.bind(this));
+        }
     }
 
     switchGroup (sOptName) {
         if (document.getElementById(sOptName).dataset.selected == "true") {
             document.getElementById(sOptName.slice(2)).style.opacity = 1;

Index: gc_lang/fr/webext/manifest.json
==================================================================
--- gc_lang/fr/webext/manifest.json
+++ gc_lang/fr/webext/manifest.json
@@ -9,10 +9,12 @@
       "id": "French-GC@grammalecte.net",
       "strict_min_version": "57.0"
     }
   },
 
+  "minimum_chrome_version": "61",
+
   "author": "Olivier R.",
   "homepage_url": "https://grammalecte.net",
   "description": "Correcteur grammatical pour le français.",
 
   "default_locale": "fr",
@@ -31,10 +33,11 @@
     "browser_style": false
   },
 
   "background": {
     "scripts": [
+      "grammalecte/helpers.js",
       "background.js"
     ]
   },
 
   "content_scripts": [
@@ -90,17 +93,17 @@
   ],
 
   "commands": {
     "conjugueur_tab": {
       "suggested_key": {
-        "default": "Ctrl+Shift+F6"
+        "default": "Ctrl+Shift+6"
       },
       "description": "Ouvre le conjugueur dans un onglet"
     },
     "conjugueur_window": {
       "suggested_key": {
-        "default": "Ctrl+Shift+F7"
+        "default": "Ctrl+Shift+7"
       },
       "description": "Ouvre le conjugueur dans une fenêtre"
     }
   },
 
@@ -121,10 +124,12 @@
 
   "chrome_settings_overrides": {
     "search_provider": {
       "name": "Grammalecte",
       "search_url": "https://www.dicollecte.org/dictionary.php?prj=fr&lemma={searchTerms}",
-      "keyword": "disc",
-      "favicon_url": "https://www.dicollecte.org/favicon.ico"
+      "keyword": "gram",
+      "favicon_url": "https://www.dicollecte.org/favicon.ico",
+      "encoding": "UTF-8",
+      "is_default": false
     }
   }
 }

Index: gc_lang/fr/webext/panel/main.css
==================================================================
--- gc_lang/fr/webext/panel/main.css
+++ gc_lang/fr/webext/panel/main.css
@@ -122,11 +122,11 @@
     overflow: auto;
 }
 #page h1 {
     margin: 0 0 10px 0;
     color: hsl(210, 50%, 50%);
-    font: bold 30px 'Yanone Kaffeesatz', "Liberation Sans Narrow", sans-serif;
+    font: bold 30px 'Yanone Kaffeesatz', "Oswald", "Liberation Sans Narrow", sans-serif;
 }
 
 
 /*
     Home
@@ -158,11 +158,11 @@
 #help_page {
     display: none;
     padding: 20px;
 }
 #help_page h2 {
-    font: bold 20px 'Yanone Kaffeesatz', "Liberation Sans Narrow", sans-serif;
+    font: bold 20px 'Yanone Kaffeesatz', "Oswald", "Liberation Sans Narrow", sans-serif;
     color: hsl(210, 50%, 50%);
 }
 #help_page .shortcut {
     margin-top: 10px;
     font-weight: bold;

Index: gc_lang/fr/webext/panel/main.html
==================================================================
--- gc_lang/fr/webext/panel/main.html
+++ gc_lang/fr/webext/panel/main.html
@@ -57,13 +57,13 @@
             <p class="right"><img src="../img/menu_button1.png" title="bouton du menu" /></p>
             <p class="right"><img src="../img/menu_button2.png" title="menu" /></p>
             <p>Pour les autres zones de texte (HTML éditable), il faut sélectionner le texte et utiliser le menu contextuel.</p>
             <p class="right"><img src="../img/contextmenu.png" title="menu contextuel sur sélection" /></p>
             <h2>Raccourcis clavier</h2>
-            <p class="shortcut">CTRL+MAJ+F6</p>
+            <p class="shortcut">CTRL+MAJ+6</p>
             <p class="shortcut_label">Conjugueur (dans un onglet)</p>
-            <p class="shortcut">CTRL+MAJ+F7</p>
+            <p class="shortcut">CTRL+MAJ+7</p>
             <p class="shortcut_label">Conjugueur (dans une fenêtre)</p>
           </div>
         </section> <!-- #help_page -->
 
         <section id="gc_options_page" class="page">

Index: gc_lang/fr/webext/panel/main.js
==================================================================
--- gc_lang/fr/webext/panel/main.js
+++ gc_lang/fr/webext/panel/main.js
@@ -5,10 +5,18 @@
 
 function showError (e) {
     console.error(e.fileName + "\n" + e.name + "\nline: " + e.lineNumber + "\n" + e.message);
 }
 
+// Chrome don’t follow the W3C specification:
+// https://browserext.github.io/browserext/
+let bChrome = false;
+if (typeof(browser) !== "object") {
+    var browser = chrome;
+    bChrome = true;
+}
+
 
 /*
     Events
 */
 window.addEventListener(
@@ -123,27 +131,38 @@
 
 
 function showTestResult (sText) {
     document.getElementById("tests_result").textContent = sText;
 }
+
 
 function setGCOptionsFromStorage () {
+    if (bChrome) {
+        browser.storage.local.get("gc_options", _setGCOptions);
+        return;
+    }
     let xPromise = browser.storage.local.get("gc_options");
-    xPromise.then(
-        function (dSavedOptions) {
-            if (dSavedOptions.hasOwnProperty("gc_options")) {
-                setGCOptions(dSavedOptions.gc_options);
-            }
-        },
-        function (e) {
-            showError(e);
-        }
-    );
+    xPromise.then(_setGCOptions, showError);
+}
+
+function _setGCOptions (dSavedOptions) {
+    if (dSavedOptions.hasOwnProperty("gc_options")) {
+        setGCOptions(dSavedOptions.gc_options);
+    }
 }
 
 function setGCOptions (dOptions) {
+    // dOptions is supposed to be a Map
+    if (bChrome) {
+        // JS crap again. Chrome can’t store/send Map object.
+        let m = new Map();
+        for (let param in dOptions) {
+            m.set(param, dOptions[param]);
+        }
+        dOptions = m;
+    }
     for (let [sOpt, bVal] of dOptions) {
         if (document.getElementById("option_"+sOpt)) {
             document.getElementById("option_"+sOpt).checked = bVal;
         }
     }
 }