From 97f560d2993c367fb84ef62eefbe90ca03c19ebc Mon Sep 17 00:00:00 2001
From: Hans Hagen <pragma@wxs.nl>
Date: Mon, 20 Mar 2023 17:14:54 +0100
Subject: 2023-03-20 15:44:00

---
 tex/context/base/mkii/cont-new.mkii                |    2 +-
 tex/context/base/mkii/context.mkii                 |    2 +-
 tex/context/base/mkii/mult-it.mkii                 |    2 +
 tex/context/base/mkiv/attr-mkr.mkiv                |    3 +-
 tex/context/base/mkiv/cont-new.mkiv                |    2 +-
 tex/context/base/mkiv/context.mkiv                 |    2 +-
 tex/context/base/mkiv/lpdf-mis.lua                 |    3 +-
 tex/context/base/mkiv/status-files.pdf             |  Bin 24650 -> 24657 bytes
 tex/context/base/mkiv/status-lua.pdf               |  Bin 266630 -> 267358 bytes
 tex/context/base/mkiv/util-prs.lua                 |    9 +-
 tex/context/base/mkxl/attr-eff.lmt                 |  134 +++
 tex/context/base/mkxl/attr-eff.mkxl                |    4 +-
 tex/context/base/mkxl/attr-mkr.lmt                 |   40 +
 tex/context/base/mkxl/attr-mkr.mkxl                |    5 +-
 tex/context/base/mkxl/attr-neg.lmt                 |  104 ++
 tex/context/base/mkxl/attr-neg.mkxl                |   13 +-
 tex/context/base/mkxl/char-tex.lmt                 |   54 +-
 tex/context/base/mkxl/cont-new.mkxl                |    2 +-
 tex/context/base/mkxl/context.mkxl                 |   12 +-
 tex/context/base/mkxl/enco-ini.mkxl                |   11 +
 tex/context/base/mkxl/font-ctx.lmt                 |   47 +-
 tex/context/base/mkxl/lang-def.mkxl                |   12 +-
 tex/context/base/mkxl/lpdf-xmp.lmt                 |    3 +-
 tex/context/base/mkxl/math-acc.mklx                |   37 +-
 tex/context/base/mkxl/math-act.lmt                 |  437 ++++++--
 tex/context/base/mkxl/math-def.mkxl                |   70 +-
 tex/context/base/mkxl/math-dld.mklx                |   85 +-
 tex/context/base/mkxl/math-fen.mkxl                |   56 +-
 tex/context/base/mkxl/math-ini.mkxl                |   12 +-
 tex/context/base/mkxl/math-rad.mklx                |    4 +-
 tex/context/base/mkxl/math-spa.lmt                 |   44 +-
 tex/context/base/mkxl/math-stc.mklx                |  308 +++---
 tex/context/base/mkxl/math-vfu.lmt                 |  205 ++--
 tex/context/base/mkxl/mult-sys.mkxl                |    2 +
 tex/context/base/mkxl/node-ali.lmt                 |    6 +-
 tex/context/base/mkxl/page-brk.mkxl                |    2 +-
 tex/context/base/mkxl/phys-dim.lmt                 | 1116 ++++++++++++++++++++
 tex/context/base/mkxl/phys-dim.mkxl                |   64 +-
 tex/context/base/mkxl/strc-flt.mklx                |    4 +-
 tex/context/base/mkxl/strc-lst.mklx                |    3 +-
 tex/context/base/mkxl/syst-aux.mkxl                |    2 +-
 tex/context/base/mkxl/syst-ini.mkxl                |    2 +-
 tex/context/base/mkxl/tabl-ntb.mkxl                |    2 +-
 tex/context/base/mkxl/tabl-tab.mkxl                |    2 +-
 tex/context/base/mkxl/tabl-tbl.mkxl                |    2 +-
 tex/context/base/mkxl/typo-ada.lmt                 |    6 +-
 tex/context/base/mkxl/typo-ada.mkxl                |    6 +
 tex/context/base/mkxl/typo-adj.mkxl                |    2 +-
 tex/context/base/mkxl/unic-ini.lmt                 |   26 +
 tex/context/base/mkxl/unic-ini.mkxl                |    5 +-
 tex/context/fonts/mkiv/antykwa-math.lfg            |   22 +-
 tex/context/fonts/mkiv/common-math-jmn.lfg         |  121 ++-
 tex/context/fonts/mkiv/ebgaramond-math.lfg         |   28 +-
 tex/context/fonts/mkiv/lucida-math.lfg             |   60 +-
 tex/context/fonts/mkiv/type-imp-concrete.mkiv      |   46 +-
 tex/context/fonts/mkiv/type-imp-ebgaramond.mkiv    |   24 +-
 tex/context/fonts/mkiv/type-imp-iwona.mkiv         |    3 +
 tex/context/fonts/mkiv/type-imp-kpfonts.mkiv       |    6 +-
 tex/context/fonts/mkiv/type-imp-kurier.mkiv        |   30 +-
 tex/context/fonts/mkiv/xcharter-math.lfg           |    3 +
 tex/context/interface/mkii/keys-it.xml             |    2 +
 tex/generic/context/luatex/luatex-fonts-merged.lua |    2 +-
 62 files changed, 2700 insertions(+), 623 deletions(-)
 create mode 100644 tex/context/base/mkxl/attr-eff.lmt
 create mode 100644 tex/context/base/mkxl/attr-mkr.lmt
 create mode 100644 tex/context/base/mkxl/attr-neg.lmt
 create mode 100644 tex/context/base/mkxl/phys-dim.lmt
 create mode 100644 tex/context/base/mkxl/unic-ini.lmt

(limited to 'tex')

diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii
index adf47a428..ec168c472 100644
--- a/tex/context/base/mkii/cont-new.mkii
+++ b/tex/context/base/mkii/cont-new.mkii
@@ -11,7 +11,7 @@
 %C therefore copyrighted by \PRAGMA. See mreadme.pdf for
 %C details.
 
-\newcontextversion{2023.03.10 12:15}
+\newcontextversion{2023.03.20 15:42}
 
 %D This file is loaded at runtime, thereby providing an
 %D excellent place for hacks, patches, extensions and new
diff --git a/tex/context/base/mkii/context.mkii b/tex/context/base/mkii/context.mkii
index cbe8cf4ff..9e6c53624 100644
--- a/tex/context/base/mkii/context.mkii
+++ b/tex/context/base/mkii/context.mkii
@@ -20,7 +20,7 @@
 %D your styles an modules.
 
 \edef\contextformat {\jobname}
-\edef\contextversion{2023.03.10 12:15}
+\edef\contextversion{2023.03.20 15:42}
 
 %D For those who want to use this:
 
diff --git a/tex/context/base/mkii/mult-it.mkii b/tex/context/base/mkii/mult-it.mkii
index d9a553cea..b700c4172 100644
--- a/tex/context/base/mkii/mult-it.mkii
+++ b/tex/context/base/mkii/mult-it.mkii
@@ -832,6 +832,7 @@
 \setinterfaceconstant{exitoffset}{exitoffset}
 \setinterfaceconstant{expansion}{espansione}
 \setinterfaceconstant{export}{export}
+\setinterfaceconstant{extradata}{extradata}
 \setinterfaceconstant{extras}{extras}
 \setinterfaceconstant{factor}{fattore}
 \setinterfaceconstant{fallback}{fallback}
@@ -955,6 +956,7 @@
 \setinterfaceconstant{lastpage}{ultimapagina}
 \setinterfaceconstant{lastpagesep}{lastpagesep}
 \setinterfaceconstant{lastpubsep}{lastpubsep}
+\setinterfaceconstant{lasttextseparator}{lasttextseparator}
 \setinterfaceconstant{layout}{layout}
 \setinterfaceconstant{left}{sinistra}
 \setinterfaceconstant{leftclass}{leftclass}
diff --git a/tex/context/base/mkiv/attr-mkr.mkiv b/tex/context/base/mkiv/attr-mkr.mkiv
index 544558dcf..a784dd9d8 100644
--- a/tex/context/base/mkiv/attr-mkr.mkiv
+++ b/tex/context/base/mkiv/attr-mkr.mkiv
@@ -20,6 +20,7 @@
 \unexpanded\def\definemarker    [#1]{\defineattribute[\s!marker:#1]}
 \unexpanded\def\setmarker [#1]#2[#3]{\dosetattribute{\s!marker:#1}{#3}}
 \unexpanded\def\resetmarker     [#1]{\dogetattribute{\s!marker:#1}}
-           \def\boxmarker       #1#2{attr \numexpr\dogetattributeid{\s!marker:#1}\numexpr \numexpr#2\relax}
+           \def\boxmarker       #1#2{attr \numexpr\dogetattributeid{\s!marker:#1}\relax \numexpr\numexpr#2\relax}
+\unexpanded\def\marker            #1{\numexpr\dogetattributeid{\s!marker:#1}\relax}
 
 \protect \endinput
diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv
index 22e4d4bae..684cf24c8 100644
--- a/tex/context/base/mkiv/cont-new.mkiv
+++ b/tex/context/base/mkiv/cont-new.mkiv
@@ -13,7 +13,7 @@
 
 % \normalend % uncomment this to get the real base runtime
 
-\newcontextversion{2023.03.10 12:15}
+\newcontextversion{2023.03.20 15:42}
 
 %D This file is loaded at runtime, thereby providing an excellent place for hacks,
 %D patches, extensions and new features. There can be local overloads in cont-loc
diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv
index 1c9effa6a..9b89b9bdf 100644
--- a/tex/context/base/mkiv/context.mkiv
+++ b/tex/context/base/mkiv/context.mkiv
@@ -49,7 +49,7 @@
 %D {YYYY.MM.DD HH:MM} format.
 
 \edef\contextformat {\jobname}
-\edef\contextversion{2023.03.10 12:15}
+\edef\contextversion{2023.03.20 15:42}
 
 %D Kind of special:
 
diff --git a/tex/context/base/mkiv/lpdf-mis.lua b/tex/context/base/mkiv/lpdf-mis.lua
index 94e9fc271..803a8860e 100644
--- a/tex/context/base/mkiv/lpdf-mis.lua
+++ b/tex/context/base/mkiv/lpdf-mis.lua
@@ -246,7 +246,8 @@ local function setupidentity()
         addtoinfo("ConTeXt.Version",version)
         addtoinfo("ConTeXt.Time",os.date("%Y-%m-%d %H:%M"))
         addtoinfo("ConTeXt.Jobname",jobname)
-        addtoinfo("ConTeXt.Url","www.pragma-ade.com")
+     -- addtoinfo("ConTeXt.Url","www.pragma-ade.com")
+        addtoinfo("ConTeXt.Url","github.com/contextgarden/context")
         addtoinfo("ConTeXt.Support","contextgarden.net")
         addtoinfo("TeX.Support","tug.org")
         --
diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf
index c073662c5..de994239b 100644
Binary files a/tex/context/base/mkiv/status-files.pdf and b/tex/context/base/mkiv/status-files.pdf differ
diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf
index 5bced88ec..e6773acf4 100644
Binary files a/tex/context/base/mkiv/status-lua.pdf and b/tex/context/base/mkiv/status-lua.pdf differ
diff --git a/tex/context/base/mkiv/util-prs.lua b/tex/context/base/mkiv/util-prs.lua
index 635b610e0..d7b7087a5 100644
--- a/tex/context/base/mkiv/util-prs.lua
+++ b/tex/context/base/mkiv/util-prs.lua
@@ -264,8 +264,13 @@ function parsers.groupedsplitat(symbol,withaction)
     if not pattern then
         local symbols   = S(symbol)
         local separator = space^0 * symbols * space^0
-        local value     = lbrace * C((nobrace + nestedbraces)^0) * rbrace
-                        + C((nestedbraces + (1-(space^0*(symbols+P(-1)))))^0)
+        local value     =
+                        lbrace
+                        * C((nobrace + nestedbraces)^0)
+                     -- * rbrace
+                        * (rbrace * (#symbols + P(-1))) -- new per 2023-03-11
+                        +
+                        C((nestedbraces + (1-(space^0*(symbols+P(-1)))))^0)
         if withaction then
             local withvalue = Carg(1) * value / function(f,s) return f(s) end
             pattern = spaces * withvalue * (separator*withvalue)^0
diff --git a/tex/context/base/mkxl/attr-eff.lmt b/tex/context/base/mkxl/attr-eff.lmt
new file mode 100644
index 000000000..d04408fb9
--- /dev/null
+++ b/tex/context/base/mkxl/attr-eff.lmt
@@ -0,0 +1,134 @@
+if not modules then modules = { } end modules ['attr-eff'] = {
+    version   = 1.001,
+    comment   = "companion to attr-eff.mkiv",
+    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+    copyright = "PRAGMA ADE / ConTeXt Development Team",
+    license   = "see context related readme files"
+}
+
+local attributes, nodes, backends, utilities = attributes, nodes, backends, utilities
+local tex = tex
+
+local states            = attributes.states
+local enableaction      = nodes.tasks.enableaction
+local nodeinjections    = backends.nodeinjections
+local texsetattribute   = tex.setattribute
+local allocate          = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
+local formatters        = string.formatters
+
+local interfaces        = interfaces
+local implement         = interfaces.implement
+
+local variables         = interfaces.variables
+local v_normal          = variables.normal
+
+attributes.effects      = attributes.effects or { }
+local effects           = attributes.effects
+
+local a_effect          = attributes.private('effect')
+
+effects.data            = allocate()
+effects.values          = effects.values     or { }
+effects.registered      = effects.registered or { }
+effects.attribute       = a_effect
+
+local data              = effects.data
+local registered        = effects.registered
+local values            = effects.values
+
+local f_stamp           = formatters["%s:%s:%s"]
+
+storage.register("attributes/effects/registered", registered, "attributes.effects.registered")
+storage.register("attributes/effects/values",     values,     "attributes.effects.values")
+
+-- valid effects: normal inner outer both hidden (stretch,rulethickness,effect)
+
+local function effect(...) effect = nodeinjections.effect return effect(...) end
+
+local function extender(effects,key)
+    if key == "none" then
+        local d = effect(0,0,0)
+        effects.none = d
+        return d
+    end
+end
+
+local function reviver(data,n)
+    local e = values[n] -- we could nil values[n] now but hardly needed
+    local d = effect(e[1],e[2],e[3])
+    data[n] = d
+    return d
+end
+
+setmetatableindex(effects,      extender)
+setmetatableindex(effects.data, reviver)
+
+effects.handler = nodes.installattributehandler {
+    name        = "effect",
+    namespace   = effects,
+    initializer = states.initialize,
+    finalizer   = states.finalize,
+    processor   = states.process,
+}
+
+local function register(specification)
+    local alternative, stretch, rulethickness
+    if specification then
+        alternative   = specification.alternative or v_normal
+        stretch       = specification.stretch or 0
+        rulethickness = specification.rulethickness or 0
+    else
+        alternative   = v_normal
+        stretch       = 0
+        rulethickness = 0
+    end
+    local stamp = f_stamp(alternative,stretch,rulethickness)
+    local n = registered[stamp]
+    if not n then
+        n = #values + 1
+        values[n] = { alternative, stretch, rulethickness }
+        registered[stamp] = n
+    end
+    return n
+end
+
+local enabled = false
+
+local function enable()
+    if not enabled then
+        enableaction("shipouts","attributes.effects.handler")
+        enabled = true
+    end
+end
+
+effects.register = register
+effects.enable   = enable
+
+-- interface
+
+implement {
+    name      = "seteffect",
+    actions   = function(specification)
+        if not enabled then
+            enable()
+        end
+        texsetattribute(a_effect,register(specification))
+    end,
+    arguments = {
+        {
+            { "alternative",   "string"  },
+            { "stretch",       "integer" },
+            { "rulethickness", "dimen"   }
+        }
+    }
+}
+
+implement {
+    name      = "reseteffect",
+    actions   = function()
+        if enabled then
+            texsetattribute(a_effect,register())
+        end
+    end
+}
diff --git a/tex/context/base/mkxl/attr-eff.mkxl b/tex/context/base/mkxl/attr-eff.mkxl
index 42aadf9a2..5a50ab60c 100644
--- a/tex/context/base/mkxl/attr-eff.mkxl
+++ b/tex/context/base/mkxl/attr-eff.mkxl
@@ -13,7 +13,7 @@
 
 \writestatus{loading}{ConTeXt Attribute Macros / Effects}
 
-\registerctxluafile{attr-eff}{}
+\registerctxluafile{attr-eff}{autosuffix}
 
 \unprotect
 
@@ -22,7 +22,7 @@
 \installcommandhandler \??effect {effect} \??effect
 
 \setupeffect
-  [\c!method=\v!none,
+  [\c!method=\v!none, % should become command or define or so
    \c!stretch=\zerocount,
    \c!rulethickness=\zeropoint,
    \c!alternative=\v!normal]
diff --git a/tex/context/base/mkxl/attr-mkr.lmt b/tex/context/base/mkxl/attr-mkr.lmt
new file mode 100644
index 000000000..10550d935
--- /dev/null
+++ b/tex/context/base/mkxl/attr-mkr.lmt
@@ -0,0 +1,40 @@
+if not modules then modules = { } end modules ['attr-mkr'] = {
+    version   = 1.001,
+    comment   = "companion to attr-mkr.mkiv",
+    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+    copyright = "PRAGMA ADE / ConTeXt Development Team",
+    license   = "see context related readme files"
+}
+
+local markers = nodes.markers or { }
+nodes.markers = markers
+
+local cache     = { }
+local numbers   = attributes.numbers
+local a_unknown = attributes.private("marker:unknown")
+
+local nuts    = nodes.nuts
+local tonut   = nodes.tonut
+local setattr = nuts.setattr
+local getattr = nuts.getattr
+
+table.setmetatableindex(cache,function(t,k)
+    local k = "marker:" .. k
+    local v = numbers[k] or a_unknown
+    t[k] = v
+    return v
+end)
+
+function markers.get(n,name)
+    local a = cache[name]
+    if a then
+        getattr(tonut(n),a)
+    end
+end
+
+function markers.set(n,name,v)
+    local a = cache[name]
+    if a then
+        setattr(tonut(n),a,v)
+    end
+end
diff --git a/tex/context/base/mkxl/attr-mkr.mkxl b/tex/context/base/mkxl/attr-mkr.mkxl
index 2209af241..24e0a2319 100644
--- a/tex/context/base/mkxl/attr-mkr.mkxl
+++ b/tex/context/base/mkxl/attr-mkr.mkxl
@@ -15,11 +15,12 @@
 
 \unprotect
 
-\registerctxluafile{attr-mkr}{}
+\registerctxluafile{attr-mkr}{autosuffix}
 
 \permanent         \protected\def\definemarker    [#1]{\defineattribute[\s!marker:#1]}
 \permanent\tolerant\protected\def\setmarker [#1]#*[#2]{\dosetattribute{\s!marker:#1}{#2}}
 \permanent         \protected\def\resetmarker     [#1]{\dogetattribute{\s!marker:#1}}
-\permanent                   \def\boxmarker       #1#2{attr \numexpr\dogetattributeid{\s!marker:#1}\numexpr \numexpr#2\relax}
+\permanent                   \def\boxmarker       #1#2{attr \numexpr\dogetattributeid{\s!marker:#1}\relax \numexpr#2\relax}
+\permanent         \protected\def\marker            #1{\numexpr\dogetattributeid{\s!marker:#1}\relax}
 
 \protect \endinput
diff --git a/tex/context/base/mkxl/attr-neg.lmt b/tex/context/base/mkxl/attr-neg.lmt
new file mode 100644
index 000000000..4739b736d
--- /dev/null
+++ b/tex/context/base/mkxl/attr-neg.lmt
@@ -0,0 +1,104 @@
+if not modules then modules = { } end modules ['attr-neg'] = {
+    version   = 1.001,
+    comment   = "companion to attr-neg.mkiv",
+    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+    copyright = "PRAGMA ADE / ConTeXt Development Team",
+    license   = "see context related readme files"
+}
+
+-- this module is being reconstructed and code will move to other places
+-- we can also do the nsnone via a metatable and then also se index 0
+
+local format = string.format
+
+local attributes, nodes, utilities, logs, backends = attributes, nodes, utilities, logs, backends
+local commands, context, interfaces = commands, context, interfaces
+local tex = tex
+
+local states            = attributes.states
+local enableaction      = nodes.tasks.enableaction
+local nodeinjections    = backends.nodeinjections
+local texsetattribute   = tex.setattribute
+local variables         = interfaces.variables
+local allocate          = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
+
+--- negative / positive
+
+attributes.negatives    = attributes.negatives or { }
+local negatives         = attributes.negatives
+
+local a_negative        = attributes.private("negative")
+
+local v_none            = interfaces.variables.none
+
+negatives.data          = allocate()
+negatives.attribute     = a_negative
+
+negatives.registered = allocate {
+    [variables.positive] = 1,
+    [variables.negative] = 2,
+}
+
+local data       = negatives.data
+local registered = negatives.registered
+
+local function extender(negatives,key)
+    if key == "none" then -- v_none then
+        local d = data[1]
+        negatives.none = d
+        return d
+    end
+end
+
+local function reviver(data,n)
+    if n == 1 then
+        local d = nodeinjections.positive() -- called once
+        data[1] = d
+        return d
+    elseif n == 2 then
+        local d = nodeinjections.negative() -- called once
+        data[2] = d
+        return d
+    end
+end
+
+setmetatableindex(negatives,      extender)
+setmetatableindex(negatives.data, reviver)
+
+negatives.handler = nodes.installattributehandler {
+    name        = "negative",
+    namespace   = negatives,
+    initializer = states.initialize,
+    finalizer   = states.finalize,
+    processor   = states.process,
+}
+
+local function register(stamp)
+    return registered[stamp] or registered.positive
+end
+
+local function enable()
+    enableaction("shipouts","attributes.negatives.handler")
+end
+
+negatives.register = register
+negatives.enable   = enable
+
+-- interface
+
+local enabled = false
+
+function negatives.set(stamp)
+    if not enabled then
+        enable()
+        enabled = true
+    end
+    texsetattribute(a_negative,register(stamp))
+end
+
+interfaces.implement {
+    name      = "setnegative",
+    actions   = negatives.set,
+    arguments = "argument",
+}
diff --git a/tex/context/base/mkxl/attr-neg.mkxl b/tex/context/base/mkxl/attr-neg.mkxl
index c849e6bf6..869ac0b2e 100644
--- a/tex/context/base/mkxl/attr-neg.mkxl
+++ b/tex/context/base/mkxl/attr-neg.mkxl
@@ -13,16 +13,19 @@
 
 \writestatus{loading}{ConTeXt Attribute Macros / Negation}
 
-\registerctxluafile{attr-neg}{}
+\registerctxluafile{attr-neg}{autosuffix}
 
 \unprotect
 
+%D This feature is kind of useless because only \ACROBAT\ seems to support it and
+%D even rather complete mupdf based viewers seem to ignore it.
+
 % positive and negative are preregistered
 
-\permanent\protected\def\startnegative{\clf_setnegative{\v!negative}}
-\permanent\protected\def\stopnegative {\clf_setnegative{\v!positive}}
+\permanent\protected\def\startnegative{\clf_setnegative\v!negative}
+\permanent\protected\def\stopnegative {\clf_setnegative\v!positive}
 
-\permanent\protected\def\startpositive{\clf_setnegative{\v!positive}}
-\permanent\protected\def\stoppositive {\clf_setnegative{\v!negative}}
+\permanent\protected\def\startpositive{\clf_setnegative\v!positive}
+\permanent\protected\def\stoppositive {\clf_setnegative\v!negative}
 
 \protect \endinput
diff --git a/tex/context/base/mkxl/char-tex.lmt b/tex/context/base/mkxl/char-tex.lmt
index 0e0297381..31023136d 100644
--- a/tex/context/base/mkxl/char-tex.lmt
+++ b/tex/context/base/mkxl/char-tex.lmt
@@ -23,6 +23,8 @@ local mark                  = utilities.storage.mark
 local context               = context
 local commands              = commands
 
+if not characters then require("char-ini") require("char-utf")  end
+
 local characters            = characters
 local texcharacters         = { }
 characters.tex              = texcharacters
@@ -401,7 +403,7 @@ if not interfaces then return end
 
 local implement = interfaces.implement
 
-local pattern
+local pattern1, pattern2
 
 local verbosemarks = characters.verbosemarks
 
@@ -418,6 +420,7 @@ else
         ["grave"]                = utfchar(0x300),
         ["acute"]                = utfchar(0x301),
         ["circumflex"]           = utfchar(0x302),
+        ["circumflex"]           = utfchar(0x302),
         ["tilde"]                = utfchar(0x303),
         ["macron"]               = utfchar(0x304), ["line"]         = utfchar(0x304),
         ["overline"]             = utfchar(0x305),
@@ -442,6 +445,7 @@ else
         ["macron below"]         = utfchar(0x331), ["line below"]   = utfchar(0x331),
 
         ["hook below"]           = utfchar(0x1FA9D),
+
     }
 
     characters.verbosemarks = verbosemarks
@@ -452,48 +456,68 @@ else
 
 end
 
-local function prepare()
-    pattern = Cs((utfchartabletopattern(verbosemarks) / verbosemarks + lpegpatterns.space/"" + lpegpatterns.utf8character)^0)
-    return pattern
+local function prepare1()
+    pattern1 = Cs(
+        (
+P("\\")/"" * (utfchartabletopattern(commandmapping) / commandmapping) * (P(" ")/"")
++            utfchartabletopattern(verbosemarks) / verbosemarks
+          + lpegpatterns.space/""
+          + lpegpatterns.utf8character
+        )^0
+    )
+    return pattern1
+end
+
+local function prepare2()
+    local back = {
+      ["ı"] = "i",
+      ["ȷ"] = "j",
+    }
+    pattern2 = Cs(
+        (
+            utfchartabletopattern(back) / back
+          + lpegpatterns.utf8character
+        )^0
+    )
+    return pattern2
 end
 
 local hash = table.setmetatableindex(function(t,k)
-    local f = ""
-    k = lpegmatch(pattern or prepare(),k) or k
+    local f = k
+    k = lpegmatch(pattern1 or prepare1(),k) or k
+    k = lpegmatch(pattern2 or prepare2(),k) or k
     local v = collapse(k) or k -- char specials
--- print("collapse",k,v)
     if k ~= v then
         goto DONE
     end
     v = combine(k) or k -- with specials
--- print("combine",k,v)
     if k ~= v then
         goto DONE
     end
     v = commandmapping[k] or k
--- print("command",k,v)
     if k ~= v then
-        f = "\\"
+        f = "\\" .. f
         goto DONE
     end
     v = textoutf(k) or k
--- print("utf",k,v)
     if k ~= v then
-        f = "\\"
+        f = "\\" .. f
         goto DONE
     end
   ::DONE::
-    report_defining("instead of old school '%s%s' you can input the utf sequence %s",f,k,v)
+    report_defining("instead of old school '%s' you can input the utf sequence %s",f,v)
     t[k] = v
     return v
 end)
 
 implement {
     name      = "chr",
-    arguments = "argument",
+ -- arguments = "argument", -- not here
+    arguments = "string",
     public    = true,
     actions   = function(str)
-        context(hash[str]) -- expandable
+        local hsh = hash[str]
+        context(hsh) -- expandable
     end
 }
 
diff --git a/tex/context/base/mkxl/cont-new.mkxl b/tex/context/base/mkxl/cont-new.mkxl
index ef7c40717..9a6fc93da 100644
--- a/tex/context/base/mkxl/cont-new.mkxl
+++ b/tex/context/base/mkxl/cont-new.mkxl
@@ -13,7 +13,7 @@
 
 % \normalend % uncomment this to get the real base runtime
 
-\newcontextversion{2023.03.10 12:15}
+\newcontextversion{2023.03.20 15:42}
 
 %D This file is loaded at runtime, thereby providing an excellent place for hacks,
 %D patches, extensions and new features. There can be local overloads in cont-loc
diff --git a/tex/context/base/mkxl/context.mkxl b/tex/context/base/mkxl/context.mkxl
index 8f9513510..1a07772eb 100644
--- a/tex/context/base/mkxl/context.mkxl
+++ b/tex/context/base/mkxl/context.mkxl
@@ -29,7 +29,7 @@
 %D {YYYY.MM.DD HH:MM} format.
 
 \immutable\edef\contextformat {\jobname}
-\immutable\edef\contextversion{2023.03.10 12:15}
+\immutable\edef\contextversion{2023.03.20 15:42}
 
 %overloadmode 1 % check frozen / warning
 %overloadmode 2 % check frozen / error
@@ -651,11 +651,7 @@
 % take a while before we dealt with all of them because I'll also clean them
 % up a bit when doing.
 %
-% % luat-bas.mkxl l-macro-imp-optimize % this will go away
-
-% c:/data/develop/context/sources/attr-eff.lua
-% c:/data/develop/context/sources/attr-mkr.lua
-% c:/data/develop/context/sources/attr-neg.lua
+% % luat-bas.mkxl l-macro-imp-optimize % this is no longer used
 
 % c:/data/develop/context/sources/buff-imp-default.lua
 % c:/data/develop/context/sources/buff-imp-escaped.lua
@@ -791,8 +787,6 @@
 % c:/data/develop/context/sources/page-mix.lua
 % c:/data/develop/context/sources/page-pst.lua
 
-% c:/data/develop/context/sources/phys-dim.lua
-
 % c:/data/develop/context/sources/publ-aut.lua % shared
 % c:/data/develop/context/sources/publ-dat.lua
 % c:/data/develop/context/sources/publ-fnd.lua
@@ -837,5 +831,3 @@
 
 % c:/data/develop/context/sources/typo-cln.lua -- wrong name for what it does
 % c:/data/develop/context/sources/typo-dha.lua
-
-% c:/data/develop/context/sources/unic-ini.lua
diff --git a/tex/context/base/mkxl/enco-ini.mkxl b/tex/context/base/mkxl/enco-ini.mkxl
index 3d87ee776..dfe534f32 100644
--- a/tex/context/base/mkxl/enco-ini.mkxl
+++ b/tex/context/base/mkxl/enco-ini.mkxl
@@ -74,6 +74,17 @@
 \immutable\letcsname\??accents\endcsname\empty
 
 %D Because now have this (\type {\chr} issues a one|-|time warning):
+%D
+%D \stopbuffer
+%D \chr {e acute}
+%D \chr {i circumflex}
+%D \^{i} \^i \^{\i}
+%D \^{a} \"{a}
+%D \withcircumflex{a}
+%D \withdiaeresis{a}
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
 
 \permanent\protected\def\dodefinecombine#1#2%
   {\ifcsname\string#1\endcsname\else
diff --git a/tex/context/base/mkxl/font-ctx.lmt b/tex/context/base/mkxl/font-ctx.lmt
index 23c676e4e..77953d64a 100644
--- a/tex/context/base/mkxl/font-ctx.lmt
+++ b/tex/context/base/mkxl/font-ctx.lmt
@@ -1383,25 +1383,35 @@ do  -- else too many locals
                 local characters = tfmdata.characters
                 local parameters = tfmdata.parameters
                 local properties = tfmdata.properties
-                -- we use char0 as signal; cf the spec pdf can handle this (no char in slot)
-                characters[0] = nil
-                tfmdata.original = specification.specification
-                local id = definefont(tfmdata,properties.id)
-                csnames[id] = specification.cs
-                properties.id = id -- already set
-                definers.register(tfmdata,id) -- to be sure, normally already done
-                texdefinefont(global,cs,id)
-             -- texdefinefont(cs,id,global and "global")
-                constructors.finalize(tfmdata)
-                if trace_defining then
-                    report_defining("defining %a, id %a, target %a, features %a / %a, fallbacks %a / %a, step %a",
-                        name,id,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks,"-")
+                if characters then
+                    -- we use char0 as signal; cf the spec pdf can handle this (no char in slot)
+                    characters[0] = nil
+                    tfmdata.original = specification.specification
+                    local id = definefont(tfmdata,properties.id)
+                    csnames[id] = specification.cs
+                    properties.id = id -- already set
+                    definers.register(tfmdata,id) -- to be sure, normally already done
+                    texdefinefont(global,cs,id)
+                 -- texdefinefont(cs,id,global and "global")
+                    constructors.finalize(tfmdata)
+                    if trace_defining then
+                        report_defining("defining %a, id %a, target %a, features %a / %a, fallbacks %a / %a, step %a",
+                            name,id,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks,"-")
+                    end
+                    -- resolved (when designsize is used):
+                    local size = round(tfmdata.parameters.size or 655360)
+                    setmacro("somefontsize",size.."sp")
+                    texsetcount(c_scaledfontsize,size)
+                    lastfontid = id
+                else
+                    -- case 1: same as **
+                    local nice = nice_cs(cs)
+                    if not reported[name][nice] then
+                        report_defining("unable to define %a as %a",name,nice)
+                    end
+                    lastfontid = -1
+                    texsetcount(c_scaledfontsize,0)
                 end
-                -- resolved (when designsize is used):
-                local size = round(tfmdata.parameters.size or 655360)
-                setmacro("somefontsize",size.."sp")
-                texsetcount(c_scaledfontsize,size)
-                lastfontid = id
             elseif tfmtype == "number" then
                 if trace_defining then
                     report_defining("reusing %s, id %a, target %a, features %a / %a, fallbacks %a / %a, goodies %a / %a, designsize %a / %a",
@@ -1417,6 +1427,7 @@ do  -- else too many locals
                 texsetcount(c_scaledfontsize,size)
                 lastfontid = tfmdata
             else
+                -- case 2: same as **
                 local nice = nice_cs(cs)
                 if not reported[name][nice] then
                     report_defining("unable to define %a as %a",name,nice)
diff --git a/tex/context/base/mkxl/lang-def.mkxl b/tex/context/base/mkxl/lang-def.mkxl
index cd5fd4ba3..04215a779 100644
--- a/tex/context/base/mkxl/lang-def.mkxl
+++ b/tex/context/base/mkxl/lang-def.mkxl
@@ -257,7 +257,7 @@
 
 \installlanguage
   [\s!sl]
-  [\c!command=\v!no,
+  [\c!define=\v!no,
    \c!spacing=\v!packed,
    \c!leftsentence=\hbox{\endash\space},
    \c!rightsentence=\hbox{\space\endash},
@@ -271,7 +271,7 @@
 
 \installlanguage % for now we copy from slovenian
   [\s!sq]
-  [\c!command=\v!no,
+  [\c!define=\v!no,
    \s!lefthyphenmin=2,
    \s!righthyphenmin=2,
    \c!spacing=\v!packed,
@@ -284,12 +284,12 @@
    \c!leftquotation=\rightguillemot,
    \c!rightquotation=\leftguillemot,
    \c!date={\v!day,{.},\space,\v!month,\space,\v!year}]
-   
+
 \installlanguage
   [\s!hy]
   [\c!spacing=\v!packed,
    \c!leftsentence=\endash, % *sentences not confirmed
-   \c!rightsentence=\endash, 
+   \c!rightsentence=\endash,
    \c!leftsubsentence=\endash,
    \c!rightsubsentence=\endash,
    \c!leftquote=\guilsingleleft,
@@ -613,7 +613,7 @@
 
 \installlanguage
   [\s!lt]
-  [\c!command=\v!no,
+  [\c!define=\v!no,
    \c!spacing=\v!packed,
    \c!leftsentence=\emdash,
    \c!rightsentence=\emdash,
@@ -755,7 +755,7 @@
 
 \installlanguage
   [\s!it]
-  [\c!command=\v!no,
+  [\c!define=\v!no,
    \c!spacing=\v!packed,
    \c!leftsentence=\emdash,
    \c!rightsentence=\emdash,
diff --git a/tex/context/base/mkxl/lpdf-xmp.lmt b/tex/context/base/mkxl/lpdf-xmp.lmt
index e147c796f..aec12b22f 100644
--- a/tex/context/base/mkxl/lpdf-xmp.lmt
+++ b/tex/context/base/mkxl/lpdf-xmp.lmt
@@ -346,7 +346,8 @@ local function setupidentity()
             pdfaddtoinfo("ConTeXt.Jobname",jobname)
         end
         --
-        pdfaddtoinfo("ConTeXt.Url","www.pragma-ade.com")
+     -- pdfaddtoinfo("ConTeXt.Url","www.pragma-ade.com")
+        pdfaddtoinfo("ConTeXt.Url","github.com/contextgarden/context")
         pdfaddtoinfo("ConTeXt.Support","contextgarden.net")
         pdfaddtoinfo("TeX.Support","tug.org")
         --
diff --git a/tex/context/base/mkxl/math-acc.mklx b/tex/context/base/mkxl/math-acc.mklx
index 49f97ae9c..c3c4a5d34 100644
--- a/tex/context/base/mkxl/math-acc.mklx
+++ b/tex/context/base/mkxl/math-acc.mklx
@@ -92,15 +92,26 @@
 
 \installlocalcurrenthandler \??mathaccents {mathaccent}
 
+%D \starttyping
+%D \im { \showboxes \showglyphs
+%D     \hat{\tilde{\dot{x}}}
+%D }
+%D \im { \showboxes \showglyphs
+%D     \hat[align=middle]{\tilde[align=middle]{\dot{x}}}
+%D }
+%D \stoptyping
+
 \tolerant\protected\def\math_accent_make_double#class#kind#top#bottom#*[#settings]#:#content%
   {\beginmathgroup
    \setlocalmathaccentcurrent{#class}% \edef\currentmathaccent{#class}%
    \startusemathstyleparameter\mathaccentparameter\c!mathstyle
    \setupcurrentmathaccent[#settings]%
-   \edef\m_fixed{\ifcstok{\mathaccentparameter\c!stretch}\v!yes\else\s!fixed\fi}%
+   \edef\m_fixed {\ifcstok{\mathaccentparameter\c!stretch}\v!yes   \else\s!fixed \space\fi}%
+   \edef\m_center{\ifcstok{\mathaccentparameter\c!align  }\v!middle     \s!center\space\fi}%
    \Umathaccent
      \usedcolorparameterattributes{\mathaccentparameter\c!color}%
    % nooverflow % there is never na overflow anyway but we do accept thekey
+   \m_center
    \ifcase#kind\or
      top \m_fixed
      \fam\zerocount#top
@@ -170,8 +181,8 @@
 %definemathtopaccent[\v!top][overturnedcomma]      ["0312]
 %definemathtopaccent[\v!top][overcommatopright]    ["0315]
 %definemathtopaccent[\v!top][leftangleabove]       ["031A]
-\definemathtopaccent[\v!top][leftharpoonaccent]    ["20D0]
-\definemathtopaccent[\v!top][rightharpoonaccent]   ["20D1]
+\definemathtopaccent[\v!top][overleftharpoon]      ["20D0]
+\definemathtopaccent[\v!top][overrightharpoon]     ["20D1]
 %definemathtopaccent[\v!top][verticaloverlayaccent]["20D2]
 %definemathtopaccent[\v!top][vec]                  ["20D7]% We expect vec to stretch, so later
 \definemathtopaccent[\v!top][dddot]                ["20DB]
@@ -208,7 +219,7 @@
 \definemathtopaccent[\v!top:\v!stretch][wideacute]["0301]
 \definemathtopaccent[\v!top:\v!stretch][widehat]  ["0302]
 \definemathtopaccent[\v!top:\v!stretch][widetilde]["0303]
-\definemathtopaccent[\v!top:\v!stretch][widebar]  ["0305]%or 305
+\definemathtopaccent[\v!top:\v!stretch][widebar]  ["0305]% (not 304, the caret)
 \definemathtopaccent[\v!top:\v!stretch][widebreve]["0306]
 \definemathtopaccent[\v!top:\v!stretch][widedot]  ["0307]
 \definemathtopaccent[\v!top:\v!stretch][wideddot] ["0308]
@@ -220,17 +231,17 @@
 
 \definemathtopaccent[\v!top:\v!stretch][wideoverleftharpoon]   ["20D0]
 \definemathtopaccent[\v!top:\v!stretch][wideoverrightharpoon]  ["20D1]
-\definemathtopaccent[\v!top:\v!stretch][wideoverleftarrow]     ["20D6] 
-\definemathtopaccent[\v!top:\v!stretch][wideoverrightarrow]    ["20D7] 
+\definemathtopaccent[\v!top:\v!stretch][wideoverleftarrow]     ["20D6]
+\definemathtopaccent[\v!top:\v!stretch][wideoverrightarrow]    ["20D7]
 \definemathtopaccent[\v!top:\v!stretch][wideoverleftrightarrow]["20E1]
 
-\definemathbottomaccent[\v!bottom:\v!stretch][wideundertilde]["0330]
-\definemathbottomaccent[\v!bottom:\v!stretch][wideunderbar]["0332]
-\definemathbottomaccent[\v!bottom:\v!stretch][wideunderleftrightarrow]["034D]
-\definemathbottomaccent[\v!bottom:\v!stretch][wideunderrightharpoon]["20EC]
-\definemathbottomaccent[\v!bottom:\v!stretch][wideunderleftharpoon]["20ED]
-\definemathbottomaccent[\v!bottom:\v!stretch][wideunderleftarrow]["20EE]
-\definemathbottomaccent[\v!bottom:\v!stretch][wideunderrightarrow]["20EF]
+\definemathbottomaccent[\v!bottom:\v!stretch][wideundertilde]         ["0330]
+\definemathbottomaccent[\v!bottom:\v!stretch][wideunderbar]           ["0332]
+\definemathbottomaccent[\v!bottom:\v!stretch][wideunderleftrightarrow]["034D] % weird code
+\definemathbottomaccent[\v!bottom:\v!stretch][wideunderrightharpoon]  ["20EC]
+\definemathbottomaccent[\v!bottom:\v!stretch][wideunderleftharpoon]   ["20ED]
+\definemathbottomaccent[\v!bottom:\v!stretch][wideunderleftarrow]     ["20EE]
+\definemathbottomaccent[\v!bottom:\v!stretch][wideunderrightarrow]    ["20EF]
 
 \aliased\let\mathring\ring % for a while
 
diff --git a/tex/context/base/mkxl/math-act.lmt b/tex/context/base/mkxl/math-act.lmt
index a6614aaa5..0c75147f6 100644
--- a/tex/context/base/mkxl/math-act.lmt
+++ b/tex/context/base/mkxl/math-act.lmt
@@ -18,6 +18,7 @@ local type, next, tonumber = type, next, tonumber
 local fastcopy, copytable, insert, remove, concat = table.fastcopy, table.copy, table.insert, table.remove, table.concat
 local formatters = string.formatters
 local byte = string.byte
+local max = math.max
 local setmetatableindex, sortedkeys, sortedhash  = table.setmetatableindex, table.sortedkeys, table.sortedhash
 local lpegmatch = lpeg.match
 
@@ -45,13 +46,18 @@ local blocks           = characters.blocks
 local stepper          = utilities.parsers.stepper
 
 local helpers          = fonts.helpers
-local upcommand        = helpers.commands.up
-local downcommand      = helpers.commands.down
-local rightcommand     = helpers.commands.right
-local leftcommand      = helpers.commands.left
-local charcommand      = helpers.commands.char
 local prependcommands  = helpers.prependcommands
 
+local vfcommands       = helpers.commands
+local upcommand        = vfcommands.up
+local downcommand      = vfcommands.down
+local rightcommand     = vfcommands.right
+local leftcommand      = vfcommands.left
+local slotcommand      = vfcommands.slot
+local charcommand      = vfcommands.char
+local push             = vfcommands.push
+local pop              = vfcommands.pop
+
 local sequencers       = utilities.sequencers
 local appendgroup      = sequencers.appendgroup
 local appendaction     = sequencers.appendaction
@@ -1710,7 +1716,7 @@ do
     datasets.accentdimensions = candidates
 
     local function adapt(c,factor,baseheight,basedepth)
---         if not c.tweaked then
+        if not c.tweaked then
             local height  = c.height or 0
             local depth   = c.depth  or 0
             local yoffset = 0
@@ -1736,8 +1742,8 @@ do
             c.yoffset = yoffset ~= 0 and yoffset or nil
             c.height  = height   > 0 and height  or nil
             c.depth   = depth    > 0 and depth   or nil
---             c.tweaked = true
---         end
+            c.tweaked = true
+        end
     end
 
     local function process(target,original,characters,list,baseheight,basedepth)
@@ -1806,46 +1812,18 @@ end
 
 do
 
-    local addprivate  = fonts.helpers.addprivate
-    local privateslot = fonts.helpers.privateslot
-
- -- function mathtweaks.addrules(target,original,parameters)
- --     local characters = target.characters
- --     local height     = target.mathparameters.OverbarRuleThickness
- --     local depth      = target.mathparameters.UnderbarRuleThickness
- --     local width      = target.parameters.emwidth/2
- --     local step       = 0.8 * width
- --     characters[0x203E] = { -- over
- --         width    = width,
- --         height   = height,
- --         depth    = 0,
- --         unicode  = 0x203E,
- --         commands = { { "rule", height, width } },
- --         parts    = {
- --             { advance = width, ["end"] = step, glyph = 0x203E, start = 0 },
- --             { advance = width, ["end"] = 0,    glyph = 0x203E, start = step, extender = 1 },
- --         }
- --     }
- --     characters[0x0332] = { -- under
- --         width    = width,
- --         height   = 0,
- --         depth    = depth,
- --         yoffset  = -depth,
- --         unicode  = 0x0332,
- --         commands = { { "rule", height, width } },
- --         parts    = {
- --             { advance = width, ["end"] = step, glyph = 0x0332, start = 0 },
- --             { advance = width, ["end"] = 0,    glyph = 0x0332, start = step, extender = 1 },
- --         }
- --     }
- -- end
+    local addprivate     = fonts.helpers.addprivate
+    local privateslot    = fonts.helpers.privateslot
+    local newprivateslot = fonts.helpers.newprivateslot
 
     function mathtweaks.addrules(target,original,parameters)
         local characters = target.characters
         local thickness  = target.mathparameters.OverbarRuleThickness
         local width      = target.parameters.emwidth / 2
-        local step       = 0.8 * width
-        characters[0x203E] = { -- over
+        local width      = target.parameters.emwidth / 3
+--         local step       = 0.8 * width
+        local step       = 0.5 * width
+        characters[0x203E] = { -- middle used for all kind
             width    = width,
             height   = thickness / 2,
             depth    = thickness / 2,
@@ -1858,8 +1836,43 @@ do
             },
             partsorientation = "horizontal",
         }
-        --
-        characters[0x0332] = characters[0x203E]
+        local function build(target,leftarrow,rightarrow)
+            if leftarrow and rightarrow then
+                -- actually the same sort of code as we have for antykwa
+                local left  = leftarrow.parts
+                local right = rightarrow.parts
+                if left and right then
+                    local leftline   = right[1].glyph
+                    local rightline  = left [#left].glyph
+                    local leftdata   = characters[leftline]
+                    local rightdata  = characters[rightline]
+                    local leftwidth  = leftdata.width
+                    local rightwidth = rightdata.width
+                    local result     = characters[target] -- copytable(leftdata)
+                    if not result or result.width == 0 then
+                        result = {
+                            height   = leftdata.height,
+                            depth    = leftdata.depth,
+                            width    = 0.9*leftwidth + rightwidth,
+                            unicode  = target,
+                            commands = {
+                                slotcommand[0][leftline],
+                                leftcommand[0.1*leftwidth],
+                                slotcommand[0][rightline],
+                            },
+                        }
+                        characters[target] = result
+                    end
+                    result.parts = {
+                        { advance = leftwidth, glyph = leftline, ["end"] = .9*leftwidth, start = 0 },
+                        { advance = rightwidth, glyph = rightline, ["end"] = .1*leftwidth, start = .9*rightwidth, extender = 1 },
+                    }
+                    result.partsorientation = "horizontal"
+                end
+            end
+        end
+        build(0x305,characters[0x20D6],characters[0x20D7]) -- overbar  accent
+        build(0x332,characters[0x20EE],characters[0x20EF]) -- underbar accent
         --
         -- lucida lacks them ...
         --
@@ -1875,11 +1888,16 @@ do
                 commands = { { "rule", thickness * 2.5, thickness } },
             })
             characters[0x23B4] = { -- over
-                width    = width,
+--                 width    = width,
+                width    = 2*thickness+width,
                 height   = half,
                 depth    = double,
                 unicode  = 0x23B4,
-                commands = { { "rule", thickness, width } },
+                commands = {
+                    slotcommand[0][tpiece],
+                    slotcommand[0][0x203E],
+                    slotcommand[0][tpiece],
+                },
                 parts    = {
                     { advance = thickness, glyph = tpiece, ["end"] = 0,    start = half },
                     { advance = width,     glyph = 0x203E, ["end"] = step, start = step, extender = 1 },
@@ -1896,12 +1914,16 @@ do
                 yoffset  = - half,
                 commands = { { "rule", thickness * 2.5, thickness } },
             })
-            characters[0x23B5] = { -- over
-                width    = width,
+            characters[0x23B5] = { -- under
+                width    = 2*thickness+width,
                 height   = double,
                 depth    = half,
                 unicode  = 0x23B5,
-                commands = { { "rule", thickness, width } },
+                commands = {
+                    slotcommand[0][bpiece],
+                    slotcommand[0][0x203E],
+                    slotcommand[0][bpiece],
+                },
                 parts    = {
                     { advance = thickness, glyph = bpiece, ["end"] = 0,    start = half },
                     { advance = width,     glyph = 0x203E, ["end"] = step, start = step, extender = 1 },
@@ -1913,6 +1935,69 @@ do
         --
     end
 
+    -- vfmath.builders.extension(target)
+
+    local rbe = newprivateslot("radical bar extender")
+
+    local function useminus(unicode,characters,parameters)
+        local minus   = characters[0x2212]
+        local xoffset = parameters.xoffset or .075
+        local yoffset = parameters.yoffset or .9
+        local xscale  = parameters.xscale or 1
+        local yscale  = parameters.yscale or 1
+        local xwidth  = parameters.width   or (1 - 2*xoffset)
+        local xheight = parameters.height  or (1 - yoffset)
+        local mheight = minus.height
+        local mwidth  = minus.width
+        local height  = xheight*mheight
+        local xshift  = xoffset * mwidth
+        local yshift  = yoffset * mheight
+        local advance = xwidth  * mwidth
+        local step    = mwidth  / 2
+        characters[unicode] = {
+            height   = height,
+            depth    = height,
+            width    = advance,
+            commands = {
+            push,
+                leftcommand[xshift],
+                downcommand[yshift],
+             -- slotcommand[0][0x2212],
+                { "slot", 0, 0x2212, xscale, yscale },
+            pop,
+            },
+            unicode = unicode,
+         -- parts = {
+         --     { extender = 0, glyph = first,  ["end"] = fw/2, start = 0,    advance = fw },
+         --     { extender = 1, glyph = middle, ["end"] = mw/2, start = mw/2, advance = mw },
+         --     { extender = 0, glyph = last,   ["end"] = 0,    start = lw/2, advance = lw },
+         -- },
+            parts   = {
+                { extender = 0, glyph = unicode, ["end"] = step, start = 0,    advance = advance },
+                { extender = 1, glyph = unicode, ["end"] = step, start = step, advance = advance },
+            },
+            partsorientation = "horizontal",
+        }
+    end
+
+    function mathtweaks.replacerules(target,original,parameters)
+        local characters = target.characters
+        local fraction   = parameters.fraction
+        local radical    = parameters.radical
+        if fraction then
+            local template = fraction.template
+            if template == 0x2212 or template == "minus" then
+                useminus(0x203E,characters,fraction)
+            end
+        end
+        if radical then
+            local template = radical.template
+            if template == 0x2212 or template == "minus" then
+                useminus(rbe,characters,radical)
+            end
+        end
+    end
+
     local force = false  experiments.register("math.arrows", function(v) force = v end)
 
     local function tighten(target,unicode,left,right,squeeze,yoffset)
@@ -1947,7 +2032,7 @@ do
             if chardata and (force or overloads[unicode] == false or not chardata.parts) then
                 if not list then
                  -- chardata.parts = nil -- when we test
-                    chardata.parts = { { glyph = unicode } }
+--                     chardata.parts = { { glyph = unicode } }
                 else
                     local overload = overloads[unicode]
                     local parts    = { }
@@ -1982,7 +2067,8 @@ do
                         end
                     end
                     if #parts == #list then
-                        chardata.parts = parts
+                        chardata.parts            = parts
+                        chardata.partsorientation = "horizontal"
                     end
                 end
             end
@@ -2259,7 +2345,8 @@ do
     local function fix(target,original,characters,u,l)
         local data = characters[u]
         if data then
-            data.innerlocation = l.location == "right" and 2 or 1
+         -- data.innerlocation = l.location == "right" and 2 or 1
+            data.innerlocation = l.location == "right" and "right" or "left"
             data.innerxoffset  = (l.hfactor or 1) *  (data.width  or 0)
             data.inneryoffset  = (l.vfactor or 1) * ((data.height or 0) + (data.depth or 0))
         end
@@ -2636,40 +2723,119 @@ do
 
 end
 
+-- do
+--
+--     local single <const> = 0x003D
+--     local double <const> = 0x2A75
+--     local triple <const> = 0x2A76
+--
+--     function mathtweaks.addequals(target,original,parameters)
+--         local characters = target.characters
+--         local basechar   = characters[single]
+--         local width      = basechar.width
+--         local height     = basechar.height
+--         local depth      = basechar.depth
+--         local advance    = (parameters.advance or 1/20) * width
+--         local char       = charcommand[single]
+--         local left       = leftcommand[advance]
+--         characters[double] = {
+--             unicode  = double,
+--             width    = 2*width - 1*advance,
+--             height   = height,
+--             depth    = depth,
+--             commands = { char, left, char },
+--         }
+--         characters[triple] = {
+--             unicode  = triple,
+--             width    = 3*width - 2*advance,
+--             height   = height,
+--             depth    = depth,
+--             commands = { char, left, char, left, char },
+--         }
+--         if trace_tweaking then
+--             report_tweak("double %U and triple %U equals added",target,original,double,triple)
+--         end
+--     end
+--
+-- end
+
 do
 
-    local single <const> = 0x003D
-    local double <const> = 0x2A75
-    local triple <const> = 0x2A76
+    local function jointwo(characters,force,unicode,ds,u1,d12,u2)
+        if force or not characters[unicode] then
+            local c1 = characters[u1]
+            local c2 = characters[u2]
+            if c1 and c2 then
+                local w1 = c1.width
+                local w2 = c2.width
+                local width
+                if d12 == false then
+                    d12   = 0
+                    width = w2
+                elseif d12 < 0 then
+                    d12   = d12 * w2
+                    width = w2
+                else
+                    d12   = d12 * ds
+                    width = w1 + w2 - d12
+                end
+                characters[unicode] = {
+                    unicode  = unicode,
+                    width    = width,
+                    height   = max(c1.height or 0, c2.height or 0),
+                    depth    = max(c1.depth  or 0, c2.depth  or 0),
+keepvirtual = true,
+                    commands = {
+                     -- { "inspect" },
+                     -- { "trace" },
+                        slotcommand[0][u1],
+                     -- { "trace" },
+                        d12 ~= 0 and leftcommand[d12] or false,
+                        slotcommand[0][u2],
+                     -- { "trace" },
+                    },
+                }
+            end
+        end
+    end
+
+    local function jointhree(characters,force,unicode,ds,u1,d12,u2,d23,u3)
+        if force or not characters[unicode] then
+            local c1 = characters[u1]
+            local c2 = characters[u2]
+            local c3 = characters[u3]
+            if c1 and c2 and c3 then
+                local w1 = c1.width
+                local w2 = c2.width
+                local w3 = c3.width
+                d12 = d12 * ds
+                d23 = d23 * ds
+                characters[unicode] = {
+                    unicode  = unicode,
+                    width    = w1 + w2 + w3 - d12 - d23,
+                    height   = max(c1.height or 0, c2.height or 0, c3.height or 0),
+                    depth    = max(c1.depth  or 0, c2.depth  or 0, c3.depth  or 0),
+                    commands = {
+                        slotcommand[0][u1],
+                        d12 ~= 0 and leftcommand[d12] or false,
+                        slotcommand[0][u2],
+                        d23 ~= 0 and leftcommand[d23] or false,
+                        slotcommand[0][u3],
+                    }
+                }
+            end
+        end
+    end
 
     function mathtweaks.addequals(target,original,parameters)
         local characters = target.characters
-        local basechar   = characters[single]
-        local width      = basechar.width
-        local height     = basechar.height
-        local depth      = basechar.depth
-        local advance    = (parameters.advance or 1/20) * width
-        local char       = charcommand[single]
-        local left       = leftcommand[advance]
-        characters[double] = {
-            unicode  = double,
-            width    = 2*width - 1*advance,
-            height   = height,
-            depth    = depth,
---             callback = "devirtualize",
-            commands = { char, left, char },
-        }
-        characters[triple] = {
-            unicode  = triple,
-            width    = 3*width - 2*advance,
-            height   = height,
-            depth    = depth,
---             callback = "devirtualize",
-            commands = { char, left, char, left, char },
-        }
-        if trace_tweaking then
-            report_tweak("double %U and triple %U equals added",target,original,double,triple)
-        end
+        local step       = target.parameters.size/18
+        local force      = parameters.force
+force = true
+        jointwo  (characters,force,0x2254,step,0x03A,0,0x03D)         -- :=
+        jointhree(characters,force,0x2A74,step,0x03A,0,0x03A,0,0x03D) -- ::=
+        jointwo  (characters,force,0x2A75,step,0x03D,0,0x03D)         -- ==
+        jointhree(characters,force,0x2A76,step,0x03D,0,0x03D,0,0x03D) -- ===
     end
 
 end
@@ -2807,28 +2973,45 @@ do
         { 0x030A, nps("delimited right ring"),    nps("delimited ghost ring")    },
         { 0x0303, nps("delimited right tilde"),   nps("delimited ghost tilde")   },
         { 0x20DB, nps("delimited right dddot"),   nps("delimited ghost dddot")   },
+
+        { 0x231C, nps("delimited left upper corner"),  nps("delimited ghost upper corner") },
+        { 0x231D, nps("delimited right upper corner"), nps("delimited ghost upper corner") },
+        { 0x231E, nps("delimited left lower corner"),  nps("delimited ghost lower corner"), true  },
+        { 0x231F, nps("delimited right lower corner"), nps("delimited ghost lower corner"), true  },
+
+        -- If needed we can have an installer:
+
         { 0x2020, nps("delimited right dagger"),  nps("delimited ghost dagger")  },
         { 0x2021, nps("delimited right ddagger"), nps("delimited ghost ddagger") },
         { 0x2217, nps("delimited right ast"),     nps("delimited ghost ast")     },
         { 0x22C6, nps("delimited right star"),    nps("delimited ghost star")    },
 
-        { 0x231C, nps("delimited left upper corner"),   nps("delimited ghost upper corner") },
-        { 0x231D, nps("delimited right upper corner"),  nps("delimited ghost upper corner") },
-        { 0x231E, nps("delimited left lower corner"),   nps("delimited ghost lower corner"), true  },
-        { 0x231F, nps("delimited right lower corner"),  nps("delimited ghost lower corner"), true  },
+        { 0x2020, nps("delimited right dagger 1"),  nps("delimited ghost dagger 1"),  false, 1 },
+        { 0x2021, nps("delimited right ddagger 1"), nps("delimited ghost ddagger 1"), false, 1 },
+        { 0x2217, nps("delimited right ast 1"),     nps("delimited ghost ast 1"),     false, 1 },
+        { 0x22C6, nps("delimited right star 1"),    nps("delimited ghost star 1"),    false, 1 },
     }
 
     function mathtweaks.addfourier(target,original,parameters)
         local characters = target.characters
         for i=1,#list do
-            local entry       = list[i]
-            local basecode    = entry[1]
-            local fouriercode = entry[2]
-            local movecode    = entry[3]
-            local reverse     = entry[4]
-            local basechar    = characters[basecode]
+            local entry        = list[i]
+            local basecode     = entry[1]
+            local fouriercode  = entry[2]
+            local movecode     = entry[3]
+            local reverse      = entry[4]
+            local size         = entry[5] or 0
+            local basechar     = characters[basecode]
+            local compactscale = 1
+            if basechar and target.properties.compactmath and size > 0 then
+                compactscale = target.parameters[size > 1 and "scriptscriptscale" or "scriptscale"] / 1000
+                for i=1,size do
+                    basecode = basechar.smaller or basecode
+                    basechar = characters[basecode]
+                end
+            end
             if basechar then
-                local scale   = parameters.scale or 1
+                local scale   = (parameters.scale or 1) * compactscale
                 local variant = parameters.variant
                 if variant then
                     for i=1,variant do
@@ -2846,9 +3029,9 @@ do
                 local basewidth  = scale * (basechar.width  or 0)
                 local used       = baseheight/2
                 local total      = baseheight + basedepth
-if reverse then
-    used = total / 2 -- basedepth / 2
-end
+                if reverse then
+                    used = total / 2 -- basedepth / 2
+                end
                 characters[movecode] = {
                     width    = basewidth,
                     height   = used,
@@ -3124,6 +3307,45 @@ do
 
 end
 
+do
+
+    function mathtweaks.sortvariants(target,original,parameters)
+        local list = parameters.list
+        if list then
+            local characters = target.characters
+            local horizontal = parameters.orientation == "horizontal"
+            for i=1,#list do
+                local u = list[i]
+                local c = characters[u]
+                if c then
+                    local t = { }
+                    while true do
+                        local n = c.next
+                        if n then
+                            c = characters[n]
+                        end
+                        if c and not c.parts then
+                            if horizontal then
+                                t[c.width or 0] = n
+                            else
+                                t[(c.height or 0) + (c.depth or 0)] = n
+                            end
+                        else
+                            break
+                        end
+                    end
+                    local c = characters[u]
+                    for k, v in sortedhash(t) do
+                        c.next = v
+                        c = characters[v]
+                    end
+                end
+            end
+        end
+    end
+
+end
+
 do
 
     -- We started with the list that xits has in rtlm but most of them can be derived from
@@ -3251,7 +3473,11 @@ do
             end
             local next = data.next
             if next then
-                add(target,original,characters,next,"next")
+                if next == unicode then
+                    report_tweak("skipping cyclic %U (%s)",target,original,unicode,"next")
+                else
+                    add(target,original,characters,next,"next")
+                end
             end
         end
     end
@@ -3462,6 +3688,7 @@ do
                 local feature   = entry.feature
                 local thesource = entry.source
                 local thetarget = entry.target or thesource
+                local keep      = (entry.keep == true) or (parameters.keep == true)
                 if thesource and thetarget then
                     local sourcerange = type(thesource) == "table" and thesource or blocks[thesource] -- .gaps
                     local targetrange = type(thetarget) == "table" and thetarget or blocks[thetarget] -- .gaps
@@ -3504,13 +3731,17 @@ do
                                     local sourceunicode = mathgaps[s] or s
                                     if chars[sourceunicode] then
                                         local targetunicode = mathgaps[t] or t
-                                        if feature then
-                                            sourceunicode = getsubstitution(dropin,sourceunicode,feature,true,"math","dflt") or sourceunicode
+                                        if keep and characters[targetunicode] then
+                                            -- okay
+                                        else
+                                            if feature then
+                                                sourceunicode = getsubstitution(dropin,sourceunicode,feature,true,"math","dflt") or sourceunicode
+                                            end
+--                                          if trace_tweaking then
+--                                              report_tweak("copying %s %U from file %a to %s %U",target,original,thesource,sourceunicode,filename,thetarget,targetunicode)
+--                                          end
+                                            characters[targetunicode] = copiedglyph(target,characters,chars,sourceunicode,index)
                                         end
---                                         if trace_tweaking then
---                                             report_tweak("copying %s %U from file %a to %s %U",target,original,thesource,sourceunicode,filename,thetarget,targetunicode)
---                                         end
-                                        characters[targetunicode] = copiedglyph(target,characters,chars,sourceunicode,index)
                                     end
                                 end
                                 --
diff --git a/tex/context/base/mkxl/math-def.mkxl b/tex/context/base/mkxl/math-def.mkxl
index a423a6a79..b2b8d776f 100644
--- a/tex/context/base/mkxl/math-def.mkxl
+++ b/tex/context/base/mkxl/math-def.mkxl
@@ -139,36 +139,58 @@
 %D \formula {A \simcoloncolon     B}
 %D \stoplines
 %D
-%D The next macros take care of the space between the colon and the
-%D relation symbol.
+%D The next macros take care of the space between the colon and the relation symbol,
+%D but they are kind of weird and not in \UNICODE. Either we define them virtual or
+%D we just keep these as bonus.
 
 \pushoverloadmode
 
-\definemathcommand [colonsep]                       {\mkern-1.2mu}
-\definemathcommand [doublecolonsep]                 {\mkern-0.9mu}
-
-\definemathcommand [centercolon]      [\s!relation] {\mathstylevcenteredhbox\colon}
-\definemathcommand [colonminus]       [\s!relation] {\centercolon\colonsep\mathrel{-}}
-%definemathcommand [minuscolon]       [\s!relation] {\mathrel{-}\colonsep\centercolon} % native char
-%definemathcommand [colonequals]      [\s!relation] {\centercolon\colonsep=}           % native char
-%definemathcommand [equalscolon]      [\s!relation] {=\centercolon\colonsep}           % native char
-\definemathcommand [colonapprox]      [\s!relation] {\centercolon\colonsep\approx}
-\definemathcommand [approxcolon]      [\s!relation] {\approx\centercolon\colonsep}
-\definemathcommand [colonsim]         [\s!relation] {\centercolon\colonsep\sim}
-\definemathcommand [simcolon]         [\s!relation] {\sim\centercolon\colonsep}
-
-\definemathcommand [coloncolon]       [\s!relation] {\centercolon\doublecolonsep\centercolon}
-\definemathcommand [coloncolonminus]  [\s!relation] {\coloncolon\colonsep\mathrel{-}}
-\definemathcommand [minuscoloncolon]  [\s!relation] {\mathrel{-}\colonsep\coloncolon}
-\definemathcommand [coloncolonequals] [\s!relation] {\coloncolon\colonsep=}            % native char
-\definemathcommand [equalscoloncolon] [\s!relation] {=\coloncolon\colonsep}
-\definemathcommand [coloncolonapprox] [\s!relation] {\coloncolon\colonsep\approx}
-\definemathcommand [approxcoloncolon] [\s!relation] {\approx\coloncolon\colonsep}
-\definemathcommand [coloncolonsim]    [\s!relation] {\coloncolon\colonsep\sim}
-\definemathcommand [simcoloncolon]    [\s!relation] {\sim\coloncolon\colonsep}
+\protected\def\math_relation_atom_ordinary{\mathatom \s!class \mathrelationcode \s!all \mathordcode}
+
+\definemathcommand [centercolon]      {\math_relation_atom_ordinary{\colon}}
+\definemathcommand [colonminus]       {\math_relation_atom_ordinary{\colon\minus}}
+\definemathcommand [colonapprox]      {\math_relation_atom_ordinary{\colon\approx}}
+\definemathcommand [approxcolon]      {\math_relation_atom_ordinary{\approx\colon}}
+\definemathcommand [colonsim]         {\math_relation_atom_ordinary{\colon\sim}}
+\definemathcommand [simcolon]         {\math_relation_atom_ordinary{\sim\colon}}
+
+\definemathcommand [coloncolon]       {\math_relation_atom_ordinary{\colon\colon}}
+\definemathcommand [coloncolonminus]  {\math_relation_atom_ordinary{\colon\colon\minus}}
+\definemathcommand [minuscoloncolon]  {\math_relation_atom_ordinary{\minus\colon\colon}}
+\definemathcommand [coloncolonequals] {\math_relation_atom_ordinary{\colon\colon\eq}} % native char
+\definemathcommand [equalscoloncolon] {\math_relation_atom_ordinary{\eq\colon\colon}}
+\definemathcommand [coloncolonapprox] {\math_relation_atom_ordinary{\colon\colon\approx}}
+\definemathcommand [approxcoloncolon] {\math_relation_atom_ordinary{\approx\colon\colon}}
+\definemathcommand [coloncolonsim]    {\math_relation_atom_ordinary{\colon\colon\sim}}
+\definemathcommand [simcoloncolon]    {\math_relation_atom_ordinary{\sim\colon\colon}}
+
+% \definemathcommand [manycolons] [relation] [ordinary] {\colon\colon\colon\colon\colon\colon\colon}
 
 \popoverloadmode
 
+%D \macros
+%D   {amedian}
+%D
+%D Something language specific, the arithmic median:
+%D
+%D \starttyping
+%D                   \im {x + \amedian {x - a} + x}
+%D \mainlanguage[cs] \im {x + \amedian {x - a} + x}
+%D \stoptyping
+
+\defcsname \s!en:amedian\endcsname#1{\widebar  {#1}}
+\defcsname \s!cs:amedian\endcsname#1{\widetilde{#1}}
+\defcsname \s!sk:amedian\endcsname#1{\widetilde{#1}}
+
+\permanent\protected\def\amedian
+  {\csname
+     \ifcsname\currentmainlanguage:amedian\endcsname
+       \currentmainlanguage\else
+       \s!en
+     \fi
+     :amedian%
+   \endcsname}
+
 % \appendtoks
 %     \def\over{\primitive\over}%
 % \to \everymathematics
diff --git a/tex/context/base/mkxl/math-dld.mklx b/tex/context/base/mkxl/math-dld.mklx
index dcbb17c5e..281ccedb2 100644
--- a/tex/context/base/mkxl/math-dld.mklx
+++ b/tex/context/base/mkxl/math-dld.mklx
@@ -28,7 +28,8 @@
 \installcommandhandler \??mathdelimited {mathdelimited} \??mathdelimited
 
 \setupmathdelimited
-  [\c!alternative=\v!normal,
+  [\c!define=\v!yes,
+   \c!alternative=\v!normal,
    \c!mpoffset=.25\exheight,
    \c!topoffset=\zeropoint,
    \c!bottomoffset=\zeropoint,
@@ -43,7 +44,7 @@
    \c!rightmargin=\zeropoint]
 
 \appendtoks
-    \ifcstok{\mathdelimitedparameter\c!rightmargin}\v!no\else
+    \ifcstok{\mathdelimitedparameter\c!define}\v!yes
       \frozen\protected\instance\edefcsname\currentmathdelimited\endcsname{\math_delimited_handle{\currentmathdelimited}}
     \fi
 \to \everydefinemathdelimited
@@ -70,7 +71,7 @@
      \s!depth \dimexpr\mathdelimitedparameter\c!depth+\mathdelimitedparameter\c!bottomoffset\relax
      \s!source\numexpr\namedboxanchor{\mathdelimitedparameter\c!source}\relax
      \s!style \normalmathstyle
-     \s!size  \numexpr\namedboxanchor{\mathdelimitedparameter\c!size}\relax
+     \s!size  \numexpr\mathdelimitedparameter\c!size\relax
      \zerocount \mathdelimitedparameter\c!left
      \zerocount \mathdelimitedparameter\c!right
   \relax}
@@ -88,7 +89,6 @@
      {\popcolor#body}%
    \fi}
 
-
 %integerdef\delimitedrightgraveuc    \privatecharactercode{delimited right grave}
 \integerdef\delimitedrightddotuc     \privatecharactercode{delimited right ddot}
 \integerdef\delimitedrightbaruc      \privatecharactercode{delimited right bar}
@@ -100,10 +100,6 @@
 \integerdef\delimitedrightringuc     \privatecharactercode{delimited right ring}
 \integerdef\delimitedrighttildeuc    \privatecharactercode{delimited right tilde}
 \integerdef\delimitedrightdddotuc    \privatecharactercode{delimited right dddot}
-\integerdef\delimitedrightdaggeruc   \privatecharactercode{delimited right dagger}
-\integerdef\delimitedrightddaggeruc  \privatecharactercode{delimited right ddagger}
-\integerdef\delimitedrightastuc      \privatecharactercode{delimited right ast}
-\integerdef\delimitedrightstaruc     \privatecharactercode{delimited right star}
 
 % \integerdef\delimitedrighthatuc   \privatecharactercode{delimited right hat}
 % \integerdef\delimitedrighttildeuc \privatecharactercode{delimited right tilde}
@@ -114,33 +110,38 @@
 
 \definemathdelimited
   [marked]
-  [\c!command=\v!no,
+  [\c!define=\v!no,
    \c!topoffset=.2\exheight]
 
 \definemathdelimited
   [ddotmarked]
   [marked]
-  [\c!right=\delimitedrightddotuc]
+  [\c!define=\v!yes,
+   \c!right=\delimitedrightddotuc]
 
 \definemathdelimited
   [barmarked]
   [marked]
-  [\c!right=\delimitedrightbaruc]
+  [\c!define=\v!yes,
+   \c!right=\delimitedrightbaruc]
 
 \definemathdelimited
   [hatmarked]
   [marked]
-  [\c!right=\delimitedrighthatuc]
+  [\c!define=\v!yes,
+   \c!right=\delimitedrighthatuc]
 
 \definemathdelimited
   [checkmarked]
   [marked]
-  [\c!right=\delimitedrightcheckuc]
+  [\c!define=\v!yes,
+   \c!right=\delimitedrightcheckuc]
 
 \definemathdelimited
   [brevemarked]
   [marked]
-  [\c!right=\delimitedrightbreveuc]
+  [\c!define=\v!yes,
+   \c!right=\delimitedrightbreveuc]
 
 \definemathdelimited
   [dotmarked]
@@ -150,44 +151,78 @@
 \definemathdelimited
   [ringmarked]
   [marked]
-  [\c!right=\delimitedrightringuc]
+  [\c!define=\v!yes,
+   \c!right=\delimitedrightringuc]
 
 \definemathdelimited
   [tildemarked]
   [marked]
-  [\c!right=\delimitedrighttildeuc]
+  [\c!define=\v!yes,
+   \c!right=\delimitedrighttildeuc]
 
 \definemathdelimited
   [dddotmarked]
   [marked]
-  [\c!right=\delimitedrightdddotuc]
+  [\c!define=\v!yes,
+   \c!right=\delimitedrightdddotuc]
 
 % The following ones are
 % not really belonging here,
 % but convenient
 
+% If there are more needed we can have:
+%
+% \c!ight=\privatecharactercode{delimited right dagger \mathdelimitedparameter\c!size}
+%
+% or even:
+%
+% \def\privatedelimitedcode#1{\privatecharactercode{delimited #1 \mathdelimitedparameter\c!size}}
+%
+% \c!right=\privatedelimitedcode{right dagger}
+%
+% with some glyph installer btu let's for now save some bytes in the format.
+
+\integerdef\delimitedrightdaggeruc        \privatecharactercode{delimited right dagger}
+\integerdef\delimitedrightddaggeruc       \privatecharactercode{delimited right ddagger}
+\integerdef\delimitedrightastuc           \privatecharactercode{delimited right ast}
+\integerdef\delimitedrightstaruc          \privatecharactercode{delimited right star}
+
+\integerdef\delimitedscriptrightdaggeruc  \privatecharactercode{delimited right dagger 1}
+\integerdef\delimitedscriptrightddaggeruc \privatecharactercode{delimited right ddagger 1}
+\integerdef\delimitedscriptrightastuc     \privatecharactercode{delimited right ast 1}
+\integerdef\delimitedscriptrightstaruc    \privatecharactercode{delimited right star 1}
+
 \definemathdelimited
   [daggermarked]
   [marked]
-  [\c!size=1,
-   \c!right=\delimitedrightdaggeruc]
+  [\c!define=\v!yes,
+   \c!size=1,
+   \c!right=\delimitedscriptrightdaggeruc]
+  %\c!right=\privatedelimitedcode{right dagger}]
 
 \definemathdelimited
   [ddaggermarked]
   [marked]
-  [\c!size=1,
-   \c!right=\delimitedrightddaggeruc]
+  [\c!define=\v!yes,
+   \c!size=1,
+   \c!right=\delimitedscriptrightddaggeruc]
+  %\c!right=\privatedelimitedcode{right ddagger}]
 
 \definemathdelimited
   [astmarked]
-  [\c!size=1,
-   \c!right=\delimitedrightastuc]
+  [marked]
+  [\c!define=\v!yes,
+   \c!size=1,
+   \c!right=\delimitedscriptrightastuc]
+  %\c!right=\privatedelimitedcode{right ast}]
 
 \definemathdelimited
   [starmarked]
   [marked]
-  [\c!size=1,
-   \c!right=\delimitedrightstaruc]
+  [\c!define=\v!yes,
+   \c!size=1,
+   \c!right=\delimitedscriptrightstaruc]
+  %\c!right=\privatedelimitedcode{right star}]
 
 % More contextual
 
diff --git a/tex/context/base/mkxl/math-fen.mkxl b/tex/context/base/mkxl/math-fen.mkxl
index 1656f4b4a..a69cafb97 100644
--- a/tex/context/base/mkxl/math-fen.mkxl
+++ b/tex/context/base/mkxl/math-fen.mkxl
@@ -15,7 +15,7 @@
 
 \unprotect
 
-% \definemathfence [fancybracket] [bracket] [command=yes,color=blue]
+% \definemathfence [fancybracket] [bracket] [define=yes,color=blue]
 %
 % test $|x|$ test \par
 % test $||x||$ test (okay) \par
@@ -42,7 +42,7 @@
    \c!middle=,
    \c!mathstyle=,
    \c!color=,
-   \c!command=,
+   \c!define=, % was \c!command
    \c!mathclass=,
    \c!leftclass=\mathopencode,
    \c!rightclass=\mathclosecode,
@@ -59,9 +59,7 @@
    \c!factor=\v!auto]
 
 \appendtoks
-    \edef\p_command{\mathfenceparameter\c!command}%
-    \ifx\p_command\v!yes
-        % \instance
+    \ifcstok{\mathfenceparameter\c!define}\v!yes
         \protected\edefcsname\currentmathfence\endcsname{\math_fenced_fenced{\currentmathfence}}%
     \fi
 \to \everydefinemathfence
@@ -338,6 +336,19 @@
 
 % \definemathfence [tupdownarrows] [text] [\c!left="2191,\c!right="2193]
 
+\def\math_fenced_check#1%
+  {\iftok{\mathfenceparameter#1}\emptytoks\letmathfenceparameter#1\v!none\fi}
+
+\appendtoks
+    \math_fenced_check\c!left
+    \math_fenced_check\c!right
+\to \everysetupmathfence
+
+\appendtoks
+    \math_fenced_check\c!left
+    \math_fenced_check\c!right
+\to \everydefinemathfence
+
 \protected\def\math_fenced_horizontal_common#1#2#3#4% \Uwhatever class symbol source
   {\c_math_fenced_class\math_class_by_parameter\mathfenceparameter#2\relax
    \edef\p_fence{#3}%
@@ -387,7 +398,7 @@
 \setupmathfence
   [\v!text]
   [\c!text=\v!yes,
-   \c!command=\v!yes,
+   \c!define=\v!yes,
    \c!distance=.125\emwidth]
 
 \tolerant\protected\def\math_fenced_vertical#1#*[#2]%
@@ -653,10 +664,23 @@
 \immutable\protected\def\Lopenbracketmirrored {\math_fenced_fenced_stop {mirroredopenbracket}}  \immutable\protected\def\Ropenbracketmirrored {\math_fenced_fenced_start{mirroredopenbracket}}
 \immutable\protected\def\Lnothingmirrored     {\math_fenced_fenced_stop {mirrorednothing}}      \immutable\protected\def\Rnothingmirrored     {\math_fenced_fenced_start{mirrorednothing}}
 
-\definemathfence [interval]                     [\c!left="2997,\c!right="2998]
-\definemathfence [openinterval]      [interval] [\c!left="2998,\c!right="2998]
-\definemathfence [leftopeninterval]  [interval] [\c!left="2997,\c!right="2997]
-\definemathfence [rightopeninterval] [interval] [\c!left="2998,\c!right="2998]
+% These tortoise chars almost only exist in stix (and ar not commonly used)
+
+% \definemathfence [interval]                     [\c!left="2997,\c!right="2998]
+% \definemathfence [openinterval]      [interval] [\c!left="2998,\c!right="2998]
+% \definemathfence [leftopeninterval]  [interval] [\c!left="2997,\c!right="2997]
+% \definemathfence [rightopeninterval] [interval] [\c!left="2998,\c!right="2998]
+
+% Different intervals. The variants are the ones suggested by Bourbaki.
+
+\definemathfence [interval]                        [\c!left="005B,\c!right="005D]
+\definemathfence [openinterval]         [interval] [\c!left="0028,\c!right="0029]
+\definemathfence [closedinterval]       [interval] [\c!left="005B,\c!right="005D]
+\definemathfence [leftopeninterval]     [interval] [\c!left="0028,\c!right="005D]
+\definemathfence [rightopeninterval]    [interval] [\c!left="005B,\c!right="0029]
+\definemathfence [varopeninterval]      [interval] [\c!left="005D,\c!right="005B]
+\definemathfence [varleftopeninterval]  [interval] [\c!left="005D,\c!right="005D]
+\definemathfence [varrightopeninterval] [interval] [\c!left="005B,\c!right="005B]
 
 \immutable\protected\def\Linterval   {\math_fenced_fenced_start{interval}}
 \immutable\protected\def\Lointerval  {\math_fenced_fenced_start{openinterval}}
@@ -1004,7 +1028,7 @@
 %     \vrule height 3cm depth 3cm
 % \right\rintegral
 
-%definemathfence [fancybracket] [bracket] [command=yes,color=red]
+%definemathfence [fancybracket] [bracket] [define=yes,color=red]
 
 %D The nested fences recovery code is needed for mathml and the original
 %D code can still be found in the mkiv file.
@@ -1211,10 +1235,10 @@
 % $x + \tdownuparrows{left}{right} + x$
 % $x + \tupanddownarrows[color=red,leftcolor=green,rightcolor=blue]{left}{right} + x$
 
-\definemathfence [tupanddownarrows] [\v!text] [\c!left="2191,\c!right="2193]
-\definemathfence [tupdownarrows]    [\v!text] [\c!left="21C5,\c!right=0]
-\definemathfence [tdownuparrows]    [\v!text] [\c!middle="21F5]
-\definemathfence [tuparrow]         [\v!text] [\c!middle="2191]
-\definemathfence [tdownarrow]       [\v!text] [\c!middle="2193]
+\definemathfence [tupanddownarrows][\v!text][\c!left="2191,\c!right="2193]
+\definemathfence [tupdownarrows]   [\v!text][\c!left="21C5,\c!right=0]
+\definemathfence [tdownuparrows]   [\v!text][\c!middle="21F5]
+\definemathfence [tuparrow]        [\v!text][\c!middle="2191]
+\definemathfence [tdownarrow]      [\v!text][\c!middle="2193]
 
 \protect
diff --git a/tex/context/base/mkxl/math-ini.mkxl b/tex/context/base/mkxl/math-ini.mkxl
index 7d0c8ef81..8c0615eb6 100644
--- a/tex/context/base/mkxl/math-ini.mkxl
+++ b/tex/context/base/mkxl/math-ini.mkxl
@@ -1732,6 +1732,9 @@
 \permanent\protected\def\mathcodecommand#1%
   {\mathatom \s!class \mathcodechecked{#1}}
 
+\permanent\protected\def\mathcodeallcommand#1#2%
+  {\mathatom \s!class \mathcodechecked{#1} \s!all \mathcodechecked{#2}}
+
 \def\math_class_by_parameter    #1#2{\normalexpanded{\noexpand\mathcodechecked{#1#2}}}
 \def\math_atom_by_parameter       #1{\normalexpanded{\noexpand\math_atom_by_parameter_indeed{#1\c!mathclass}}}
 \def\math_atom_by_parameter_indeed#1{\mathatom \s!class \mathcodechecked{#1}}
@@ -1750,15 +1753,14 @@
 
 \installcorenamespace{mathcommand}
 
-% todo: define these commands as frozen!
-
 \permanent\tolerant\protected\def\definemathcommand[#1]#*[#2]#*[#3]#:#*#4% command class args meaning
   {\ifparameter#3\or
-     \edef\scratchstringone{#3}% make this one m_arguments
-     \ifx\scratchstringone\v!one
+     \ifcstok{#3}\v!one
        \frozen\protected\defcsname\??mathcommand#1\endcsname##1{\mathcodecommand{#2}{#4{##1}}}%
-     \orelse\ifx\scratchstringone\v!two
+     \orelse\ifcstok{#3}\v!two
        \frozen\protected\defcsname\??mathcommand#1\endcsname##1##2{\mathcodecommand{#2}{#4{##1}{##2}}}%
+     \orelse\ifchknum\mathcodechecked{#3}\or
+       \frozen\protected\defcsname\??mathcommand#1\endcsname{\mathcodeallcommand{#2}{#3}{#4}}%
      \else
        \frozen\protected\defcsname\??mathcommand#1\endcsname{\mathcodecommand{#2}{#4}}%
      \fi
diff --git a/tex/context/base/mkxl/math-rad.mklx b/tex/context/base/mkxl/math-rad.mklx
index 703481c08..863bb2128 100644
--- a/tex/context/base/mkxl/math-rad.mklx
+++ b/tex/context/base/mkxl/math-rad.mklx
@@ -195,8 +195,8 @@
      \zerocount
    \fi
    \Urooted
-     \s!height\dimexpr\mathradicalparameter\c!height\relax
-     \s!depth \dimexpr\mathradicalparameter\c!depth\relax
+     \s!height\dimexpr\ifcstok{\mathradicalparameter\c!height}\v!none\scaledpoint\else\mathradicalparameter\c!height\fi\relax
+     \s!depth \dimexpr\ifcstok{\mathradicalparameter\c!depth }\v!none\scaledpoint\else\mathradicalparameter\c!depth \fi\relax
      \s!source\numexpr\namedboxanchor{\mathradicalparameter\c!source}\relax
      \s!style \normalmathstyle
      \ifzeronum\scratchcounter\else
diff --git a/tex/context/base/mkxl/math-spa.lmt b/tex/context/base/mkxl/math-spa.lmt
index 9875f8b2d..d2927ff58 100644
--- a/tex/context/base/mkxl/math-spa.lmt
+++ b/tex/context/base/mkxl/math-spa.lmt
@@ -47,6 +47,9 @@ local nextlist          = nuts.traversers.list
 local nextboundary      = nuts.traversers.boundary
 local nextnode          = nuts.traversers.node
 
+local insertafter       = nuts.insertafter
+local newkern           = nuts.pool.kern
+
 local texsetdimen       = tex.setdimen
 local texgetdimen       = tex.getdimen
 local texsetcount       = tex.setcount
@@ -83,42 +86,6 @@ local function moveon(s)
     return s
 end
 
--- stages[1] = function(specification,stage)
---     local box      = getbox(specification.box)
---     local head     = getlist(box)
---     local align    = specification.alignstate
---     local distance = specification.distance
---     for s in nextboundary, head do
---         local data = getdata(s)
---         if data == boundary then
---             -- todo: skip over ghost, maybe penalty, maybe glues all in one loop
---             s = moveon(s)
---             for n, id, subtype in nextnode, getnext(s) do
---                 s = n
---                 if id == kern_code then
---                     -- move on (s_2 case)
---                 elseif id == glue_code then
---                     -- move on
---                 elseif id == penalty_code then
---                     -- move on (untested)
---                 elseif id == hlist_code and subtype == ghost_code then
---                     -- move on
---                 else
---                     break
---                 end
---             end
---             distance = distance + getdimensions(head,s)
---             break
---         end
---     end
---     texsetdimen("global",d_strc_math_indent,distance)
---     if align == 2 then
---         for n in nextglue, head do
---             setglue(n,getwidth(n),0,0,0,0)
---         end
---     end
--- end
-
 -- -- todo: skip over ghost, maybe penalty, maybe glues all in one loop
 --
 -- local n = getnext(s)
@@ -175,12 +142,11 @@ stages[1] = function(specification,stage)
         local f = found[1]
         local delta = f[2] - max
         if delta ~= 0 then
-            nuts.insertafter(head,moveon(head),nuts.pool.kern(-delta))
+            insertafter(head,moveon(head),newkern(-delta))
         end
         for i=2,#found do
             local f = found[i]
-            local delta = f[2] - max
-            nuts.insertafter(head,moveon(f[3]),nuts.pool.kern(-f[2])) -- check head
+            insertafter(head,moveon(f[3]),newkern(-f[2])) -- check head
         end
     end
     texsetdimen("global",d_strc_math_indent,max)
diff --git a/tex/context/base/mkxl/math-stc.mklx b/tex/context/base/mkxl/math-stc.mklx
index 5922fb116..fdad71978 100644
--- a/tex/context/base/mkxl/math-stc.mklx
+++ b/tex/context/base/mkxl/math-stc.mklx
@@ -78,47 +78,35 @@
 % At some point we can consider to use the more natural \LUAMETATEX\ features but the
 % problem is that we lack proper support in fonts and we also have less control.
 
-\installcorenamespace {mathextensiblefallbacks}
+%installcorenamespace {mathextensiblefallbacks}
 
-% currently no italic correction ... problem is that we don't know yet if we have an italic
-% below so we we need to postpone
-
-% \def\math_stackers_fallback
-%   {\hbox to \scratchwidth{\csname\??mathextensiblefallbacks\ifcsname\??mathextensiblefallbacks\number\scratchunicode\endcsname\number\scratchunicode\fi\endcsname}}
-%  %{\csname\??mathextensiblefallbacks\ifcsname\??mathextensiblefallbacks\number\scratchunicode\endcsname\number\scratchunicode\fi\endcsname }
+% In math mode we no longer fallback, simply because only a few fonts implement
+% extensible using minus and equal signs. So either we provide a tweaked one or we
+% simply ignore the lack. Better choose a font that matches expectations that some
+% fragile imperfect hackery.
 
 \def\math_stackers_fallback
   {\mathstylehbox to \scratchwidth{\usemathstackerscolorparameter\c!color
      \hss
      \hskip\mathstackersparameter\c!topoffset\relax % for manual italic correction
-     \ifcsname\??mathextensiblefallbacks\number\scratchunicode\endcsname
-       \lastnamedcs
-     \else
+   % \ifcsname\??mathextensiblefallbacks\number\scratchunicode\endcsname
+   %   \lastnamedcs
+   % \else
        \Umathchar\zerocount\zerocount\scratchunicode
-     \fi
+   % \fi
      \hss}}
 
-% \def\math_stackers_regular
-%   {\mathstylehbox{\usemathstackerscolorparameter\c!color
-%      \hskip\d_math_stackers_offset_l
-%      \Umathaccent\zerocount\zerocount\scratchunicode
-%        {\hskip\dimexpr\scratchwidth-\d_math_stackers_offset_l-\d_math_stackers_offset_r}%
-%      \hskip\d_math_stackers_offset_r
-%    }}
-
-% \def\math_stackers_stretch % we don't have that one yet
-%   {\mathstylehbox{\usemathstackerscolorparameter\c!color
-%      \hskip\d_math_stackers_offset_l
-%      \Umathaccent\zerocount\zerocount\scratchunicode
-%        {\hskip\dimexpr\hsize-\d_math_stackers_offset_l-\d_math_stackers_offset_r}%
-%      \hskip\d_math_stackers_offset_r
-%    }}
-
 \def\math_stackers_regular
   {\mathstylehbox{\usemathstackerscolorparameter\c!color
      \hskip\d_math_stackers_offset_l
      \Uhextensible
        middle
+       \ifcstok{\mathstackersparameter\c!stretch}\v!yes
+         stretch
+       \fi
+       \ifcstok{\mathstackersparameter\c!shrink}\v!yes
+         shrink
+       \fi
        width \dimexpr\scratchwidth-\d_math_stackers_offset_l-\d_math_stackers_offset_r\relax
        \zerocount\scratchunicode
      \relax
@@ -130,18 +118,8 @@
 % $\Umathaccent   0 0 "2190{x}$ \par $\Umathaccent   0 0 "27F8{x}$\par
 % $\Udelimiterunder 0 "2190{x}$ \par $\Udelimiterunder 0 "27F8{x}$\par
 
-\defcsname\??mathextensiblefallbacks\endcsname
-  {\hpack{\vrule\s!width\scratchwidth\s!height.1\mathexheight\s!depth\zeropoint}}
-
-% \def\math_stackers_with_fallback#codepoint%
-%   {\begingroup
-%    \scratchunicode#codepoint\relax
-%    \ifcase\mathextensiblecode\fam\scratchunicode\relax
-%      \math_stackers_fallback
-%    \else
-%      \math_stackers_stretch
-%    \fi
-%    \endgroup}
+% \defcsname\??mathextensiblefallbacks\endcsname
+%   {\hpack{\vrule\s!width\scratchwidth\s!height.1\mathexheight\s!depth\zeropoint}}
 
 %D We don't really need this because we can assume that fonts have the right
 %D extensibles. If needed I will make a general virtual extender for \OPENTYPE\
@@ -337,6 +315,28 @@
      \scratchbottomoffset\zeropoint
    \fi}
 
+\def\math_stackers_get_max_width
+  {\ifdim\wd\scratchboxone>\scratchwidth
+     \scratchwidth\wd\scratchboxone
+   \fi
+   \ifdim\wd\scratchboxtwo>\scratchwidth
+     \scratchwidth\wd\scratchboxtwo
+   \fi
+   \ifdim\wd\scratchboxthree>\scratchwidth
+     \scratchwidth\wd\scratchboxthree
+   \fi}
+
+\def\math_stackers_set_max_width
+  {\ifdim\wd\scratchboxone<\scratchwidth
+     \setbox\scratchboxone\hpack to \scratchwidth{\hss\unhbox\scratchboxone\hss}% unhboxing makes leaders work
+   \fi
+   \ifdim\wd\scratchboxtwo<\scratchwidth
+     \setbox\scratchboxtwo\hpack to \scratchwidth{\hss\unhbox\scratchboxtwo\hss}%
+   \fi
+   \ifdim\wd\scratchboxthree<\scratchwidth
+     \setbox\scratchboxthree\hpack to \scratchwidth{\hss\unhbox\scratchboxthree\hss}%
+   \fi}
+
 \protected\def\math_stackers_triplet#method#category#codepoint#toptext#bottomtext%
   {\begingroup
    \edef\currentmathstackers{#category}%
@@ -395,19 +395,7 @@
         \else
           \setmathtextbox\scratchboxthree\hbox{\math_stackers_middletext}%
         \fi
-        \scratchwidth\wd
-          \ifdim\wd\scratchboxone>\wd\scratchboxtwo
-            \ifdim\wd\scratchboxone>\wd\scratchboxthree
-              \scratchboxone
-            \else
-              \scratchboxthree
-            \fi
-          \orelse\ifdim\wd\scratchboxtwo>\wd\scratchboxthree
-            \scratchboxtwo
-          \else
-            \scratchboxthree
-          \fi
-        \relax
+        \math_stackers_get_max_width
       \fi
       %
       \scratchdimen\mathstackersparameter\c!minwidth\relax
@@ -421,19 +409,11 @@
         \setbox\scratchboxthree\csname\??mathstackersalternative\p_alternative\endcsname
         \dostoptagged
       \fi
-      \ifdim\wd\scratchboxthree>\scratchwidth
-        \scratchwidth\wd\scratchboxthree
-      \fi
+%       \ifdim\wd\scratchboxthree>\scratchwidth
+%         \scratchwidth\wd\scratchboxthree
+%       \fi
       %
-      \ifdim\wd\scratchboxone<\scratchwidth
-        \setbox\scratchboxone\hpack to \scratchwidth{\hss\unhbox\scratchboxone\hss}% unhboxing makes leaders work
-      \fi
-      \ifdim\wd\scratchboxtwo<\scratchwidth
-        \setbox\scratchboxtwo\hpack to \scratchwidth{\hss\unhbox\scratchboxtwo\hss}%
-      \fi
-      \ifdim\wd\scratchboxthree<\scratchwidth
-        \setbox\scratchboxthree\hpack to \scratchwidth{\hss\unhbox\scratchboxthree\hss}%
-      \fi
+      \math_stackers_set_max_width
       %
       \ifcsname\??mathstackerslocation\p_location\endcsname
         \ifcase\csname\??mathstackerslocation\p_location\endcsname\relax
@@ -458,7 +438,6 @@
       \ifzeropt\scratchdistance\else
         \setbox\scratchboxthree\hpack{\lower\scratchdistance\box\scratchboxthree}%
       \fi
-      %
       \math_stackers_normalize_three
       % analysis
       \ifdim\htdp\scratchboxtwo>\zeropoint
@@ -625,6 +604,8 @@
       \fi
       %
       \math_stackers_normalize_three
+      \math_stackers_get_max_width
+      \math_stackers_set_max_width
       % analysis
       \ifcase\c_math_stackers_bottom
         \ifcase\c_math_stackers_top
@@ -654,7 +635,7 @@
             \math_stackers_bottom\bgroup
               \lower\dimexpr
                  \scratchdepth
-                +\ht\scratchboxtwo
+                +\ht\ifcase\c_math_stackers_top\scratchboxtwo\else\scratchboxone\fi
                 +\mathstackersparameter\c!distance % was \c!voffset
               \relax
               \ifcase\c_math_stackers_top
@@ -973,6 +954,7 @@
   [\v!both]
   [\v!mathematics]
   [\c!location=\v!top, % ?
+   \c!mathclass=\s!accent,  % check chemistry
    \c!strut=\v!no,
    \c!middlecommand=\mathematics,
    \c!hoffset=\zeropoint]
@@ -989,7 +971,10 @@
   [\v!vfenced]
   [\v!both]
   [\c!mathclass=\s!ordinary,
-   \c!mathlimits=\v!yes]
+   \c!mathlimits=\v!yes,
+   % only these arrows make sense
+   \c!stretch=\v!yes,
+   \c!shrink=\v!yes]
 
 % these are needed for mathml:
 
@@ -1085,10 +1070,10 @@
 \definemathextensible [\v!mathematics] [mequal]              ["003D]
 \definemathextensible [\v!mathematics] [mleftarrow]          ["2190] % ["27F5]
 \definemathextensible [\v!mathematics] [mrightarrow]         ["2192] % ["27F6]
-\definemathextensible [\v!mathematics] [mleftrightarrow]     ["27F7]
-\definemathextensible [\v!mathematics] [mLeftarrow]          ["27F8]
-\definemathextensible [\v!mathematics] [mRightarrow]         ["27F9]
-\definemathextensible [\v!mathematics] [mLeftrightarrow]     ["27FA]
+\definemathextensible [\v!mathematics] [mleftrightarrow]     ["2194]
+\definemathextensible [\v!mathematics] [mLeftarrow]          ["21D0]
+\definemathextensible [\v!mathematics] [mRightarrow]         ["21D2]
+\definemathextensible [\v!mathematics] [mLeftrightarrow]     ["21D4]
 \definemathextensible [\v!mathematics] [mtwoheadleftarrow]   ["219E]
 \definemathextensible [\v!mathematics] [mtwoheadrightarrow]  ["21A0]
 \definemathextensible [\v!mathematics] [mmapsto]             ["21A6]
@@ -1109,12 +1094,13 @@
 \definemathextensible [\v!text] [tmapsto]             ["21A6]
 \definemathextensible [\v!text] [tleftarrow]          ["2190] % ["27F5]
 \definemathextensible [\v!text] [trightarrow]         ["2192] % ["27F6]
-\definemathextensible [\v!text] [tleftrightarrow]     ["27F7]
-\definemathextensible [\v!text] [tLeftarrow]          ["27F8]
-\definemathextensible [\v!text] [tRightarrow]         ["27F9]
-\definemathextensible [\v!text] [tLeftrightarrow]     ["27FA]
+\definemathextensible [\v!text] [tleftrightarrow]     ["2194]
+\definemathextensible [\v!text] [tLeftarrow]          ["21D0]
+\definemathextensible [\v!text] [tRightarrow]         ["21D2]
+\definemathextensible [\v!text] [tLeftrightarrow]     ["21D4]
 \definemathextensible [\v!text] [ttwoheadleftarrow]   ["219E]
 \definemathextensible [\v!text] [ttwoheadrightarrow]  ["21A0]
+\definemathextensible [\v!text] [tmapsto]             ["21A6]
 \definemathextensible [\v!text] [thookleftarrow]      ["21A9]
 \definemathextensible [\v!text] [thookrightarrow]     ["21AA]
 \definemathextensible [\v!text] [tleftharpoondown]    ["21BD]
@@ -1127,25 +1113,47 @@
 \definemathextensible [\v!text] [trightleftharpoons]  ["21CC]
 \definemathextensible [\v!text] [ttriplerel]          ["2261]
 
-\definemathoverextensible [\v!top] [overleftarrow]         ["2190] % ["27F5]
-\definemathoverextensible [\v!top] [overrightarrow]        ["2192] % ["27F6]
-\definemathoverextensible [\v!top] [overleftrightarrow]    ["27F7]
-\definemathoverextensible [\v!top] [overtwoheadleftarrow]  ["27F8]
-\definemathoverextensible [\v!top] [overtwoheadrightarrow] ["27F9]
-\definemathoverextensible [\v!top] [overleftharpoondown]   ["21BD]
-\definemathoverextensible [\v!top] [overleftharpoonup]     ["21BC]
-\definemathoverextensible [\v!top] [overrightharpoondown]  ["21C1]
-\definemathoverextensible [\v!top] [overrightharpoonup]    ["21C0]
+\definemathoverextensible [\v!top] [overleftarrow]          ["2190] % ["27F5]
+\definemathoverextensible [\v!top] [overrightarrow]         ["2192] % ["27F6]
+\definemathoverextensible [\v!top] [overleftrightarrow]     ["2194] % ["27F7]
+\definemathoverextensible [\v!top] [overtwoheadleftarrow]   ["219E] % ["27F8]
+\definemathoverextensible [\v!top] [overtwoheadrightarrow]  ["21A0] % ["27F9]
+\definemathoverextensible [\v!top] [overlefttailarrow]      ["21A2]
+\definemathoverextensible [\v!top] [overrighttailarrow]     ["21A3]
+\definemathoverextensible [\v!top] [overleftbararrow]       ["21A4]
+\definemathoverextensible [\v!top] [overrightbararrow]      ["21A6]
+\definemathoverextensible [\v!top] [overlefthookarrow]      ["21A9]
+\definemathoverextensible [\v!top] [overrighthookarrow]     ["21AA]
+\definemathoverextensible [\v!top] [overleftharpoondown]    ["21BD]
+\definemathoverextensible [\v!top] [overleftharpoonup]      ["21BC]
+\definemathoverextensible [\v!top] [overrightharpoondown]   ["21C1]
+\definemathoverextensible [\v!top] [overrightharpoonup]     ["21C0]
+\definemathoverextensible [\v!top] [overRightarrow]         ["21D2] % ["27F9]
+\definemathoverextensible [\v!top] [overLeftarrow]          ["21D0] % ["27F8]
+\definemathoverextensible [\v!top] [overLeftrightarrow]     ["21D4] % ["27F8]
+\definemathoverextensible [\v!top] [overLeftbararrow]       ["2906]
+\definemathoverextensible [\v!top] [overRightbararrow]      ["2907]
 
 \definemathunderextensible [\v!bottom] [underleftarrow]         ["2190] % ["27F5]
 \definemathunderextensible [\v!bottom] [underrightarrow]        ["2192] % ["27F6]
-\definemathunderextensible [\v!bottom] [underleftrightarrow]    ["27F7]
-\definemathunderextensible [\v!bottom] [undertwoheadleftarrow]  ["27F8]
-\definemathunderextensible [\v!bottom] [undertwoheadrightarrow] ["27F9]
+\definemathunderextensible [\v!bottom] [underleftrightarrow]    ["2194] % ["27F7]
+\definemathunderextensible [\v!bottom] [undertwoheadleftarrow]  ["219E] % ["27F8]
+\definemathunderextensible [\v!bottom] [undertwoheadrightarrow] ["21A0] % ["27F9]
+\definemathunderextensible [\v!bottom] [underlefttailarrow]     ["21A2]
+\definemathunderextensible [\v!bottom] [underrighttailarrow]    ["21A3]
+\definemathunderextensible [\v!bottom] [underleftbararrow]      ["21A4]
+\definemathunderextensible [\v!bottom] [underrightbararrow]     ["21A6]
+\definemathunderextensible [\v!bottom] [underlefthookarrow]     ["21A9]
+\definemathunderextensible [\v!bottom] [underrighthookarrow]    ["21AA]
 \definemathunderextensible [\v!bottom] [underleftharpoondown]   ["21BD]
 \definemathunderextensible [\v!bottom] [underleftharpoonup]     ["21BC]
 \definemathunderextensible [\v!bottom] [underrightharpoondown]  ["21C1]
 \definemathunderextensible [\v!bottom] [underrightharpoonup]    ["21C0]
+\definemathunderextensible [\v!bottom] [underRightarrow]        ["21D2] % ["27F9]
+\definemathunderextensible [\v!bottom] [underLeftarrow]         ["21D0] % ["27F8]
+\definemathunderextensible [\v!bottom] [underLeftrightarrow]    ["21D4] % ["27F8]
+\definemathunderextensible [\v!bottom] [underLeftbararrow]      ["2906]
+\definemathunderextensible [\v!bottom] [underRightbararrow]     ["2907]
 
 %D We don't use overline and underline. This is one of the overlooked aspects of
 %D unicode cq. opentype math: why treat rules different than e.g. arrows and
@@ -1206,53 +1214,76 @@
 \definemathextensible [\v!chemistry] [crightoverleftarrow] ["21C4]
 \definemathextensible [\v!chemistry] [cleftoverrightarrow] ["21C6]
 
-\def\math_stackers_hacked_fill#1#2#3%
-  {\mathematics
-     {\begingroup
-      \mathsurround\zeropoint
-      \thickmuskip \zeromuskip
-      \medmuskip   \zeromuskip
-      \thinmuskip  \zeromuskip
-      \tinymuskip  \zeromuskip
-      \pettymuskip \zeromuskip
-      \ifrelax#1%
-        \cleaders\mathstylehbox{#2}\hfill
-      \else
-        #1%
-        \mkern-7\onemuskip
-        \cleaders\mathstylehbox{\mkern-2\onemuskip#2\mkern-2\onemuskip}\hfill
-        \mkern-7\onemuskip
-        #3%
-      \fi
-      \endgroup}}
-
-\immutable\protected\def\rightarrowfill        {\math_stackers_hacked_fill \relbar               \relbar              \rightarrow}
-\immutable\protected\def\leftarrowfill         {\math_stackers_hacked_fill \leftarrow            \relbar              \relbar}
-\immutable\protected\def\rightoverleftarrowfill{\math_stackers_hacked_fill \relax                \crightoverleftarrow \relax}
-\immutable\protected\def\leftoverrightarrowfill{\math_stackers_hacked_fill \relax                \cleftoverrightarrow \relax}
-\immutable\protected\def\equalfill             {\math_stackers_hacked_fill \Relbar               \Relbar              \Relbar}
-\immutable\protected\def\Rightarrowfill        {\math_stackers_hacked_fill \Relbar               \Relbar              \Rightarrow}
-\immutable\protected\def\Leftarrowfill         {\math_stackers_hacked_fill \Leftarrow            \Relbar              \Relbar}
-\immutable\protected\def\Leftrightarrowfill    {\math_stackers_hacked_fill \Leftarrow            \Relbar              \Rightarrow}
-\immutable\protected\def\leftrightarrowfill    {\math_stackers_hacked_fill \leftarrow            \relbar              \rightarrow}
-\immutable\protected\def\mapstofill            {\math_stackers_hacked_fill{\mapstochar\relbar}   \relbar              \rightarrow}
-\immutable\protected\def\twoheadrightarrowfill {\math_stackers_hacked_fill \relbar               \relbar              \twoheadrightarrow}
-\immutable\protected\def\twoheadleftarrowfill  {\math_stackers_hacked_fill \twoheadleftarrow     \relbar              \relbar}
-\immutable\protected\def\rightharpoondownfill  {\math_stackers_hacked_fill \relbar               \relbar              \rightharpoondown}
-\immutable\protected\def\rightharpoonupfill    {\math_stackers_hacked_fill \relbar               \relbar              \rightharpoonup}
-\immutable\protected\def\leftharpoondownfill   {\math_stackers_hacked_fill \leftharpoondown      \relbar              \relbar}
-\immutable\protected\def\leftharpoonupfill     {\math_stackers_hacked_fill \leftharpoonup        \relbar              \relbar}
-\immutable\protected\def\hookleftfill          {\math_stackers_hacked_fill \leftarrow            \relbar             {\relbar\joinrel\rhook}}
-\immutable\protected\def\hookrightfill         {\math_stackers_hacked_fill{\lhook\joinrel\relbar}\relbar              \rightarrow}
-\immutable\protected\def\relfill               {\math_stackers_hacked_fill \relbar               \relbar              \relbar}
-\immutable\protected\def\triplerelfill         {\math_stackers_hacked_fill \equiv                \equiv               \equiv}
-
-%D For the moment (needs checking):
+% \def\math_stackers_hacked_fill#1#2#3%
+%   {\mathematics
+%      {\begingroup
+%       \mathsurround\zeropoint
+%       \thickmuskip \zeromuskip
+%       \medmuskip   \zeromuskip
+%       \thinmuskip  \zeromuskip
+%       \tinymuskip  \zeromuskip
+%       \pettymuskip \zeromuskip
+%       \ifrelax#1%
+%         \cleaders\mathstylehbox{#2}\hfill
+%       \else
+%         #1%
+%         \mkern-7\onemuskip
+%         \cleaders\mathstylehbox{\mkern-2\onemuskip#2\mkern-2\onemuskip}\hfill
+%         \mkern-7\onemuskip
+%         #3%
+%       \fi
+%       \endgroup}}
+%
+% \immutable\protected\def\rightarrowfill        {\math_stackers_hacked_fill \relbar               \relbar              \rightarrow}
+% \immutable\protected\def\leftarrowfill         {\math_stackers_hacked_fill \leftarrow            \relbar              \relbar}
+% \immutable\protected\def\rightoverleftarrowfill{\math_stackers_hacked_fill \relax                \crightoverleftarrow \relax}
+% \immutable\protected\def\leftoverrightarrowfill{\math_stackers_hacked_fill \relax                \cleftoverrightarrow \relax}
+% \immutable\protected\def\equalfill             {\math_stackers_hacked_fill \Relbar               \Relbar              \Relbar}
+% \immutable\protected\def\Rightarrowfill        {\math_stackers_hacked_fill \Relbar               \Relbar              \Rightarrow}
+% \immutable\protected\def\Leftarrowfill         {\math_stackers_hacked_fill \Leftarrow            \Relbar              \Relbar}
+% \immutable\protected\def\Leftrightarrowfill    {\math_stackers_hacked_fill \Leftarrow            \Relbar              \Rightarrow}
+% \immutable\protected\def\leftrightarrowfill    {\math_stackers_hacked_fill \leftarrow            \relbar              \rightarrow}
+% \immutable\protected\def\mapstofill            {\math_stackers_hacked_fill{\mapstochar\relbar}   \relbar              \rightarrow}
+% \immutable\protected\def\twoheadrightarrowfill {\math_stackers_hacked_fill \relbar               \relbar              \twoheadrightarrow}
+% \immutable\protected\def\twoheadleftarrowfill  {\math_stackers_hacked_fill \twoheadleftarrow     \relbar              \relbar}
+% \immutable\protected\def\rightharpoondownfill  {\math_stackers_hacked_fill \relbar               \relbar              \rightharpoondown}
+% \immutable\protected\def\rightharpoonupfill    {\math_stackers_hacked_fill \relbar               \relbar              \rightharpoonup}
+% \immutable\protected\def\leftharpoondownfill   {\math_stackers_hacked_fill \leftharpoondown      \relbar              \relbar}
+% \immutable\protected\def\leftharpoonupfill     {\math_stackers_hacked_fill \leftharpoonup        \relbar              \relbar}
+% \immutable\protected\def\hookleftfill          {\math_stackers_hacked_fill \leftarrow            \relbar             {\relbar\joinrel\rhook}}
+% \immutable\protected\def\hookrightfill         {\math_stackers_hacked_fill{\lhook\joinrel\relbar}\relbar              \rightarrow}
+% \immutable\protected\def\relfill               {\math_stackers_hacked_fill \relbar               \relbar              \relbar}
+% \immutable\protected\def\triplerelfill         {\math_stackers_hacked_fill \equiv                \equiv               \equiv}
+%
+% \permanent\tolerant\protected\def\defineextensiblefiller[#1]#*[#2]%
+%   {\immutable\letcsname\??mathextensiblefallbacks\number#2\expandafter\endcsname\csname#1\endcsname}
+
+\installcorenamespace {mathadaptiveextensible}
+
+\defineadaptive
+  [mathfiller]
+  [\c!setups=adaptive:mathfiller,
+   \c!stretch=1fill]
+
+\startsetups adaptive:mathfiller
+    \setbox\usedadaptivebox\hbox to \usedadaptivewidth \bgroup
+        \startimath
+            \Uhextensible
+                \s!width  \usedadaptivewidth
+                \s!middle \zerocount \usedadaptivealternative
+            \relax
+        \stopimath
+    \egroup
+\stopsetups
+
+\def\mathfiller#1%
+  {\begingroup
+   \scratchunicode#1\relax
+   \adaptivebox[mathfiller][\c!alternative=#1]{\hss\strut\hss}%
+   \endgroup}
 
 \permanent\tolerant\protected\def\defineextensiblefiller[#1]#*[#2]%
-  {\immutable\letcsname\??mathextensiblefallbacks\number#2\expandafter\endcsname\csname#1\endcsname
-   %\immutable\letcsname#1\expandafter\endcsname\csname#1\endcsname
-   } % huh?
+  {\frozen\instance\edefcsname#1\endcsname{\mathfiller{\number#2}}}
 
 %defineextensiblefiller [barfill]                ["203E] % yet undefined
 \defineextensiblefiller [relfill]                ["002D]
@@ -1302,14 +1333,18 @@
   {\begingroup
    \edef\currentmathstackers{#category}%
    \edef\p_moffset{\mathstackersparameter\c!moffset}%
-   \ifempty\p_moffset \else
-     \mskip\p_moffset\relax
+   \ifconditional\indisplaymath
+     \ifempty\p_moffset \else
+       \ifmmode\mskip\else\hskip\fi\p_moffset\relax
+     \fi
    \fi
    \ifmmode\math_atom_by_parameter\mathstackersparameter\else\dontleavehmode\fi
      {\usemathstackerscolorparameter\c!color
       \Umathchar\zerocount\zerocount#codepoint}%
-   \ifempty\p_moffset \else
-     \mskip\p_moffset\relax
+   \ifconditional\indisplaymath
+     \ifempty\p_moffset \else
+       \ifmmode\mskip\else\hskip\fi\p_moffset\relax
+     \fi
    \fi
    \endgroup}
 
@@ -1319,6 +1354,7 @@
 \definemathunstacked [\v!wide] [impliedby] ["27F8] % \mathrel{\;\Longleftarrow\;}
 \definemathunstacked [\v!wide] [implies]   ["27F9] % \mathrel{\;\Longrightarrow\;}
 \definemathunstacked [\v!wide] [iff]       ["27FA] % \mathrel{\;\Longleftrightarrow\;}
+\definemathunstacked [\v!wide] [impliesby] ["27FA] % \mathrel{\;\Longleftrightarrow\;}
 
 % New (an example of using \mathexheight):
 
diff --git a/tex/context/base/mkxl/math-vfu.lmt b/tex/context/base/mkxl/math-vfu.lmt
index f3e0ea814..0a2b440a1 100644
--- a/tex/context/base/mkxl/math-vfu.lmt
+++ b/tex/context/base/mkxl/math-vfu.lmt
@@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['math-vfu'] = {
     license   = "see context related readme files"
 }
 
+-- somehow an italic gets passed for 'next'
+
 -- All these math vectors .. thanks to Aditya and Mojca they become better and
 -- better. If you have problems with math fonts or miss characters report it to the
 -- ConTeXt mailing list. Also thanks to Boguslaw for finding a couple of errors.
@@ -62,6 +64,25 @@ local staycommand       = vfcommands.stay
 local nps = fonts.helpers.newprivateslot
 local ps  = fonts.helpers.privateslot
 
+nps("rule middle piece")
+nps("rule right piece")
+nps("rule left piece")
+nps("double rule middle piece")
+nps("double rule right piece")
+nps("double rule left piece")
+nps("arrow left piece")
+nps("arrow right piece")
+nps("double arrow left piece")
+nps("double arrow right piece")
+
+nps("flat rule left piece")
+nps("flat rule middle piece")
+nps("flat rule right piece")
+
+nps("flat double rule left piece")
+nps("flat double rule middle piece")
+nps("flat double rule right piece")
+
 do
 
     local function horibar(main,unicode,rule,left,right,normal)
@@ -89,11 +110,11 @@ do
                 if not characters[p_rule] then
                     p_rule = addprivate(main,f_rule,{
                         height   = height,
-                        width    = mwidth,
-    width    = .95*mwidth,
+                        width    = .95*mwidth,
+-- keepvirtual      = true,
                         commands = {
                             push,
-    leftcommand[.025*mwidth],
+                            leftcommand[.025*mwidth],
                             downcommand[down],
                             slotcommand[0][rule],
                             pop,
@@ -103,11 +124,11 @@ do
                 if not characters[p_left] then
                     p_left = addprivate(main,f_left,{
                         height   = height,
-                        width    = lwidth,
-    width    = .95*lwidth,
+                        width    = .95*lwidth,
+-- keepvirtual      = true,
                         commands = {
                             push,
-    leftcommand[.025*lwidth],
+                            leftcommand[.025*lwidth],
                             downcommand[down],
                             slotcommand[0][left],
                             pop,
@@ -117,11 +138,11 @@ do
                 if not characters[p_right] then
                     p_right = addprivate(main,f_right,{
                         height   = height,
-                        width    = rwidth,
-    width    = .95*rwidth,
+                        width    = .95*rwidth,
+-- keepvirtual      = true,
                         commands = {
                             push,
-    leftcommand[.025*rwidth],
+                            leftcommand[.025*rwidth],
                             downcommand[down],
                             slotcommand[0][right],
                             pop,
@@ -133,6 +154,7 @@ do
                     partsorientation = "horizontal",
                     height           = height,
                     width            = nwidth,
+-- keepvirtual      = true,
                     commands         = {
                         downcommand[down],
                         slotcommand[0][normal]
@@ -149,11 +171,14 @@ do
                     p_rule = addprivate(main,f_rule,{
                         height   = height,
                         width    = width,
+-- keepvirtual      = true,
                         commands = { push, { "rule", height, width }, pop },
                     })
                 end
                 characters[unicode] = {
-                    keepvirtual      = true,
+                    height           = height,
+                    width            = nwidth,
+-- keepvirtual      = true,
                     partsorientation = "horizontal",
                     parts            = {
                         { glyph = p_rule },
@@ -234,21 +259,29 @@ do
         if characters[unicode] then
             local template = characters[first]
             if template then
-                if not characters[rule] then
-                    local xheight = main.mathparameters.xheight
+                local crule   = characters[rule]
+                local xheight = main.mathparameters.xheight
+                local rheight = 0
+                local rdepth  = 0
+--                 if crule then
+--                     rheight = crule.height
+--                     rdepth  = crule.depth
+--                 else
                     local width   = template.width / 4
                     local height  = template.height
                     local depth   = template.depth
-                    local rheight = where == "top" and   height or 3*height
-                    local rdepth  = where == "top" and 2*height or 0
+                    rheight = where == "top" and   height or 3*height
+                    rdepth  = where == "top" and 2*height or 0
                     characters[rule] = {
                         height   = rheight,
                         depth    = rdepth,
                         width    = width,
                         commands = { push, { "rule", height, width }, pop },
                     }
-                    characters[first].depth = rdepth
-                    characters[last] .depth = rdepth
+--                 end
+                characters[first].depth = rdepth
+                characters[last] .depth = rdepth
+                if where == "top" then
                     while true do
                         chardata.height  = chardata.height - xheight
                         chardata.depth   = 0
@@ -261,41 +294,49 @@ do
                             break
                         end
                     end
+                else
+                    while true do
+                        chardata.height  = 0
+                        local next = chardata.next
+                        if next then
+                            unicode  = next
+                            chardata = characters[unicode]
+                        else
+                            break
+                        end
+                    end
                 end
                 chardata.keepvirtual      = true
                 chardata.partsorientation = "horizontal"
                 chardata.parts            = {
                     { glyph = first },
-                    { glyph = rule, extender = 1 },
+                    { glyph = rule, extender = 1, start = width/2, ["end"] = width/2 },
                     { glyph = last  },
                 }
             end
         end
     end
 
-    local function brace(main,unicode,first,rule,left,right,rule,last)
+    local function brace(main,unicode,first,rule,left,right,rule,last,where)
         local characters = main.characters
         local chardata   = characters[unicode]
         if chardata then
             local template = characters[first]
             if template then
-                if not characters[rule] then
-                    local xheight = main.mathparameters.xheight
-                    local width   = template.width / 4
-                    local height  = template.height
-                    local depth   = template.depth
-                    local rheight = 3*height
-                    local rdepth  = 2*height
-                    characters[rule] = {
-                        height   = rheight,
-                        depth    = rdepth,
-                        width    = width,
-                        commands = { push, { "rule", height, width }, pop },
-                    }
-                    characters[first].depth  = rdepth
-                    characters[last] .depth  = rdepth
-                    characters[left] .height = rheight
-                    characters[right].height = rheight
+                local xheight = main.mathparameters.xheight
+                local width   = template.width / 4
+                local height  = template.height
+                local depth   = template.depth
+                local rheight = 3*height
+                local rdepth  = 2*height
+                characters[rule] = {
+                    height   = rheight,
+                    depth    = rdepth,
+                    width    = width,
+                    commands = { push, { "rule", height, width }, pop },
+                }
+                -- don't change snippets, they serve dual purposes
+                if where == "top" then
                     while true do
                         chardata.height  = chardata.height - xheight
                         chardata.depth   = 0
@@ -308,15 +349,26 @@ do
                             break
                         end
                     end
+                else
+                    while true do
+                        chardata.height = 0
+                        local next = chardata.next
+                        if next then
+                            unicode  = next
+                            chardata = characters[unicode]
+                        else
+                            break
+                        end
+                    end
                 end
                 chardata.keepvirtual = true
                 chardata.partsorientation = "horizontal"
                 chardata.parts            = {
                     { glyph = first },
-                    { glyph = rule, extender = 1 },
+                    { glyph = rule, extender = 1, start = width/2, ["end"] = width/2 },
                     { glyph = left  },
                     { glyph = right },
-                    { glyph = rule, extender = 1 },
+                    { glyph = rule, extender = 1, start = width/2, ["end"] = width/2 },
                     { glyph = last  },
                 }
             end
@@ -436,9 +488,11 @@ do
                 width = w1 + w2 - d12
             end
             characters[unicode] = {
+                unicode  = unicode,
                 width    = width,
                 height   = max(c1.height or 0, c2.height or 0),
                 depth    = max(c1.depth  or 0, c2.depth  or 0),
+keepvirtual = true,
                 commands = {
                  -- { "inspect" },
                  -- { "trace" },
@@ -482,10 +536,11 @@ do
             local w1 = c1.width
             local w2 = c2.width
             local w3 = c3.width
-            local mu = main.parameters.size/18
+            local ds = main.parameters.size/18
             d12 = d12 * ds
             d23 = d23 * ds
             characters[unicode] = {
+                unicode  = unicode,
                 width    = w1 + w2 + w3 - d12 - d23,
                 height   = max(c1.height or 0, c2.height or 0, c3.height or 0),
                 depth    = max(c1.depth  or 0, c2.depth  or 0, c3.depth  or 0),
@@ -572,6 +627,40 @@ do
         end
     end
 
+    local function extension(main,unicode,first,middle,last,ffactor,mfactor,lfactor)
+        local characters = main.characters
+        local chardata   = characters[unicode]
+        if chardata then
+            local fw = first  and characters[first]
+            local mw = middle and characters[middle]
+            local lw = last   and characters[last]
+            if fw and lw then
+                fw = fw.width ; if fw == 0 then fw = 1 end
+                lw = lw.width ; if lw == 0 then lw = 1 end
+                if middle == "left" then
+                    chardata.parts = {
+                        { extender = 0, glyph = first,  ["end"] = fw/2, start = 0,    advance = fw },
+                        { extender = 1, glyph = last,   ["end"] = lw/2, start = lw/2, advance = lw },
+                    }
+                elseif middle == "right" then
+                    chardata.parts = {
+                        { extender = 1, glyph = first,  ["end"] = fw/2, start = fw/2, advance = fw },
+                        { extender = 0, glyph = last,   ["end"] = lw/2, start = 0,    advance = lw },
+                    }
+                elseif mw then
+                    mw = mw.width ; if mw == 0 then mw = 1 end
+                    chardata.parts = {
+                        { extender = 0, glyph = first,  ["end"] = fw/2, start = 0,    advance = (ffactor or 1)*fw },
+                        { extender = 1, glyph = middle, ["end"] = mw/2, start = mw/2, advance = (mfactor or 1)*mw },
+                        { extender = 0, glyph = last,   ["end"] = 0,    start = lw/2, advance = (lfactor or 1)*lw },
+                    }
+                end
+                chardata.keepvirtual      = true -- why this issue with nested virtuals
+                chardata.partsorientation = "horizontal"
+            end
+        end
+    end
+
     vfmath.builders = {
         horibar    = horibar,
         rootbar    = rootbar,
@@ -583,6 +672,7 @@ do
         jointhree  = jointhree,
         stack      = stack,
         repeated   = repeated,
+        extension  = extension,
     }
 
     -- todo: move this to the lfg files
@@ -1113,6 +1203,11 @@ function vfmath.define(specification,set,goodies)
        fake   = 0.9, -- replace multiples with this width proportion
     })
     --
+    mathematics.tweaks.addequals(main, main, {
+       tweak = "addequals",
+       force = true,
+    })
+    --
 --     mathematics.tweaks.addbars(main,main,{
 --         tweak   = "addbars",
 --         advance = 0.52,
@@ -1148,40 +1243,6 @@ function vfmath.setdigits(font_encoding, name, digits)
     end
 end
 
--- local function extension(main,characters,id,size,unicode,first,middle,last)
---     local chr = characters[unicode]
---     if not chr then
---         return -- skip
---     end
---     local fw = characters[first]
---     if not fw then
---         return
---     end
---     local mw = characters[middle]
---     if not mw then
---         return
---     end
---     local lw = characters[last]
---     if not lw then
---         return
---     end
---     fw = fw.width
---     mw = mw.width
---     lw = lw.width
---     if fw == 0 then
---         fw = 1
---     end
---     if lw == 0 then
---         lw = 1
---     end
---     chr.partsorientation = "horizontal"
---     chr.parts = {
---         { extender = 0, glyph = first,  ["end"] = fw/2, start = 0,    advance = fw },
---         { extender = 1, glyph = middle, ["end"] = mw/2, start = mw/2, advance = mw },
---         { extender = 0, glyph = last,   ["end"] = 0,    start = lw/2, advance = lw },
---     }
--- end
-
 -- local step = 0.2 -- 0.1 is nicer but gives larger files
 
 -- local function clipped(main,characters,id,size,unicode,original) -- push/pop needed?
diff --git a/tex/context/base/mkxl/mult-sys.mkxl b/tex/context/base/mkxl/mult-sys.mkxl
index 428a8ddcf..47119ad20 100644
--- a/tex/context/base/mkxl/mult-sys.mkxl
+++ b/tex/context/base/mkxl/mult-sys.mkxl
@@ -114,6 +114,7 @@
 
 %D For proper \UNICODE\ support we need a few font related constants.
 
+\definesystemconstant {accent}
 \definesystemconstant {action}
 \definesystemconstant {all}
 \definesystemconstant {ampersand}
@@ -164,6 +165,7 @@
 \definesystemconstant {leftclass}
 \definesystemconstant {rightclass}
 \definesystemconstant {calligraphic}
+\definesystemconstant {center}
 \definesystemconstant {clone}
 \definesystemconstant {close}
 \definesystemconstant {cmyk}
diff --git a/tex/context/base/mkxl/node-ali.lmt b/tex/context/base/mkxl/node-ali.lmt
index ba2ccdde7..5eff779dc 100644
--- a/tex/context/base/mkxl/node-ali.lmt
+++ b/tex/context/base/mkxl/node-ali.lmt
@@ -21,7 +21,6 @@ local setnext            = nuts.setnext
 local getnext            = nuts.getnext
 local getprev            = nuts.getprev
 local getboth            = nuts.getboth
-local setglue            = nuts.setglue
 local getglue            = nuts.getglue
 local setglue            = nuts.setglue
 local getwhd             = nuts.getwhd
@@ -372,6 +371,7 @@ do
         if noflines > 0 then
             local currentline = 1
             for n, subtype in nextglue, head do
+-- print(currentline,height/65536,depth/65536)
                 -- one day we can decide what to do with intertext stuff based on the
                 -- subtype but not now ... on our agenda (intertext etc)
                 if subtype == baselineskip_code or subtype == lineskip_code then
@@ -383,9 +383,11 @@ do
                     if prevdp < depth then
                         setdepth(lines[currentline][1],depth)
                         delta = delta + (depth - prevdp)
+-- lines[currentline][5] = depth
                     end
                     if nextht < height then
                         setheight(lines[nextline][1],height)
+-- lines[nextline][4] = height
                         delta = delta + (height - nextht)
                     end
 --                     if subtype == lineskip_code then
@@ -394,7 +396,7 @@ do
 --                     else
                         setglue(n,amount+inbetween-delta,stretch,shrink)
 --                     end
-                    curline = nextline
+                    currentline = nextline -- was curline
 -- if currentline > noflines then
 --     break
 -- end
diff --git a/tex/context/base/mkxl/page-brk.mkxl b/tex/context/base/mkxl/page-brk.mkxl
index 23ffc872d..8c92148fc 100644
--- a/tex/context/base/mkxl/page-brk.mkxl
+++ b/tex/context/base/mkxl/page-brk.mkxl
@@ -90,7 +90,7 @@
        % disable reset after shipout
        \global\pageornamentstate\plustwo
      \fi
-     % maybe \ifcstok{#1}\emptytoks
+     % maybe \iftok{#1}\emptytoks
      \ifparameter#1\or
        \page_breaks_handle{#1}%
      \else % so, no pagebreak when \pagebreak[] ! ! !
diff --git a/tex/context/base/mkxl/phys-dim.lmt b/tex/context/base/mkxl/phys-dim.lmt
new file mode 100644
index 000000000..8575962e9
--- /dev/null
+++ b/tex/context/base/mkxl/phys-dim.lmt
@@ -0,0 +1,1116 @@
+if not modules then modules = { } end modules ['phys-dim'] = {
+    version   = 1.001,
+    comment   = "companion to phys-dim.mkiv",
+    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+    copyright = "PRAGMA ADE / ConTeXt Development Team",
+    license   = "see context related readme files"
+}
+
+-- This is pretty old code that I found back, but let's give it a try
+-- in practice. It started out as m-units.lua but as we want to keep that
+-- module around we moved the code to the dimensions module.
+--
+-- todo: maybe also an sciunit command that converts to si units (1 inch -> 0.0254 m)
+-- etc .. typical something to do when listening to a news whow or b-movie
+--
+-- todo: collect used units for logging (and list of units, but then we need
+-- associations too).
+
+-- The lists have been checked and completed by Robin Kirkham.
+
+-- dubious/wrong
+
+--  Atom                        = [[u]], -- should be amu (atomic mass unit)
+--  Bell                        = [[B]], -- should be bel
+--  Sterant                     = [[sr]], -- should be steradian
+--  Equivalent                  = [[eql]], -- qualifier?
+--  At                          = [[at]], -- qualifier?
+--  Force                       = [[f]], -- qualifier?
+--  eVolt                       = [[eV]],
+--  -- AC or DC voltages should be qualified in the text
+--  VoltAC                      = [[V\unitsbackspace\unitslower{ac}]],
+--  VoltDC                      = [[V\unitsbackspace\unitslower{dc}]],
+--  AC                          = [[V\unitsbackspace\unitslower{ac}]],
+--  DC                          = [[V\unitsbackspace\unitslower{dc}]],
+--  -- probably not harmful but there are better alternatives
+--  -- e.g., revolution per second (rev/s)
+--  RPS                         = [[RPS]],
+--  RPM                         = [[RPM]],
+--  RevPerSec                   = [[RPS]],
+--  RevPerMin                   = [[RPM]],
+
+local rawset, next = rawset, next
+local V, P, S, R, C, Cc, Cs, matchlpeg = lpeg.V, lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.match
+local format, lower, gsub = string.format, string.lower, string.gsub
+local appendlpeg = lpeg.append
+local utfchartabletopattern = lpeg.utfchartabletopattern
+local mergetable, mergedtable, keys, loweredkeys, sortedhash = table.merge, table.merged, table.keys, table.loweredkeys, table.sortedhash
+local setmetatablenewindex = table.setmetatablenewindex
+local utfchar = utf.char
+
+physics            = physics or { }
+physics.units      = physics.units or { }
+
+local allocate     = utilities.storage.allocate
+
+local context      = context
+local commands     = commands
+local implement    = interfaces.implement
+
+local trace_units  = false
+local report_units = logs.reporter("units")
+
+trackers.register("physics.units", function(v) trace_units = v end)
+
+-- digits parser (todo : use patterns)
+
+local math_one       = Cs((P("$")    /"") * (1-P("$"))^1 * (P("$")/"")) / context.m
+local math_two       = Cs((P("\\m {")/"") * (1-P("}"))^1 * (P("}")/"")) / context.m -- watch the space after \m
+
+local digit          = R("09")
+local plus           = P("+")
+local minus          = P("-")
+local plusminus      = P("±")
+local sign           = plus + minus
+local power          = S("^e")
+local digitspace     = S("~@_")
+local comma          = P(",")
+local period         = P(".")
+local semicolon      = P(";")
+local colon          = P(":")
+local signspace      = P("/")
+local positive       = P("++") -- was p
+local negative       = P("--") -- was n
+local highspace      = P("//") -- was s
+local padding        = P("=")
+local space          = P(" ")
+local lparent        = P("(")
+local rparent        = P(")")
+
+local lbrace         = P("{")
+local rbrace         = P("}")
+
+local digits         = digit^1
+
+local powerdigits    = plus  * C(digits) / context.digitspowerplus
+                     + minus * C(digits) / context.digitspowerminus
+                     +         C(digits) / context.digitspower
+
+local ddigitspace    = digitspace  / "" / context.digitsspace
+local ddigit         = digits           / context.digitsdigit
+local dsemicomma     = semicolon   / "" / context.digitsseparatorspace
+local dsemiperiod    = colon       / "" / context.digitsseparatorspace
+local dfinalcomma    = comma       / "" / context.digitsfinalcomma
+local dfinalperiod   = period      / "" / context.digitsfinalperiod
+local dintercomma    = comma       / "" / context.digitsintermediatecomma
+local dinterperiod   = period      / "" / context.digitsintermediateperiod
+local dskipcomma     = comma       / "" / context.digitsseparatorspace
+local dskipperiod    = period      / "" / context.digitsseparatorspace
+local dsignspace     = signspace   / "" / context.digitssignspace
+local dpositive      = positive    / "" / context.digitspositive
+local dnegative      = negative    / "" / context.digitsnegative
+local dhighspace     = highspace   / "" / context.digitshighspace
+local dsomesign      = plus        / "" / context.digitsplus
+                     + minus       / "" / context.digitsminus
+                     + plusminus   / "" / context.digitsplusminus
+local dpower         = power       / "" * ( powerdigits + lbrace * powerdigits * rbrace )
+
+local dpadding       = padding     / "" / context.digitszeropadding -- todo
+
+local dleader        = (dpositive + dnegative + dhighspace + dsomesign + dsignspace)^0
+local dtrailer       = dpower^0
+local dfinal         = P(-1) + #P(1 - comma - period - semicolon - colon)
+local dnumber        = (ddigitspace + ddigit)^1
+
+-- ___,000,000  ___,___,000  ___,___,__0  000,000,000  000.00  000,000,000.00  000,000,000.==
+
+-- : ; for the moment not used, maybe for invisible fraction . , when no leading number
+
+-- local c_p = (ddigitspace^1 * dskipcomma)^0            -- ___,
+--           * (ddigitspace^0 * ddigit * dintercomma)^0  -- _00, 000,
+--           * ddigitspace^0  * ddigit^0                 -- _00 000
+--           * (
+--              dfinalperiod * ddigit                    -- .00
+--            + dskipperiod  * dpadding^1                -- .==
+--            + dsemiperiod  * ddigit                    -- :00
+--            + dsemiperiod  * dpadding^1                -- :==
+--             )^0
+--           + ddigit                                    -- 00
+--
+-- local p_c = (ddigitspace^1 * dskipperiod)^0           -- ___.
+--           * (ddigitspace^0 * ddigit * dinterperiod)^0 -- _00. 000.
+--           * ddigitspace^0  * ddigit^0                 -- _00 000
+--           * (
+--              dfinalcomma * ddigit                     -- ,00
+--            + dskipcomma  * dpadding^1                 -- ,==
+--            + dsemicomma  * ddigit                     -- :00
+--            + dsemicomma  * dpadding^1                 -- :==
+--             )^0
+--           + ddigit                                    -- 00
+--
+-- fix by WS/SB (needs further testing)
+
+local c_p = (ddigitspace^1 * dskipcomma)^0                    -- ___,
+          * (ddigitspace^0 * ddigit * dintercomma)^0          -- _00, 000,
+          * ddigitspace^0  * ddigit^0                         -- _00 000
+          * (
+             dfinalperiod * ddigit^1 * dpadding^1             -- .0=
+           + dfinalperiod * ddigit * (dintercomma * ddigit)^0 -- .00
+           + dskipperiod  * dpadding^1                        -- .==
+           + dsemiperiod  * ddigit * (dintercomma * ddigit)^0 -- :00
+           + dsemiperiod  * dpadding^1                        -- :==
+            )^0
+          + ddigit                                            -- 00
+
+local p_c = (ddigitspace^1 * dskipperiod)^0                   -- ___.
+          * (ddigitspace^0 * ddigit * dinterperiod)^0         -- _00. 000.
+          * ddigitspace^0  * ddigit^0                         -- _00 000
+          * (
+             dfinalcomma * ddigit^1 * dpadding^1              -- ,0=
+           + dfinalcomma * ddigit * (dinterperiod * ddigit)^0 -- 00
+           + dskipcomma  * dpadding^1                         -- ,==
+           + dsemicomma  * ddigit * (dinterperiod * ddigit)^0 -- :00
+           + dsemicomma  * dpadding^1                         -- :==
+            )^0
+          + ddigit                                            -- 00
+
+local p_c_dparser = math_one + math_two + dleader * p_c * dtrailer * dfinal
+local c_p_dparser = math_one + math_two + dleader * c_p * dtrailer * dfinal
+
+local function makedigits(str,reverse)
+    if reverse then
+        matchlpeg(p_c_dparser,str)
+    else
+        matchlpeg(c_p_dparser,str)
+    end
+end
+
+-- tables:
+
+local user_long_prefixes   = { }
+local user_long_units      = { }
+local user_long_operators  = { }
+local user_long_suffixes   = { }
+local user_symbol_units    = { }
+local user_packaged_units  = { }
+
+local user_short_prefixes  = { }
+local user_short_units     = { }
+local user_short_operators = { }
+local user_short_suffixes  = { }
+
+local long_prefixes = {
+
+    -- Le Système international d'unités (SI) 8e édition (Table 5)
+
+    Yocto = "yocto",  -- 10^{-24}
+    Zepto = "zepto",  -- 10^{-21}
+    Atto  = "atto",   -- 10^{-18}
+    Femto = "femto",  -- 10^{-15}
+    Pico  = "pico",   -- 10^{-12}
+    Nano  = "nano",   -- 10^{-9}
+    Micro = "micro",  -- 10^{-6}
+    Milli = "milli",  -- 10^{-3}
+    Centi = "centi",  -- 10^{-2}
+    Deci  = "deci",   -- 10^{-1}
+
+    Deca  = "deca",   -- 10^{1}
+    Hecto = "hecto",  -- 10^{2}
+    Kilo  = "kilo",   -- 10^{3}
+    Mega  = "mega",   -- 10^{6}
+    Giga  = "giga",   -- 10^{9}
+    Tera  = "tera",   -- 10^{12}
+    Peta  = "peta",   -- 10^{15}
+    Exa   = "exa",    -- 10^{18}
+    Zetta = "zetta",  -- 10^{21}
+    Yotta = "yotta",  -- 10^{24}
+
+    -- IEC 60027-2: 2005, third edition, Part 2
+
+    Kibi  = "kibi", -- 2^{10} (not ki)
+    Mebi  = "mebi", -- 2^{20}
+    Gibi  = "gibi", -- 2^{30}
+    Tebi  = "tebi", -- 2^{40}
+    Pebi  = "pebi", -- 2^{50}
+    Exbi  = "exbi", -- 2^{60}
+
+    -- not standard
+
+    Zebi  = "zebi", -- binary
+    Yobi  = "yobi", -- binary
+
+    Micro = "micro",
+    Root  = "root",
+}
+
+local long_units = {
+
+    -- Le Système international d'unités (SI) 8e édition (except synonyms)
+    -- SI base units (Table 1)
+
+    Meter                       = "meter",
+    Gram                        = "gram",
+    Second                      = "second",
+    Ampere                      = "ampere",
+    Kelvin                      = "kelvin",
+    Mole                        = "mole",
+    Candela                     = "candela",
+
+    -- synonyms
+
+    Mol                         = "mole",
+    Metre                       = "meter",
+
+    -- SI derived units with special names (Table 3)
+
+    Radian                      = "radian",
+    Steradian                   = "steradian",
+    Hertz                       = "hertz",
+    Newton                      = "newton",
+    Pascal                      = "pascal",
+    Joule                       = "joule",
+    Watt                        = "watt",
+    Coulomb                     = "coulomb",
+    Volt                        = "volt",
+    Farad                       = "farad",
+    Ohm                         = "ohm",
+    Siemens                     = "siemens",
+    Weber                       = "weber",
+    Tesla                       = "tesla",
+    Henry                       = "henry",
+    Celsius                     = "celsius",
+    Lumen                       = "lumen",
+    Lux                         = "lux",
+    Becquerel                   = "becquerel",
+    Gray                        = "gray",
+    Sievert                     = "sievert",
+    Katal                       = "katal",
+
+    -- non SI units accepted for use with SI (Table 6)
+
+    Minute                      = "minute",
+    Hour                        = "hour",
+    Day                         = "day",
+
+    -- (degree, minute, second of arc are treated specially later)
+
+    Gon                         = "gon",
+    Grad                        = "grad",
+    Hectare                     = "hectare",
+    Liter                       = "liter",
+
+    Tonne                       = "tonne",
+
+    -- synonyms
+
+    MetricTon                   = "tonne",
+    Litre                       = "liter",
+
+    ["Metric Ton"]              = "tonne",
+
+    -- non-SI units whose values must be obtained experimentally (Table 7)
+
+    AtomicMassUnit              = "atomicmassunit",
+    AstronomicalUnit            = "astronomicalunit",
+    ElectronVolt                = "electronvolt",
+    Dalton                      = "dalton",
+
+    ["Atomic Mass Unit"]        = "atomicmassunit",
+    ["Astronomical Unit"]       = "astronomicalunit",
+    ["Electron Volt"]           = "electronvolt",
+
+    -- special cases (catch doubles, okay, a bit over the top)
+
+    DegreesCelsius              = "celsius",
+    DegreesFahrenheit           = "fahrenheit",
+    DegreeCelsius               = "celsius",
+    DegreeFahrenheit            = "fahrenheit",
+
+    ["Degrees Celsius"]         = "celsius",
+    ["Degrees Fahrenheit"]      = "fahrenheit",
+    ["Degree Celsius"]          = "celsius",
+    ["Degree Fahrenheit"]       = "fahrenheit",
+
+ -- too late as we already have connected symbols catched:
+ --
+ -- ["° Celsius"]               = "celsius",
+ -- ["° Fahrenheit"]            = "fahrenheit",
+ -- ["°Celsius"]                = "celsius",
+ -- ["°Fahrenheit"]             = "fahrenheit",
+
+    -- the "natural units" and "atomic units" are omitted for now
+    -- synonyms
+
+    eV                          = "electronvolt",
+    AMU                         = "atomicmassunit",
+
+    -- other non-SI units (Table 8)
+
+    Bar                         = "bar",
+    Hg                          = "mercury",
+ -- ["Millimetre Of Mercury"]   = [[mmHg]],
+    Angstrom                    = "angstrom", -- strictly Ångström
+    NauticalMile                = "nauticalmile",
+    Barn                        = "barn",
+    Knot                        = "knot",
+    Neper                       = "neper",
+    Bel                         = "bel", -- in practice only decibel used
+
+    ["Nautical Mile"]           = "nauticalmile",
+
+    -- other non-SI units from CGS system (Table 9)
+
+    Erg                         = "erg",
+    Dyne                        = "dyne",
+    Poise                       = "poise",
+    Stokes                      = "stokes",
+    Stilb                       = "stilb",
+    Phot                        = "phot",
+    Gal                         = "gal",
+    Maxwell                     = "maxwell",
+    Gauss                       = "gauss",
+    Oersted                     = "oersted",
+
+    -- end of SI
+
+    -- data: for use with the binary prefixes (except Erlang)
+
+    Bit                         = "bit",
+    Byte                        = "byte" ,
+    Baud                        = "baud",
+    Erlang                      = "erlang",
+
+    -- common units, not part of SI
+
+    Atmosphere                  = "atmosphere",
+    Revolution                  = "revolution",
+
+    -- synonyms
+
+    Atm                         = "atmosphere",
+    Rev                         = "revolution",
+
+    -- imperial units (very incomplete)
+
+    Fahrenheit                  = "fahrenheit",
+    Foot                        = "foot",
+    Inch                        = "inch",
+    Calorie                     = "calorie",
+
+    -- synonyms
+
+    Cal                         = "calorie",
+
+}
+
+local long_operators = {
+
+    Times   = "times",
+    Solidus = "solidus",
+    Per     = "per",
+    OutOf   = "outof",
+
+}
+
+local long_suffixes = {
+
+    Linear     = "linear",
+    Square     = "square",
+    Cubic      = "cubic",
+    Quadratic  = "quadratic",
+    Inverse    = "inverse",
+    ILinear    = "ilinear",
+    ISquare    = "isquare",
+    ICubic     = "icubic",
+    IQuadratic = "iquadratic",
+
+}
+
+local short_prefixes = {
+
+    y  = "yocto",
+    z  = "zetto",
+    a  = "atto",
+    f  = "femto",
+    p  = "pico",
+    n  = "nano",
+    u  = "micro",
+    m  = "milli",
+    c  = "centi",
+    d  = "deci",
+    da = "deca",
+    h  = "hecto",
+    k  = "kilo",
+    M  = "mega",
+    G  = "giga",
+    T  = "tera",
+    P  = "peta",
+    E  = "exa",
+    Z  = "zetta",
+    Y  = "yotta",
+
+}
+
+local short_units = { -- I'm not sure about casing
+
+    m  = "meter",
+    Hz = "hertz",
+    hz = "hertz",
+    B  = "bel",
+    b  = "bel",
+    lx = "lux",
+ -- da = "dalton",
+    h  = "hour",
+    s  = "second",
+    g  = "gram",
+    n  = "newton",
+    v  = "volt",
+    t  = "tonne",
+    l  = "liter",
+ -- w  = "watt",
+    W  = "watt",
+ -- a  = "ampere",
+    A  = "ampere",
+
+--  C  = "coulomb", -- needs checking with (c)enti
+--  K  = "kelvin",  -- needs checking with (k)ilo
+--  N  = "newton",  -- needs checking with (n)ewton
+
+    min = "minute",
+
+    [utfchar(0x2103)] = "celsius",
+    [utfchar(0x2109)] = "fahrenheit",
+}
+
+local short_operators = {
+    ["."] = "times",
+    ["*"] = "times",
+    ["/"] = "solidus",
+    [":"] = "outof",
+}
+
+local short_suffixes = { -- maybe just raw digit match
+    ["1"]   = "linear",
+    ["2"]   = "square",
+    ["3"]   = "cubic",
+    ["4"]   = "quadratic",
+    ["+1"]  = "linear",
+    ["+2"]  = "square",
+    ["+3"]  = "cubic",
+    ["+4"]  = "quadratic",
+    ["-1"]  = "inverse",
+    ["-1"]  = "ilinear",
+    ["-2"]  = "isquare",
+    ["-3"]  = "icubic",
+    ["-4"]  = "iquadratic",
+    ["^1"]  = "linear",
+    ["^2"]  = "square",
+    ["^3"]  = "cubic",
+    ["^4"]  = "quadratic",
+    ["^+1"] = "linear",
+    ["^+2"] = "square",
+    ["^+3"] = "cubic",
+    ["^+4"] = "quadratic",
+    ["^-1"] = "inverse",
+    ["^-1"] = "ilinear",
+    ["^-2"] = "isquare",
+    ["^-3"] = "icubic",
+    ["^-4"] = "iquadratic",
+}
+
+local symbol_units = {
+    Degrees    = "degree",
+    Degree     = "degree",
+ -- Deg        = "degree",
+    ["°"]      = "degree",
+    ArcMinute  = "arcminute",
+    ["′"]      = "arcminute", -- 0x2032
+    ArcSecond  = "arcsecond",
+    ["″"]      = "arcsecond", -- 0x2033
+    Percent    = "percent",
+    ["%"]      = "percent",
+    Promille   = "permille",
+    Permille   = "permille",
+}
+
+local packaged_units = {
+    Micron = "micron",
+    mmHg   = "millimetermercury",
+}
+
+-- rendering:
+
+local ctx_unitsPUS    = context.unitsPUS
+local ctx_unitsPU     = context.unitsPU
+local ctx_unitsPS     = context.unitsPS
+local ctx_unitsP      = context.unitsP
+local ctx_unitsUS     = context.unitsUS
+local ctx_unitsU      = context.unitsU
+local ctx_unitsS      = context.unitsS
+local ctx_unitsO      = context.unitsO
+local ctx_unitsN      = context.unitsN
+local ctx_unitsC      = context.unitsC
+local ctx_unitsQ      = context.unitsQ
+local ctx_unitsRPM    = context.unitsRPM
+local ctx_unitsRTO    = context.unitsRTO
+local ctx_unitsRabout = context.unitsRabout
+local ctx_unitsNstart = context.unitsNstart
+local ctx_unitsNstop  = context.unitsNstop
+local ctx_unitsNspace = context.unitsNspace
+local ctx_unitsPopen  = context.unitsPopen
+local ctx_unitsPclose = context.unitsPclose
+
+local labels = languages.data.labels
+
+labels.prefixes = allocate {
+    yocto = { labels = { en = [[y]]   } }, -- 10^{-24}
+    zepto = { labels = { en = [[z]]   } }, -- 10^{-21}
+    atto  = { labels = { en = [[a]]   } }, -- 10^{-18}
+    femto = { labels = { en = [[f]]   } }, -- 10^{-15}
+    pico  = { labels = { en = [[p]]   } }, -- 10^{-12}
+    nano  = { labels = { en = [[n]]   } }, -- 10^{-9}
+    micro = { labels = { en = [[\mu]] } }, -- 10^{-6}
+    milli = { labels = { en = [[m]]   } }, -- 10^{-3}
+    centi = { labels = { en = [[c]]   } }, -- 10^{-2}
+    deci  = { labels = { en = [[d]]   } }, -- 10^{-1}
+    deca  = { labels = { en = [[da]]  } }, -- 10^{1}
+    hecto = { labels = { en = [[h]]   } }, -- 10^{2}
+    kilo  = { labels = { en = [[k]]   } }, -- 10^{3}
+    mega  = { labels = { en = [[M]]   } }, -- 10^{6}
+    giga  = { labels = { en = [[G]]   } }, -- 10^{9}
+    tera  = { labels = { en = [[T]]   } }, -- 10^{12}
+    peta  = { labels = { en = [[P]]   } }, -- 10^{15}
+    exa   = { labels = { en = [[E]]   } }, -- 10^{18}
+    zetta = { labels = { en = [[Z]]   } }, -- 10^{21}
+    yotta = { labels = { en = [[Y]]   } }, -- 10^{24}
+    kibi  = { labels = { en = [[Ki]]  } }, -- 2^{10} (not ki)
+    mebi  = { labels = { en = [[Mi]]  } }, -- 2^{20}
+    gibi  = { labels = { en = [[Gi]]  } }, -- 2^{30}
+    tebi  = { labels = { en = [[Ti]]  } }, -- 2^{40}
+    pebi  = { labels = { en = [[Pi]]  } }, -- 2^{50}
+    exbi  = { labels = { en = [[Ei]]  } }, -- 2^{60}
+    zebi  = { labels = { en = [[Zi]]  } }, -- binary
+    yobi  = { labels = { en = [[Yi]]  } }, -- binary
+    micro = { labels = { en = [[µ]]   } }, -- 0x00B5 \textmu
+    root  = { labels = { en = [[√]]   } }, -- 0x221A
+}
+
+labels.units = allocate {
+    meter                       = { labels = { en = [[m]]                        } },
+    gram                        = { labels = { en = [[g]]                        } }, -- strictly kg is the base unit
+    second                      = { labels = { en = [[s]]                        } },
+    ampere                      = { labels = { en = [[A]]                        } },
+    kelvin                      = { labels = { en = [[K]]                        } },
+    mole                        = { labels = { en = [[mol]]                      } },
+    candela                     = { labels = { en = [[cd]]                       } },
+    mol                         = { labels = { en = [[mol]]                      } },
+    radian                      = { labels = { en = [[rad]]                      } },
+    steradian                   = { labels = { en = [[sr]]                       } },
+    hertz                       = { labels = { en = [[Hz]]                       } },
+    newton                      = { labels = { en = [[N]]                        } },
+    pascal                      = { labels = { en = [[Pa]]                       } },
+    joule                       = { labels = { en = [[J]]                        } },
+    watt                        = { labels = { en = [[W]]                        } },
+    coulomb                     = { labels = { en = [[C]]                        } },
+    volt                        = { labels = { en = [[V]]                        } },
+    farad                       = { labels = { en = [[F]]                        } },
+    ohm                         = { labels = { en = [[Ω]]                        } }, -- 0x2126 \textohm
+    siemens                     = { labels = { en = [[S]]                        } },
+    weber                       = { labels = { en = [[Wb]]                       } },
+    mercury                     = { labels = { en = [[Hg]]                       } },
+    millimetermercury           = { labels = { en = [[mmHg]]                     } }, -- connected
+    tesla                       = { labels = { en = [[T]]                        } },
+    henry                       = { labels = { en = [[H]]                        } },
+    celsius                     = { labels = { en = [[\checkedtextcelsius]]      } }, -- 0x2103
+    lumen                       = { labels = { en = [[lm]]                       } },
+    lux                         = { labels = { en = [[lx]]                       } },
+    becquerel                   = { labels = { en = [[Bq]]                       } },
+    gray                        = { labels = { en = [[Gy]]                       } },
+    sievert                     = { labels = { en = [[Sv]]                       } },
+    katal                       = { labels = { en = [[kat]]                      } },
+    minute                      = { labels = { en = [[min]]                      } },
+    hour                        = { labels = { en = [[h]]                        } },
+    day                         = { labels = { en = [[d]]                        } },
+    gon                         = { labels = { en = [[gon]]                      } },
+    grad                        = { labels = { en = [[grad]]                     } },
+    hectare                     = { labels = { en = [[ha]]                       } },
+    liter                       = { labels = { en = [[l]]                        } }, -- symbol l or L
+    tonne                       = { labels = { en = [[t]]                        } },
+    electronvolt                = { labels = { en = [[eV]]                       } },
+    dalton                      = { labels = { en = [[Da]]                       } },
+    atomicmassunit              = { labels = { en = [[u]]                        } },
+    astronomicalunit            = { labels = { en = [[au]]                       } },
+    bar                         = { labels = { en = [[bar]]                      } },
+    angstrom                    = { labels = { en = [[Å]]                        } }, -- strictly Ångström
+    nauticalmile                = { labels = { en = [[M]]                        } },
+    barn                        = { labels = { en = [[b]]                        } },
+    knot                        = { labels = { en = [[kn]]                       } },
+    neper                       = { labels = { en = [[Np]]                       } },
+    bel                         = { labels = { en = [[B]]                        } }, -- in practice only decibel used
+    erg                         = { labels = { en = [[erg]]                      } },
+    dyne                        = { labels = { en = [[dyn]]                      } },
+    poise                       = { labels = { en = [[P]]                        } },
+    stokes                      = { labels = { en = [[St]]                       } },
+    stilb                       = { labels = { en = [[sb]]                       } },
+    phot                        = { labels = { en = [[phot]]                     } },
+    gal                         = { labels = { en = [[gal]]                      } },
+    maxwell                     = { labels = { en = [[Mx]]                       } },
+    gauss                       = { labels = { en = [[G]]                        } },
+    oersted                     = { labels = { en = [[Oe]]                       } }, -- strictly Œrsted
+    bit                         = { labels = { en = [[bit]]                      } },
+    byte                        = { labels = { en = [[B]]                        } },
+    baud                        = { labels = { en = [[Bd]]                       } },
+    erlang                      = { labels = { en = [[E]]                        } },
+    atmosphere                  = { labels = { en = [[atm]]                      } },
+    revolution                  = { labels = { en = [[rev]]                      } },
+    fahrenheit                  = { labels = { en = [[\checkedtextfahrenheit]]   } }, -- 0x2109
+    foot                        = { labels = { en = [[ft]]                       } },
+    inch                        = { labels = { en = [[inch]]                     } },
+    calorie                     = { labels = { en = [[cal]]                      } },
+    --
+    degree                      = { labels = { en = [[°]]} },
+    arcminute                   = { labels = { en = [[\checkedtextprime]]        } }, -- ′ 0x2032
+    arcsecond                   = { labels = { en = [[\checkedtextdoubleprime]]  } }, -- ″ 0x2033
+    percent                     = { labels = { en = [[\percent]]                 } },
+    permille                    = { labels = { en = [[\promille]]                } },
+    --
+    micron                      = { labels = { en = [[\textmu m]]                } },
+}
+
+labels.operators = allocate {
+    times   = { labels = { en = [[\unitsTIMES]]   } },
+    solidus = { labels = { en = [[\unitsSOLIDUS]] } },
+    per     = { labels = { en = [[\unitsSOLIDUS]] } },
+    outof   = { labels = { en = [[\unitsOUTOF]]   } },
+}
+
+labels.suffixes = allocate {
+    linear     = { labels = { en = [[1]]  } },
+    square     = { labels = { en = [[2]]  } },
+    cubic      = { labels = { en = [[3]]  } },
+    quadratic  = { labels = { en = [[4]]  } },
+    inverse    = { labels = { en = [[\mathminus1]] } },
+    ilinear    = { labels = { en = [[\mathminus1]] } },
+    isquare    = { labels = { en = [[\mathminus2]] } },
+    icubic     = { labels = { en = [[\mathminus3]] } },
+    iquadratic = { labels = { en = [[\mathminus4]] } },
+}
+
+local function dimpus(p,u,s)
+    if trace_units then
+        report_units("prefix %a, unit %a, suffix %a",p,u,s)
+    end    --
+    if p ~= "" then
+        if u ~= ""  then
+            if s ~= ""  then
+                ctx_unitsPUS(p,u,s)
+            else
+                ctx_unitsPU(p,u)
+            end
+        elseif s ~= ""  then
+            ctx_unitsPS(p,s)
+        else
+            ctx_unitsP(p)
+        end
+    else
+        if u ~= ""  then
+            if s ~= ""  then
+                ctx_unitsUS(u,s)
+         -- elseif c then
+         --     ctx_unitsC(u)
+            else
+                ctx_unitsU(u)
+            end
+        elseif s ~= ""  then
+            ctx_unitsS(s)
+        else
+            ctx_unitsP(p)
+        end
+    end
+end
+
+local function dimspu(s,p,u)
+    return dimpus(p,u,s)
+end
+
+local function dimop(o)
+    if trace_units then
+        report_units("operator %a",o)
+    end
+    if o then
+        ctx_unitsO(o)
+    end
+end
+
+local function dimsym(s)
+    if trace_units then
+        report_units("symbol %a",s)
+    end
+    s = symbol_units[s] or s
+    if s then
+        ctx_unitsC(s)
+    end
+end
+
+local function dimpre(p)
+    if trace_units then
+        report_units("prefix [%a",p)
+    end
+    p = packaged_units[p] or p
+    if p then
+        ctx_unitsU(p)
+    end
+end
+
+-- patterns:
+--
+-- space inside Cs else funny captures and args to function
+--
+-- square centi meter per square kilo seconds
+
+-- todo 0x -> rm
+
+local function update_parsers(keepcase) -- todo: don't remap utf sequences
+
+    local all_long_prefixes   = { }
+    local all_long_units      = { }
+    local all_long_operators  = { }
+    local all_long_suffixes   = { }
+    local all_symbol_units    = { }
+    local all_packaged_units  = { }
+
+    local all_short_prefixes  = { }
+    local all_short_units     = { }
+    local all_short_operators = { }
+    local all_short_suffixes  = { }
+
+    for k, v in sortedhash(long_prefixes)  do all_long_prefixes [k] = v all_long_prefixes [lower(k)] = v end
+    for k, v in sortedhash(long_units)     do all_long_units    [k] = v all_long_units    [lower(k)] = v end
+    for k, v in sortedhash(long_operators) do all_long_operators[k] = v all_long_operators[lower(k)] = v end
+    for k, v in sortedhash(long_suffixes)  do all_long_suffixes [k] = v all_long_suffixes [lower(k)] = v end
+    for k, v in sortedhash(symbol_units)   do all_symbol_units  [k] = v all_symbol_units  [lower(k)] = v end
+    for k, v in sortedhash(packaged_units) do all_packaged_units[k] = v all_packaged_units[lower(k)] = v end
+
+    for k, v in sortedhash(user_long_prefixes)  do all_long_prefixes [k] = v if not keepcase then all_long_prefixes [lower(k)] = v end end
+    for k, v in sortedhash(user_long_units)     do all_long_units    [k] = v if not keepcase then all_long_units    [lower(k)] = v end end
+    for k, v in sortedhash(user_long_operators) do all_long_operators[k] = v if not keepcase then all_long_operators[lower(k)] = v end end
+    for k, v in sortedhash(user_long_suffixes)  do all_long_suffixes [k] = v if not keepcase then all_long_suffixes [lower(k)] = v end end
+    for k, v in sortedhash(user_symbol_units)   do all_symbol_units  [k] = v if not keepcase then all_symbol_units  [lower(k)] = v end end
+    for k, v in sortedhash(user_packaged_units) do all_packaged_units[k] = v if not keepcase then all_packaged_units[lower(k)] = v end end
+
+    for k, v in sortedhash(short_prefixes)  do all_short_prefixes [k] = v end
+    for k, v in sortedhash(short_units)     do all_short_units    [k] = v end
+    for k, v in sortedhash(short_operators) do all_short_operators[k] = v end
+    for k, v in sortedhash(short_suffixes)  do all_short_suffixes [k] = v end
+
+    for k, v in sortedhash(user_short_prefixes)  do all_short_prefixes [k] = v end
+    for k, v in sortedhash(user_short_units)     do all_short_units    [k] = v end
+    for k, v in sortedhash(user_short_operators) do all_short_operators[k] = v end
+    for k, v in sortedhash(user_short_suffixes)  do all_short_suffixes [k] = v end
+
+    local somespace        = P(" ")^0/""
+
+    local p_long_prefix    = appendlpeg(all_long_prefixes,nil,true)
+    local p_long_unit      = appendlpeg(all_long_units,nil,true)
+    local p_long_operator  = appendlpeg(all_long_operators,nil,true)
+    local p_long_suffix    = appendlpeg(all_long_suffixes,nil,true)
+    local p_symbol         = appendlpeg(all_symbol_units,nil,true)
+    local p_packaged       = appendlpeg(all_packaged_units,nil,true)
+
+    local p_short_prefix   = appendlpeg(all_short_prefixes)
+    local p_short_unit     = appendlpeg(all_short_units)
+    local p_short_operator = appendlpeg(all_short_operators)
+    local p_short_suffix   = appendlpeg(all_short_suffixes)
+
+    -- more efficient but needs testing
+
+--     local p_long_prefix    = utfchartabletopattern(all_long_prefixes)  / all_long_prefixes
+--     local p_long_unit      = utfchartabletopattern(all_long_units)     / all_long_units
+--     local p_long_operator  = utfchartabletopattern(all_long_operators) / all_long_operators
+--     local p_long_suffix    = utfchartabletopattern(all_long_suffixes)  / all_long_suffixes
+--     local p_symbol         = utfchartabletopattern(all_symbol_units)   / all_symbol_units
+--     local p_packaged       = utfchartabletopattern(all_packaged_units) / all_packaged_units
+
+--     local p_short_prefix   = utfchartabletopattern(all_short_prefixes)  / all_short_prefixes
+--     local p_short_unit     = utfchartabletopattern(all_short_units)     / all_short_units
+--     local p_short_operator = utfchartabletopattern(all_short_operators) / all_short_operators
+--     local p_short_suffix   = utfchartabletopattern(all_short_suffixes)  / all_short_suffixes
+
+    -- we can can cleanup some space issues here (todo)
+
+    local unitparser = P { "unit",
+        --
+        longprefix    = Cs(V("somespace") * p_long_prefix),
+        shortprefix   = Cs(V("somespace") * p_short_prefix),
+        longsuffix    = Cs(V("somespace") * p_long_suffix),
+        shortsuffix   = Cs(V("somespace") * p_short_suffix),
+        shortunit     = Cs(V("somespace") * p_short_unit),
+        longunit      = Cs(V("somespace") * p_long_unit),
+        longoperator  = Cs(V("somespace") * p_long_operator),
+        shortoperator = Cs(V("somespace") * p_short_operator),
+        packaged      = Cs(V("somespace") * p_packaged),
+        --
+        nothing       = Cc(""),
+        somespace     = somespace,
+        nospace       = (1-somespace)^1, -- was 0
+     -- ignore        = P(-1),
+        --
+        qualifier     = Cs(V("somespace") * (lparent/"") * (1-rparent)^1 * (rparent/"")),
+        --
+        somesymbol    = V("somespace")
+                      * (p_symbol/dimsym)
+                      * V("somespace"),
+        somepackaged  = V("somespace")
+                      * (V("packaged") / dimpre)
+                      * V("somespace"),
+     -- someunknown   = V("somespace")
+     --               * (V("nospace")/ctx_unitsU)
+     --               * V("somespace"),
+        --
+        combination   = V("longprefix")  * V("longunit")   -- centi meter
+                      + V("nothing")     * V("longunit")
+                      + V("shortprefix") * V("shortunit")  -- c m
+                      + V("nothing")     * V("shortunit")
+                      + V("longprefix")  * V("shortunit")  -- centi m
+                      + V("shortprefix") * V("longunit"),  -- c meter
+
+--         combination   = (   V("longprefix")   -- centi meter
+--                           + V("nothing")
+--                         ) * V("longunit")
+--                       + (   V("shortprefix")  -- c m
+--                           + V("nothing")
+--                           + V("longprefix")
+--                         ) * V("shortunit")    -- centi m
+--                       + (   V("shortprefix")  -- c meter
+--                         ) * V("longunit"),
+
+
+        dimension     = V("somespace")
+                      * (
+                            V("packaged") / dimpre
+                          + (V("longsuffix") * V("combination")) / dimspu
+                          + (V("combination") * (V("shortsuffix") + V("nothing"))) / dimpus
+                        )
+                      * (V("qualifier") / ctx_unitsQ)^-1
+                      * V("somespace"),
+        operator      = V("somespace")
+                      * ((V("longoperator") + V("shortoperator")) / dimop)
+                      * V("somespace"),
+        snippet       = V("dimension")
+                      + V("somesymbol"),
+        unit          = (   V("snippet") * (V("operator") * V("snippet"))^0
+                          + V("somepackaged")
+                        )^1,
+    }
+
+    -- todo: avoid \ctx_unitsNstart\ctx_unitsNstop (weird that it can happen .. now catched at tex end)
+
+    local letter = R("az","AZ")
+    local bound  = #(1-letter)
+ -- local number = lpeg.patterns.number
+    local number = Cs( P("$")     * (1-P("$"))^1 * P("$")
+                     + P([[\m{]]) * (1-P("}"))^1 * P("}")
+                     + (1-letter-P(" "))^1 -- todo: catch { } -- not ok
+                   ) / ctx_unitsN
+
+    local start   = Cc(nil) / ctx_unitsNstart
+    local stop    = Cc(nil) / ctx_unitsNstop
+    local space   = P(" ") * Cc(nil) / ctx_unitsNspace
+    local open    = P("(") * Cc(nil) / ctx_unitsPopen
+    local close   = P(")") * Cc(nil) / ctx_unitsPclose
+
+    local range   = somespace
+                  * ( (P("±") + P("pm") * bound) / "" / ctx_unitsRPM
+                    + (P("–") + P("to") * bound) / "" / ctx_unitsRTO )
+                  * somespace
+
+    local about   = (P("±") + P("pm") * bound) / "" / ctx_unitsRabout
+                  * somespace
+
+    -- todo: start / stop
+
+    local function combine(parser)
+        return P { "start",
+            number  = start * dleader * (parser + number) * stop,
+            anumber = space
+                    * open
+                    * V("about")^-1
+                    * V("number")
+                    * close,
+            rule    = V("number")^-1
+                    * (V("range") * V("number") + V("anumber"))^-1,
+            unit    = unitparser,
+            about   = about,
+            range   = range,
+            space   = space,
+            start   = V("rule")
+                    * V("unit")
+                    * (V("space") * V("rule") * V("unit"))^0
+                    + open
+                    * V("number")
+                    * (V("range") * V("number"))^-1
+                    * close
+                    * dtrailer^-1
+                    * V("unit")
+                    + V("number")
+        }
+    end
+
+    return combine(p_c_dparser), combine(c_p_dparser)
+end
+
+local p_c_parser_lowercase = nil
+local c_p_parser_lowercase = nil
+local p_c_parser_keepcase  = nil
+local c_p_parser_keepcase  = nil
+
+local dirty_lowercase = true
+local dirty_keepcase  = true
+
+local v_reverse = interfaces.variables.reverse
+local v_keep    = interfaces.variables.keep
+
+local function makeunit(order,option,str)
+    local reverse = order  == v_reverse
+    local keep    = option == v_keep
+    local parser
+    if keep then
+        if dirty_keepcase then
+            if trace_units then
+                report_units("initializing case %s parser","sensititive")
+            end
+            p_c_parser_keepcase, c_p_parser_keepcase = update_parsers(true)
+            dirty_keepcase = false
+        end
+        parser = reverse and p_c_parser_keepcase or c_p_parser_keepcase
+    else
+        if dirty_lowercase then
+            if trace_units then
+                report_units("initializing case %s parser","insensititive")
+            end
+            p_c_parser_lowercase, c_p_parser_lowercase = update_parsers()
+            dirty_lowercase = false
+        end
+        parser = reverse and p_c_parser_lowercase or c_p_parser_lowercase
+    end
+    if not matchlpeg(parser,str) then
+        report_units("unable to parse: %s",str)
+        context(str)
+    end
+end
+
+local function trigger(t,k,v)
+    rawset(t,k,v)
+    dirty_lowercase = true
+    dirty_keepcase  = true
+end
+
+local t_units = {
+    prefixes  = setmetatablenewindex(long_prefixes,trigger),
+    units     = setmetatablenewindex(long_units,trigger),
+    operators = setmetatablenewindex(long_operators,trigger),
+    suffixes  = setmetatablenewindex(long_suffixes,trigger),
+    symbols   = setmetatablenewindex(symbol_units,trigger),
+    packaged  = setmetatablenewindex(packaged_units,trigger),
+}
+
+local t_shortcuts = {
+    prefixes  = setmetatablenewindex(short_prefixes,trigger),
+    units     = setmetatablenewindex(short_units,trigger),
+    operators = setmetatablenewindex(short_operators,trigger),
+    suffixes  = setmetatablenewindex(short_suffixes,trigger),
+}
+
+local t_userunits = {
+    prefixes  = setmetatablenewindex(user_long_prefixes,trigger),
+    units     = setmetatablenewindex(user_long_units,trigger),
+    operators = setmetatablenewindex(user_long_operators,trigger),
+    suffixes  = setmetatablenewindex(user_long_suffixes,trigger),
+    symbols   = setmetatablenewindex(user_symbol_units,trigger),
+    packaged  = setmetatablenewindex(user_packaged_units,trigger),
+}
+
+local t_usershortcuts = {
+    prefixes  = setmetatablenewindex(user_short_prefixes,trigger),
+    units     = setmetatablenewindex(user_short_units,trigger),
+    operators = setmetatablenewindex(user_short_operators,trigger),
+    suffixes  = setmetatablenewindex(user_short_suffixes,trigger),
+}
+
+physics.units.tables = allocate {
+    units         = t_units,
+    shortcuts     = t_shortcuts,
+    userunits     = t_userunits,
+    usershortcuts = t_usershortcuts,
+}
+
+local mapping = {
+    prefix   = "prefixes",
+    unit     = "units",
+    operator = "operators",
+    suffix   = "suffixes",
+    symbol   = "symbols",
+    packaged = "packaged",
+}
+
+local function register(category,list,target)
+    if not list or list == "" then
+        list = category
+        category = "unit"
+    end
+    local t = target[mapping[category]]
+    if t then
+        for k, v in next, utilities.parsers.settings_to_hash(list or "") do
+            t[k] = v
+        end
+    end
+ -- inspect(tables)
+end
+
+local function registerunit    (category,list) register(category,list,t_userunits) end
+local function registershortcut(category,list) register(category,list,t_usershortcuts) end
+
+physics.units.registerunit     = registerunit
+physics.units.registershortcut = registershortcut
+
+implement {
+    name      = "digits_normal",
+    actions   = makedigits,
+    arguments = "string",
+}
+
+implement {
+    name      = "digits_reverse",
+    actions   = makedigits,
+    arguments = { "string", true },
+}
+
+implement {
+    name      = "unit",
+    actions   = makeunit,
+    arguments = "3 strings"
+}
+
+implement {
+    name      = "registerunit",
+    actions   = registerunit,
+    arguments = "2 strings",
+}
+
+implement {
+    name      = "registerunitshortcut",
+    actions   = registershortcut,
+    arguments = "2 strings",
+}
+
+implement {
+    name      = "hyphenateddigits",
+    public    = true,
+    protected = true,
+    arguments = { "optional", "string" },
+    actions   = function(filler, digits)
+        digits = gsub(digits,"(%d)","%1\\digitsbreak ") -- space needed for following letters
+        digits = gsub(digits,"\\-$",filler)
+        context(digits)
+    end
+}
diff --git a/tex/context/base/mkxl/phys-dim.mkxl b/tex/context/base/mkxl/phys-dim.mkxl
index 8277ba231..1d5e7fff6 100644
--- a/tex/context/base/mkxl/phys-dim.mkxl
+++ b/tex/context/base/mkxl/phys-dim.mkxl
@@ -11,7 +11,7 @@
 %C therefore copyrighted by \PRAGMA. See mreadme.pdf for
 %C details.
 
-\registerctxluafile{phys-dim}{}
+\registerctxluafile{phys-dim}{autosuffix}
 
 % TAGGING NEEDS CHECKING ... WILL DO WHEN PARSER IS OK
 
@@ -354,7 +354,8 @@
   [\c!alternative=,              % done: text
    \c!separator=\v!normal,       % done: cdot|big|medium|space
    \s!language=\currentlanguage, % done: (no interface yet)
-   \c!order=\v!normal,           % ,. (reverse: .,)
+   \c!order=,                    % reverse
+   \c!option=,                   % keep (case)
    \c!method=0,
   %\c!grid=\v!yes,               % (maybe)
   %\c!style=...,                 % done
@@ -431,7 +432,7 @@
 \to \everyunits
 
 \appendtoks
-    \frozen\instance\setuevalue\currentunit{\phys_units_direct{\currentunit}}
+    \frozen\protected\instance\edefcsname\currentunit\endcsname{\phys_units_direct{\currentunit}}
 \to \everydefineunit
 
 \protected\def\phys_units_direct#1%
@@ -441,9 +442,10 @@
      \settrue\c_phys_units_dospace
      \removelastskip
    \fi
+   \edef\currentunit{#1}%
    \c_phys_digits_method\unitparameter\c!method\relax
    \ifmmode\else\dontleavehmode\fi
-   \edef\currentunit{#1}%
+%    \edef\currentunit{#1}%
    \enforced\edef\unitlanguage{\unitparameter\s!language}%
    \enforced\let\prefixlanguage\unitlanguage
    \enforced\let\operatorlanguage\unitlanguage
@@ -503,9 +505,17 @@
     \let\phys_units_direct\phys_units_direct_nested
 \to \everyunits
 
+% \protected\def\phys_units_indeed#1%
+%   {\edef\p_order{\unitparameter\c!order}%
+%    \ifx\p_order\v!reverse
+%      \expandafter\clf_unit_reverse
+%    \else
+%      \expandafter\clf_unit_normal
+%    \fi
+%    {\detokenize{#1}}}
+
 \protected\def\phys_units_indeed#1%
-  {\edef\p_order{\unitparameter\c!order}%
-   \ifx\p_order\v!reverse\expandafter\clf_unit_reverse\else\expandafter\clf_unit_normal\fi{\detokenize{#1}}}
+  {\clf_unit{\unitparameter\c!order}{\unitparameter\c!option}{\detokenize{#1}}}
 
 \permanent\protected\def\unitsPUS#1#2#3{\phys_units_next\prefixtext{#1}\unittext{#2}\unitsraise{\suffixtext{#3}}\c_phys_units_state\plusone} % suffix
 \permanent\protected\def\unitsPU   #1#2{\phys_units_next\prefixtext{#1}\unittext{#2}\c_phys_units_state\plusthree}                           % unit
@@ -682,7 +692,7 @@
    \setfalse\c_phys_units_dospace
    \phys_units_start}
 
-\permanent\protected\def\unitsTIMES % GP: Does this do anything? HH: yes "times" 
+\permanent\protected\def\unitsTIMES % GP: Does this do anything? HH: yes "times"
   {\ifnum\c_phys_units_state=\plusone % suffix
    \else
      \unitssmallspace
@@ -737,8 +747,44 @@
 %D    cicero=cc]
 %D \stoptyping
 
-\permanent\tolerant\protected\def\registerunit[#1]#*[#2]% todo: public implementer
-  {\clf_registerunit{#1}{#2}}
+\permanent\tolerant\protected\def\registerunit        [#1]#*[#2]{\clf_registerunit        {#1}{#2}}
+\permanent\tolerant\protected\def\registerunitshortcut[#1]#*[#2]{\clf_registerunitshortcut{#1}{#2}}
+
+%D \starttyping
+%D \registerunit
+%D   [unit]
+%D   [Point=PT,
+%D    point=pt,
+%D    Basepoint=BP,
+%D  % basepoint=bp,
+%D    ]
+%D
+%D \registerunitshortcut
+%D   [unit]
+%D   [C=coulomb]
+%D
+%D \startlines
+%D 10 \unit {square meter per second}
+%D 10 \unit {square Meter per Second}
+%D 10 \unit {point}
+%D 10 \unit {Point}
+%D 10 \unit {basepoint}
+%D 10 \unit {Basepoint}
+%D 10 \unit {C}
+%D \stoplines
+%D
+%D \setupunit[unit][option=keep]
+%D
+%D \startlines
+%D 10 \unit {square meter per second}
+%D 10 \unit {square Meter per Second}
+%D 10 \unit {point}
+%D 10 \unit {Point}
+%D 10 \unit {basepoint}
+%D 10 \unit {Basepoint}
+%D 10 \unit {C}
+%D \stoplines
+%D \stoptyping
 
 %D You can generate a list as follows:
 %D
diff --git a/tex/context/base/mkxl/strc-flt.mklx b/tex/context/base/mkxl/strc-flt.mklx
index 6af22631a..c96fb02d0 100644
--- a/tex/context/base/mkxl/strc-flt.mklx
+++ b/tex/context/base/mkxl/strc-flt.mklx
@@ -531,9 +531,9 @@
 
 \def\strc_floats_apply_caption_command
   {\setbox\b_strc_floats_caption\hbox\bgroup
-    %\unless\ifcstok{\floatcaptionparameter\c!command}\emptytoks
+    %\unless\iftok{\floatcaptionparameter\c!command}\emptytoks
        \floatcaptionparameter\c!command{\box\b_strc_floats_caption}%
-    %\orunless\ifcstok{\floatcaptionparameter\c!deeptextcommand}\emptytoks
+    %\orunless\iftok{\floatcaptionparameter\c!deeptextcommand}\emptytoks
     %  \floatcaptionparameter\c!deeptextcommand{\unvbox\b_strc_floats_caption}%
     %\else
     %  \box\b_strc_floats_caption
diff --git a/tex/context/base/mkxl/strc-lst.mklx b/tex/context/base/mkxl/strc-lst.mklx
index 6b8f2504f..dd9f1fb4d 100644
--- a/tex/context/base/mkxl/strc-lst.mklx
+++ b/tex/context/base/mkxl/strc-lst.mklx
@@ -1498,7 +1498,8 @@
    \ifcsname\??listinteractions\p_interaction_forward\endcsname
     %\expandafter\let\expandafter\p_interaction_forward\csname\??listinteractions\p_interaction_forward\endcsname
      \expandafter\let\expandafter\p_interaction_forward\lastnamedcs
-     \ifcstok{\structurelistexternal}\emptytoks % luacall
+    %\ifcstok{\structurelistexternal}\emptytoks % luacall
+     \iftok{\structurelistexternal}\emptytoks % luacall
        \strc_references_get_simple_reference{internal(\currentlistentrylocation)}%
      \else
      % \writestatus{FAR OUT LIST}{\structurelistexternal::page(\number\structurelistrealpagenumber)}%
diff --git a/tex/context/base/mkxl/syst-aux.mkxl b/tex/context/base/mkxl/syst-aux.mkxl
index 2b87f4b3d..c3a4a97b2 100644
--- a/tex/context/base/mkxl/syst-aux.mkxl
+++ b/tex/context/base/mkxl/syst-aux.mkxl
@@ -587,7 +587,7 @@
 % or (test this):
 %
 % \permanent\protected\def\processallactionsinset[#1]%
-%   {\ifcstok{#1}\emptytoks
+%   {\iftok{#1}\emptytoks
 %      \expandafter\processaction
 %    \else
 %      \expandafter\syst_helpers_process_all_actions_in_set_indeed
diff --git a/tex/context/base/mkxl/syst-ini.mkxl b/tex/context/base/mkxl/syst-ini.mkxl
index 2b37e30c6..46f02653a 100644
--- a/tex/context/base/mkxl/syst-ini.mkxl
+++ b/tex/context/base/mkxl/syst-ini.mkxl
@@ -1308,7 +1308,7 @@
    \endlocalcontrol
    #2}
 
-\permanent\protected\def\suggestedalias#1#2%
+\permanent\protected\def\suggestedalias#1#2% old new
   {\ifflags#2\permanent\permanent\fi % the rest is taken with the copy
    \def#1{\syst_suggested_alias#1#2}}
 
diff --git a/tex/context/base/mkxl/tabl-ntb.mkxl b/tex/context/base/mkxl/tabl-ntb.mkxl
index 414a04f3a..6e95512cd 100644
--- a/tex/context/base/mkxl/tabl-ntb.mkxl
+++ b/tex/context/base/mkxl/tabl-ntb.mkxl
@@ -2377,7 +2377,7 @@
    \tabl_ntb_section_disable}
 
 \tolerant\permanent\protected\def\bTABLEsection[#1]%
-  {\ifempty{#1}%
+  {\iftok{#1}\emptytoks
      \global\c_tabl_ntb_section_repeat\zerocount
    \else
      \letdummyparameter\c!repeat\zerocount
diff --git a/tex/context/base/mkxl/tabl-tab.mkxl b/tex/context/base/mkxl/tabl-tab.mkxl
index 8c872cd47..c680a4474 100644
--- a/tex/context/base/mkxl/tabl-tab.mkxl
+++ b/tex/context/base/mkxl/tabl-tab.mkxl
@@ -504,7 +504,7 @@
 % Key "M": Displaymath mode.
 
 \newtableformatkey M%
-  {\doreadtableformatkeys \{ b{\normalstartimath\displaystyle} a{\normalstopimath}}
+  {\doreadtableformatkeys \{ b{\normalstartimath\forcedisplaymath} a{\normalstopimath}}
 
 % Key "\m": Template ${}#\hfil$
 
diff --git a/tex/context/base/mkxl/tabl-tbl.mkxl b/tex/context/base/mkxl/tabl-tbl.mkxl
index 6c4c3fd47..d353074d5 100644
--- a/tex/context/base/mkxl/tabl-tbl.mkxl
+++ b/tex/context/base/mkxl/tabl-tbl.mkxl
@@ -589,7 +589,7 @@
 \installtabulatepreambleoption{m}{\t_tabl_tabulate_bmath{\normalstartimath}%
                                   \t_tabl_tabulate_emath{\normalstopimath}%
                                   \tabl_tabulate_set_preamble}
-\installtabulatepreambleoption{M}{\t_tabl_tabulate_bmath{\normalstartimath\displaystyle}%
+\installtabulatepreambleoption{M}{\t_tabl_tabulate_bmath{\normalstartimath\forcedisplaymath}%
                                   \t_tabl_tabulate_emath{\normalstopimath}%
                                   \tabl_tabulate_set_preamble}
 \installtabulatepreambleoption{h}{\tabl_tabulate_set_hook}
diff --git a/tex/context/base/mkxl/typo-ada.lmt b/tex/context/base/mkxl/typo-ada.lmt
index 37393ca77..099479383 100644
--- a/tex/context/base/mkxl/typo-ada.lmt
+++ b/tex/context/base/mkxl/typo-ada.lmt
@@ -62,12 +62,13 @@ function adaptive.set(settings)
     texsetattribute(a_adaptive,registervalue(a_adaptive,settings))
 end
 
-local function setadaptive(w,h,d,l,c)
+local function setadaptive(w,h,d,l,c,a)
     setdimen(d_adaptive_width,w)
     setdimen(d_adaptive_height,h)
     setdimen(d_adaptive_depth,d)
     setdimen(d_adaptive_line,l)
     setmacro("m_adaptive_color",c)
+    setmacro("m_adaptive_alternative",a)
 end
 
 local methods = {
@@ -76,7 +77,7 @@ local methods = {
         local setups = settings.setups
         if setups and setups ~= ""  then
             local w, h, d = getwhd(parent)
-            setadaptive(w,h,d,settings.rulethickness,settings.color)
+            setadaptive(w,h,d,settings.rulethickness,settings.color,settings.alternative)
             expandmacro("setup",true,setups)
             local l = takebox("b_adaptive_box")
             if l then
@@ -150,6 +151,7 @@ interfaces.implement {
             { "mp", "string" },
             { "color", "string" },
             { "rulethickness", "dimension" },
+            { "alternative", "string" },
         }
     }
 }
diff --git a/tex/context/base/mkxl/typo-ada.mkxl b/tex/context/base/mkxl/typo-ada.mkxl
index 733b2ca5b..d6eae4249 100644
--- a/tex/context/base/mkxl/typo-ada.mkxl
+++ b/tex/context/base/mkxl/typo-ada.mkxl
@@ -39,6 +39,10 @@
 \aliased\let\usedadaptivebox\b_adaptive_box
 
 \mutable\lettonothing\m_adaptive_color
+\mutable\lettonothing\m_adaptive_alternative
+
+\permanent\def\usedadaptivecolor      {\m_adaptive_color}
+\permanent\def\usedadaptivealternative{\m_adaptive_alternative}
 
 \protected\untraced\def\usedadaptivetotal{\dimexpr\usedadaptiveheight+\usedadaptivedepth\relax}
 
@@ -56,6 +60,7 @@
   [\c!foregroundstyle=,
    \c!foregroundcolor=,
    \c!color=gray,
+   \c!alternative=,
    \c!rulethickness=\linewidth,
    \c!method=1,
    \c!stretch=,
@@ -95,6 +100,7 @@
            method         \adaptiveparameter\c!method
            setups        {\p_setups}%
            color         {\adaptiveparameter\c!color}%
+           alternative   {\adaptiveparameter\c!alternative}%
            rulethickness  \adaptiveparameter\c!rulethickness
          }%
        \fi
diff --git a/tex/context/base/mkxl/typo-adj.mkxl b/tex/context/base/mkxl/typo-adj.mkxl
index 5c129f07e..bf754cdbf 100644
--- a/tex/context/base/mkxl/typo-adj.mkxl
+++ b/tex/context/base/mkxl/typo-adj.mkxl
@@ -51,7 +51,7 @@
 
 \tolerant\def\typo_adjusters_blank#1[#2]% no need for speed
   {\begingroup
- % \setbox\scratchbox\vbox{\ifcstok{#2}\emptytoks\blank\else\blank[#2]\fi}%
+ % \setbox\scratchbox\vbox{\iftok{#2}\emptytoks\blank\else\blank[#2]\fi}%
    \setbox\scratchbox\vbox{\blank[#2]}%
    \vadjust #1 index \plustwo {\vskip\htdp\scratchbox}%
    \endgroup}
diff --git a/tex/context/base/mkxl/unic-ini.lmt b/tex/context/base/mkxl/unic-ini.lmt
new file mode 100644
index 000000000..aafaf0ae7
--- /dev/null
+++ b/tex/context/base/mkxl/unic-ini.lmt
@@ -0,0 +1,26 @@
+if not modules then modules = { } end modules ['unic-ini'] = {
+    version   = 1.001,
+    comment   = "companion to unic-ini.mkiv",
+    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+    copyright = "PRAGMA ADE / ConTeXt Development Team",
+    license   = "see context related readme files"
+}
+
+local context = context
+local utfchar = utf.char
+
+-- Beware, initializing unicodechar happens at first usage and takes
+-- 0.05 -- 0.1 second (lots of function calls).
+
+interfaces.implement {
+    name      = "unicodechar",
+    public    = true,
+    protected = true,
+    arguments = "argument",
+    actions   = function(asked)
+        local n = characters.unicodechar(asked)
+        if n then
+            context(utfchar(n))
+        end
+    end
+}
diff --git a/tex/context/base/mkxl/unic-ini.mkxl b/tex/context/base/mkxl/unic-ini.mkxl
index aedfe47ed..7d2302dae 100644
--- a/tex/context/base/mkxl/unic-ini.mkxl
+++ b/tex/context/base/mkxl/unic-ini.mkxl
@@ -13,7 +13,7 @@
 
 \writestatus{loading}{ConTeXt Unicode Support / Initialization}
 
-\registerctxluafile{unic-ini}{}
+\registerctxluafile{unic-ini}{autosuffix}
 
 \unprotect
 
@@ -26,7 +26,8 @@
 %D
 %D \typebuffer \getbuffer
 
-\permanent\def\unicodechar#1{\clf_unicodechar{#1}}
+% \permanent\def\unicodechar#1% defined at the lua end
+%   {\clf_unicodechar{#1}}
 
 \permanent\protected\def\unknownchar
   {\dontleavehmode\hpack{\vrule\s!width.5\emwidth\s!height\exheight\s!depth\zeropoint}}
diff --git a/tex/context/fonts/mkiv/antykwa-math.lfg b/tex/context/fonts/mkiv/antykwa-math.lfg
index 5bbd2cf6c..2965332e4 100644
--- a/tex/context/fonts/mkiv/antykwa-math.lfg
+++ b/tex/context/fonts/mkiv/antykwa-math.lfg
@@ -3,19 +3,19 @@ local helpers = common.mathematics.helpers
 
 if not fonts.encodings.math["extensible-jmn-private"] then
 
-    local nps = fonts.helpers.newprivateslot
+    local ps = fonts.helpers.privateslot
 
     fonts.encodings.math["extensible-jmn-private"] = {
-        [nps("rule middle piece")]         = 200, -- minusjmn
-        [nps("rule right piece")]          = 201, -- minusrightjmn
-        [nps("rule left piece")]           = 202, -- minusleftjmn
-        [nps("double rule middle piece")]  = 203, -- equaljmn
-        [nps("double rule right piece")]   = 204, -- equalrightjmn
-        [nps("double rule left piece")]    = 205, -- equalleftjmn
-        [nps("arrow left piece")]          = 206, -- arrowleftjmn
-        [nps("arrow right piece")]         = 207, -- arrowrightjmn
-        [nps("double arrow left piece")]   = 208, -- arrowdblleftjmn
-        [nps("double arrow right piece")]  = 209, -- arrowdblrightjmn
+        [ps("rule middle piece")]        = 200, -- minusjmn
+        [ps("rule right piece")]         = 201, -- minusrightjmn
+        [ps("rule left piece")]          = 202, -- minusleftjmn
+        [ps("double rule middle piece")] = 203, -- equaljmn
+        [ps("double rule right piece")]  = 204, -- equalrightjmn
+        [ps("double rule left piece")]   = 205, -- equalleftjmn
+        [ps("arrow left piece")]         = 206, -- arrowleftjmn
+        [ps("arrow right piece")]        = 207, -- arrowrightjmn
+        [ps("double arrow left piece")]  = 208, -- arrowdblleftjmn
+        [ps("double arrow right piece")] = 209, -- arrowdblrightjmn
     }
 
 end
diff --git a/tex/context/fonts/mkiv/common-math-jmn.lfg b/tex/context/fonts/mkiv/common-math-jmn.lfg
index 331d65a5d..bcbe77962 100644
--- a/tex/context/fonts/mkiv/common-math-jmn.lfg
+++ b/tex/context/fonts/mkiv/common-math-jmn.lfg
@@ -8,6 +8,10 @@ return {
         helpers = {
             addmissing = function(main)
 
+                local max            = math.max
+                local copytable      = table.copy
+                local slotcommand    = fonts.helpers.commands.slot
+
                 local builders       = fonts.handlers.vf.math.builders
                 local ps             = fonts.helpers.privateslot
 
@@ -25,8 +29,8 @@ return {
                 local llbracepiece = ps("ll brace piece")
                 local lrbracepiece = ps("lr brace piece")
 
-                builders.brace(main,0x23DE,ulbracepiece,cmbracepiece,lrbracepiece,llbracepiece,cmbracepiece,urbracepiece)
-                builders.brace(main,0x23DF,llbracepiece,cmbracepiece,urbracepiece,ulbracepiece,cmbracepiece,lrbracepiece)
+                builders.brace(main,0x23DE,ulbracepiece,cmbracepiece,lrbracepiece,llbracepiece,cmbracepiece,urbracepiece,"top")
+                builders.brace(main,0x23DF,llbracepiece,cmbracepiece,urbracepiece,ulbracepiece,cmbracepiece,lrbracepiece,"bottom")
 
                 builders.parent(main,0x23DC,ulbracepiece,umbracepiece,urbracepiece,"top")
                 builders.parent(main,0x23DD,llbracepiece,lmbracepiece,lrbracepiece,"bottom")
@@ -39,13 +43,21 @@ return {
 
                 builders.jointwo(main,0x21A6,ps("maps to piece"),.15,0x02192) -- \mapstochar\rightarrow
 
+                local srl = ps("rule left piece")
                 local srm = ps("rule middle piece")
                 local srr = ps("rule right piece")
-                local srl = ps("rule left piece")
 
+                local drl = ps("double rule left piece")
                 local drm = ps("double rule middle piece")
                 local drr = ps("double rule right piece")
-                local drl = ps("double rule left piece")
+
+                local sfl = ps("flat rule left piece")
+                local sfm = ps("flat rule middle piece")
+                local sfr = ps("flat rule right piece")
+
+                local dfl = ps("flat double rule left piece")
+                local dfm = ps("flat double rule middle piece")
+                local dfr = ps("flat double rule right piece")
 
                 local sal = ps("arrow left piece")
                 local sar = ps("arrow right piece")
@@ -55,32 +67,90 @@ return {
 
                 local rad = ps("radical bar extender")
 
-                if characters[srm] then
+                local antykwa = characters[srm]
+
+                if not antykwa then
 
-                    builders.jointwo(main,0x27F5,sak,joinrelfactor,srr)
-                    builders.jointwo(main,0x27F6,srl,joinrelfactor,sar)
-                    builders.jointwo(main,0x27F7,sak,joinrelfactor,sar)
-                    builders.jointwo(main,0x27F8,dal,joinrelfactor,drr)
-                    builders.jointwo(main,0x27F9,drl,joinrelfactor,dar)
-                    builders.jointwo(main,0x27FA,dal,joinrelfactor,dar)
+                    sal = 0x02190  sar = 0x02192
+                    dal = 0x021D0  dar = 0x021D2
 
+                    srl = 0x0002D  srr = 0x0002D
+                    drl = 0x0003D  drr = 0x0003D
+
+                    sfl = 0x0002D  srm = 0x0002D
+                    dfl = 0x0003D  drm = 0x0003D
+
+                end
+
+                if not characters[sfm] then
+
+                    local csal = characters[sal]  local sheight = csal.height  local sdepth = csal.depth
+                    local cdal = characters[dal]  local dheight = cdal.height  local ddepth = cdal.depth
+
+                    local csfl = copytable(characters[srl])  characters[sfl] = csfl  csfl.height = sheight  csfl.depth = sdepth csfl.italic = nil
+                    local csfm = copytable(characters[srm])  characters[sfm] = csfm  csfm.height = sheight  csfm.depth = sdepth csfm.italic = nil
+                    local csfr = copytable(characters[srr])  characters[sfr] = csfr  csfr.height = sheight  csfr.depth = sdepth csfr.italic = nil
+                    local cdfl = copytable(characters[drl])  characters[dfl] = cdfl  cdfl.height = dheight  cdfl.depth = ddepth cdfl.italic = nil
+                    local cdfm = copytable(characters[drm])  characters[dfm] = cdfm  cdfm.height = dheight  cdfm.depth = ddepth cdfm.italic = nil
+                    local cdfr = copytable(characters[drr])  characters[dfr] = cdfr  cdfr.height = dheight  cdfr.depth = ddepth cdfr.italic = nil
+
+                end
+
+                builders.jointwo(main,0x27F5,sal,joinrelfactor,srr)
+                builders.jointwo(main,0x27F6,srl,joinrelfactor,sar)
+                builders.jointwo(main,0x27F7,sal,joinrelfactor,sar)
+                builders.jointwo(main,0x27F8,dal,joinrelfactor,drr)
+                builders.jointwo(main,0x27F9,drl,joinrelfactor,dar)
+                builders.jointwo(main,0x27FA,dal,joinrelfactor,dar)
+
+                if antykwa then
                     builders.horibar(main,0x203E,srm,srl,srr,0x02212) -- overbar underbar fraction (we take 90/91/92 too!)
                  -- builders.horibar(main,0x203E,srm,srl,srr,0x0002D) -- overbar underbar fraction (we take 90/91/92 too!)
+                    builders.rootbar(main,rad,srm,srr,0x02212) -- radical
+                else
+                    builders.horibar(main,0x203E,0xFE073) -- overbar underbar
+                end
 
-                    builders.rootbar(main,ps("radical bar extender"),srm,srr,0x02212) -- radical
+                local ffactor = antykwa and 1 or 1
+                local mfactor = antykwa and 1 or .8
+                local lfactor = antykwa and 1 or .8
 
-                else
+                builders.extension(main,0x2190,sal,sfm,sfr,ffactor,mfactor,lfactor) -- \leftarrow
+                builders.extension(main,0x2192,sfl,sfm,sar,ffactor,mfactor,lfactor) -- \rightarrow
+                builders.extension(main,0x27F5,sal,sfm,sfr,ffactor,mfactor,lfactor)
+                builders.extension(main,0x27F6,sfl,sfm,sar,ffactor,mfactor,lfactor)
+                builders.extension(main,0x27F7,sal,sfm,sar,ffactor,mfactor,lfactor)
+                builders.extension(main,0x27F8,dal,dfm,dfr,ffactor,mfactor,lfactor)
+                builders.extension(main,0x27F9,dfl,dfm,dar,ffactor,mfactor,lfactor)
+                builders.extension(main,0x27FA,dal,dfm,dar,ffactor,mfactor,lfactor)
 
-                    builders.jointwo(main,0x27F5,0x02190,joinrelfactor,0x0002D) -- \leftarrow\joinrel\relbar
-                    builders.jointwo(main,0x27F6,0x0002D,joinrelfactor,0x02192) -- \relbar\joinrel\rightarrow
-                    builders.jointwo(main,0x27F7,0x02190,joinrelfactor,0x02192) -- \leftarrow\joinrel\rightarrow
-                    builders.jointwo(main,0x27F8,0x021D0,joinrelfactor,0x0003D) -- \Leftarrow\joinrel\Relbar
-                    builders.jointwo(main,0x27F9,0x0003D,joinrelfactor,0x021D2) -- \Relbar\joinrel\Rightarrow
-                    builders.jointwo(main,0x27FA,0x021D0,joinrelfactor,0x021D2) -- \Leftarrow\joinrel\Rightarrow
+                local tfactor = antykwa and -0.8 or -0.8
+                local bfactor = antykwa and  0.1  or  0.1
 
-                    builders.horibar(main,0x203E,0xFE073) -- overbar underbar
+                local left  = characters[0x27F5]
+                local right = characters[0x27F6]
+                local both  = characters[0x27F7]
 
-                end
+                local height = max(left.height or 0,right.height or 0,both.height or 0)
+                local depth  = max(left.depth  or 0,right.depth  or 0,both.depth  or 0)
+
+                left .height = height  left .depth = depth
+                right.height = height  right.depth = depth
+                both .height = height  both .depth = depth
+
+                local t = copytable(left)  characters[0x20D6] = t t.inneryoffset = tfactor*height t.innerlocation = "top"    t.next = nil t.italic = nil -- over
+                local t = copytable(right) characters[0x20D7] = t t.inneryoffset = tfactor*height t.innerlocation = "top"    t.next = nil t.italic = nil
+                local t = copytable(both)  characters[0x20E1] = t t.inneryoffset = tfactor*height t.innerlocation = "top"    t.next = nil t.italic = nil
+
+                local t = copytable(left)  characters[0x20EE] = t t.inneryoffset = bfactor*height t.innerlocation = "bottom" t.next = nil t.italic = nil -- under
+                local t = copytable(right) characters[0x20EF] = t t.inneryoffset = bfactor*height t.innerlocation = "bottom" t.next = nil t.italic = nil
+                local t = copytable(both)  characters[0x034D] = t t.inneryoffset = bfactor*height t.innerlocation = "bottom" t.next = nil t.italic = nil
+
+                local tfactor = antykwa and -15 or -15
+                local bfactor = antykwa and   1 or   1
+
+                local t = copytable(characters[0x203E]) characters[0x0305] = t t.inneryoffset = tfactor*t.height t.innerlocation = "top"    t.next = nil t.italic = nil
+                local t = copytable(characters[0x203E]) characters[0x0332] = t t.inneryoffset = bfactor*t.height t.innerlocation = "bottom" t.next = nil t.italic = nil
 
                 builders.jointwo(main,0x2016,0x007C,0.20,0x007C)
                 builders.jointwo(main,0x2980,0x007C,0.20,0x007C,0.20,0x007C)
@@ -105,7 +175,9 @@ return {
                 builders.overlaytwo(main,0x2285,0x00338,notshiftfactor,0x02283) -- \not\supset
                 builders.overlaytwo(main,0x2209,0x00338,notshiftfactor,0x02208) -- \not\in
 
-                builders.jointwo(main,0x2254,0x03A,0,0x03D) -- := (≔)
+                -- builders.jointwo  (main,0x2254,0x03A,0,0x03D)         -- :=
+                -- builders.jointhree(main,0x2A74,0x03A,0,0x03A,0,0x03D) -- ::=
+                -- builders.jointwo  (main,0x2A75,0x03D,0,0x03D)         -- ==
 
                 builders.repeated(main,0x222B,0x222B,1,1/2)
                 builders.repeated(main,0x222C,0x222B,2,1/2)
@@ -113,6 +185,11 @@ return {
 
                 characters[0x02B9] = characters[0x2032] -- we're nice
 
+                -- some things are done automatically:
+
+                -- add primes
+                -- add equals and alike
+
             end
         }
     }
diff --git a/tex/context/fonts/mkiv/ebgaramond-math.lfg b/tex/context/fonts/mkiv/ebgaramond-math.lfg
index 812430525..f6f552dfe 100644
--- a/tex/context/fonts/mkiv/ebgaramond-math.lfg
+++ b/tex/context/fonts/mkiv/ebgaramond-math.lfg
@@ -12,8 +12,8 @@ return {
             FractionRuleThickness             =  60,
             OverbarRuleThickness              =  60,
             UnderbarRuleThickness             =  60,
-            AccentTopShiftUp                  = -75,
-            FlattenedAccentTopShiftUp         = -75,
+            AccentTopShiftUp                  = -25, -- was 075
+            FlattenedAccentTopShiftUp         = -25, -- was 075
             AccentBaseDepth                   =  75,
             DelimiterPercent                  =  90,
             DelimiterShortfall                = 400,
@@ -82,9 +82,9 @@ return {
                         [0x27EB]                = { topright = -0.1,  bottomright = -0.1  },
                         ["0x27EB.variants.*"]   = { topright = -0.2,  bottomright = -0.2  },
 
-                        [0x51]                  = { bottomright = 0.25 }, -- Upright Q
-                        [0x211A]                = { bottomright = 0.2 }, -- Blackboard bold Q
-                        [0x1D410]               = { bottomright = 0.2 }, -- Bold Q
+                        [0x00051]               = { bottomright = 0.25 }, -- Upright Q
+                        [0x0211A]               = { bottomright = 0.2  }, -- Blackboard bold Q
+                        [0x1D410]               = { bottomright = 0.2  }, -- Bold Q
                         [0x1D478]               = { bottomright = 0.05 }, -- Bold Q
                         [0x1D5B0]               = { bottomright = 0.05 }, -- Sans Q
                     },
@@ -172,6 +172,24 @@ return {
                 {
                     tweak = "addrules",
                 },
+                {
+                    tweak    = "replacerules",
+                    fraction = {
+                        template = "minus", -- 0x2212,
+                        xoffset  = 0.075,
+                        yoffset  = 0.9,
+                     -- width    = 0.85,
+                     -- height   = 0.1,
+                    },
+                    radical = {
+                        template = "minus", -- 0x2212,
+                        xoffset  = 0.075,
+                        yoffset  = 0.9,
+                        yscale   = 0.975,
+                     -- width    = 0.85,
+                     -- height   = 0.1,
+                    },
+                },
                 {
                     tweak   = "addbars",
                     advance = 0.6,
diff --git a/tex/context/fonts/mkiv/lucida-math.lfg b/tex/context/fonts/mkiv/lucida-math.lfg
index 64f53dc33..28510ac2d 100644
--- a/tex/context/fonts/mkiv/lucida-math.lfg
+++ b/tex/context/fonts/mkiv/lucida-math.lfg
@@ -14,7 +14,7 @@ return {
     mathematics = {
         parameters = {
             FractionRuleThickness             =  55,
-            AccentBaseDepth                   = 250,
+         -- AccentBaseDepth                   = 250,
             DelimiterPercent                  =  90,
             DelimiterShortfall                = 400,
             SuperscriptBottomMaxWithSubscript = 325,
@@ -32,18 +32,18 @@ return {
                     tweak   = "fixoldschool",
                     version = "Version 1.802",
                 },
-{
-    tweak   = "parameters",
-    feature = "boldmath",
-    list    = {
---             RadicalRuleThickness  = 55,
-            RadicalRuleThickness  = 60,
---             RadicalRuleThickness  = "1.09*RadicalRuleThickness",
---             FractionRuleThickness = 65,
---             OverRuleThickness     = 65,
---             UnderRuleThickness    = 65,
-    }
-},
+                {
+                    tweak   = "parameters",
+                    feature = "boldmath",
+                    list    = {
+                --             RadicalRuleThickness  = 55,
+                            RadicalRuleThickness  = 60,
+                --             RadicalRuleThickness  = "1.09*RadicalRuleThickness",
+                --             FractionRuleThickness = 65,
+                --             OverRuleThickness     = 65,
+                --             UnderRuleThickness    = 65,
+                    }
+                },
                 {
                     tweak = "addmirrors",
                 },
@@ -58,6 +58,22 @@ return {
                 presets.moveitalics          { correct = true, letters = true },
                 presets.moveintegrals        { factor = 1.5 },
                 presets.wipeitalics          { },
+                {
+                    tweak    = "replacealphabets",
+                    filename = "lucidabrightot.otf",
+                    keep     = true,
+                    list     = {
+                        { source = "latinsupplement" },
+                --         { source = "latinextendeda" },
+                --         { source = "latinextendedadditional" },
+                --         { source = "latinextendedb" },
+                --         { source = "latinextendedc" },
+                --         { source = "latinextendedd" },
+                --         { source = "latinextendede" },
+                --         { source = "latinextendedf" },
+                --         { source = "latinextendedg" },
+                    },
+                },
                 {
                     tweak   = "replacealphabets",
                     list    = {
@@ -140,12 +156,12 @@ return {
                     tweak = "kerns",
                     list  = {
                         [0x002F]                = { topleft  = -0.2,  bottomright = -0.2  },
-                        ["0x7D.parts.top"]      = { topright = -0.15                      }, -- right brace top
-                        ["0x7D.parts.bottom"]   = {                   bottomright = -0.15 }, -- right brace bottom
-                        ["0x7D.variants.*"]     = { topright = -0.15, bottomright = -0.15 }, -- right brace variants
-                        ["0x29.parts.top"]      = { topright = -0.25                      }, -- right parenthesis top
-                        ["0x29.parts.bottom"]   = {                   bottomright = -0.25 }, -- right parenthesis bottom
-                        ["0x29.variants.*"]     = { topright = -0.2,  bottomright = -0.2  }, -- right parenthesis variants
+                        ["0x007D.parts.top"]    = { topright = -0.15                      }, -- right brace top
+                        ["0x007D.parts.bottom"] = {                   bottomright = -0.15 }, -- right brace bottom
+                        ["0x007D.variants.*"]   = { topright = -0.15, bottomright = -0.15 }, -- right brace variants
+                        ["0x0029.parts.top"]    = { topright = -0.25                      }, -- right parenthesis top
+                        ["0x0029.parts.bottom"] = {                   bottomright = -0.25 }, -- right parenthesis bottom
+                        ["0x0029.variants.*"]   = { topright = -0.2,  bottomright = -0.2  }, -- right parenthesis variants
                         ["0x221A.parts.top"]    = { topright = 0.2                        }, -- right radical top
                         ["0x221A.parts.bottom"] = {                   bottomright =  0.2  }, -- right radical bottom
                         ["0x221A.variants.*"]   = { topright = 0.2,   bottomright =  0.2  }, -- right radical variants
@@ -196,6 +212,12 @@ return {
                         [0x21A0] = false,
                     }
                 },
+                -- fix a bug (todo: version)
+                {
+                    tweak       = "sortvariants",
+                    list        = { 0x23DE },
+                    orientation = "horizontal",
+                },
                 -- this is the mkiv section
                 {
                     tweak   = "emulatelmtx",
diff --git a/tex/context/fonts/mkiv/type-imp-concrete.mkiv b/tex/context/fonts/mkiv/type-imp-concrete.mkiv
index ff4033f81..abf9b2cb1 100644
--- a/tex/context/fonts/mkiv/type-imp-concrete.mkiv
+++ b/tex/context/fonts/mkiv/type-imp-concrete.mkiv
@@ -1,5 +1,5 @@
 %D \module
-%D   [       file=type-imp-erewhon,
+%D   [       file=type-imp-concrete,
 %D        version=2022.30.09, % a bit older
 %D          title=\CONTEXT\ Typescript Macros,
 %D       subtitle=\TEX Gyre Fonts,
@@ -11,9 +11,7 @@
 %C therefore copyrighted by \PRAGMA. See mreadme.pdf for
 %C details.
 
-%\loadtypescriptfile[texgyre]
-%\resetfontfallback  [concrete-euler-fix]
-%\definefontfallback[concrete-euler-fix][texgyrepagella-math] [0x022EE,0x022F0,0x022F1,0x02661,0x02220][force=yes]
+% lm is already preloaded so we can actually move this to lm
 
 \starttypescriptcollection[concrete]
 
@@ -21,33 +19,35 @@
     %\definefontfeature[none-slanted-concrete]   [none]   [slant=.2]
 
     \doifunknownfontfeature {concrete-math-bold} {\definefontfeature[concrete-math-bold][boldened]}
+    \doifunknownfontfeature {concrete-text-bold} {\definefontfeature[concrete-text-bold][boldened-15]}
 
     \starttypescript [\s!serif] [concrete]
-        \definefontsynonym [\s!Serif]            [\s!file:cmunorm] [\s!features=\s!default]
-        \definefontsynonym [\s!SerifItalic]      [\s!file:cmunoti] [\s!features=\s!default]
-        \definefontsynonym [\s!SerifSlanted]     [\s!file:cmunorm] [\s!features=default-slanted-concrete]
-        \definefontsynonym [\s!SerifBold]        [\s!file:cmunobx] [\s!features=\s!default]
-        \definefontsynonym [\s!SerifBoldItalic]  [\s!file:cmunobi] [\s!features=\s!default]
-        \definefontsynonym [\s!SerifBoldSlanted] [\s!file:cmunobx] [\s!features=default-slanted-concrete]
+        \definefontsynonym [\s!Serif]            [LMTypewriterVarWd-Regular]     [\s!features={\s!default,concrete-text-bold}]
+        \definefontsynonym [\s!SerifBold]        [LMTypewriterVarWd-Dark]        [\s!features={\s!default,concrete-text-bold}]
+        \definefontsynonym [\s!SerifItalic]      [LMTypewriterVarWd-Oblique]     [\s!features={\s!default,concrete-text-bold}]
+        \definefontsynonym [\s!SerifSlanted]     [LMTypewriterVarWd-Oblique]     [\s!features={\s!default,concrete-text-bold}]
+        \definefontsynonym [\s!SerifBoldItalic]  [LMTypewriterVarWd-DarkOblique] [\s!features={\s!default,concrete-text-bold}]
+        \definefontsynonym [\s!SerifBoldSlanted] [LMTypewriterVarWd-DarkOblique] [\s!features={\s!default,concrete-text-bold}]
     \stoptypescript
 
     \starttypescript [\s!sans] [concrete]
-        \definefontsynonym [\s!Sans]            [\s!file:cmunss] [\s!features=\s!default]
-        \definefontsynonym [\s!SansItalic]      [\s!file:cmunsi] [\s!features=\s!default]
-        \definefontsynonym [\s!SansSlanted]     [\s!file:cmunss] [\s!features=default-slanted-concrete]
-        \definefontsynonym [\s!SansBold]        [\s!file:cmunsx] [\s!features=\s!default]
-        \definefontsynonym [\s!SansBoldItalic]  [\s!file:cmunso] [\s!features=\s!default]
-        \definefontsynonym [\s!SansBoldSlanted] [\s!file:cmunsx] [\s!features=default-slanted-concrete]
+        \definefontsynonym [\s!Sans]            [LMTypewriterVarWd-Regular]     [\s!features={\s!default,concrete-text-bold}]
+        \definefontsynonym [\s!SansItalic]      [LMTypewriterVarWd-Dark]        [\s!features={\s!default,concrete-text-bold}]
+        \definefontsynonym [\s!SansSlanted]     [LMTypewriterVarWd-Oblique]     [\s!features={\s!default,concrete-text-bold}]
+        \definefontsynonym [\s!SansBold]        [LMTypewriterVarWd-Oblique]     [\s!features={\s!default,concrete-text-bold}]
+        \definefontsynonym [\s!SansBoldItalic]  [LMTypewriterVarWd-DarkOblique] [\s!features={\s!default,concrete-text-bold}]
+        \definefontsynonym [\s!SansBoldSlanted] [LMTypewriterVarWd-DarkOblique] [\s!features={\s!default,concrete-text-bold}]
     \stoptypescript
 
     \starttypescript [\s!mono] [concrete]
-        \definefontsynonym [\s!Mono]            [\s!file:cmuntt] [\s!features=\s!none]
-        \definefontsynonym [\s!MonoItalic]      [\s!file:cmunit] [\s!features=\s!none]
-        \definefontsynonym [\s!MonoSlanted]     [\s!file:cmunst] [\s!features=\s!none]
-        \definefontsynonym [\s!MonoBold]        [\s!file:cmuntb] [\s!features=\s!none]
-        \definefontsynonym [\s!MonoBoldItalic]  [\s!file:cmuntx] [\s!features=\s!none]
-        \definefontsynonym [\s!MonoBoldSlanted] [\s!file:cmuntb] [\s!features=none-slanted-concrete]
-    \stoptypescript
+        \loadfontgoodies[lm]
+        \definefontsynonym [\s!Mono]            [LMTypewriter-Regular]     [\s!features={\s!none,concrete-text-bold}]
+        \definefontsynonym [\s!MonoBold]        [LMTypewriter-Dark]        [\s!features={\s!none,concrete-text-bold}]
+        \definefontsynonym [\s!MonoItalic]      [LMTypewriter-Italic]      [\s!features={\s!none,concrete-text-bold}]
+        \definefontsynonym [\s!MonoSlanted]     [LMTypewriter-Oblique]     [\s!features={\s!none,concrete-text-bold}]
+        \definefontsynonym [\s!MonoBoldItalic]  [LMTypewriter-DarkOblique] [\s!features={\s!none,concrete-text-bold}]
+        \definefontsynonym [\s!MonoBoldSlanted] [LMTypewriter-DarkOblique] [\s!features={\s!none,concrete-text-bold}]
+   \stoptypescript
 
     \starttypescript [\s!math] [concrete]
         \checkedmapfontsize[\typescripttwo][\s!script]      [.76]
diff --git a/tex/context/fonts/mkiv/type-imp-ebgaramond.mkiv b/tex/context/fonts/mkiv/type-imp-ebgaramond.mkiv
index 31026df5b..966e50ba8 100644
--- a/tex/context/fonts/mkiv/type-imp-ebgaramond.mkiv
+++ b/tex/context/fonts/mkiv/type-imp-ebgaramond.mkiv
@@ -65,6 +65,14 @@
 
 \starttypescriptcollection[ebgaramond]
 
+    \startsetups[ebgaramond]
+        \letmathfractionparameter\c!rule\v!symbol
+        \setmathfractionparameter\c!middle{"203E}%
+        \letmathradicalparameter \c!rule\v!symbol
+        \setmathradicalparameter \c!top{\radicalbarextenderuc}%
+      % \setmathfenceparameter   \c!alternative{1}%
+    \stopsetups
+
     \doifunknownfontfeature {ebgaramond-math-bold} {\definefontfeature[ebgaramond-math-bold][boldened]}
 
     \starttypescript [\s!serif] [ebgaramond]
@@ -76,15 +84,13 @@
         \definefontsynonym [\s!SerifCaps]      [\s!Serif]                     [\s!features=eb-garamond-smallcaps]
     \stoptypescript
 
-
-
-     \starttypescript [\s!sans] [ysabeau]
-         % \setups[font:fallback:sans]
-         \definefontsynonym [\s!Sans]          [\s!file:ysabeau-regular]       [\s!features=\s!default]
-         \definefontsynonym [\s!SansItalic]    [\s!file:ysabeau-italic]        [\s!features=\s!default]
-         \definefontsynonym [\s!SansBold]      [\s!file:ysabeau-bold]          [\s!features=\s!default]
-         \definefontsynonym [\s!SansBoldItalic][\s!file:ysabeau-bolditalic]    [\s!features=\s!default]
-         \definefontsynonym [\s!SansCaps]      [\s!Sans]                       [\s!features=ysabeau-smallcaps]
+    \starttypescript [\s!sans] [ysabeau]
+        % \setups[font:fallback:sans]
+        \definefontsynonym [\s!Sans]          [\s!file:ysabeau-regular]       [\s!features=\s!default]
+        \definefontsynonym [\s!SansItalic]    [\s!file:ysabeau-italic]        [\s!features=\s!default]
+        \definefontsynonym [\s!SansBold]      [\s!file:ysabeau-bold]          [\s!features=\s!default]
+        \definefontsynonym [\s!SansBoldItalic][\s!file:ysabeau-bolditalic]    [\s!features=\s!default]
+        \definefontsynonym [\s!SansCaps]      [\s!Sans]                       [\s!features=ysabeau-smallcaps]
      \stoptypescript
 
     \starttypescript [\s!math] [ebgaramond,ebgaramond-nt]
diff --git a/tex/context/fonts/mkiv/type-imp-iwona.mkiv b/tex/context/fonts/mkiv/type-imp-iwona.mkiv
index f43731250..528cb3208 100644
--- a/tex/context/fonts/mkiv/type-imp-iwona.mkiv
+++ b/tex/context/fonts/mkiv/type-imp-iwona.mkiv
@@ -66,12 +66,15 @@
 
     \starttypescript [\s!math][iwona][\s!all]
         \definefontsynonym[\s!MathRoman]    [iwonamath@iwona-math]
+        \definefontsynonym[\s!MathRomanBold][iwonamediummath@iwona-medium-math]
     \stoptypescript
     \starttypescript [\s!math][iwona-light][\s!all]
         \definefontsynonym[\s!MathRoman]    [iwonalightmath@iwona-light-math]
+        \definefontsynonym[\s!MathRomanBold][iwonamath@kurier-medium-math]
     \stoptypescript
     \starttypescript [\s!math][iwona-medium][\s!all]
         \definefontsynonym[\s!MathRoman]    [iwonamediummath@iwona-medium-math]
+        \definefontsynonym[\s!MathRomanBold][kurierheavymath@kurier-heavy-math]
     \stoptypescript
     \starttypescript [\s!math][iwona-heavy][\s!all]
         \definefontsynonym[\s!MathRoman][iwonaheavymath@iwona-heavy-math]
diff --git a/tex/context/fonts/mkiv/type-imp-kpfonts.mkiv b/tex/context/fonts/mkiv/type-imp-kpfonts.mkiv
index 472619cd9..c8e92d20b 100644
--- a/tex/context/fonts/mkiv/type-imp-kpfonts.mkiv
+++ b/tex/context/fonts/mkiv/type-imp-kpfonts.mkiv
@@ -68,14 +68,14 @@
 
     \starttypescript [\s!serif] [kpfonts-bold]
         \setups[\s!font:\s!fallback:\s!serif]
-        \definefontsynonym [\s!Serif]           [\s!file:KpRoman-Regular.otf]
+        \definefontsynonym [\s!Serif]           [\s!file:KpRoman-SemiBold.otf]
         \definefontsynonym [\s!SerifBold]       [\s!file:KpRoman-Bold.otf]
-        \definefontsynonym [\s!SerifItalic]     [\s!file:KpRoman-Italic.otf]
+        \definefontsynonym [\s!SerifItalic]     [\s!file:KpRoman-SemiboldItalic.otf]
         \definefontsynonym [\s!SerifBoldItalic] [\s!file:KpRoman-BoldItalic.otf]
     \stoptypescript
 
     \starttypescript [\s!math] [kpfonts-bold]
-        \definefontsynonym [\s!MathRoman]     [\s!file:KpMath-Regular.otf] [\s!features={\s!math\mathsizesuffix,kpfonts:mathextra,mathextra},\s!goodies=kpfonts-math]
+        \definefontsynonym [\s!MathRoman]     [\s!file:KpMath-SemiBold.otf] [\s!features={\s!math\mathsizesuffix,kpfonts:mathextra,mathextra},\s!goodies=kpfonts-math]
         \definefontsynonym [\s!MathRomanBold] [\s!file:KpMath-Bold.otf]    [\s!features={\s!math\mathsizesuffix,kpfonts:mathextra,mathextra},\s!goodies=kpfonts-math]
     \stoptypescript
 
diff --git a/tex/context/fonts/mkiv/type-imp-kurier.mkiv b/tex/context/fonts/mkiv/type-imp-kurier.mkiv
index 0bf1a43ca..af1e2a28d 100644
--- a/tex/context/fonts/mkiv/type-imp-kurier.mkiv
+++ b/tex/context/fonts/mkiv/type-imp-kurier.mkiv
@@ -13,12 +13,30 @@
 
 \starttypescriptcollection [kurier]
 
+    \startsetups[kurier]
+      % \setupmathfence   [\c!alternative=1]%
+        \setmathfenceparameter   \c!alternative{1}%
+%         \letmathfractionparameter\c!rule\v!symbol
+%         \setmathfractionparameter\c!middle{"203E}%
+%         \letmathradicalparameter \c!rule\v!symbol
+%         \setmathradicalparameter \c!top{\radicalbarextenderuc}%
+%         \setmathfenceparameter   \c!alternative{1}%
+    \stopsetups
+
+    \startsetups[kurier-light]      \directsetup{antykwa}\stopsetups
+    \startsetups[kurier-medium]     \directsetup{antykwa}\stopsetups
+    \startsetups[kurier-heavy]      \directsetup{antykwa}\stopsetups
+    \startsetups[kurier-cond]       \directsetup{antykwa}\stopsetups
+    \startsetups[kurier-light-cond] \directsetup{antykwa}\stopsetups
+    \startsetups[kurier-medium-cond]\directsetup{antykwa}\stopsetups
+    \startsetups[kurier-heavy-cond] \directsetup{antykwa}\stopsetups
+
     \definefontfeature[virtualmath-kurier]       [virtualmath][virtualweight=kurier]
     \definefontfeature[virtualmath-kurier-light] [virtualmath][virtualweight=kurier-light]
     \definefontfeature[virtualmath-kurier-medium][virtualmath][virtualweight=kurier-medium]
     \definefontfeature[virtualmath-kurier-heavy] [virtualmath][virtualweight=kurier-heavy]
 
-    \starttypescript [\s!sans] [kurier-light,kurier,kurier-medium]
+    \starttypescript [\s!sans] [kurier-light,kurier,kurier-medium,kurier-heavy]
         \definefontsynonym [Kurier-Light]        [\s!file:kurierlightregular]  [\s!features=\s!default]
         \definefontsynonym [Kurier-LightItalic]  [\s!file:kurierlightitalic]   [\s!features=\s!default]
         \definefontsynonym [Kurier-Regular]      [\s!file:kurierregular]       [\s!features=\s!default]
@@ -88,6 +106,14 @@
         \definefontsynonym [\s!SansBoldItalic] [Kurier-HeavyItalic]
     \stoptypescript
 
+    \starttypescript [\s!sans] [kurier-heavy] [\s!name]
+        \setups[\s!font:\s!fallback:\s!sans]
+        \definefontsynonym [\s!Sans]           [Kurier-Heavy]
+        \definefontsynonym [\s!SansItalic]     [Kurier-HeavyItalic]
+        \definefontsynonym [\s!SansBold]       [Kurier-Heavy]
+        \definefontsynonym [\s!SansBoldItalic] [Kurier-Heavy]
+    \stoptypescript
+
     \starttypescript [\s!sans] [kurier-lightcond]
         \setups[\s!font:\s!fallback:\s!sans]
         \definefontsynonym [\s!Sans]           [Kurier-CondLight]
@@ -112,7 +138,7 @@
         \definefontsynonym [\s!SansBoldItalic] [Kurier-CondHeavyItalic]
     \stoptypescript
 
-    \starttypescript [kurier-light,kurier,kurier-medium,kurier-lightcond,kurier-cond,kurier-mediumcond]
+    \starttypescript [kurier-light,kurier,kurier-medium,kurier-heavy,kurier-lightcond,kurier-cond,kurier-mediumcond]
         \definetypeface [\typescriptone] [\s!ss] [\s!sans]  [\typescriptone] [\s!default]
         \definetypeface [\typescriptone] [\s!rm] [\s!serif] [modern]         [\s!default]
         \definetypeface [\typescriptone] [\s!tt] [\s!mono]  [modern]         [\s!default]
diff --git a/tex/context/fonts/mkiv/xcharter-math.lfg b/tex/context/fonts/mkiv/xcharter-math.lfg
index 1ff5d41d8..193c0fd1b 100644
--- a/tex/context/fonts/mkiv/xcharter-math.lfg
+++ b/tex/context/fonts/mkiv/xcharter-math.lfg
@@ -86,6 +86,9 @@ return {
                 {
                     tweak = "addprimed",
                 },
+-- {
+--     tweak = "addarrows",
+-- },
                 {
                     tweak = "addfourier",
                     variant = 2,
diff --git a/tex/context/interface/mkii/keys-it.xml b/tex/context/interface/mkii/keys-it.xml
index e456732ef..4804c39a7 100644
--- a/tex/context/interface/mkii/keys-it.xml
+++ b/tex/context/interface/mkii/keys-it.xml
@@ -838,6 +838,7 @@
 		<cd:constant name='exitoffset' value='exitoffset'/>
 		<cd:constant name='expansion' value='espansione'/>
 		<cd:constant name='export' value='export'/>
+		<cd:constant name='extradata' value='extradata'/>
 		<cd:constant name='extras' value='extras'/>
 		<cd:constant name='factor' value='fattore'/>
 		<cd:constant name='fallback' value='fallback'/>
@@ -961,6 +962,7 @@
 		<cd:constant name='lastpage' value='ultimapagina'/>
 		<cd:constant name='lastpagesep' value='lastpagesep'/>
 		<cd:constant name='lastpubsep' value='lastpubsep'/>
+		<cd:constant name='lasttextseparator' value='lasttextseparator'/>
 		<cd:constant name='layout' value='layout'/>
 		<cd:constant name='left' value='sinistra'/>
 		<cd:constant name='leftclass' value='leftclass'/>
diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua
index 614793314..e885a56ed 100644
--- a/tex/generic/context/luatex/luatex-fonts-merged.lua
+++ b/tex/generic/context/luatex/luatex-fonts-merged.lua
@@ -1,6 +1,6 @@
 -- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua
 -- parent file : c:/data/develop/context/sources/luatex-fonts.lua
--- merge date  : 2023-03-10 12:15
+-- merge date  : 2023-03-20 15:42
 
 do -- begin closure to overcome local limits and interference
 
-- 
cgit v1.2.3