@@ 28,7 28,7 @@ data CounterStyle = CounterStyle {
     speakAs :: Maybe Text
 }
 data CounterSystem = Cyclic | Fixed Int | Symbolic | Alphabetic | Numeric
-        | Additive | Chinese { isSimplified :: Bool }
+        | Additive | Chinese { isSimplified :: Bool } | Ethiopic
 
 defaultCounter, decimalCounter, simpChineseInformal, cjkDecimal :: CounterStyle
 defaultCounter = CounterStyle {
@@ 71,6 71,9 @@ isValid CounterStyle { system = Additive, additiveSymbols = [] } = False
 isValid self@CounterStyle {
         system = Chinese _, symbols = syms, additiveSymbols = markers
     } = length syms == 10 && length markers >= 4 && ranges self == Nothing
+isValid CounterStyle {
+        system = Ethiopic, symbols = units, additiveSymbols = tens
+    } = length units == 10 && length tens == 10
 isValid CounterStyle { symbols = [] } = False
 isValid _ = True
 
@@ 89,6 92,8 @@ parseCounterProperty _ ("system", [Ident "numeric"]) self =
     self { system = Numeric }
 parseCounterProperty _ ("system", [Ident "-argo-chinese", Ident x]) self =
     self { system = Chinese (x == "simplified") }
+parseCounterProperty _ ("system", [Ident "-argo-ethiopic"]) self =
+    self { system = Ethiopic }
 -- Handled by caller so property overrides work correctly.
 parseCounterProperty _ ("system", [Ident "extends", Ident _]) self = self
 
@@ 245,6 250,34 @@ counterRenderCore CounterStyle {
     -- Select characters per steps 2 & 5
     renderDigit (place, digit) = Txt.concat [syms !! digit, markers' !! place]
     markers' = map snd markers
+-- Following https://w3c.github.io/csswg-drafts/css-counter-styles-3/#ethiopic-numeric-counter-style
+-- 1. If the number is 1, return "፩" (U+1369).
+counterRenderCore CounterStyle { system = Ethiopic, symbols = (sym:_) } 1 = sym
+counterRenderCore CounterStyle {
+        system = Ethiopic, symbols = unitSyms, additiveSymbols = tenSyms
+    } x = Txt.concat $ renderPairs True $
+        reverse $ enumerate $ pairDigits $ decimalDigits x
+  where
+    -- 2. Split the number into groups of two digits,
+    -- starting with the least significant decimal digit.
+    pairDigits (units:tens:digits) = (tens,units):pairDigits digits
+    pairDigits [units] = (0, units):[]
+    pairDigits [] = []
+
+    renderPairs isBigEnd (group:groups) =
+        renderPair isBigEnd group:renderPairs False groups
+    -- Handle step 4's exceptions.
+    renderPair' _ (_,(0, 0)) = ""
+    renderPair' True (_, (0,1)) = ""
+    renderPair' _ (i, (0,1)) | odd i = ""
+    -- Step 5
+    renderPair' _ (_, (tens, units)) =
+        (map snd tenSyms !! tens) `Txt.append` (unitSyms !! units)
+    -- Step 6 & 7
+    renderPair _ (i, (0,0)) = ""
+    renderPair isBigEnd (i, group)
+        | odd i = renderPair' isBigEnd (i, group) `Txt.append` "፻"
+        | even i = renderPair' isBigEnd (i, group) `Txt.append` "፼"
 decimalDigits :: Int -> [Int]
 decimalDigits 0 = []
 decimalDigits x = rem x 10:decimalDigits (quot x 10)
@@ 291,6 324,7 @@ ranges' CounterStyle { system = Alphabetic } = [(1, maxBound)]
 ranges' CounterStyle { system = Symbolic } = [(1, maxBound)]
 ranges' CounterStyle { system = Additive } = [(0, maxBound)]
 ranges' CounterStyle { system = Chinese _ } = [(-9999, 9999)]
+ranges' CounterStyle { system = Ethiopic } = [(1, maxBound)]
 
 speakAs' :: CounterStyle -> Text
 speakAs' CounterStyle { speakAs = Just ret } = ret