///|
/// Returns the Unicode mathematical alphanumeric character for a given font
/// style and ASCII letter/digit, or `None` when no mapping exists.
///
/// Font styles that match LaTeX commands:
/// - `mathbf` / `boldsymbol` — Bold / Bold Italic
/// - `mathit` — Italic
/// - `mathbb` — Double-struck (blackboard bold)
/// - `mathcal` — Calligraphic / Script
/// - `mathfrak` — Fraktur
/// - `mathscr` — Script (rsfs)
/// - `mathsf` — Sans-serif
/// - `mathtt` — Monospace
/// - `mathsfit` — Sans-serif Italic
/// - `mathrm` / `mathnormal` — Roman (identity, not handled here) / Italic
pub fn unicode_font_character(font : String, char : String) -> String? {
  if char.length() != 1 {
    return None
  }
  let c = char[0]
  let cp = match font {
    "mathbf" | "boldsymbol" => {
      let base = if font == "boldsymbol" { 0x1D468 } else { 0x1D400 }
      let greek_cap = if font == "boldsymbol" { 0x1D71C } else { 0x1D6A8 }
      let greek_small = if font == "boldsymbol" { 0x1D736 } else { 0x1D6C2 }
      let greek_symbols = if font == "boldsymbol" { 0x1D750 } else { 0x1D6DC }
      match c {
        'A'..='Z' => Some(base + c.to_int() - ('A' : Char).to_int())
        'a'..='z' => Some(base + 26 + c.to_int() - ('a' : Char).to_int())
        '0'..='9' if font != "boldsymbol" =>
          Some(0x1D7CE + c.to_int() - ('0' : Char).to_int())
        'Α'..='Ω' => Some(greek_cap + c.to_int() - ('Α' : Char).to_int())
        'α'..='ω' => Some(greek_small + c.to_int() - ('α' : Char).to_int())
        'ϵ' => Some(greek_symbols + 0)
        'ϑ' => Some(greek_symbols + 1)
        'ϰ' => Some(greek_symbols + 2)
        'ϕ' => Some(greek_symbols + 3)
        'ϱ' => Some(greek_symbols + 4)
        'ϖ' => Some(greek_symbols + 5)
        '∇' => Some(greek_cap + 0x19)
        '∂' => Some(greek_small + 0x19)
        _ => None
      }
    }
    "mathit" | "mathnormal" =>
      match c {
        'A'..='Z' => Some(0x1D434 + c.to_int() - ('A' : Char).to_int())
        'a'..='z' => Some(0x1D44E + c.to_int() - ('a' : Char).to_int())
        'Α'..='Ω' => Some(0x1D6E2 + c.to_int() - ('Α' : Char).to_int())
        'α'..='ω' => Some(0x1D6FC + c.to_int() - ('α' : Char).to_int())
        'ϵ' => Some(0x1D716)
        'ϑ' => Some(0x1D717)
        'ϰ' => Some(0x1D718)
        'ϕ' => Some(0x1D719)
        'ϱ' => Some(0x1D71A)
        'ϖ' => Some(0x1D71B)
        '∇' => Some(0x1D6FB)
        '∂' => Some(0x1D715)
        _ => None
      }
    "mathsf" =>
      match c {
        'A'..='Z' => Some(0x1D5A0 + c.to_int() - ('A' : Char).to_int())
        'a'..='z' => Some(0x1D5BA + c.to_int() - ('a' : Char).to_int())
        '0'..='9' => Some(0x1D7E2 + c.to_int() - ('0' : Char).to_int())
        _ => None
      }
    "mathtt" =>
      match c {
        'A'..='Z' => Some(0x1D670 + c.to_int() - ('A' : Char).to_int())
        'a'..='z' => Some(0x1D68A + c.to_int() - ('a' : Char).to_int())
        '0'..='9' => Some(0x1D7F6 + c.to_int() - ('0' : Char).to_int())
        _ => None
      }
    "mathbb" =>
      match c {
        'A' => Some(0x1D538)
        'B' => Some(0x1D539)
        'C' => Some(0x2102)
        'D' => Some(0x1D53B)
        'E' => Some(0x1D53C)
        'F' => Some(0x1D53D)
        'G' => Some(0x1D53E)
        'H' => Some(0x210D)
        'I' => Some(0x1D540)
        'J' => Some(0x1D541)
        'K' => Some(0x1D542)
        'L' => Some(0x1D543)
        'M' => Some(0x1D544)
        'N' => Some(0x2115)
        'O' => Some(0x1D546)
        'P' => Some(0x2119)
        'Q' => Some(0x211A)
        'R' => Some(0x211D)
        'S' => Some(0x1D54A)
        'T' => Some(0x1D54B)
        'U' => Some(0x1D54C)
        'V' => Some(0x1D54D)
        'W' => Some(0x1D54E)
        'X' => Some(0x1D54F)
        'Y' => Some(0x1D550)
        'Z' => Some(0x2124)
        'a'..='z' => Some(0x1D552 + c.to_int() - ('a' : Char).to_int())
        '0'..='9' => Some(0x1D7D8 + c.to_int() - ('0' : Char).to_int())
        _ => None
      }
    "mathcal" =>
      match c {
        'A' => Some(0x1D49C)
        'B' => Some(0x212C)
        'C' => Some(0x1D49E)
        'D' => Some(0x1D49F)
        'E' => Some(0x2130)
        'F' => Some(0x2131)
        'G' => Some(0x1D4A2)
        'H' => Some(0x210B)
        'I' => Some(0x2110)
        'J' => Some(0x1D4A5)
        'K' => Some(0x1D4A6)
        'L' => Some(0x2112)
        'M' => Some(0x2133)
        'N' => Some(0x1D4A9)
        'O' => Some(0x1D4AA)
        'P' => Some(0x1D4AB)
        'Q' => Some(0x1D4AC)
        'R' => Some(0x211B)
        'S' => Some(0x1D4AE)
        'T' => Some(0x1D4AF)
        'U' => Some(0x1D4B0)
        'V' => Some(0x1D4B1)
        'W' => Some(0x1D4B2)
        'X' => Some(0x1D4B3)
        'Y' => Some(0x1D4B4)
        'Z' => Some(0x1D4B5)
        _ => None
      }
    "mathfrak" =>
      match c {
        'A' => Some(0x1D504)
        'B' => Some(0x1D505)
        'C' => Some(0x212D)
        'D' => Some(0x1D507)
        'E' => Some(0x1D508)
        'F' => Some(0x1D509)
        'G' => Some(0x1D50A)
        'H' => Some(0x210C)
        'I' => Some(0x2111)
        'J' => Some(0x1D50D)
        'K' => Some(0x1D50E)
        'L' => Some(0x1D50F)
        'M' => Some(0x1D510)
        'N' => Some(0x1D511)
        'O' => Some(0x1D512)
        'P' => Some(0x1D513)
        'Q' => Some(0x1D514)
        'R' => Some(0x211C)
        'S' => Some(0x1D516)
        'T' => Some(0x1D517)
        'U' => Some(0x1D518)
        'V' => Some(0x1D519)
        'W' => Some(0x1D51A)
        'X' => Some(0x1D51B)
        'Y' => Some(0x1D51C)
        'Z' => Some(0x2128)
        'a'..='z' => Some(0x1D51E + c.to_int() - ('a' : Char).to_int())
        _ => None
      }
    "mathscr" =>
      match c {
        'A'..='Z' => Some(0x1D4D0 + c.to_int() - ('A' : Char).to_int())
        'a'..='z' => Some(0x1D4EA + c.to_int() - ('a' : Char).to_int())
        _ => None
      }
    "mathsfit" =>
      match c {
        'A'..='Z' => Some(0x1D608 + c.to_int() - ('A' : Char).to_int())
        'a'..='z' => Some(0x1D622 + c.to_int() - ('a' : Char).to_int())
        _ => None
      }
    _ => None
  }
  cp.map(cp => String::from_array([Int::unsafe_to_char(cp)]))
}