Commit 16baee5aafa for php.net

commit 16baee5aafad148c297fff4ae861607e3d13ca2c
Author: ndossche <7771979+ndossche@users.noreply.github.com>
Date:   Sat Mar 14 14:30:10 2026 +0100

    Upgrade Lexbor to v2.7.0

    Co-authored-by: Ilija Tovilo <ilija.tovilo@me.com>

diff --git a/ext/dom/config.m4 b/ext/dom/config.m4
index 265dce7d50a..f5f8a1cae8c 100644
--- a/ext/dom/config.m4
+++ b/ext/dom/config.m4
@@ -27,15 +27,23 @@ if test "$PHP_DOM" != "no"; then
       $LEXBOR_DIR/core/shs.c
       $LEXBOR_DIR/core/str.c
       $LEXBOR_DIR/core/strtod.c
+      $LEXBOR_DIR/css/at_rule.c
+      $LEXBOR_DIR/css/at_rule/state.c
+      $LEXBOR_DIR/css/blank.c
       $LEXBOR_DIR/css/css.c
+      $LEXBOR_DIR/css/declaration.c
       $LEXBOR_DIR/css/log.c
       $LEXBOR_DIR/css/parser.c
+      $LEXBOR_DIR/css/property.c
+      $LEXBOR_DIR/css/property/state.c
+      $LEXBOR_DIR/css/rule.c
       $LEXBOR_DIR/css/selectors/pseudo_state.c
       $LEXBOR_DIR/css/selectors/pseudo.c
       $LEXBOR_DIR/css/selectors/selector.c
       $LEXBOR_DIR/css/selectors/selectors.c
       $LEXBOR_DIR/css/selectors/state.c
       $LEXBOR_DIR/css/state.c
+      $LEXBOR_DIR/css/stylesheet.c
       $LEXBOR_DIR/css/syntax/anb.c
       $LEXBOR_DIR/css/syntax/parser.c
       $LEXBOR_DIR/css/syntax/state.c
@@ -43,6 +51,8 @@ if test "$PHP_DOM" != "no"; then
       $LEXBOR_DIR/css/syntax/token.c
       $LEXBOR_DIR/css/syntax/tokenizer.c
       $LEXBOR_DIR/css/syntax/tokenizer/error.c
+      $LEXBOR_DIR/css/unit.c
+      $LEXBOR_DIR/css/value.c
       $LEXBOR_DIR/dom/interface.c
       $LEXBOR_DIR/dom/interfaces/attr.c
       $LEXBOR_DIR/dom/interfaces/cdata_section.c
@@ -118,7 +128,9 @@ if test "$PHP_DOM" != "no"; then
       $LEXBOR_DIR/html/interfaces/progress_element.c
       $LEXBOR_DIR/html/interfaces/quote_element.c
       $LEXBOR_DIR/html/interfaces/script_element.c
+      $LEXBOR_DIR/html/interfaces/search_element.c
       $LEXBOR_DIR/html/interfaces/select_element.c
+      $LEXBOR_DIR/html/interfaces/selectedcontent_element.c
       $LEXBOR_DIR/html/interfaces/slot_element.c
       $LEXBOR_DIR/html/interfaces/source_element.c
       $LEXBOR_DIR/html/interfaces/span_element.c
@@ -139,6 +151,7 @@ if test "$PHP_DOM" != "no"; then
       $LEXBOR_DIR/html/interfaces/video_element.c
       $LEXBOR_DIR/html/interfaces/window.c
       $LEXBOR_DIR/html/parser.c
+      $LEXBOR_DIR/html/tag.c
       $LEXBOR_DIR/html/token_attr.c
       $LEXBOR_DIR/html/token.c
       $LEXBOR_DIR/html/tokenizer.c
@@ -168,8 +181,6 @@ if test "$PHP_DOM" != "no"; then
       $LEXBOR_DIR/html/tree/insertion_mode/in_head_noscript.c
       $LEXBOR_DIR/html/tree/insertion_mode/in_head.c
       $LEXBOR_DIR/html/tree/insertion_mode/in_row.c
-      $LEXBOR_DIR/html/tree/insertion_mode/in_select_in_table.c
-      $LEXBOR_DIR/html/tree/insertion_mode/in_select.c
       $LEXBOR_DIR/html/tree/insertion_mode/in_table_body.c
       $LEXBOR_DIR/html/tree/insertion_mode/in_table_text.c
       $LEXBOR_DIR/html/tree/insertion_mode/in_table.c
@@ -225,6 +236,8 @@ if test "$PHP_DOM" != "no"; then
     PHP_ADD_BUILD_DIR([
       $ext_builddir/parentnode
       $ext_builddir/$LEXBOR_DIR/core
+      $ext_builddir/$LEXBOR_DIR/css/at_rule
+      $ext_builddir/$LEXBOR_DIR/css/property
       $ext_builddir/$LEXBOR_DIR/css/selectors
       $ext_builddir/$LEXBOR_DIR/css/syntax/tokenizer
       $ext_builddir/$LEXBOR_DIR/css/tokenizer
diff --git a/ext/dom/config.w32 b/ext/dom/config.w32
index 9e922d7a3f1..d5e3af57824 100644
--- a/ext/dom/config.w32
+++ b/ext/dom/config.w32
@@ -25,12 +25,14 @@ if (PHP_DOM == "yes") {
 		ADD_SOURCES("ext/dom/lexbor/lexbor/dom/interfaces", "attr.c cdata_section.c character_data.c comment.c document.c document_fragment.c document_type.c element.c node.c processing_instruction.c shadow_root.c text.c", "dom");
 		ADD_SOURCES("ext/dom/lexbor/lexbor/html/tokenizer", "error.c state_comment.c state_doctype.c state_rawtext.c state_rcdata.c state_script.c state.c", "dom");
 		ADD_SOURCES("ext/dom/lexbor/lexbor/html/tree", "active_formatting.c open_elements.c error.c", "dom");
-		ADD_SOURCES("ext/dom/lexbor/lexbor/html/tree/insertion_mode", "after_after_body.c after_after_frameset.c after_body.c after_frameset.c after_head.c before_head.c before_html.c foreign_content.c in_body.c in_caption.c in_cell.c in_column_group.c in_frameset.c in_head.c in_head_noscript.c initial.c in_row.c in_select.c in_select_in_table.c in_table_body.c in_table.c in_table_text.c in_template.c text.c", "dom");
-		ADD_SOURCES("ext/dom/lexbor/lexbor/html", "encoding.c interface.c parser.c token.c token_attr.c tokenizer.c tree.c", "dom");
+		ADD_SOURCES("ext/dom/lexbor/lexbor/html/tree/insertion_mode", "after_after_body.c after_after_frameset.c after_body.c after_frameset.c after_head.c before_head.c before_html.c foreign_content.c in_body.c in_caption.c in_cell.c in_column_group.c in_frameset.c in_head.c in_head_noscript.c initial.c in_row.c in_table_body.c in_table.c in_table_text.c in_template.c text.c", "dom");
+		ADD_SOURCES("ext/dom/lexbor/lexbor/html", "encoding.c interface.c parser.c tag.c token.c token_attr.c tokenizer.c tree.c", "dom");
 		ADD_SOURCES("ext/dom/lexbor/lexbor/encoding", "decode.c encode.c encoding.c multi.c range.c res.c single.c", "dom");
-		ADD_SOURCES("ext/dom/lexbor/lexbor/html/interfaces", "anchor_element.c area_element.c audio_element.c base_element.c body_element.c br_element.c button_element.c canvas_element.c data_element.c data_list_element.c details_element.c dialog_element.c directory_element.c div_element.c d_list_element.c document.c element.c embed_element.c field_set_element.c font_element.c form_element.c frame_element.c frame_set_element.c head_element.c heading_element.c hr_element.c html_element.c iframe_element.c image_element.c input_element.c label_element.c legend_element.c li_element.c link_element.c map_element.c marquee_element.c media_element.c menu_element.c meta_element.c meter_element.c mod_element.c object_element.c o_list_element.c opt_group_element.c option_element.c output_element.c paragraph_element.c param_element.c picture_element.c pre_element.c progress_element.c quote_element.c script_element.c select_element.c slot_element.c source_element.c span_element.c style_element.c table_caption_element.c table_cell_element.c table_col_element.c table_element.c table_row_element.c table_section_element.c template_element.c text_area_element.c time_element.c title_element.c track_element.c u_list_element.c unknown_element.c video_element.c window.c", "dom");
+		ADD_SOURCES("ext/dom/lexbor/lexbor/html/interfaces", "anchor_element.c area_element.c audio_element.c base_element.c body_element.c br_element.c button_element.c canvas_element.c data_element.c data_list_element.c details_element.c dialog_element.c directory_element.c div_element.c d_list_element.c document.c element.c embed_element.c field_set_element.c font_element.c form_element.c frame_element.c frame_set_element.c head_element.c heading_element.c hr_element.c html_element.c iframe_element.c image_element.c input_element.c label_element.c legend_element.c li_element.c link_element.c map_element.c marquee_element.c media_element.c menu_element.c meta_element.c meter_element.c mod_element.c object_element.c o_list_element.c opt_group_element.c option_element.c output_element.c paragraph_element.c param_element.c picture_element.c pre_element.c progress_element.c quote_element.c script_element.c search_element.c select_element.c selectedcontent_element.c slot_element.c source_element.c span_element.c style_element.c table_caption_element.c table_cell_element.c table_col_element.c table_element.c table_row_element.c table_section_element.c template_element.c text_area_element.c time_element.c title_element.c track_element.c u_list_element.c unknown_element.c video_element.c window.c", "dom");
 		ADD_SOURCES("ext/dom/lexbor/lexbor/selectors-adapted", "selectors.c", "dom");
-		ADD_SOURCES("ext/dom/lexbor/lexbor/css", "state.c log.c parser.c css.c", "dom");
+		ADD_SOURCES("ext/dom/lexbor/lexbor/css", "at_rule.c blank.c css.c declaration.c log.c parser.c property.c rule.c state.c stylesheet.c unit.c value.c", "dom");
+		ADD_SOURCES("ext/dom/lexbor/lexbor/css/at_rule", "state.c", "dom");
+		ADD_SOURCES("ext/dom/lexbor/lexbor/css/property", "state.c", "dom");
 		ADD_SOURCES("ext/dom/lexbor/lexbor/css/selectors", "state.c selectors.c selector.c pseudo_state.c pseudo.c", "dom");
 		ADD_SOURCES("ext/dom/lexbor/lexbor/css/syntax", "state.c parser.c syntax.c anb.c tokenizer.c token.c", "dom");
 		ADD_SOURCES("ext/dom/lexbor/lexbor/css/syntax/tokenizer", "error.c", "dom");
diff --git a/ext/dom/lexbor/lexbor/core/base.h b/ext/dom/lexbor/lexbor/core/base.h
index d3a04880f22..e488dcf7334 100644
--- a/ext/dom/lexbor/lexbor/core/base.h
+++ b/ext/dom/lexbor/lexbor/core/base.h
@@ -27,7 +27,7 @@ extern "C" {
 #include "lexbor/core/lexbor.h"

 #define LEXBOR_VERSION_MAJOR 2
-#define LEXBOR_VERSION_MINOR 0
+#define LEXBOR_VERSION_MINOR 7
 #define LEXBOR_VERSION_PATCH 0

 #define LEXBOR_VERSION_STRING LEXBOR_STRINGIZE(LEXBOR_VERSION_MAJOR) "."       \
@@ -39,6 +39,10 @@ extern "C" {
 #define lexbor_max(val1, val2) ((val1) > (val2) ? (val1) : (val2))
 #define lexbor_min(val1, val2) ((val1) < (val2) ? (val1) : (val2))

+#define LEXBOR_STR_RES_MAP_CHAR_OTHER      0x00
+#define LEXBOR_STR_RES_MAP_CHAR_A_Z_a_z    0x01
+#define LEXBOR_STR_RES_MAP_CHAR_WHITESPACE 0x02
+#define LEXBOR_STR_RES_SLIP                0xFF

 /*
  * Very important!!!
diff --git a/ext/dom/lexbor/lexbor/core/def.h b/ext/dom/lexbor/lexbor/core/def.h
index 5a48f59e994..c8b94400a2d 100644
--- a/ext/dom/lexbor/lexbor/core/def.h
+++ b/ext/dom/lexbor/lexbor/core/def.h
@@ -54,4 +54,6 @@

 #define LXB_EXTERN extern LXB_API

+#define lxb_size(_size) ((size_t) (_size))
+
 #endif /* LEXBOR_DEF_H */
diff --git a/ext/dom/lexbor/lexbor/core/diyfp.c b/ext/dom/lexbor/lexbor/core/diyfp.c
index 62020bbc645..7bdbcbbcb08 100644
--- a/ext/dom/lexbor/lexbor/core/diyfp.c
+++ b/ext/dom/lexbor/lexbor/core/diyfp.c
@@ -1,16 +1,44 @@
 /*
- * Copyright (C) Alexander Borisov
+ * Copyright (C) 2015-2019 NGINX, Inc.
+ * Copyright (C) 2019-2025 F5, Inc.
+ * Copyright (C) 2015-2021 Igor Sysoev
+ * Copyright (C) 2017-2025 Dmitry Volyntsev
+ * Copyright (C) 2019-2022 Alexander Borisov
+ * Copyright (C) 2022-2025 Vadim Zhestikov
+ * All rights reserved.
  *
- * Based on nxt_diyfp.c from NGINX NJS project
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
  *
- * Copyright (C) Dmitry Volyntsev
- * Copyright (C) NGINX, Inc.
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (C) Alexander Borisov
  *
+ * Based on nxt_diyfp.h from NGINX NJS project
  * An internal diy_fp implementation.
  * For details, see Loitsch, Florian. "Printing floating-point numbers quickly
  * and accurately with integers." ACM Sigplan Notices 45.6 (2010): 233-243.
  */

+
 #include "lexbor/core/diyfp.h"


diff --git a/ext/dom/lexbor/lexbor/core/diyfp.h b/ext/dom/lexbor/lexbor/core/diyfp.h
index 47fedb9da99..86c5336f2e0 100644
--- a/ext/dom/lexbor/lexbor/core/diyfp.h
+++ b/ext/dom/lexbor/lexbor/core/diyfp.h
@@ -1,11 +1,38 @@
 /*
- * Copyright (C) Alexander Borisov
+ * Copyright (C) 2015-2019 NGINX, Inc.
+ * Copyright (C) 2019-2025 F5, Inc.
+ * Copyright (C) 2015-2021 Igor Sysoev
+ * Copyright (C) 2017-2025 Dmitry Volyntsev
+ * Copyright (C) 2019-2022 Alexander Borisov
+ * Copyright (C) 2022-2025 Vadim Zhestikov
+ * All rights reserved.
  *
- * Based on nxt_diyfp.h from NGINX NJS project
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
  *
- * Copyright (C) Dmitry Volyntsev
- * Copyright (C) NGINX, Inc.
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (C) Alexander Borisov
  *
+ * Based on nxt_diyfp.h from NGINX NJS project
  * An internal diy_fp implementation.
  * For details, see Loitsch, Florian. "Printing floating-point numbers quickly
  * and accurately with integers." ACM Sigplan Notices 45.6 (2010): 233-243.
diff --git a/ext/dom/lexbor/lexbor/core/dtoa.c b/ext/dom/lexbor/lexbor/core/dtoa.c
index b1a4ee03258..7da7ce01322 100644
--- a/ext/dom/lexbor/lexbor/core/dtoa.c
+++ b/ext/dom/lexbor/lexbor/core/dtoa.c
@@ -1,39 +1,36 @@
 /*
- * Copyright (C) Alexander Borisov
- *
- * Based on nxt_dtoa.c from NGINX NJS project
- *
- * Copyright (C) Dmitry Volyntsev
- * Copyright (C) NGINX, Inc.
- *
- * Grisu2 algorithm implementation for printing floating-point numbers based
- * upon the work of Milo Yip and Doug Currie.
- *
- * For algorithm information, see Loitsch, Florian. "Printing
- * floating-point numbers quickly and accurately with integers." ACM Sigplan
- * Notices 45.6 (2010): 233-243.
- *
- * Copyright (C) 2015 Doug Currie
- * based on dtoa_milo.h
- * Copyright (C) 2014 Milo Yip
+ * Copyright (C) 2015-2019 NGINX, Inc.
+ * Copyright (C) 2019-2025 F5, Inc.
+ * Copyright (C) 2015-2021 Igor Sysoev
+ * Copyright (C) 2017-2025 Dmitry Volyntsev
+ * Copyright (C) 2019-2022 Alexander Borisov
+ * Copyright (C) 2022-2025 Vadim Zhestikov
+ * All rights reserved.
  *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
  *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (C) Alexander Borisov
  */

 #include "lexbor/core/str.h"
diff --git a/ext/dom/lexbor/lexbor/core/dtoa.h b/ext/dom/lexbor/lexbor/core/dtoa.h
index c60c28803b7..2d569cfff97 100644
--- a/ext/dom/lexbor/lexbor/core/dtoa.h
+++ b/ext/dom/lexbor/lexbor/core/dtoa.h
@@ -1,10 +1,36 @@
 /*
- * Copyright (C) Alexander Borisov
+ * Copyright (C) 2015-2019 NGINX, Inc.
+ * Copyright (C) 2019-2025 F5, Inc.
+ * Copyright (C) 2015-2021 Igor Sysoev
+ * Copyright (C) 2017-2025 Dmitry Volyntsev
+ * Copyright (C) 2019-2022 Alexander Borisov
+ * Copyright (C) 2022-2025 Vadim Zhestikov
+ * All rights reserved.
  *
- * Based on nxt_dtoa.h from NGINX NJS project
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
  *
- * Copyright (C) Dmitry Volyntsev
- * Copyright (C) Nginx, Inc.
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (C) Alexander Borisov
  */

 #ifndef LEXBOR_DTOA_H
diff --git a/ext/dom/lexbor/lexbor/core/hash.c b/ext/dom/lexbor/lexbor/core/hash.c
index 2fdd4caa9d9..c16466effd3 100644
--- a/ext/dom/lexbor/lexbor/core/hash.c
+++ b/ext/dom/lexbor/lexbor/core/hash.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 Alexander Borisov
+ * Copyright (C) 2019-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -10,9 +10,10 @@

 #include "lexbor/core/str.h"

-#define LEXBOR_STR_RES_MAP_LOWERCASE
-#define LEXBOR_STR_RES_MAP_UPPERCASE
-#include "lexbor/core/str_res.h"
+#ifndef LEXBOR_DISABLE_INTERNAL_EXTERN
+    LXB_EXTERN const lxb_char_t lexbor_str_res_map_lowercase[256];
+    LXB_EXTERN const lxb_char_t lexbor_str_res_map_uppercase[256];
+#endif


 /* Insert variable. */
diff --git a/ext/dom/lexbor/lexbor/core/in.c b/ext/dom/lexbor/lexbor/core/in.c
index 951e585cbd3..363256b732a 100644
--- a/ext/dom/lexbor/lexbor/core/in.c
+++ b/ext/dom/lexbor/lexbor/core/in.c
@@ -1,11 +1,10 @@
 /*
- * Copyright (C) 2018 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */

 #include "lexbor/core/in.h"
-#include "lexbor/core/str_res.h"


 lexbor_in_t *
diff --git a/ext/dom/lexbor/lexbor/core/shs.c b/ext/dom/lexbor/lexbor/core/shs.c
index 679143bf45c..c2753457d74 100644
--- a/ext/dom/lexbor/lexbor/core/shs.c
+++ b/ext/dom/lexbor/lexbor/core/shs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018-2019 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -7,10 +7,10 @@
 #include "lexbor/core/shs.h"
 #include "lexbor/core/str.h"

-#define LEXBOR_STR_RES_MAP_LOWERCASE
-#define LEXBOR_STR_RES_MAP_UPPERCASE
-#include "lexbor/core/str_res.h"
-
+#ifndef LEXBOR_DISABLE_INTERNAL_EXTERN
+    LXB_EXTERN const lxb_char_t lexbor_str_res_map_lowercase[256];
+    LXB_EXTERN const lxb_char_t lexbor_str_res_map_uppercase[256];
+#endif

 #define lexbor_shs_make_id_m(key, size, table_size)                            \
     (((((key[0] * key[size - 1]) * key[0]) + size) % table_size) + 0x01)
diff --git a/ext/dom/lexbor/lexbor/core/str.c b/ext/dom/lexbor/lexbor/core/str.c
index d11a08614dd..3d164ebf82d 100644
--- a/ext/dom/lexbor/lexbor/core/str.c
+++ b/ext/dom/lexbor/lexbor/core/str.c
@@ -1,14 +1,10 @@
 /*
- * Copyright (C) 2018 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */

 #include "lexbor/core/str.h"
-
-#define LEXBOR_STR_RES_ANSI_REPLACEMENT_CHARACTER
-#define LEXBOR_STR_RES_MAP_LOWERCASE
-#define LEXBOR_STR_RES_MAP_UPPERCASE
 #include "lexbor/core/str_res.h"


@@ -80,6 +76,7 @@ lexbor_str_destroy(lexbor_str_t *str, lexbor_mraw_t *mraw, bool destroy_obj)
     }

     if (str->data != NULL) {
+        lexbor_str_clean(str);
         str->data = lexbor_mraw_free(mraw, str->data);
     }

@@ -380,6 +377,30 @@ lexbor_str_whitespace_from_end(lexbor_str_t *target)
     return 0;
 }

+lxb_char_t *
+lexbor_str_copy_to(lexbor_str_t *str, const lxb_char_t *buff, size_t length)
+{
+    lxb_char_t *data_begin;
+
+    data_begin = &str->data[str->length];
+    memcpy(data_begin, buff, sizeof(lxb_char_t) * length);
+
+    str->length += length;
+
+    return data_begin;
+}
+
+lxb_char_t *
+lexbor_str_copy_to_with_null(lexbor_str_t *str,
+                             const lxb_char_t *buff, size_t length)
+{
+    lxb_char_t *data_begin = lexbor_str_copy_to(str, buff, length);
+
+    str->data[str->length] = '\0';
+
+    return data_begin;
+}
+
 /*
  * Data utils
  * TODO: All functions need optimization.
diff --git a/ext/dom/lexbor/lexbor/core/str.h b/ext/dom/lexbor/lexbor/core/str.h
index 3bee1453738..8e5f3806fe9 100644
--- a/ext/dom/lexbor/lexbor/core/str.h
+++ b/ext/dom/lexbor/lexbor/core/str.h
@@ -21,7 +21,6 @@ extern "C" {
 #define lexbor_str_len(str) lexbor_str_get(str, length)
 #define lexbor_str(p) {.data = (lxb_char_t *) (p), sizeof(p) - 1}

-
 #define lexbor_str_check_size_arg_m(str, size, mraw, plus_len, return_fail)    \
     do {                                                                       \
         void *tmp;                                                             \
@@ -117,6 +116,12 @@ lexbor_str_whitespace_from_begin(lexbor_str_t *target);
 LXB_API size_t
 lexbor_str_whitespace_from_end(lexbor_str_t *target);

+LXB_API lxb_char_t *
+lexbor_str_copy_to(lexbor_str_t *str, const lxb_char_t *buff, size_t length);
+
+LXB_API lxb_char_t *
+lexbor_str_copy_to_with_null(lexbor_str_t *str,
+                             const lxb_char_t *buff, size_t length);

 /* Data utils */
 /*
diff --git a/ext/dom/lexbor/lexbor/core/str_res.h b/ext/dom/lexbor/lexbor/core/str_res.h
index cebbda8aa53..be34a0eeb42 100644
--- a/ext/dom/lexbor/lexbor/core/str_res.h
+++ b/ext/dom/lexbor/lexbor/core/str_res.h
@@ -1,32 +1,16 @@
 /*
- * Copyright (C) 2018 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */

-#ifndef LEXBOR_STR_RES_H
-#define LEXBOR_STR_RES_H

-#define LEXBOR_STR_RES_MAP_CHAR_OTHER      '\00'
-#define LEXBOR_STR_RES_MAP_CHAR_A_Z_a_z    '\01'
-#define LEXBOR_STR_RES_MAP_CHAR_WHITESPACE '\02'
+LXB_API const lxb_char_t
+lexbor_str_res_ansi_replacement_character[4] = "\xEF\xBF\xBD";

-#define LEXBOR_STR_RES_SLIP 0xFF
-
-#endif /* LEXBOR_STR_RES_H */
-
-#ifdef LEXBOR_STR_RES_ANSI_REPLACEMENT_CHARACTER
-#ifndef LEXBOR_STR_RES_ANSI_REPLACEMENT_CHARACTER_ENABLED
-#define LEXBOR_STR_RES_ANSI_REPLACEMENT_CHARACTER_ENABLED
-static const lxb_char_t
-lexbor_str_res_ansi_replacement_character[] = "\xEF\xBF\xBD";
-#endif /* LEXBOR_STR_RES_ANSI_REPLACEMENT_CHARACTER_ENABLED */
-#endif /* LEXBOR_STR_RES_ANSI_REPLACEMENT_CHARACTER */
-
-#ifdef LEXBOR_STR_RES_MAP_NUM
-#ifndef LEXBOR_STR_RES_MAP_NUM_ENABLED
-#define LEXBOR_STR_RES_MAP_NUM_ENABLED
-static const lxb_char_t lexbor_str_res_map_num[] = {
+LXB_API const lxb_char_t
+lexbor_str_res_map_num[256] =
+{
     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
@@ -57,14 +41,10 @@ static const lxb_char_t lexbor_str_res_map_num[] = {
     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     0xff, 0xff, 0xff, 0xff
 };
-#endif /* LEXBOR_STR_RES_MAP_NUM_ENABLED */
-#endif /* LEXBOR_STR_RES_MAP_NUM */

-
-#ifdef LEXBOR_STR_RES_MAP_HEX
-#ifndef LEXBOR_STR_RES_MAP_HEX_ENABLED
-#define LEXBOR_STR_RES_MAP_HEX_ENABLED
-static const lxb_char_t lexbor_str_res_map_hex[] = {
+LXB_API const lxb_char_t
+lexbor_str_res_map_hex[256] =
+{
     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
@@ -95,14 +75,10 @@ static const lxb_char_t lexbor_str_res_map_hex[] = {
     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     0xff, 0xff, 0xff, 0xff
 };
-#endif /* LEXBOR_STR_RES_MAP_HEX_ENABLED */
-#endif /* LEXBOR_STR_RES_MAP_HEX */
-

-#ifdef LEXBOR_STR_RES_MAP_LOWERCASE
-#ifndef LEXBOR_STR_RES_MAP_LOWERCASE_ENABLED
-#define LEXBOR_STR_RES_MAP_LOWERCASE_ENABLED
-static const lxb_char_t lexbor_str_res_map_lowercase[] = {
+LXB_API const lxb_char_t
+lexbor_str_res_map_lowercase[256] =
+{
     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
     0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
     0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
@@ -133,14 +109,10 @@ static const lxb_char_t lexbor_str_res_map_lowercase[] = {
     0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb,
     0xfc, 0xfd, 0xfe, 0xff
 };
-#endif /* LEXBOR_STR_RES_MAP_LOWERCASE_ENABLED */
-#endif /* LEXBOR_STR_RES_MAP_LOWERCASE */
-

-#ifdef LEXBOR_STR_RES_MAP_UPPERCASE
-#ifndef LEXBOR_STR_RES_MAP_UPPERCASE_ENABLED
-#define LEXBOR_STR_RES_MAP_UPPERCASE_ENABLED
-static const lxb_char_t lexbor_str_res_map_uppercase[] = {
+LXB_API const lxb_char_t
+lexbor_str_res_map_uppercase[256] =
+{
     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
     0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
     0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
@@ -171,14 +143,10 @@ static const lxb_char_t lexbor_str_res_map_uppercase[] = {
     0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb,
     0xfc, 0xfd, 0xfe, 0xff
 };
-#endif /* LEXBOR_STR_RES_MAP_UPPERCASE_ENABLED */
-#endif /* LEXBOR_STR_RES_MAP_UPPERCASE */

-
-#ifdef LEXBOR_STR_RES_REPLACEMENT_CHARACTER
-#ifndef LEXBOR_STR_RES_REPLACEMENT_CHARACTER_ENABLED
-#define LEXBOR_STR_RES_REPLACEMENT_CHARACTER_ENABLED
-static const size_t lexbor_str_res_replacement_character[] = {
+LXB_API const size_t
+lexbor_str_res_replacement_character[160] =
+{
     65533, 1, 2, 3, 4, 5, 6, 7, 8,
     9, 10, 11, 12, 13, 14, 15, 16, 17,
     18, 19, 20, 21, 22, 23, 24, 25, 26,
@@ -198,14 +166,10 @@ static const size_t lexbor_str_res_replacement_character[] = {
     144, 8216, 8217, 8220, 8221, 8226, 8211, 8212, 732,
     8482, 353, 8250, 339, 157, 382, 376
 };
-#endif /* LEXBOR_STR_RES_REPLACEMENT_CHARACTER_ENABLED */
-#endif /* LEXBOR_STR_RES_REPLACEMENT_CHARACTER */
-

-#ifdef LEXBOR_STR_RES_ALPHANUMERIC_CHARACTER
-#ifndef LEXBOR_STR_RES_ALPHANUMERIC_CHARACTER_ENABLED
-#define LEXBOR_STR_RES_ALPHANUMERIC_CHARACTER_ENABLED
-static const size_t lexbor_str_res_alphanumeric_character[] = {
+LXB_API const size_t
+lexbor_str_res_alphanumeric_character[256] =
+{
     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
@@ -236,14 +200,10 @@ static const size_t lexbor_str_res_alphanumeric_character[] = {
     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     0xff, 0xff, 0xff, 0xff
 };
-#endif /* LEXBOR_STR_RES_ALPHANUMERIC_CHARACTER_ENABLED */
-#endif /* LEXBOR_STR_RES_ALPHANUMERIC_CHARACTER */
-

-#ifdef LEXBOR_STR_RES_ALPHA_CHARACTER
-#ifndef LEXBOR_STR_RES_ALPHA_CHARACTER_ENABLED
-#define LEXBOR_STR_RES_ALPHA_CHARACTER_ENABLED
-static const size_t lexbor_str_res_alpha_character[] = {
+LXB_API const size_t
+lexbor_str_res_alpha_character[256] =
+{
     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
@@ -274,14 +234,10 @@ static const size_t lexbor_str_res_alpha_character[] = {
     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     0xff, 0xff, 0xff, 0xff
 };
-#endif /* LEXBOR_STR_RES_ALPHA_CHARACTER_ENABLED */
-#endif /* LEXBOR_STR_RES_ALPHA_CHARACTER */

-
-#ifdef LEXBOR_TOKENIZER_CHARS_MAP
-#ifndef LEXBOR_TOKENIZER_CHARS_MAP_ENABLED
-#define LEXBOR_TOKENIZER_CHARS_MAP_ENABLED
-static const unsigned char lexbor_tokenizer_chars_map[] = {
+LXB_API const unsigned char
+lexbor_tokenizer_chars_map[256] =
+{
     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     0x02, 0x02, 0xff, 0x02, 0x02, 0xff, 0xff, 0xff, 0xff,
     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
@@ -312,35 +268,24 @@ static const unsigned char lexbor_tokenizer_chars_map[] = {
     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     0xff, 0xff, 0xff, 0xff
 };
-#endif /* LEXBOR_TOKENIZER_CHARS_MAP_ENABLED */
-#endif /* LEXBOR_TOKENIZER_CHARS_MAP */
-

-#ifdef LEXBOR_STR_RES_MAP_HEX_TO_CHAR
-#ifndef LEXBOR_STR_RES_MAP_HEX_TO_CHAR_ENABLED
-#define LEXBOR_STR_RES_MAP_HEX_TO_CHAR_ENABLED
-static const lxb_char_t lexbor_str_res_map_hex_to_char[] = {
+LXB_API const lxb_char_t
+lexbor_str_res_map_hex_to_char[17] =
+{
     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
     0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x00
 };
-#endif /* LEXBOR_STR_RES_MAP_HEX_TO_CHAR_ENABLED */
-#endif /* LEXBOR_STR_RES_MAP_HEX_TO_CHAR */

-#ifdef LEXBOR_STR_RES_MAP_HEX_TO_CHAR_LOWERCASE
-#ifndef LEXBOR_STR_RES_MAP_HEX_TO_CHAR_LOWERCASE_ENABLED
-#define LEXBOR_STR_RES_MAP_HEX_TO_CHAR_LOWERCASE_ENABLED
-static const lxb_char_t lexbor_str_res_map_hex_to_char_lowercase[] = {
+LXB_API const lxb_char_t
+lexbor_str_res_map_hex_to_char_lowercase[17] =
+{
     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
     0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x00
 };
-#endif /* LEXBOR_STR_RES_MAP_HEX_TO_CHAR_LOWERCASE_ENABLED */
-#endif /* LEXBOR_STR_RES_MAP_HEX_TO_CHAR_LOWERCASE */
-

-#ifdef LEXBOR_STR_RES_CHAR_TO_TWO_HEX_VALUE
-#ifndef LEXBOR_STR_RES_CHAR_TO_TWO_HEX_VALUE_ENABLED
-#define LEXBOR_STR_RES_CHAR_TO_TWO_HEX_VALUE_ENABLED
-static const char * lexbor_str_res_char_to_two_hex_value[257] = {
+LXB_API const char *
+lexbor_str_res_char_to_two_hex_value[257] =
+{
     "00", "01", "02", "03", "04", "05", "06", "07",
     "08", "09", "0A", "0B", "0C", "0D", "0E", "0F",
     "10", "11", "12", "13", "14", "15", "16", "17",
@@ -375,13 +320,10 @@ static const char * lexbor_str_res_char_to_two_hex_value[257] = {
     "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF",
     NULL
 };
-#endif /* LEXBOR_STR_RES_CHAR_TO_TWO_HEX_VALUE_ENABLED */
-#endif /* LEXBOR_STR_RES_CHAR_TO_TWO_HEX_VALUE */

-#ifdef LEXBOR_STR_RES_CHAR_TO_TWO_HEX_VALUE_LOWERCASE
-#ifndef LEXBOR_STR_RES_CHAR_TO_TWO_HEX_VALUE_LOWERCASE_ENABLED
-#define LEXBOR_STR_RES_CHAR_TO_TWO_HEX_VALUE_LOWERCASE_ENABLED
-static const char * lexbor_str_res_char_to_two_hex_value_lowercase[257] = {
+LXB_API const char *
+lexbor_str_res_char_to_two_hex_value_lowercase[257] =
+{
     "00", "01", "02", "03", "04", "05", "06", "07",
     "08", "09", "0a", "0b", "0c", "0d", "0e", "0f",
     "10", "11", "12", "13", "14", "15", "16", "17",
@@ -416,5 +358,3 @@ static const char * lexbor_str_res_char_to_two_hex_value_lowercase[257] = {
     "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff",
     NULL
 };
-#endif /* LEXBOR_STR_RES_CHAR_TO_TWO_HEX_VALUE_LOWERCASE_ENABLED */
-#endif /* LEXBOR_STR_RES_CHAR_TO_TWO_HEX_VALUE_LOWERCASE */
diff --git a/ext/dom/lexbor/lexbor/core/strtod.c b/ext/dom/lexbor/lexbor/core/strtod.c
index 6389fc3156f..2dad45c109b 100644
--- a/ext/dom/lexbor/lexbor/core/strtod.c
+++ b/ext/dom/lexbor/lexbor/core/strtod.c
@@ -1,14 +1,36 @@
 /*
- * Copyright (C) Alexander Borisov
- *
- * Based on nxt_strtod.c from NGINX NJS project
+ * Copyright (C) 2015-2019 NGINX, Inc.
+ * Copyright (C) 2019-2025 F5, Inc.
+ * Copyright (C) 2015-2021 Igor Sysoev
+ * Copyright (C) 2017-2025 Dmitry Volyntsev
+ * Copyright (C) 2019-2022 Alexander Borisov
+ * Copyright (C) 2022-2025 Vadim Zhestikov
+ * All rights reserved.
  *
- * An internal strtod() implementation based upon V8 src/strtod.cc
- * without bignum support.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
  *
- * Copyright 2012 the V8 project authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file.
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (C) Alexander Borisov
  */

 #include <stdint.h>
diff --git a/ext/dom/lexbor/lexbor/core/strtod.h b/ext/dom/lexbor/lexbor/core/strtod.h
index 7f15706bc94..0f834bab486 100644
--- a/ext/dom/lexbor/lexbor/core/strtod.h
+++ b/ext/dom/lexbor/lexbor/core/strtod.h
@@ -1,10 +1,36 @@
 /*
- * Copyright (C) Alexander Borisov
+ * Copyright (C) 2015-2019 NGINX, Inc.
+ * Copyright (C) 2019-2025 F5, Inc.
+ * Copyright (C) 2015-2021 Igor Sysoev
+ * Copyright (C) 2017-2025 Dmitry Volyntsev
+ * Copyright (C) 2019-2022 Alexander Borisov
+ * Copyright (C) 2022-2025 Vadim Zhestikov
+ * All rights reserved.
  *
- * Based on nxt_strtod.h from NGINX NJS project
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
  *
- * Copyright (C) Dmitry Volyntsev
- * Copyright (C) Nginx, Inc.
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (C) Alexander Borisov
  */

 #ifndef LEXBOR_STRTOD_H
diff --git a/ext/dom/lexbor/lexbor/css/at_rule.c b/ext/dom/lexbor/lexbor/css/at_rule.c
new file mode 100644
index 00000000000..6c5435d22e0
--- /dev/null
+++ b/ext/dom/lexbor/lexbor/css/at_rule.c
@@ -0,0 +1,449 @@
+/*
+ * Copyright (C) 2021-2026 Alexander Borisov
+ *
+ * Author: Alexander Borisov <borisov@lexbor.com>
+ */
+
+#include "lexbor/css/at_rule.h"
+#include "lexbor/css/css.h"
+#include "lexbor/css/parser.h"
+#include "lexbor/css/stylesheet.h"
+#include "lexbor/css/at_rule/state.h"
+#include "lexbor/css/at_rule/types.h"
+#include "lexbor/css/at_rule/res.h"
+#include "lexbor/core/serialize.h"
+
+
+const lxb_css_entry_at_rule_data_t *
+lxb_css_at_rule_by_name(const lxb_char_t *name, size_t length)
+{
+    const lexbor_shs_entry_t *entry;
+
+    entry = lexbor_shs_entry_get_lower_static(lxb_css_at_rule_shs,
+                                              name, length);
+    if (entry == NULL) {
+        return NULL;
+    }
+
+    return entry->value;
+}
+
+const lxb_css_entry_at_rule_data_t *
+lxb_css_at_rule_by_id(uintptr_t id)
+{
+    return &lxb_css_at_rule_data[id];
+}
+
+lxb_css_rule_at_t *
+lxb_css_at_rule_create(lxb_css_parser_t *parser,
+                       const lxb_char_t *name, size_t length,
+                       const lxb_css_entry_at_rule_data_t **out_entry)
+{
+    void *prop;
+    const lxb_css_entry_at_rule_data_t *entry;
+    lxb_css_at_rule__custom_t *custom;
+    lxb_css_rule_at_t *at;
+
+    at = lxb_css_rule_at_create(parser->memory);
+    if (at == NULL) {
+        return NULL;
+    }
+
+    entry = lxb_css_at_rule_by_name(name, length);
+    if (entry == NULL) {
+        entry = lxb_css_at_rule_by_id(LXB_CSS_AT_RULE__CUSTOM);
+
+        prop = entry->create(parser->memory);
+        if (prop == NULL) {
+            goto failed;
+        }
+
+        custom = prop;
+
+        (void) lexbor_str_init(&custom->name, parser->memory->mraw, length);
+        if (custom->name.data == NULL) {
+            goto failed;
+        }
+
+        memcpy(custom->name.data, name, length);
+
+        custom->name.length = length;
+        custom->name.data[custom->name.length] = 0x00;
+    }
+    else {
+        prop = entry->create(parser->memory);
+        if (prop == NULL) {
+            goto failed;
+        }
+    }
+
+    at->type = entry->unique;
+    at->u.user = prop;
+
+    if (out_entry != NULL) {
+        *out_entry = entry;
+    }
+
+    return at;
+
+failed:
+
+    if (prop != NULL) {
+        (void) entry->destroy(parser->memory, prop, true);
+    }
+
+    if (at != NULL) {
+        (void) lxb_css_rule_at_destroy(at, true);
+    }
+
+    if (out_entry != NULL) {
+        *out_entry = NULL;
+    }
+
+    return NULL;
+}
+
+void *
+lxb_css_at_rule_destroy(lxb_css_memory_t *memory, void *value,
+                        lxb_css_at_rule_type_t type, bool self_destroy)
+{
+    const lxb_css_entry_at_rule_data_t *data;
+
+    data = lxb_css_at_rule_by_id(type);
+    if (data == NULL) {
+        return value;
+    }
+
+    return data->destroy(memory, value, self_destroy);
+}
+
+lxb_status_t
+lxb_css_at_rule_convert_to_undef(lxb_css_parser_t *parser,
+                                 lxb_css_rule_at_t *at)
+{
+    lxb_css_at_rule__undef_t *undef;
+
+    undef = lxb_css_at_rule__undef_create(parser->memory);
+    if (undef == NULL) {
+        return LXB_STATUS_ERROR_MEMORY_ALLOCATION;
+    }
+
+    undef->type = at->type;
+
+    (void) lxb_css_at_rule_destroy(parser->memory, at, undef->type, false);
+
+    at->type = LXB_CSS_AT_RULE__UNDEF;
+    at->u.undef = undef;
+
+    return lxb_css_make_data(parser, &at->u.undef->prelude,
+                             at->prelude_begin, at->prelude_end);
+}
+
+lxb_status_t
+lxb_css_at_rule_serialize(const void *style, lxb_css_at_rule_type_t type,
+                          lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_entry_at_rule_data_t *data;
+
+    data = lxb_css_at_rule_by_id(type);
+    if (data == NULL) {
+        return LXB_STATUS_ERROR_UNEXPECTED_DATA;
+    }
+
+    return data->serialize(style, cb, ctx);
+}
+
+lxb_status_t
+lxb_css_at_rule_serialize_str(const void *style, lxb_css_at_rule_type_t type,
+                              lexbor_mraw_t *mraw, lexbor_str_t *str)
+{
+    const lxb_css_entry_at_rule_data_t *data;
+
+    data = lxb_css_at_rule_by_id(type);
+    if (data == NULL) {
+        return LXB_STATUS_ERROR_UNEXPECTED_DATA;
+    }
+
+    return lxb_css_serialize_str_handler(style, str, mraw, data->serialize);
+}
+
+lxb_status_t
+lxb_css_at_rule_serialize_name(const void *style, lxb_css_at_rule_type_t type,
+                               lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_entry_at_rule_data_t *data;
+
+    if (type == LXB_CSS_AT_RULE__UNDEF) {
+        return lxb_css_at_rule__undef_serialize_name(style, cb, ctx);
+    }
+    else if (type == LXB_CSS_AT_RULE__CUSTOM) {
+        return lxb_css_at_rule__custom_serialize_name(style, cb, ctx);
+    }
+
+    data = lxb_css_at_rule_by_id(type);
+    if (data == NULL) {
+        return LXB_STATUS_ERROR_UNEXPECTED_DATA;
+    }
+
+    return cb(data->name, data->length, ctx);
+}
+
+lxb_status_t
+lxb_css_at_rule_serialize_name_str(const void *style, lxb_css_at_rule_type_t type,
+                                   lexbor_mraw_t *mraw, lexbor_str_t *str)
+{
+    const lxb_css_entry_at_rule_data_t *data;
+
+    if (type == LXB_CSS_AT_RULE__UNDEF) {
+        return lxb_css_serialize_str_handler(style, str, mraw,
+                                        lxb_css_at_rule__undef_serialize_name);
+    }
+    else if (type == LXB_CSS_AT_RULE__CUSTOM) {
+        return lxb_css_serialize_str_handler(style, str, mraw,
+                                       lxb_css_at_rule__custom_serialize_name);
+    }
+
+    data = lxb_css_at_rule_by_id(type);
+    if (data == NULL) {
+        return LXB_STATUS_ERROR_UNEXPECTED_DATA;
+    }
+
+    if (str->data == NULL) {
+        lexbor_str_init(str, mraw, data->length);
+        if (str->data == NULL) {
+            return LXB_STATUS_ERROR_MEMORY_ALLOCATION;
+        }
+    }
+
+    (void) lexbor_str_append(str, mraw, data->name, data->length);
+
+    return LXB_STATUS_OK;
+}
+
+/* _undef. */
+
+void *
+lxb_css_at_rule__undef_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_at_rule__undef_t));
+}
+
+void *
+lxb_css_at_rule__undef_destroy(lxb_css_memory_t *memory,
+                               void *style, bool self_destroy)
+{
+    if (style == NULL) {
+        return NULL;
+    }
+
+    if (self_destroy) {
+        return lexbor_mraw_free(memory->mraw, style);
+    }
+
+    return style;
+}
+
+lxb_status_t
+lxb_css_at_rule__undef_serialize(const void *at, lexbor_serialize_cb_f cb,
+                                 void *ctx)
+{
+    lxb_status_t status;
+    const lxb_css_entry_at_rule_data_t *data;
+    const lxb_css_at_rule__undef_t *undef = at;
+
+    static const lxb_char_t wc_str[] = " ";
+    static const lxb_char_t lb_str[] = "{";
+    static const lxb_char_t rb_str[] = "}";
+    static const lxb_char_t sm_str[] = ";";
+
+    data = lxb_css_at_rule_by_id(undef->type);
+    if (data == NULL) {
+        return LXB_STATUS_ERROR_UNEXPECTED_DATA;
+    }
+
+    if (undef->prelude.data != NULL) {
+        lexbor_serialize_write(cb, wc_str, (sizeof(wc_str) - 1), ctx, status);
+        lexbor_serialize_write(cb, undef->prelude.data, undef->prelude.length,
+                               ctx, status);
+    }
+
+    if (undef->block != NULL) {
+        lexbor_serialize_write(cb, lb_str, (sizeof(lb_str) - 1), ctx, status);
+
+        status = lxb_css_rule_list_serialize(undef->block, cb, ctx);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+
+        lexbor_serialize_write(cb, rb_str, (sizeof(rb_str) - 1), ctx, status);
+    }
+    else {
+        lexbor_serialize_write(cb, sm_str, (sizeof(sm_str) - 1), ctx, status);
+    }
+
+    return LXB_STATUS_OK;
+}
+
+lxb_status_t
+lxb_css_at_rule__undef_serialize_name(const void *at, lexbor_serialize_cb_f cb,
+                                      void *ctx)
+{
+    const lxb_css_entry_at_rule_data_t *data;
+    const lxb_css_at_rule__undef_t *undef = at;
+
+    data = lxb_css_at_rule_by_id(undef->type);
+    if (data == NULL) {
+        return LXB_STATUS_ERROR_UNEXPECTED_DATA;
+    }
+
+    return cb(data->name, data->length, ctx);
+}
+
+/* _custom. */
+
+void *
+lxb_css_at_rule__custom_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_at_rule__custom_t));
+}
+
+void *
+lxb_css_at_rule__custom_destroy(lxb_css_memory_t *memory,
+                                void *style, bool self_destroy)
+{
+    if (style == NULL) {
+        return NULL;
+    }
+
+    if (self_destroy) {
+        return lexbor_mraw_free(memory->mraw, style);
+    }
+
+    return style;
+}
+
+lxb_status_t
+lxb_css_at_rule__custom_serialize(const void *at, lexbor_serialize_cb_f cb,
+                                  void *ctx)
+{
+    lxb_status_t status;
+    const lxb_css_at_rule__custom_t *custom = at;
+
+    static const lxb_char_t ws_str[] = " ";
+    static const lxb_char_t lb_str[] = "{";
+    static const lxb_char_t rb_str[] = "}";
+
+
+    if (custom->prelude.data != NULL) {
+        lexbor_serialize_write(cb, ws_str, (sizeof(ws_str) - 1), ctx, status);
+        lexbor_serialize_write(cb, custom->prelude.data, custom->prelude.length,
+                               ctx, status);
+    }
+
+    if (custom->block != NULL) {
+        lexbor_serialize_write(cb, lb_str, (sizeof(lb_str) - 1), ctx, status);
+
+        status = lxb_css_rule_list_serialize(custom->block, cb, ctx);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+
+        lexbor_serialize_write(cb, rb_str, (sizeof(rb_str) - 1), ctx, status);
+    }
+
+    return LXB_STATUS_OK;
+}
+
+lxb_status_t
+lxb_css_at_rule__custom_serialize_name(const void *at, lexbor_serialize_cb_f cb,
+                                       void *ctx)
+{
+    const lxb_css_at_rule__custom_t *custom = at;
+
+    return cb(custom->name.data, custom->name.length, ctx);
+}
+
+/* Media. */
+
+void *
+lxb_css_at_rule_media_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_at_rule_media_t));
+}
+
+void *
+lxb_css_at_rule_media_destroy(lxb_css_memory_t *memory,
+                              void *style, bool self_destroy)
+{
+    return lxb_css_at_rule__undef_destroy(memory, style, self_destroy);
+}
+
+lxb_status_t
+lxb_css_at_rule_media_serialize(const void *style, lexbor_serialize_cb_f cb,
+                                void *ctx)
+{
+    return LXB_STATUS_OK;
+}
+
+/* Namespace. */
+
+void *
+lxb_css_at_rule_namespace_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_at_rule_namespace_t));
+}
+
+void *
+lxb_css_at_rule_namespace_destroy(lxb_css_memory_t *memory,
+                                  void *style, bool self_destroy)
+{
+    return lxb_css_at_rule__undef_destroy(memory, style, self_destroy);
+}
+
+lxb_status_t
+lxb_css_at_rule_namespace_serialize(const void *style, lexbor_serialize_cb_f cb,
+                                    void *ctx)
+{
+    return LXB_STATUS_OK;
+}
+
+/* Font-face. */
+
+void *
+lxb_css_at_rule_font_face_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_at_rule_font_face_t));
+}
+
+void *
+lxb_css_at_rule_font_face_destroy(lxb_css_memory_t *memory,
+                                  void *style, bool self_destroy)
+{
+    return lxb_css_at_rule__undef_destroy(memory, style, self_destroy);
+}
+
+lxb_status_t
+lxb_css_at_rule_font_face_serialize(const void *font_face,
+                                    lexbor_serialize_cb_f cb, void *ctx)
+{
+    lxb_status_t status;
+    const lxb_css_at_rule_font_face_t *ff = font_face;
+
+    static const lxb_char_t lb_str[] = " {";
+    static const lxb_char_t rb_str[] = "}";
+
+    if (ff->block != NULL) {
+        lexbor_serialize_write(cb, lb_str, (sizeof(lb_str) - 1), ctx, status);
+
+        status = lxb_css_rule_list_serialize(ff->block, cb, ctx);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+
+        lexbor_serialize_write(cb, rb_str, (sizeof(rb_str) - 1), ctx, status);
+    }
+
+    return LXB_STATUS_OK;
+}
diff --git a/ext/dom/lexbor/lexbor/css/at_rule.h b/ext/dom/lexbor/lexbor/css/at_rule.h
index a11455c14cd..cacfa4c8cf2 100644
--- a/ext/dom/lexbor/lexbor/css/at_rule.h
+++ b/ext/dom/lexbor/lexbor/css/at_rule.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021-2022 Alexander Borisov
+ * Copyright (C) 2021-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -19,19 +19,19 @@ extern "C" {
 typedef struct {
     lxb_css_at_rule_type_t type;
     lexbor_str_t           prelude;
-    lexbor_str_t           block;
+    lxb_css_rule_list_t    *block;
 }
 lxb_css_at_rule__undef_t;

 typedef struct {
-    lexbor_str_t name;
-    lexbor_str_t prelude;
-    lexbor_str_t block;
+    lexbor_str_t        name;
+    lexbor_str_t        prelude;
+    lxb_css_rule_list_t *block;
 }
 lxb_css_at_rule__custom_t;

 typedef struct {
-    uintptr_t reserved;
+    lxb_css_rule_list_t *block;
 }
 lxb_css_at_rule_media_t;

@@ -40,17 +40,31 @@ typedef struct {
 }
 lxb_css_at_rule_namespace_t;

+typedef struct {
+    lxb_css_rule_list_t *block;
+}
+lxb_css_at_rule_font_face_t;

-LXB_API const lxb_css_entry_data_t *
+
+LXB_API const lxb_css_entry_at_rule_data_t *
 lxb_css_at_rule_by_name(const lxb_char_t *name, size_t length);

-LXB_API const lxb_css_entry_data_t *
+LXB_API const lxb_css_entry_at_rule_data_t *
 lxb_css_at_rule_by_id(uintptr_t id);

+LXB_API lxb_css_rule_at_t *
+lxb_css_at_rule_create(lxb_css_parser_t *parser,
+                       const lxb_char_t *name, size_t length,
+                       const lxb_css_entry_at_rule_data_t **out_entry);
+
 LXB_API void *
 lxb_css_at_rule_destroy(lxb_css_memory_t *memory, void *value,
                         lxb_css_at_rule_type_t type, bool self_destroy);

+LXB_API lxb_status_t
+lxb_css_at_rule_convert_to_undef(lxb_css_parser_t *parser,
+                                 lxb_css_rule_at_t *at);
+
 LXB_API lxb_status_t
 lxb_css_at_rule_serialize(const void *style, lxb_css_at_rule_type_t type,
                           lexbor_serialize_cb_f cb, void *ctx);
@@ -73,10 +87,6 @@ LXB_API void *
 lxb_css_at_rule__undef_destroy(lxb_css_memory_t *memory,
                                void *style, bool self_destroy);
 LXB_API lxb_status_t
-lxb_css_at_rule__undef_make(lxb_css_parser_t *parser,
-                            lxb_css_at_rule__undef_t *undef,
-                            const lxb_css_syntax_at_rule_offset_t *at_rule);
-LXB_API lxb_status_t
 lxb_css_at_rule__undef_serialize(const void *style, lexbor_serialize_cb_f cb,
                                  void *ctx);
 LXB_API lxb_status_t
@@ -92,10 +102,6 @@ LXB_API void *
 lxb_css_at_rule__custom_destroy(lxb_css_memory_t *memory,
                                 void *style, bool self_destroy);
 LXB_API lxb_status_t
-lxb_css_at_rule__custom_make(lxb_css_parser_t *parser,
-                             lxb_css_at_rule__custom_t *custom,
-                             const lxb_css_syntax_at_rule_offset_t *at_rule);
-LXB_API lxb_status_t
 lxb_css_at_rule__custom_serialize(const void *style, lexbor_serialize_cb_f cb,
                                   void *ctx);
 LXB_API lxb_status_t
@@ -126,6 +132,18 @@ LXB_API lxb_status_t
 lxb_css_at_rule_namespace_serialize(const void *style, lexbor_serialize_cb_f cb,
                                     void *ctx);

+/* Font-face. */
+
+LXB_API void *
+lxb_css_at_rule_font_face_create(lxb_css_memory_t *memory);
+
+LXB_API void *
+lxb_css_at_rule_font_face_destroy(lxb_css_memory_t *memory,
+                                  void *style, bool self_destroy);
+
+LXB_API lxb_status_t
+lxb_css_at_rule_font_face_serialize(const void *style, lexbor_serialize_cb_f cb,
+                                    void *ctx);

 #ifdef __cplusplus
 } /* extern "C" */
diff --git a/ext/dom/lexbor/lexbor/css/at_rule/const.h b/ext/dom/lexbor/lexbor/css/at_rule/const.h
index 961f933a236..29ba3dd9548 100644
--- a/ext/dom/lexbor/lexbor/css/at_rule/const.h
+++ b/ext/dom/lexbor/lexbor/css/at_rule/const.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2023 Alexander Borisov
+ * Copyright (C) 2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -21,9 +21,10 @@
 enum {
     LXB_CSS_AT_RULE__UNDEF      = 0x0000,
     LXB_CSS_AT_RULE__CUSTOM     = 0x0001,
-    LXB_CSS_AT_RULE_MEDIA       = 0x0002,
-    LXB_CSS_AT_RULE_NAMESPACE   = 0x0003,
-    LXB_CSS_AT_RULE__LAST_ENTRY = 0x0004
+    LXB_CSS_AT_RULE_FONT_FACE   = 0x0002,
+    LXB_CSS_AT_RULE_MEDIA       = 0x0003,
+    LXB_CSS_AT_RULE_NAMESPACE   = 0x0004,
+    LXB_CSS_AT_RULE__LAST_ENTRY = 0x0005
 };
 typedef uintptr_t lxb_css_at_rule_type_t;

diff --git a/ext/dom/lexbor/lexbor/css/at_rule/res.h b/ext/dom/lexbor/lexbor/css/at_rule/res.h
index 026a88ae0dd..6604fb923f4 100644
--- a/ext/dom/lexbor/lexbor/css/at_rule/res.h
+++ b/ext/dom/lexbor/lexbor/css/at_rule/res.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2023 Alexander Borisov
+ * Copyright (C) 2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -18,16 +18,19 @@
 #include "lexbor/css/at_rule/const.h"


-static const lxb_css_entry_data_t lxb_css_at_rule_data[LXB_CSS_AT_RULE__LAST_ENTRY] =
+static const lxb_css_entry_at_rule_data_t lxb_css_at_rule_data[LXB_CSS_AT_RULE__LAST_ENTRY] =
 {
-    {(lxb_char_t *) "#undef", 6, LXB_CSS_AT_RULE__UNDEF, lxb_css_at_rule_state__undef,
+    {(lxb_char_t *) "#undef", 6, LXB_CSS_AT_RULE__UNDEF, &lxb_css_at_rule__undef_cb,
      lxb_css_at_rule__undef_create, lxb_css_at_rule__undef_destroy, lxb_css_at_rule__undef_serialize, (void *) (uintptr_t) LXB_CSS_AT_RULE__UNDEF},
-    {(lxb_char_t *) "#сustom", 7, LXB_CSS_AT_RULE__CUSTOM, lxb_css_at_rule_state__custom,
+    {(lxb_char_t *) "#сustom", 7, LXB_CSS_AT_RULE__CUSTOM, &lxb_css_at_rule__custom_cb,
      lxb_css_at_rule__custom_create, lxb_css_at_rule__custom_destroy, lxb_css_at_rule__custom_serialize, (void *) (uintptr_t) LXB_CSS_AT_RULE__CUSTOM},
-    {(lxb_char_t *) "media", 5, LXB_CSS_AT_RULE_MEDIA, lxb_css_at_rule_state_media,
+    {(lxb_char_t *) "font-face", 9, LXB_CSS_AT_RULE_FONT_FACE, &lxb_css_at_rule_font_face_cb,
+     lxb_css_at_rule_font_face_create, lxb_css_at_rule_font_face_destroy, lxb_css_at_rule_font_face_serialize,
+     NULL},
+    {(lxb_char_t *) "media", 5, LXB_CSS_AT_RULE_MEDIA, &lxb_css_at_rule_media_cb,
      lxb_css_at_rule_media_create, lxb_css_at_rule_media_destroy, lxb_css_at_rule_media_serialize,
      NULL},
-    {(lxb_char_t *) "namespace", 9, LXB_CSS_AT_RULE_NAMESPACE, lxb_css_at_rule_state_namespace,
+    {(lxb_char_t *) "namespace", 9, LXB_CSS_AT_RULE_NAMESPACE, &lxb_css_at_rule_namespace_cb,
      lxb_css_at_rule_namespace_create, lxb_css_at_rule_namespace_destroy, lxb_css_at_rule_namespace_serialize,
      NULL}
 };
@@ -38,7 +41,7 @@ static const lexbor_shs_entry_t lxb_css_at_rule_shs[6] =
     {NULL, NULL, 0, 0},
     {NULL, NULL, 0, 0},
     {"media", (void *) &lxb_css_at_rule_data[LXB_CSS_AT_RULE_MEDIA], 5, 0},
-    {NULL, NULL, 0, 0},
+    {"font-face", (void *) &lxb_css_at_rule_data[LXB_CSS_AT_RULE_FONT_FACE], 9, 0},
     {"namespace", (void *) &lxb_css_at_rule_data[LXB_CSS_AT_RULE_NAMESPACE], 9, 0}
 };

diff --git a/ext/dom/lexbor/lexbor/css/at_rule/state.c b/ext/dom/lexbor/lexbor/css/at_rule/state.c
new file mode 100644
index 00000000000..4df2f6085ad
--- /dev/null
+++ b/ext/dom/lexbor/lexbor/css/at_rule/state.c
@@ -0,0 +1,374 @@
+/*
+ * Copyright (C) 2021-2026 Alexander Borisov
+ *
+ * Author: Alexander Borisov <borisov@lexbor.com>
+ */
+
+#include "lexbor/css/css.h"
+#include "lexbor/css/at_rule.h"
+#include "lexbor/css/parser.h"
+#include "lexbor/css/rule.h"
+#include "lexbor/css/blank.h"
+#include "lexbor/css/at_rule/state.h"
+
+
+/* Undef */
+
+bool
+lxb_css_at_rule__undef_prelude(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_rule_at_t *at = ctx;
+
+    at->prelude_begin = token->offset;
+
+    /* Skip all prelude. */
+
+    while (token != NULL && token->type != LXB_CSS_SYNTAX_TOKEN__END) {
+        lxb_css_syntax_parser_consume(parser);
+        token = lxb_css_syntax_parser_token(parser);
+    }
+
+    return lxb_css_parser_success(parser);
+}
+
+lxb_status_t
+lxb_css_at_rule__undef_prelude_end(lxb_css_parser_t *parser,
+                                   const lxb_css_syntax_token_t *token,
+                                   void *ctx, bool failed)
+{
+    lxb_status_t status;
+    lxb_css_rule_at_t *at = ctx;
+
+    at->prelude_end = token->offset;
+
+    status = lxb_css_make_data(parser, &at->u.undef->prelude,
+                               at->prelude_begin, at->prelude_end);
+    if (status != LXB_STATUS_OK) {
+        return lxb_css_parser_memory_fail_status(parser);
+    }
+
+    return LXB_STATUS_OK;
+}
+
+const lxb_css_syntax_cb_block_t *
+lxb_css_at_rule__undef_block(lxb_css_parser_t *parser,
+                             const lxb_css_syntax_token_t *token,
+                             void *ctx, void **out_rule)
+{
+    return lxb_css_state_at_rule_block_begin(parser, token, ctx, out_rule);
+}
+
+bool
+lxb_css_at_rule__undef_prelude_failed(lxb_css_parser_t *parser,
+                                      const lxb_css_syntax_token_t *token,
+                                      void *ctx)
+{
+    /* For _UNDEF and _CUSTOM, access here is not possible. */
+
+    while (token != NULL && token->type != LXB_CSS_SYNTAX_TOKEN__END) {
+        lxb_css_syntax_parser_consume(parser);
+        token = lxb_css_syntax_parser_token(parser);
+    }
+
+    return lxb_css_parser_success(parser);
+}
+
+lxb_status_t
+lxb_css_at_rule__undef_end(lxb_css_parser_t *parser,
+                           const lxb_css_syntax_token_t *token,
+                           void *ctx, bool failed)
+{
+    lxb_css_rule_at_t *at = ctx;
+    lxb_css_rule_list_t *block = lxb_css_syntax_returned(parser);
+
+    /*
+     * Here we do not check for failed because it cannot happen; we do not call
+     * failed anywhere in _UNDEF and _CUSTOM, we simply skip the tokens.
+     */
+
+    at->u.undef->block = block;
+
+    lxb_css_syntax_set_return(parser, at);
+
+    return LXB_STATUS_OK;
+}
+
+/* Custom */
+
+bool
+lxb_css_at_rule__custom_prelude(lxb_css_parser_t *parser,
+                                const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_at_rule__undef_prelude(parser, token, ctx);
+}
+
+lxb_status_t
+lxb_css_at_rule__custom_prelude_end(lxb_css_parser_t *parser,
+                                    const lxb_css_syntax_token_t *token,
+                                    void *ctx, bool failed)
+{
+    lxb_status_t status;
+    lxb_css_rule_at_t *at = ctx;
+
+    at->prelude_end = token->offset;
+
+    status = lxb_css_make_data(parser, &at->u.custom->prelude,
+                               at->prelude_begin, at->prelude_end);
+    if (status != LXB_STATUS_OK) {
+        return lxb_css_parser_memory_fail_status(parser);
+    }
+
+    return LXB_STATUS_OK;
+}
+
+const lxb_css_syntax_cb_block_t *
+lxb_css_at_rule__custom_block(lxb_css_parser_t *parser,
+                             const lxb_css_syntax_token_t *token,
+                             void *ctx, void **out_rule)
+{
+    return lxb_css_state_at_rule_block_begin(parser, token, ctx, out_rule);
+}
+
+bool
+lxb_css_at_rule__custom_prelude_failed(lxb_css_parser_t *parser,
+                                       const lxb_css_syntax_token_t *token,
+                                       void *ctx)
+{
+    return lxb_css_at_rule__undef_prelude_failed(parser, token, ctx);
+}
+
+lxb_status_t
+lxb_css_at_rule__custom_end(lxb_css_parser_t *parser,
+                            const lxb_css_syntax_token_t *token,
+                            void *ctx, bool failed)
+{
+    lxb_css_rule_at_t *at = ctx;
+    lxb_css_rule_list_t *block = lxb_css_syntax_returned(parser);
+
+    /*
+     * Here we do not check for failed because it cannot happen; we do not call
+     * failed anywhere in _UNDEF and _CUSTOM, we simply skip the tokens.
+     */
+
+    at->u.custom->block = block;
+
+    lxb_css_syntax_set_return(parser, at);
+
+    return LXB_STATUS_OK;
+}
+
+/* Namespace */
+
+bool
+lxb_css_at_rule_namespace_prelude(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token,
+                                  void *ctx)
+{
+    lxb_css_rule_at_t *at = ctx;
+
+    at->prelude_begin = token->offset;
+
+    while (token != NULL && token->type != LXB_CSS_SYNTAX_TOKEN__END) {
+        lxb_css_syntax_parser_consume(parser);
+        token = lxb_css_syntax_parser_token(parser);
+    }
+
+    return lxb_css_parser_success(parser);
+}
+
+lxb_status_t
+lxb_css_at_rule_namespace_prelude_end(lxb_css_parser_t *parser,
+                                      const lxb_css_syntax_token_t *token,
+                                      void *ctx, bool failed)
+{
+    lxb_css_rule_at_t *at = ctx;
+
+    at->prelude_end = token->offset;
+
+    return LXB_STATUS_OK;
+}
+
+const lxb_css_syntax_cb_block_t *
+lxb_css_at_rule_namespace_block(lxb_css_parser_t *parser,
+                                const lxb_css_syntax_token_t *token,
+                                void *ctx, void **out_rule)
+{
+    lxb_css_parser_failed_set(parser, true);
+
+    return lxb_css_state_at_rule_block_begin(parser, token, ctx, out_rule);
+}
+
+bool
+lxb_css_at_rule_namespace_prelude_failed(lxb_css_parser_t *parser,
+                                         const lxb_css_syntax_token_t *token,
+                                         void *ctx)
+{
+    return lxb_css_at_rule__undef_prelude_failed(parser, token, ctx);
+}
+
+lxb_status_t
+lxb_css_at_rule_namespace_end(lxb_css_parser_t *parser,
+                              const lxb_css_syntax_token_t *token,
+                              void *ctx, bool failed)
+{
+    lxb_status_t status;
+    lxb_css_rule_at_t *at = ctx;
+
+    if (failed) {
+        status = lxb_css_at_rule_convert_to_undef(parser, at);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+
+        at->u.undef->block = lxb_css_syntax_returned(parser);
+    }
+
+    lxb_css_syntax_set_return(parser, at);
+
+    return LXB_STATUS_OK;
+}
+
+/* Media */
+
+bool
+lxb_css_at_rule_media_prelude(lxb_css_parser_t *parser,
+                              const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_rule_at_t *at = ctx;
+
+    at->prelude_begin = token->offset;
+
+    while (token != NULL && token->type != LXB_CSS_SYNTAX_TOKEN__END) {
+        lxb_css_syntax_parser_consume(parser);
+        token = lxb_css_syntax_parser_token(parser);
+    }
+
+    return lxb_css_parser_success(parser);
+}
+
+lxb_status_t
+lxb_css_at_rule_media_prelude_end(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token,
+                                  void *ctx, bool failed)
+{
+    lxb_css_rule_at_t *at = ctx;
+
+    at->prelude_end = token->offset;
+
+    return LXB_STATUS_OK;
+}
+
+const lxb_css_syntax_cb_block_t *
+lxb_css_at_rule_media_block(lxb_css_parser_t *parser,
+                            const lxb_css_syntax_token_t *token,
+                            void *ctx, void **out_rule)
+{
+    return lxb_css_state_at_rule_block_begin(parser, token, ctx, out_rule);
+}
+
+bool
+lxb_css_at_rule_media_prelude_failed(lxb_css_parser_t *parser,
+                                     const lxb_css_syntax_token_t *token,
+                                     void *ctx)
+{
+    return lxb_css_at_rule__undef_prelude_failed(parser, token, ctx);
+}
+
+lxb_status_t
+lxb_css_at_rule_media_end(lxb_css_parser_t *parser,
+                          const lxb_css_syntax_token_t *token,
+                          void *ctx, bool failed)
+{
+    lxb_status_t status;
+    lxb_css_rule_at_t *at = ctx;
+    lxb_css_rule_list_t *list = lxb_css_syntax_returned(parser);
+
+    if (list != NULL && !failed) {
+        at->u.media->block = list;
+    }
+    else {
+        status = lxb_css_at_rule_convert_to_undef(parser, at);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+
+        at->u.undef->block = list;
+    }
+
+    lxb_css_syntax_set_return(parser, at);
+
+    return LXB_STATUS_OK;
+}
+
+/* Font-face */
+
+bool
+lxb_css_at_rule_font_face_prelude(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token,
+                                  void *ctx)
+{
+    lxb_css_rule_at_t *at = ctx;
+
+    at->prelude_begin = token->offset;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN__END) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    return lxb_css_parser_success(parser);
+}
+
+lxb_status_t
+lxb_css_at_rule_font_face_prelude_end(lxb_css_parser_t *parser,
+                                      const lxb_css_syntax_token_t *token,
+                                      void *ctx, bool failed)
+{
+    lxb_css_rule_at_t *at = ctx;
+
+    at->prelude_end = token->offset;
+
+    return LXB_STATUS_OK;
+}
+
+const lxb_css_syntax_cb_block_t *
+lxb_css_at_rule_font_face_block(lxb_css_parser_t *parser,
+                                const lxb_css_syntax_token_t *token,
+                                void *ctx, void **out_rule)
+{
+    return lxb_css_state_at_rule_block_begin(parser, token, ctx, out_rule);
+}
+
+bool
+lxb_css_at_rule_font_face_prelude_failed(lxb_css_parser_t *parser,
+                                         const lxb_css_syntax_token_t *token,
+                                         void *ctx)
+{
+    return lxb_css_at_rule__undef_prelude_failed(parser, token, ctx);
+}
+
+lxb_status_t
+lxb_css_at_rule_font_face_end(lxb_css_parser_t *parser,
+                              const lxb_css_syntax_token_t *token,
+                              void *ctx, bool failed)
+{
+    lxb_status_t status;
+    lxb_css_rule_at_t *at = ctx;
+    lxb_css_rule_list_t *block = lxb_css_syntax_returned(parser);
+
+    if (!failed) {
+        at->u.font_face->block = block;
+    }
+    else {
+        status = lxb_css_at_rule_convert_to_undef(parser, at);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+
+        at->u.undef->block = block;
+    }
+
+    lxb_css_syntax_set_return(parser, at);
+
+    return LXB_STATUS_OK;
+}
diff --git a/ext/dom/lexbor/lexbor/css/at_rule/state.h b/ext/dom/lexbor/lexbor/css/at_rule/state.h
index 65e17e40d0f..337a23c8671 100644
--- a/ext/dom/lexbor/lexbor/css/at_rule/state.h
+++ b/ext/dom/lexbor/lexbor/css/at_rule/state.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021-2022 Alexander Borisov
+ * Copyright (C) 2021-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -15,18 +15,110 @@ extern "C" {


 LXB_API bool
-lxb_css_at_rule_state__undef(lxb_css_parser_t *parser,
-                             const lxb_css_syntax_token_t *token, void *ctx);
+lxb_css_at_rule__undef_prelude(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token, void *ctx);
+LXB_API lxb_status_t
+lxb_css_at_rule__undef_prelude_end(lxb_css_parser_t *parser,
+                                   const lxb_css_syntax_token_t *token,
+                                   void *ctx, bool failed);

+LXB_API const lxb_css_syntax_cb_block_t *
+lxb_css_at_rule__undef_block(lxb_css_parser_t *parser,
+                             const lxb_css_syntax_token_t *token,
+                             void *ctx, void **out_rule);
 LXB_API bool
-lxb_css_at_rule_state__custom(lxb_css_parser_t *parser,
+lxb_css_at_rule__undef_prelude_failed(lxb_css_parser_t *parser,
+                                      const lxb_css_syntax_token_t *token,
+                                      void *ctx);
+LXB_API lxb_status_t
+lxb_css_at_rule__undef_end(lxb_css_parser_t *parser,
+                           const lxb_css_syntax_token_t *token,
+                           void *ctx, bool failed);
+
+LXB_API bool
+lxb_css_at_rule__custom_prelude(lxb_css_parser_t *parser,
+                                const lxb_css_syntax_token_t *token, void *ctx);
+LXB_API lxb_status_t
+lxb_css_at_rule__custom_prelude_end(lxb_css_parser_t *parser,
+                                    const lxb_css_syntax_token_t *token,
+                                    void *ctx, bool failed);
+
+LXB_API const lxb_css_syntax_cb_block_t *
+lxb_css_at_rule__custom_block(lxb_css_parser_t *parser,
+                              const lxb_css_syntax_token_t *token,
+                              void *ctx, void **out_rule);
+LXB_API bool
+lxb_css_at_rule__custom_prelude_failed(lxb_css_parser_t *parser,
+                                       const lxb_css_syntax_token_t *token,
+                                       void *ctx);
+LXB_API lxb_status_t
+lxb_css_at_rule__custom_end(lxb_css_parser_t *parser,
+                            const lxb_css_syntax_token_t *token,
+                            void *ctx, bool failed);
+
+LXB_API bool
+lxb_css_at_rule_namespace_prelude(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token, void *ctx);
+LXB_API lxb_status_t
+lxb_css_at_rule_namespace_prelude_end(lxb_css_parser_t *parser,
+                                      const lxb_css_syntax_token_t *token,
+                                      void *ctx, bool failed);
+
+LXB_API const lxb_css_syntax_cb_block_t *
+lxb_css_at_rule_namespace_block(lxb_css_parser_t *parser,
+                                const lxb_css_syntax_token_t *token,
+                                void *ctx, void **out_rule);
+LXB_API bool
+lxb_css_at_rule_namespace_prelude_failed(lxb_css_parser_t *parser,
+                                         const lxb_css_syntax_token_t *token,
+                                         void *ctx);
+LXB_API lxb_status_t
+lxb_css_at_rule_namespace_end(lxb_css_parser_t *parser,
+                              const lxb_css_syntax_token_t *token,
+                              void *ctx, bool failed);
+
+LXB_API bool
+lxb_css_at_rule_media_prelude(lxb_css_parser_t *parser,
                               const lxb_css_syntax_token_t *token, void *ctx);
+LXB_API lxb_status_t
+lxb_css_at_rule_media_prelude_end(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token,
+                                  void *ctx, bool failed);
+
+LXB_API const lxb_css_syntax_cb_block_t *
+lxb_css_at_rule_media_block(lxb_css_parser_t *parser,
+                            const lxb_css_syntax_token_t *token,
+                            void *ctx, void **out_rule);
 LXB_API bool
-lxb_css_at_rule_state_media(lxb_css_parser_t *parser,
-                            const lxb_css_syntax_token_t *token, void *ctx);
+lxb_css_at_rule_media_prelude_failed(lxb_css_parser_t *parser,
+                                     const lxb_css_syntax_token_t *token,
+                                     void *ctx);
+LXB_API lxb_status_t
+lxb_css_at_rule_media_end(lxb_css_parser_t *parser,
+                          const lxb_css_syntax_token_t *token,
+                          void *ctx, bool failed);
+
 LXB_API bool
-lxb_css_at_rule_state_namespace(lxb_css_parser_t *parser,
-                                const lxb_css_syntax_token_t *token, void *ctx);
+lxb_css_at_rule_font_face_prelude(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token,
+                                  void *ctx);
+LXB_API lxb_status_t
+lxb_css_at_rule_font_face_prelude_end(lxb_css_parser_t *parser,
+                                      const lxb_css_syntax_token_t *token,
+                                      void *ctx, bool failed);
+
+LXB_API const lxb_css_syntax_cb_block_t *
+lxb_css_at_rule_font_face_block(lxb_css_parser_t *parser,
+                                const lxb_css_syntax_token_t *token,
+                                void *ctx, void **out_rule);
+LXB_API bool
+lxb_css_at_rule_font_face_prelude_failed(lxb_css_parser_t *parser,
+                                         const lxb_css_syntax_token_t *token,
+                                         void *ctx);
+LXB_API lxb_status_t
+lxb_css_at_rule_font_face_end(lxb_css_parser_t *parser,
+                              const lxb_css_syntax_token_t *token,
+                              void *ctx, bool failed);


 #ifdef __cplusplus
diff --git a/ext/dom/lexbor/lexbor/css/at_rule/types.h b/ext/dom/lexbor/lexbor/css/at_rule/types.h
new file mode 100644
index 00000000000..1079bb63223
--- /dev/null
+++ b/ext/dom/lexbor/lexbor/css/at_rule/types.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2026 Alexander Borisov
+ *
+ * Author: Alexander Borisov <borisov@lexbor.com>
+ */
+
+/*
+ * Caution!
+ * This file generated by the script "utils/lexbor/css/names.py"!
+ * Do not change this file!
+ */
+
+
+#ifndef LXB_CSS_AT_RULE_TYPES_H
+#define LXB_CSS_AT_RULE_TYPES_H
+
+
+static const lxb_css_syntax_cb_at_rule_t lxb_css_at_rule__undef_cb = {
+    .prelude = lxb_css_at_rule__undef_prelude,
+    .prelude_end = lxb_css_at_rule__undef_prelude_end,
+    .block = lxb_css_at_rule__undef_block,
+    .cb.failed = lxb_css_at_rule__undef_prelude_failed,
+    .cb.end = lxb_css_at_rule__undef_end
+};
+
+static const lxb_css_syntax_cb_at_rule_t lxb_css_at_rule__custom_cb = {
+    .prelude = lxb_css_at_rule__custom_prelude,
+    .prelude_end = lxb_css_at_rule__custom_prelude_end,
+    .block = lxb_css_at_rule__custom_block,
+    .cb.failed = lxb_css_at_rule__custom_prelude_failed,
+    .cb.end = lxb_css_at_rule__custom_end
+};
+
+static const lxb_css_syntax_cb_at_rule_t lxb_css_at_rule_font_face_cb = {
+    .prelude = lxb_css_at_rule_font_face_prelude,
+    .prelude_end = lxb_css_at_rule_font_face_prelude_end,
+    .block = lxb_css_at_rule_font_face_block,
+    .cb.failed = lxb_css_at_rule_font_face_prelude_failed,
+    .cb.end = lxb_css_at_rule_font_face_end
+};
+
+static const lxb_css_syntax_cb_at_rule_t lxb_css_at_rule_media_cb = {
+    .prelude = lxb_css_at_rule_media_prelude,
+    .prelude_end = lxb_css_at_rule_media_prelude_end,
+    .block = lxb_css_at_rule_media_block,
+    .cb.failed = lxb_css_at_rule_media_prelude_failed,
+    .cb.end = lxb_css_at_rule_media_end
+};
+
+static const lxb_css_syntax_cb_at_rule_t lxb_css_at_rule_namespace_cb = {
+    .prelude = lxb_css_at_rule_namespace_prelude,
+    .prelude_end = lxb_css_at_rule_namespace_prelude_end,
+    .block = lxb_css_at_rule_namespace_block,
+    .cb.failed = lxb_css_at_rule_namespace_prelude_failed,
+    .cb.end = lxb_css_at_rule_namespace_end
+};
+
+
+
+#endif /* LXB_CSS_AT_RULE_TYPES_H */
diff --git a/ext/dom/lexbor/lexbor/css/base.h b/ext/dom/lexbor/lexbor/css/base.h
index 3d3cdc6a7f2..26712ce7048 100644
--- a/ext/dom/lexbor/lexbor/css/base.h
+++ b/ext/dom/lexbor/lexbor/css/base.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019-2025 Alexander Borisov
+ * Copyright (C) 2019-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -18,7 +18,7 @@ extern "C" {


 #define LXB_CSS_VERSION_MAJOR 1
-#define LXB_CSS_VERSION_MINOR 3
+#define LXB_CSS_VERSION_MINOR 4
 #define LXB_CSS_VERSION_PATCH 0

 #define LXB_CSS_VERSION_STRING                                                 \
@@ -45,6 +45,8 @@ typedef struct lxb_css_parser_error lxb_css_parser_error_t;
 typedef struct lxb_css_syntax_tokenizer lxb_css_syntax_tokenizer_t;
 typedef struct lxb_css_syntax_token lxb_css_syntax_token_t;

+/* Callbacks. */
+
 typedef bool
 (*lxb_css_parser_state_f)(lxb_css_parser_t *parser,
                           const lxb_css_syntax_token_t *token, void *ctx);
@@ -82,6 +84,21 @@ typedef struct {
 }
 lxb_css_entry_data_t;

+typedef struct {
+    lxb_char_t                        *name;
+    size_t                            length;
+    uintptr_t                         unique;
+
+    /* const lxb_css_syntax_cb_at_rule_t */
+    const void                        *cbs;
+
+    lxb_css_style_create_f            create;
+    lxb_css_style_destroy_f           destroy;
+    lxb_css_style_serialize_f         serialize;
+    void                              *initial;
+}
+lxb_css_entry_at_rule_data_t;
+
 typedef struct {
     lxb_char_t *name;
     size_t     length;
diff --git a/ext/dom/lexbor/lexbor/css/blank.c b/ext/dom/lexbor/lexbor/css/blank.c
new file mode 100644
index 00000000000..80e60f76e19
--- /dev/null
+++ b/ext/dom/lexbor/lexbor/css/blank.c
@@ -0,0 +1,389 @@
+/*
+ * Copyright (C) 2026 Alexander Borisov
+ *
+ * Author: Alexander Borisov <borisov@lexbor.com>
+ */
+
+#include "lexbor/css/blank.h"
+#include "lexbor/css/state.h"
+#include "lexbor/css/css.h"
+#include "lexbor/css/at_rule/state.h"
+
+
+static bool
+lxb_css_blank_list_rules_next(lxb_css_parser_t *parser,
+                              const lxb_css_syntax_token_t *token, void *ctx);
+
+static lxb_status_t
+lxb_css_blank_list_rules_end(lxb_css_parser_t *parser,
+                             const lxb_css_syntax_token_t *token,
+                             void *ctx, bool failed);
+
+static const lxb_css_syntax_cb_at_rule_t *
+lxb_css_blank_at_rule_begin(lxb_css_parser_t *parser,
+                            const lxb_css_syntax_token_t *token, void *ctx,
+                            void **out_rule);
+
+static bool
+lxb_css_blank_at_rule_prelude(lxb_css_parser_t *parser,
+                              const lxb_css_syntax_token_t *token,
+                              void *ctx);
+
+static lxb_status_t
+lxb_css_blank_at_rule_prelude_end(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token,
+                                  void *ctx, bool failed);
+
+static const lxb_css_syntax_cb_block_t *
+lxb_css_blank_at_rule_block_begin(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token,
+                                  void *ctx, void **out_rule);
+static bool
+lxb_css_blank_at_rule_prelude_failed(lxb_css_parser_t *parser,
+                                     const lxb_css_syntax_token_t *token,
+                                     void *ctx);
+static lxb_status_t
+lxb_css_blank_at_rule_end(lxb_css_parser_t *parser,
+                          const lxb_css_syntax_token_t *token,
+                          void *ctx, bool failed);
+
+static const lxb_css_syntax_cb_qualified_rule_t *
+lxb_css_blank_qualified_rule_begin(lxb_css_parser_t *parser,
+                                   const lxb_css_syntax_token_t *token,
+                                   void *ctx, void **out_rule);
+
+static bool
+lxb_css_blank_qualified_rule_prelude(lxb_css_parser_t *parser,
+                                     const lxb_css_syntax_token_t *token,
+                                     void *ctx);
+
+static lxb_status_t
+lxb_css_blank_qualified_rule_prelude_end(lxb_css_parser_t *parser,
+                                         const lxb_css_syntax_token_t *token,
+                                         void *ctx, bool failed);
+
+static const lxb_css_syntax_cb_block_t *
+lxb_css_blank_qualified_rule_block_begin(lxb_css_parser_t *parser,
+                                         const lxb_css_syntax_token_t *token,
+                                         void *ctx, void **out_rule);
+
+static bool
+lxb_css_blank_qualified_rule_prelude_failed(lxb_css_parser_t *parser,
+                                            const lxb_css_syntax_token_t *token,
+                                            void *ctx);
+static lxb_status_t
+lxb_css_blank_qualified_rule_end(lxb_css_parser_t *parser,
+                                 const lxb_css_syntax_token_t *token,
+                                 void *ctx, bool failed);
+static bool
+lxb_css_blank_block_next(lxb_css_parser_t *parser,
+                         const lxb_css_syntax_token_t *token, void *ctx);
+
+static lxb_status_t
+lxb_css_blank_block_end(lxb_css_parser_t *parser,
+                        const lxb_css_syntax_token_t *token,
+                        void *ctx, bool failed);
+
+static const lxb_css_syntax_cb_declarations_t *
+lxb_css_blank_declarations_begin(lxb_css_parser_t *parser,
+                                 const lxb_css_syntax_token_t *token,
+                                 void *ctx, void **out_rule);
+
+static lxb_css_parser_state_f
+lxb_css_blank_declaration_name(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token,
+                               void *ctx, void **out_rule);
+static bool
+lxb_css_blank_declaration_value(lxb_css_parser_t *parser,
+                                const lxb_css_syntax_token_t *token, void *ctx);
+
+static lxb_status_t
+lxb_css_blank_declaration_end(lxb_css_parser_t *parser,
+                              void *declarations, void *ctx,
+                              const lxb_css_syntax_token_t *token,
+                              lxb_css_syntax_declaration_offset_t *offset,
+                              bool important, bool failed);
+
+static lxb_status_t
+lxb_css_blank_declarations_end(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token,
+                               void *ctx, bool failed);
+
+static bool
+lxb_css_blank_declarations_bad(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token, void *ctx);
+
+
+static const lxb_css_syntax_cb_list_rules_t lxb_css_blank_list_rules = {
+    .at_rule = lxb_css_blank_at_rule_begin,
+    .qualified_rule = lxb_css_blank_qualified_rule_begin,
+    .next = lxb_css_blank_list_rules_next,
+    .cb.failed = lxb_css_state_failed,
+    .cb.end = lxb_css_blank_list_rules_end
+};
+
+static const lxb_css_syntax_cb_at_rule_t lxb_css_blank_at_rule = {
+    .prelude = lxb_css_blank_at_rule_prelude,
+    .prelude_end = lxb_css_blank_at_rule_prelude_end,
+    .block = lxb_css_blank_at_rule_block_begin,
+    .cb.failed = lxb_css_blank_at_rule_prelude_failed,
+    .cb.end = lxb_css_blank_at_rule_end
+};
+
+static const lxb_css_syntax_cb_qualified_rule_t lxb_css_blank_qualified_rule = {
+    .prelude = lxb_css_blank_qualified_rule_prelude,
+    .prelude_end = lxb_css_blank_qualified_rule_prelude_end,
+    .block = lxb_css_blank_qualified_rule_block_begin,
+    .cb.failed = lxb_css_blank_qualified_rule_prelude_failed,
+    .cb.end = lxb_css_blank_qualified_rule_end
+};
+
+static const lxb_css_syntax_cb_block_t lxb_css_blank_block = {
+    .at_rule = lxb_css_blank_at_rule_begin,
+    .declarations = lxb_css_blank_declarations_begin,
+    .qualified_rule = lxb_css_blank_qualified_rule_begin,
+    .next = lxb_css_blank_block_next,
+    .cb.failed = lxb_css_state_failed,
+    .cb.end = lxb_css_blank_block_end,
+};
+
+static const lxb_css_syntax_cb_declarations_t lxb_css_blank_declaration = {
+    .name = lxb_css_blank_declaration_name,
+    .end = lxb_css_blank_declaration_end,
+    .cb.failed = lxb_css_blank_declarations_bad,
+    .cb.end = lxb_css_blank_declarations_end
+};
+
+
+const lxb_css_syntax_cb_list_rules_t *
+lxb_css_blank_cb_list_rules(void)
+{
+    return &lxb_css_blank_list_rules;
+}
+
+const lxb_css_syntax_cb_at_rule_t *
+lxb_css_blank_cb_at_rule(void)
+{
+    return &lxb_css_blank_at_rule;
+}
+
+const lxb_css_syntax_cb_qualified_rule_t *
+lxb_css_blank_cb_qualified_rule(void)
+{
+    return &lxb_css_blank_qualified_rule;
+}
+
+const lxb_css_syntax_cb_block_t *
+lxb_css_blank_cb_block(void)
+{
+    return &lxb_css_blank_block;
+}
+
+const lxb_css_syntax_cb_declarations_t *
+lxb_css_blank_cb_declarations(void)
+{
+    return &lxb_css_blank_declaration;
+}
+
+static bool
+lxb_css_blank_list_rules_next(lxb_css_parser_t *parser,
+                              const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_parser_success(parser);
+}
+
+static lxb_status_t
+lxb_css_blank_list_rules_end(lxb_css_parser_t *parser,
+                             const lxb_css_syntax_token_t *token,
+                             void *ctx, bool failed)
+{
+    return LXB_STATUS_OK;
+}
+
+static const lxb_css_syntax_cb_at_rule_t *
+lxb_css_blank_at_rule_begin(lxb_css_parser_t *parser,
+                            const lxb_css_syntax_token_t *token, void *ctx,
+                            void **out_rule)
+{
+    return &lxb_css_blank_at_rule;
+}
+
+static bool
+lxb_css_blank_at_rule_prelude(lxb_css_parser_t *parser,
+                              const lxb_css_syntax_token_t *token, void *ctx)
+{
+    while (token != NULL && token->type != LXB_CSS_SYNTAX_TOKEN__END) {
+        lxb_css_syntax_parser_consume(parser);
+        token = lxb_css_syntax_parser_token(parser);
+    }
+
+    return lxb_css_parser_success(parser);
+}
+
+static lxb_status_t
+lxb_css_blank_at_rule_prelude_end(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token,
+                                  void *ctx, bool failed)
+{
+    return LXB_STATUS_OK;
+}
+
+static const lxb_css_syntax_cb_block_t *
+lxb_css_blank_at_rule_block_begin(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token,
+                                  void *ctx, void **out_rule)
+{
+    return &lxb_css_blank_block;
+}
+
+static bool
+lxb_css_blank_at_rule_prelude_failed(lxb_css_parser_t *parser,
+                                     const lxb_css_syntax_token_t *token,
+                                     void *ctx)
+{
+    while (token != NULL && token->type != LXB_CSS_SYNTAX_TOKEN__END) {
+        lxb_css_syntax_parser_consume(parser);
+        token = lxb_css_syntax_parser_token(parser);
+    }
+
+    return lxb_css_parser_success(parser);
+}
+
+static lxb_status_t
+lxb_css_blank_at_rule_end(lxb_css_parser_t *parser,
+                          const lxb_css_syntax_token_t *token,
+                          void *ctx, bool failed)
+{
+    return LXB_STATUS_OK;
+}
+
+static const lxb_css_syntax_cb_qualified_rule_t *
+lxb_css_blank_qualified_rule_begin(lxb_css_parser_t *parser,
+                                   const lxb_css_syntax_token_t *token,
+                                   void *ctx, void **out_rule)
+{
+    return &lxb_css_blank_qualified_rule;
+}
+
+static bool
+lxb_css_blank_qualified_rule_prelude(lxb_css_parser_t *parser,
+                                     const lxb_css_syntax_token_t *token,
+                                     void *ctx)
+{
+    while (token != NULL && token->type != LXB_CSS_SYNTAX_TOKEN__END) {
+        lxb_css_syntax_parser_consume(parser);
+        token = lxb_css_syntax_parser_token(parser);
+    }
+
+    return lxb_css_parser_success(parser);
+}
+
+static lxb_status_t
+lxb_css_blank_qualified_rule_prelude_end(lxb_css_parser_t *parser,
+                                         const lxb_css_syntax_token_t *token,
+                                         void *ctx, bool failed)
+{
+    return LXB_STATUS_OK;
+}
+
+static const lxb_css_syntax_cb_block_t *
+lxb_css_blank_qualified_rule_block_begin(lxb_css_parser_t *parser,
+                                         const lxb_css_syntax_token_t *token,
+                                         void *ctx, void **out_rule)
+{
+    return &lxb_css_blank_block;
+}
+
+static bool
+lxb_css_blank_qualified_rule_prelude_failed(lxb_css_parser_t *parser,
+                                            const lxb_css_syntax_token_t *token,
+                                            void *ctx)
+{
+    while (token != NULL && token->type != LXB_CSS_SYNTAX_TOKEN__END) {
+        lxb_css_syntax_parser_consume(parser);
+        token = lxb_css_syntax_parser_token(parser);
+    }
+
+    return lxb_css_parser_success(parser);
+}
+
+static lxb_status_t
+lxb_css_blank_qualified_rule_end(lxb_css_parser_t *parser,
+                                 const lxb_css_syntax_token_t *token,
+                                 void *ctx, bool failed)
+{
+    return LXB_STATUS_OK;
+}
+
+static bool
+lxb_css_blank_block_next(lxb_css_parser_t *parser,
+                         const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_parser_success(parser);
+}
+
+static lxb_status_t
+lxb_css_blank_block_end(lxb_css_parser_t *parser,
+                        const lxb_css_syntax_token_t *token,
+                        void *ctx, bool failed)
+{
+    return LXB_STATUS_OK;
+}
+
+static const lxb_css_syntax_cb_declarations_t *
+lxb_css_blank_declarations_begin(lxb_css_parser_t *parser,
+                                 const lxb_css_syntax_token_t *token,
+                                 void *ctx, void **out_rule)
+{
+    return &lxb_css_blank_declaration;
+}
+
+static lxb_css_parser_state_f
+lxb_css_blank_declaration_name(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token,
+                               void *ctx, void **out_rule)
+{
+    return lxb_css_blank_declaration_value;
+}
+
+static bool
+lxb_css_blank_declaration_value(lxb_css_parser_t *parser,
+                                const lxb_css_syntax_token_t *token, void *ctx)
+{
+    while (token != NULL && token->type != LXB_CSS_SYNTAX_TOKEN__END) {
+        lxb_css_syntax_parser_consume(parser);
+        token = lxb_css_syntax_parser_token(parser);
+    }
+
+    return lxb_css_parser_success(parser);
+}
+
+static lxb_status_t
+lxb_css_blank_declaration_end(lxb_css_parser_t *parser,
+                              void *declarations, void *ctx,
+                              const lxb_css_syntax_token_t *token,
+                              lxb_css_syntax_declaration_offset_t *offset,
+                              bool important, bool failed)
+{
+    return LXB_STATUS_OK;
+}
+
+static lxb_status_t
+lxb_css_blank_declarations_end(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token,
+                               void *ctx, bool failed)
+{
+    return LXB_STATUS_OK;
+}
+
+static bool
+lxb_css_blank_declarations_bad(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token, void *ctx)
+{
+    while (token != NULL && token->type != LXB_CSS_SYNTAX_TOKEN__END) {
+        lxb_css_syntax_parser_consume(parser);
+        token = lxb_css_syntax_parser_token(parser);
+    }
+
+    return lxb_css_parser_success(parser);
+}
diff --git a/ext/dom/lexbor/lexbor/css/blank.h b/ext/dom/lexbor/lexbor/css/blank.h
new file mode 100644
index 00000000000..05a13bfa120
--- /dev/null
+++ b/ext/dom/lexbor/lexbor/css/blank.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2026 Alexander Borisov
+ *
+ * Author: Alexander Borisov <borisov@lexbor.com>
+ */
+
+#ifndef LXB_CSS_BLANK_H
+#define LXB_CSS_BLANK_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "lexbor/css/base.h"
+#include "lexbor/css/syntax/syntax.h"
+
+
+LXB_API const lxb_css_syntax_cb_list_rules_t *
+lxb_css_blank_cb_list_rules(void);
+
+LXB_API const lxb_css_syntax_cb_at_rule_t *
+lxb_css_blank_cb_at_rule(void);
+
+LXB_API const lxb_css_syntax_cb_qualified_rule_t *
+lxb_css_blank_cb_qualified_rule(void);
+
+LXB_API const lxb_css_syntax_cb_block_t *
+lxb_css_blank_cb_block(void);
+
+LXB_API const lxb_css_syntax_cb_declarations_t *
+lxb_css_blank_cb_declarations(void);
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* LXB_CSS_BLANK_H */
diff --git a/ext/dom/lexbor/lexbor/css/css.c b/ext/dom/lexbor/lexbor/css/css.c
index 3b6f0cb0f2f..68c6c977e83 100644
--- a/ext/dom/lexbor/lexbor/css/css.c
+++ b/ext/dom/lexbor/lexbor/css/css.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021-2022 Alexander Borisov
+ * Copyright (C) 2021-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -155,15 +155,12 @@ lxb_css_memory_ref_dec_destroy(lxb_css_memory_t *memory)

 lxb_status_t
 lxb_css_make_data(lxb_css_parser_t *parser, lexbor_str_t *str,
-                  uintptr_t begin, uintptr_t end)
+                  size_t begin, size_t end)
 {
-    size_t length, offlen, len;
-    const lxb_char_t *pos;
-    const lexbor_str_t *tmp;
+    size_t length;
+    const lxb_char_t *p;

-    tmp = &parser->str;
-
-    offlen = begin - parser->offset;
+    p = parser->tkz->in_begin;
     length = end - begin;

     if (str->data == NULL) {
@@ -173,31 +170,9 @@ lxb_css_make_data(lxb_css_parser_t *parser, lexbor_str_t *str,
         }
     }

-    if (tmp->length > offlen) {
-        len = tmp->length - offlen;
-
-        if (len >= length) {
-            memcpy(str->data + str->length, tmp->data + offlen, length);
-            goto done;
-        }
-        else {
-            memcpy(str->data + str->length, tmp->data + offlen, len);
-        }
-
-        str->length += len;
-
-        pos = parser->pos;
-        length -= len;
-    }
-    else {
-        pos = parser->pos + (offlen - tmp->length);
-    }
-
-    memcpy(str->data + str->length, pos, length);
-
-done:
+    memcpy(str->data, p + begin, length);

-    str->length += length;
+    str->length = length;
     str->data[str->length] = '\0';

     return LXB_STATUS_OK;
diff --git a/ext/dom/lexbor/lexbor/css/css.h b/ext/dom/lexbor/lexbor/css/css.h
index bb12978e3ee..4ba7152334b 100644
--- a/ext/dom/lexbor/lexbor/css/css.h
+++ b/ext/dom/lexbor/lexbor/css/css.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020-2022 Alexander Borisov
+ * Copyright (C) 2020-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -35,7 +35,7 @@ extern "C" {

 LXB_API lxb_status_t
 lxb_css_make_data(lxb_css_parser_t *parser, lexbor_str_t *str,
-                  uintptr_t begin, uintptr_t end);
+                  size_t begin, size_t end);

 LXB_API lxb_char_t *
 lxb_css_serialize_char_handler(const void *style, lxb_css_style_serialize_f cb,
diff --git a/ext/dom/lexbor/lexbor/css/declaration.c b/ext/dom/lexbor/lexbor/css/declaration.c
new file mode 100644
index 00000000000..e27571486f1
--- /dev/null
+++ b/ext/dom/lexbor/lexbor/css/declaration.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2022-2026 Alexander Borisov
+ *
+ * Author: Alexander Borisov <borisov@lexbor.com>
+ */
+
+#include "lexbor/css/declaration.h"
+
+
+lxb_css_rule_declaration_t *
+lxb_css_declaration_create(lxb_css_parser_t *parser,
+                           const lxb_char_t *name, size_t length,
+                           const lxb_css_entry_data_t **out_entry)
+{
+    void *prop;
+    const lxb_css_entry_data_t *entry;
+    lxb_css_property__custom_t *custom;
+    lxb_css_rule_declaration_t *declar;
+
+    declar = lxb_css_rule_declaration_create(parser->memory);
+    if (declar == NULL) {
+        return NULL;
+    }
+
+    entry = lxb_css_property_by_name(name, length);
+    if (entry == NULL) {
+        entry = lxb_css_property_by_id(LXB_CSS_PROPERTY__CUSTOM);
+
+        prop = entry->create(parser->memory);
+        if (prop == NULL) {
+            goto failed;
+        }
+
+        custom = prop;
+
+        (void) lexbor_str_init(&custom->name, parser->memory->mraw, length);
+        if (custom->name.data == NULL) {
+            goto failed;
+        }
+
+        memcpy(custom->name.data, name, length);
+
+        custom->name.length = length;
+        custom->name.data[custom->name.length] = 0x00;
+    }
+    else {
+        prop = entry->create(parser->memory);
+        if (prop == NULL) {
+            goto failed;
+        }
+    }
+
+    declar->type = entry->unique;
+    declar->u.user = prop;
+
+    if (out_entry != NULL) {
+        *out_entry = entry;
+    }
+
+    return declar;
+
+failed:
+
+    if (prop != NULL) {
+        (void) entry->destroy(parser->memory, prop, true);
+    }
+
+    if (declar != NULL) {
+        (void) lxb_css_rule_declaration_destroy(declar, true);
+    }
+
+    if (out_entry != NULL) {
+        *out_entry = NULL;
+    }
+
+    return NULL;
+}
+
+lxb_css_rule_declaration_list_t *
+lxb_css_declaration_list_parse(lxb_css_parser_t *parser,
+                               const lxb_char_t *data, size_t length)
+{
+    return lxb_css_syntax_parse_declarations(parser,
+                                             lxb_css_state_cb_declarations(),
+                                             data, length);
+}
diff --git a/ext/dom/lexbor/lexbor/css/declaration.h b/ext/dom/lexbor/lexbor/css/declaration.h
index 1ea414e10bc..53ab061aaa4 100644
--- a/ext/dom/lexbor/lexbor/css/declaration.h
+++ b/ext/dom/lexbor/lexbor/css/declaration.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Alexander Borisov
+ * Copyright (C) 2022-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -15,19 +15,14 @@ extern "C" {
 #include "lexbor/core/mraw.h"


-LXB_API lxb_status_t
-lxb_css_declaration_list_prepare(lxb_css_parser_t *parser,
-                                 lxb_css_memory_t *mem);
+LXB_API lxb_css_rule_declaration_t *
+lxb_css_declaration_create(lxb_css_parser_t *parser,
+                           const lxb_char_t *name, size_t length,
+                           const lxb_css_entry_data_t **out_entry);

-LXB_API lxb_css_rule_declaration_list_t *
-lxb_css_declaration_list_process(lxb_css_parser_t *parser,
-                                 const lxb_char_t *data, size_t length);
-
-LXB_API void
-lxb_css_declaration_list_finish(lxb_css_parser_t *parser);

 LXB_API lxb_css_rule_declaration_list_t *
-lxb_css_declaration_list_parse(lxb_css_parser_t *parser, lxb_css_memory_t *mem,
+lxb_css_declaration_list_parse(lxb_css_parser_t *parser,
                                const lxb_char_t *data, size_t length);


diff --git a/ext/dom/lexbor/lexbor/css/log.c b/ext/dom/lexbor/lexbor/css/log.c
index 08f6fc4fc5a..d993e4715c6 100644
--- a/ext/dom/lexbor/lexbor/css/log.c
+++ b/ext/dom/lexbor/lexbor/css/log.c
@@ -152,7 +152,7 @@ lxb_css_log_format(lxb_css_log_t *log, lxb_css_log_type_t type,
         return NULL;
     }

-    msg = lxb_css_log_push(log, LXB_CSS_LOG_SYNTAX_ERROR, psize);
+    msg = lxb_css_log_push(log, type, psize);
     if (msg == NULL) {
         return NULL;
     }
diff --git a/ext/dom/lexbor/lexbor/css/parser.c b/ext/dom/lexbor/lexbor/css/parser.c
index 5ceffed0f97..62514386488 100644
--- a/ext/dom/lexbor/lexbor/css/parser.c
+++ b/ext/dom/lexbor/lexbor/css/parser.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 Alexander Borisov
+ * Copyright (C) 2021-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -73,7 +73,6 @@ lxb_css_parser_init(lxb_css_parser_t *parser, lxb_css_syntax_tokenizer_t *tkz)
     parser->rules->context = NULL;

     /* Temp */
-    parser->pos = NULL;
     parser->str.length = 0;
     parser->str_size = 4096;

@@ -93,13 +92,35 @@ lxb_css_parser_init(lxb_css_parser_t *parser, lxb_css_syntax_tokenizer_t *tkz)
     parser->types_pos = NULL;
     parser->types_end = NULL;
     parser->stage = LXB_CSS_PARSER_CLEAN;
-    parser->receive_endings = false;
     parser->status = LXB_STATUS_OK;
     parser->fake_null = false;
+    parser->token_end.type = LXB_CSS_SYNTAX_TOKEN__END;

     return LXB_STATUS_OK;
 }

+lxb_status_t
+lxb_css_parser_selectors_init(lxb_css_parser_t *parser)
+{
+    lxb_status_t status;
+
+    parser->selectors = lxb_css_selectors_create();
+    status = lxb_css_selectors_init(parser->selectors);
+    if (status != LXB_STATUS_OK) {
+        parser->selectors = lxb_css_selectors_destroy(parser->selectors, true);
+    }
+
+    return status;
+}
+
+void
+lxb_css_parser_selectors_destroy(lxb_css_parser_t *parser)
+{
+    if (parser->selectors != NULL) {
+        parser->selectors = lxb_css_selectors_destroy(parser->selectors, true);
+    }
+}
+
 void
 lxb_css_parser_clean(lxb_css_parser_t *parser)
 {
@@ -111,7 +132,6 @@ lxb_css_parser_clean(lxb_css_parser_t *parser)
     parser->types_pos = parser->types_begin;
     parser->stage = LXB_CSS_PARSER_CLEAN;
     parser->status = LXB_STATUS_OK;
-    parser->pos = NULL;
     parser->str.length = 0;
     parser->fake_null = false;
 }
@@ -331,6 +351,14 @@ lxb_css_parser_unexpected_data_status(lxb_css_parser_t *parser,
     return LXB_STATUS_ERROR_UNEXPECTED_DATA;
 }

+void *
+lxb_css_parser_memory_fail_null(lxb_css_parser_t *parser)
+{
+    parser->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
+    parser->loop = false;
+    return NULL;
+}
+
 bool
 lxb_css_parser_memory_fail(lxb_css_parser_t *parser)
 {
@@ -347,3 +375,189 @@ lxb_css_parser_memory_fail_status(lxb_css_parser_t *parser)

     return LXB_STATUS_ERROR_MEMORY_ALLOCATION;
 }
+
+/*
+ * No-inline functions for ABI.
+ */
+lxb_status_t
+lxb_css_parser_status_noi(lxb_css_parser_t *parser)
+{
+    return lxb_css_parser_status(parser);
+}
+
+lxb_css_memory_t *
+lxb_css_parser_memory_noi(lxb_css_parser_t *parser)
+{
+    return lxb_css_parser_memory(parser);
+}
+
+void
+lxb_css_parser_memory_set_noi(lxb_css_parser_t *parser, lxb_css_memory_t *memory)
+{
+    lxb_css_parser_memory_set(parser, memory);
+}
+
+lxb_css_selectors_t *
+lxb_css_parser_selectors_noi(lxb_css_parser_t *parser)
+{
+    return lxb_css_parser_selectors(parser);
+}
+
+void
+lxb_css_parser_selectors_set_noi(lxb_css_parser_t *parser,
+                                 lxb_css_selectors_t *selectors)
+{
+    lxb_css_parser_selectors_set(parser, selectors);
+}
+
+bool
+lxb_css_parser_is_running_noi(lxb_css_parser_t *parser)
+{
+    return lxb_css_parser_is_running(parser);
+}
+
+bool
+lxb_css_parser_status_is_unexpected_data_noi(lxb_css_parser_t *parser)
+{
+    return lxb_css_parser_status_is_unexpected_data(parser);
+}
+
+void
+lxb_css_parser_failed_set_noi(lxb_css_parser_t *parser, bool is)
+{
+    lxb_css_parser_failed_set(parser, is);
+}
+
+void
+lxb_css_parser_failed_set_by_id_noi(lxb_css_parser_t *parser, int idx, bool is)
+{
+    lxb_css_parser_failed_set_by_id(parser, idx, is);
+}
+
+bool
+lxb_css_parser_is_failed_noi(lxb_css_parser_t *parser)
+{
+    return lxb_css_parser_is_failed(parser);
+}
+
+void
+lxb_css_parser_set_ok_noi(lxb_css_parser_t *parser)
+{
+    lxb_css_parser_set_ok(parser);
+}
+
+const lxb_char_t *
+lxb_css_parser_buffer_noi(lxb_css_parser_t *parser, size_t *length)
+{
+    return lxb_css_parser_buffer(parser, length);
+}
+
+void
+lxb_css_parser_buffer_set_noi(lxb_css_parser_t *parser,
+                              const lxb_char_t *data, size_t length)
+{
+    lxb_css_parser_buffer_set(parser, data, length);
+}
+
+lxb_css_parser_state_f
+lxb_css_parser_state_noi(lxb_css_parser_t *parser)
+{
+    return lxb_css_parser_state(parser);
+}
+
+void
+lxb_css_parser_state_set_noi(lxb_css_parser_t *parser, lxb_css_parser_state_f state)
+{
+    lxb_css_parser_state_set(parser, state);
+}
+
+lxb_css_syntax_rule_t *
+lxb_css_parser_current_rule_noi(lxb_css_parser_t *parser)
+{
+    return lxb_css_parser_current_rule(parser);
+}
+
+size_t
+lxb_css_parser_rule_deep_noi(lxb_css_parser_t *parser)
+{
+    return lxb_css_parser_rule_deep(parser);
+}
+
+lxb_css_parser_state_t *
+lxb_css_parser_states_pop_noi(lxb_css_parser_t *parser)
+{
+    return lxb_css_parser_states_pop(parser);
+}
+
+lxb_css_parser_state_t *
+lxb_css_parser_states_to_root_noi(lxb_css_parser_t *parser)
+{
+    return lxb_css_parser_states_to_root(parser);
+}
+
+bool
+lxb_css_parser_states_set_back_noi(lxb_css_parser_t *parser)
+{
+    return lxb_css_parser_states_set_back(parser);
+}
+
+void
+lxb_css_parser_states_clean_noi(lxb_css_parser_t *parser)
+{
+    lxb_css_parser_states_clean(parser);
+}
+
+lxb_css_parser_state_t *
+lxb_css_parser_states_current_noi(lxb_css_parser_t *parser)
+{
+    return lxb_css_parser_states_current(parser);
+}
+
+void
+lxb_css_parser_states_set_noi(lxb_css_parser_state_t *states,
+                              lxb_css_parser_state_f state, void *context)
+{
+    lxb_css_parser_states_set(states, state, context);
+}
+
+void
+lxb_css_parser_states_up_noi(lxb_css_parser_t *parser)
+{
+    lxb_css_parser_states_up(parser);
+}
+
+void
+lxb_css_parser_states_down_noi(lxb_css_parser_t *parser)
+{
+    lxb_css_parser_states_down(parser);
+}
+
+lxb_css_log_t *
+lxb_css_parser_log_noi(lxb_css_parser_t *parser)
+{
+    return lxb_css_parser_log(parser);
+}
+
+const lxb_css_syntax_token_t *
+lxb_css_parser_token_end_noi(lxb_css_parser_t *parser, size_t offset)
+{
+    return lxb_css_parser_token_end(parser, offset);
+}
+
+void
+lxb_css_parser_set_context_noi(lxb_css_parser_t *parser, void *ctx)
+{
+    lxb_css_parser_set_context(parser, ctx);
+}
+
+void
+lxb_css_syntax_set_return_noi(lxb_css_parser_t *parser, void *value)
+{
+    lxb_css_syntax_set_return(parser, value);
+}
+
+void *
+lxb_css_syntax_returned_noi(lxb_css_parser_t *parser)
+{
+    return lxb_css_syntax_returned(parser);
+}
diff --git a/ext/dom/lexbor/lexbor/css/parser.h b/ext/dom/lexbor/lexbor/css/parser.h
index 9a4dfae0b70..d703dcc2f13 100644
--- a/ext/dom/lexbor/lexbor/css/parser.h
+++ b/ext/dom/lexbor/lexbor/css/parser.h
@@ -1,6 +1,5 @@
 /*
-
- * Copyright (C) 2021-2022 Alexander Borisov
+ * Copyright (C) 2021-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -70,7 +69,6 @@ extern "C" {
     }                                                                          \
     while (false)

-
 #define lxb_css_parser_token_status_wo_ws_m(parser, token)                     \
     do {                                                                       \
         if ((token = lxb_css_syntax_parser_token(parser)) == NULL) {           \
@@ -129,49 +127,44 @@ typedef enum {
 lxb_css_parser_stage_t;

 struct lxb_css_parser {
-    lxb_css_parser_state_f           block;
-    void                             *context;
-
     /* Modules */
-    lxb_css_syntax_tokenizer_t       *tkz;
-    lxb_css_selectors_t              *selectors;
-    lxb_css_selectors_t              *old_selectors;
+    lxb_css_syntax_tokenizer_t          *tkz;
+    lxb_css_selectors_t                 *selectors;

     /* Memory for all structures. */
-    lxb_css_memory_t                 *memory;
-    lxb_css_memory_t                 *old_memory;
+    lxb_css_memory_t                    *memory;

     /* Syntax parse rules. */
-    lxb_css_syntax_rule_t            *rules_begin;
-    lxb_css_syntax_rule_t            *rules_end;
-    lxb_css_syntax_rule_t            *rules;
+    lxb_css_syntax_rule_t               *rules_begin;
+    lxb_css_syntax_rule_t               *rules_end;
+    lxb_css_syntax_rule_t               *rules;

     /* States */
-    lxb_css_parser_state_t           *states_begin;
-    lxb_css_parser_state_t           *states_end;
-    lxb_css_parser_state_t           *states;
+    lxb_css_parser_state_t              *states_begin;
+    lxb_css_parser_state_t              *states_end;
+    lxb_css_parser_state_t              *states;

     /* Types */
-    lxb_css_syntax_token_type_t      *types_begin;
-    lxb_css_syntax_token_type_t      *types_end;
-    lxb_css_syntax_token_type_t      *types_pos;
+    lxb_css_syntax_token_type_t         *types_begin;
+    lxb_css_syntax_token_type_t         *types_end;
+    lxb_css_syntax_token_type_t         *types_pos;

-    const lxb_char_t                 *pos;
-    uintptr_t                        offset;
+    lxb_css_syntax_token_t              token_end;

-    lexbor_str_t                     str;
-    size_t                           str_size;
+    lexbor_str_t                        str;
+    size_t                              str_size;

-    lxb_css_log_t                    *log;
+    lxb_css_log_t                       *log;

-    lxb_css_parser_stage_t           stage;
+    lxb_css_parser_stage_t              stage;

-    bool                             loop;
-    bool                             fake_null;
-    bool                             my_tkz;
-    bool                             receive_endings;
+    lxb_css_syntax_declaration_offset_t offset;

-    lxb_status_t                     status;
+    bool                                loop;
+    bool                                fake_null;
+    bool                                my_tkz;
+
+    lxb_status_t                        status;
 };

 struct lxb_css_parser_state {
@@ -185,47 +178,197 @@ struct lxb_css_parser_error {
 };


+/*
+ * Create a new CSS parser object.
+ *
+ * @return lxb_css_parser_t* if successful, otherwise NULL.
+ */
 LXB_API lxb_css_parser_t *
 lxb_css_parser_create(void);

+/*
+ * Initialize the CSS parser with a tokenizer.
+ *
+ * @param[in] parser Required. The CSS parser object.
+ *                   If NULL, the function returns
+ *                   LXB_STATUS_ERROR_OBJECT_IS_NULL.
+ * @param[in] tkz    Optional. The tokenizer object.
+ *                   If NULL, a new tokenizer will be created and used.
+ *                   (In that case the parser manages the tokenizer lifetime.)
+ *
+ * @return LXB_STATUS_OK if successful, otherwise an error status value.
+ */
 LXB_API lxb_status_t
 lxb_css_parser_init(lxb_css_parser_t *parser, lxb_css_syntax_tokenizer_t *tkz);

+/*
+ * Initialize the Selectors module in the parser.
+ *
+ * Note:
+ *   Be sure to destroy the Selectors object you created yourself using
+ *   the lxb_css_parser_selectors_destroy() function.
+ *
+ * @param[in] parser Required. The CSS parser object.
+ *
+ * @return LXB_STATUS_OK if successful, otherwise an error status value.
+ */
+LXB_API lxb_status_t
+lxb_css_parser_selectors_init(lxb_css_parser_t *parser);
+
+/*
+ * Destroy the selectors module in the parser.
+ *
+ * @param[in] parser Required. The CSS parser object.
+ */
+LXB_API void
+lxb_css_parser_selectors_destroy(lxb_css_parser_t *parser);
+
+/*
+ * Clean the parser object.
+ *
+ * This resets internal parser state, but keeps allocated memory so the parser
+ * can be reused.
+ *
+ * @param[in] parser Required. The CSS parser object.
+ */
 LXB_API void
 lxb_css_parser_clean(lxb_css_parser_t *parser);

+/*
+ * Erase the parser object.
+ *
+ * This resets internal parser state and releases internal allocations owned by
+ * the parser so it can be re-initialized.
+ *
+ * @param[in] parser Required. The CSS parser object.
+ */
 LXB_API void
 lxb_css_parser_erase(lxb_css_parser_t *parser);

+/*
+ * Destroy the parser object.
+ *
+ * @param[in] parser        Optional. The CSS parser object.
+ *                          If NULL, the function returns NULL.
+ * @param[in] self_destroy  Optional flag.
+ *                          If true, also frees the parser object itself.
+ *                          If false, only inner resources are freed and the
+ *                          parser object remains valid.
+ *
+ * @return parser if self_destroy is false, otherwise NULL.
+ */
 LXB_API lxb_css_parser_t *
 lxb_css_parser_destroy(lxb_css_parser_t *parser, bool self_destroy);

-LXB_API lxb_css_parser_state_t *
-lxb_css_parser_states_push(lxb_css_parser_t *parser,
-                           lxb_css_parser_state_f state,
-                           void *context, bool stop);
-
-LXB_API lxb_css_parser_state_t *
-lxb_css_parser_states_next(lxb_css_parser_t *parser,
-                           lxb_css_parser_state_f next,
-                           lxb_css_parser_state_f back, void *ctx, bool root);
-
-LXB_API lxb_status_t
-lxb_css_parser_types_push(lxb_css_parser_t *parser,
-                          lxb_css_syntax_token_type_t type);
-
+/*
+ * Stop the parser main loop.
+ *
+ * This is a helper for state callbacks that want to immediately stop parsing
+ * without marking the current rule as failed.
+ *
+ * @param[in] parser Required. The CSS parser object.
+ *
+ * @return true (convenience return value, useful for state callbacks).
+ */
 LXB_API bool
 lxb_css_parser_stop(lxb_css_parser_t *parser);

+/*
+ * Fail the parser with a status and stop the main loop.
+ *
+ * This is used for hard errors (OOM, overflow, etc.). It sets parser->status
+ * and stops the parser loop.
+ *
+ * @param[in] parser  Required. The CSS parser object.
+ * @param[in] status  Required. Status code describing the failure.
+ *
+ * @return true (convenience return value, useful for state callbacks).
+ */
 LXB_API bool
 lxb_css_parser_fail(lxb_css_parser_t *parser, lxb_status_t status);

+/*
+ * Mark the current token as unexpected.
+ *
+ * This is a specialized helper for the common "unexpected data" parse error.
+ * It sets parser->status to LXB_STATUS_ERROR_UNEXPECTED_DATA and marks the
+ * current rule as failed.
+ *
+ * @param[in] parser Required. The CSS parser object.
+ *
+ * @return true (convenience return value, useful for state callbacks).
+ */
 LXB_API bool
 lxb_css_parser_unexpected(lxb_css_parser_t *parser);

+/*
+ * Mark parsing of the current grammar/rule as successful.
+ *
+ * Why this function exists:
+ * - Most callbacks in the CSS parser work as a state machine: each callback
+ *   receives the current token and returns bool to decide what to do next.
+ * - "Success" is not just a bool. The parser must switch to a special
+ *   lxb_css_state_success state to properly handle trailing whitespace and
+ *   the end-of-input token.
+ * - If you don't consume all tokens up to LXB_CSS_SYNTAX_TOKEN__END in the
+ *   current rule and call this function, the parser will switch to "failed"
+ *   mode. This is the same as calling the lxb_css_parser_failed() function.
+ *   The exception is the LXB_CSS_SYNTAX_TOKEN_WHITESPACE token. If you are
+ *   sure that only this token remains, the parser will simply exclude it.
+ *
+ * What it does:
+ * - Sets the current rule state to lxb_css_state_success.
+ * - Does not stop the parser loop by itself.
+ *
+ * Typical usage:
+ * - In css/property/state.c, after you have parsed and consumed the last token
+ *   of a property value, you do:
+ *   return lxb_css_parser_success(parser);
+ * - That transfers control to lxb_css_state_success, which consumes any
+ *   whitespace and completes on LXB_CSS_SYNTAX_TOKEN__END.
+ *
+ * @param[in] parser Required. The CSS parser object.
+ *
+ * @return true (convenience return value, useful for state callbacks).
+ */
 LXB_API bool
 lxb_css_parser_success(lxb_css_parser_t *parser);

+/*
+ * Mark parsing of the current grammar/rule as failed.
+ *
+ * Why this function exists:
+ * - In the state machine, failure is also not "just return false". The parser
+ *   needs to switch to a rule-specific recovery state so it can safely skip
+ *   input until it is allowed to stop (usually until end-of-input or a known
+ *   synchronisation point).
+ *
+ * What it does:
+ * - Sets the current rule state to the rule-specific "failed" handler
+ *   (rule->cbx.cb->failed).
+ * - Sets rule->failed = true.
+ * - Does not directly change parser->status. Use lxb_css_parser_fail() or
+ *   lxb_css_parser_unexpected() when you need a concrete status code.
+ *
+ * Typical usage:
+ * - In css/property/state.c, if a token doesn't match the expected grammar,
+ *   you do:
+ *   return lxb_css_parser_failed(parser);
+ * - That switches the parser into the failed handler. For properties this lets
+ *   the parser consume/skip tokens until it reaches LXB_CSS_SYNTAX_TOKEN__END.
+ *   (See lxb_css_state_failed(): it consumes tokens until end, then calls
+ *   lxb_css_parser_success() to finish.)
+ *
+ * Important!
+ *   The user sets the callback to "failed" and must decide what to do in this
+ *   situation. If the user does not consume all tokens before
+ *   LXB_CSS_SYNTAX_TOKEN__END, there will be an infinite loop.
+ *
+ * @param[in] parser Required. The CSS parser object.
+ *
+ * @return true (convenience return value, useful for state callbacks).
+ */
+
 LXB_API bool
 lxb_css_parser_failed(lxb_css_parser_t *parser);

@@ -240,12 +383,64 @@ LXB_API lxb_status_t
 lxb_css_parser_unexpected_data_status(lxb_css_parser_t *parser,
                                       const lxb_css_syntax_token_t *token);

+LXB_API void *
+lxb_css_parser_memory_fail_null(lxb_css_parser_t *parser);
+
 LXB_API bool
 lxb_css_parser_memory_fail(lxb_css_parser_t *parser);

-lxb_status_t
+LXB_API lxb_status_t
 lxb_css_parser_memory_fail_status(lxb_css_parser_t *parser);

+/*
+ * Push a new state to the parser.
+ *
+ * @param[in] parser   Required. The CSS parser object.
+ * @param[in] state    Required. State callback to execute.
+ * @param[in] context  Optional user pointer associated with this state.
+ *                     Stored as-is; the parser doesn't own it.
+ * @param[in] stop     If true, the pushed state is marked as a "stop point".
+ *                     This is used by the parser to stop/return control when
+ *                     this state is reached.
+ *
+ * @return lxb_css_parser_state_t* if successful, otherwise NULL.
+ */
+LXB_API lxb_css_parser_state_t *
+lxb_css_parser_states_push(lxb_css_parser_t *parser,
+                           lxb_css_parser_state_f state,
+                           void *context, bool stop);
+
+/*
+ * Go to the next state in the parser.
+ *
+ * @param[in] parser  Required. The CSS parser object.
+ * @param[in] next    Required. Next state callback.
+ * @param[in] back    Required. State callback to return to.
+ * @param[in] ctx     Optional user pointer for the next state.
+ *                    Stored as-is; the parser doesn't own it.
+ * @param[in] root    If true, marks this state as a "root" state. Root states
+ *                    are used by helper functions (e.g. to rewind to root).
+ *
+ * @return lxb_css_parser_state_t* if successful, otherwise NULL.
+ */
+LXB_API lxb_css_parser_state_t *
+lxb_css_parser_states_next(lxb_css_parser_t *parser,
+                           lxb_css_parser_state_f next,
+                           lxb_css_parser_state_f back, void *ctx, bool root);
+
+/*
+ * Push a token type to the parser.
+ *
+ * @param[in] parser Required. The CSS parser object.
+ * @param[in] type   Required. Token type to push.
+ *
+ * @return LXB_STATUS_OK if successful, otherwise an error status value.
+ */
+LXB_API lxb_status_t
+lxb_css_parser_types_push(lxb_css_parser_t *parser,
+                          lxb_css_syntax_token_type_t type);
+
+
 /*
  * Inline functions
  */
@@ -350,32 +545,6 @@ lxb_css_parser_state_set(lxb_css_parser_t *parser, lxb_css_parser_state_f state)
     parser->rules->state = state;
 }

-lxb_inline void
-lxb_css_parser_state_block_set(lxb_css_parser_t *parser,
-                               lxb_css_parser_state_f state)
-{
-    parser->block = state;
-}
-
-lxb_inline void
-lxb_css_parser_state_value_set(lxb_css_parser_t *parser,
-                               lxb_css_parser_state_f state)
-{
-    lxb_css_parser_state_block_set(parser, state);
-}
-
-lxb_inline void *
-lxb_css_parser_context(lxb_css_parser_t *parser)
-{
-    return parser->context;
-}
-
-lxb_inline void
-lxb_css_parser_context_set(lxb_css_parser_t *parser, void *context)
-{
-    parser->context = context;
-}
-
 lxb_inline lxb_css_syntax_rule_t *
 lxb_css_parser_current_rule(lxb_css_parser_t *parser)
 {
@@ -420,13 +589,6 @@ lxb_css_parser_states_set_back(lxb_css_parser_t *parser)
     return true;
 }

-lxb_inline void
-lxb_css_parser_states_change_back(lxb_css_parser_t *parser,
-                                  lxb_css_parser_state_f state)
-{
-    parser->rules->state_back = state;
-}
-
 lxb_inline void
 lxb_css_parser_states_clean(lxb_css_parser_t *parser)
 {
@@ -465,47 +627,127 @@ lxb_css_parser_log(lxb_css_parser_t *parser)
     return parser->log;
 }

-lxb_inline void
-lxb_css_parser_offset_set(lxb_css_parser_t *parser,
-                          const lxb_css_syntax_token_t *token)
+lxb_inline const lxb_css_syntax_token_t *
+lxb_css_parser_token_end(lxb_css_parser_t *parser, size_t offset)
 {
-    if (parser->pos == NULL) {
-        if (token == NULL) {
-            parser->pos = parser->tkz->in_begin;
-            parser->offset = 0;
-        }
-        else {
-            parser->pos = lxb_css_syntax_token_base(token)->begin
-                          + lxb_css_syntax_token_base(token)->length;
-            parser->offset = token->offset + lxb_css_syntax_token_base(token)->length;
-        }
-    }
+    parser->token_end.offset = offset;
+    return &parser->token_end;
 }

-lxb_inline const lxb_css_syntax_list_rules_offset_t *
-lxb_css_parser_list_rules_offset(lxb_css_parser_t *parser)
+lxb_inline void
+lxb_css_parser_set_context(lxb_css_parser_t *parser, void *ctx)
 {
-    return &parser->rules->u.list_rules;
+    parser->rules->context = ctx;
 }

-lxb_inline const lxb_css_syntax_at_rule_offset_t *
-lxb_css_parser_at_rule_offset(lxb_css_parser_t *parser)
+lxb_inline void
+lxb_css_syntax_set_return(lxb_css_parser_t *parser, void *value)
 {
-    return &parser->rules->u.at_rule;
+    parser->rules[-1].returned = value;
 }

-lxb_inline const lxb_css_syntax_qualified_offset_t *
-lxb_css_parser_qualified_rule_offset(lxb_css_parser_t *parser)
+lxb_inline void *
+lxb_css_syntax_returned(lxb_css_parser_t *parser)
 {
-    return &parser->rules->u.qualified;
+    return parser->rules->returned;
 }

-lxb_inline const lxb_css_syntax_declarations_offset_t *
-lxb_css_parser_declarations_offset(lxb_css_parser_t *parser)
-{
-    return &parser->rules->u.declarations;
-}
+/*
+ * No-inline functions for ABI.
+ */
+LXB_API lxb_status_t
+lxb_css_parser_status_noi(lxb_css_parser_t *parser);
+
+LXB_API lxb_css_memory_t *
+lxb_css_parser_memory_noi(lxb_css_parser_t *parser);
+
+LXB_API void
+lxb_css_parser_memory_set_noi(lxb_css_parser_t *parser, lxb_css_memory_t *memory);
+
+LXB_API lxb_css_selectors_t *
+lxb_css_parser_selectors_noi(lxb_css_parser_t *parser);
+
+LXB_API void
+lxb_css_parser_selectors_set_noi(lxb_css_parser_t *parser,
+                                 lxb_css_selectors_t *selectors);
+
+LXB_API bool
+lxb_css_parser_is_running_noi(lxb_css_parser_t *parser);
+
+LXB_API bool
+lxb_css_parser_status_is_unexpected_data_noi(lxb_css_parser_t *parser);
+
+LXB_API void
+lxb_css_parser_failed_set_noi(lxb_css_parser_t *parser, bool is);
+
+LXB_API void
+lxb_css_parser_failed_set_by_id_noi(lxb_css_parser_t *parser, int idx, bool is);
+
+LXB_API bool
+lxb_css_parser_is_failed_noi(lxb_css_parser_t *parser);
+
+LXB_API void
+lxb_css_parser_set_ok_noi(lxb_css_parser_t *parser);
+
+LXB_API const lxb_char_t *
+lxb_css_parser_buffer_noi(lxb_css_parser_t *parser, size_t *length);
+
+LXB_API void
+lxb_css_parser_buffer_set_noi(lxb_css_parser_t *parser,
+                              const lxb_char_t *data, size_t length);
+
+LXB_API lxb_css_parser_state_f
+lxb_css_parser_state_noi(lxb_css_parser_t *parser);
+
+LXB_API void
+lxb_css_parser_state_set_noi(lxb_css_parser_t *parser,
+                             lxb_css_parser_state_f state);
+
+LXB_API lxb_css_syntax_rule_t *
+lxb_css_parser_current_rule_noi(lxb_css_parser_t *parser);
+
+LXB_API size_t
+lxb_css_parser_rule_deep_noi(lxb_css_parser_t *parser);
+
+LXB_API lxb_css_parser_state_t *
+lxb_css_parser_states_pop_noi(lxb_css_parser_t *parser);
+
+LXB_API lxb_css_parser_state_t *
+lxb_css_parser_states_to_root_noi(lxb_css_parser_t *parser);
+
+LXB_API bool
+lxb_css_parser_states_set_back_noi(lxb_css_parser_t *parser);
+
+LXB_API void
+lxb_css_parser_states_clean_noi(lxb_css_parser_t *parser);
+
+LXB_API lxb_css_parser_state_t *
+lxb_css_parser_states_current_noi(lxb_css_parser_t *parser);
+
+LXB_API void
+lxb_css_parser_states_set_noi(lxb_css_parser_state_t *states,
+                              lxb_css_parser_state_f state, void *context);
+
+LXB_API void
+lxb_css_parser_states_up_noi(lxb_css_parser_t *parser);
+
+LXB_API void
+lxb_css_parser_states_down_noi(lxb_css_parser_t *parser);
+
+LXB_API lxb_css_log_t *
+lxb_css_parser_log_noi(lxb_css_parser_t *parser);
+
+LXB_API const lxb_css_syntax_token_t *
+lxb_css_parser_token_end_noi(lxb_css_parser_t *parser, size_t offset);
+
+LXB_API void
+lxb_css_parser_set_context_noi(lxb_css_parser_t *parser, void *ctx);
+
+LXB_API void
+lxb_css_syntax_set_return_noi(lxb_css_parser_t *parser, void *value);

+LXB_API void *
+lxb_css_syntax_returned_noi(lxb_css_parser_t *parser);

 #ifdef __cplusplus
 } /* extern "C" */
diff --git a/ext/dom/lexbor/lexbor/css/property.c b/ext/dom/lexbor/lexbor/css/property.c
new file mode 100644
index 00000000000..6e460c3492f
--- /dev/null
+++ b/ext/dom/lexbor/lexbor/css/property.c
@@ -0,0 +1,3171 @@
+/*
+ * Copyright (C) 2021-2023 Alexander Borisov
+ *
+ * Author: Alexander Borisov <borisov@lexbor.com>
+ */
+
+#include "lexbor/css/css.h"
+#include "lexbor/css/property.h"
+#include "lexbor/css/parser.h"
+#include "lexbor/css/stylesheet.h"
+#include "lexbor/css/property/state.h"
+#include "lexbor/css/property/res.h"
+#include "lexbor/core/serialize.h"
+#include "lexbor/core/conv.h"
+
+
+const lxb_css_entry_data_t *
+lxb_css_property_by_name(const lxb_char_t *name, size_t length)
+{
+    const lexbor_shs_entry_t *entry;
+
+    entry = lexbor_shs_entry_get_lower_static(lxb_css_property_shs,
+                                              name, length);
+    if (entry == NULL) {
+        return NULL;
+    }
+
+    return entry->value;
+}
+
+const lxb_css_entry_data_t *
+lxb_css_property_by_id(uintptr_t id)
+{
+    return &lxb_css_property_data[id];
+}
+
+const void *
+lxb_css_property_initial_by_id(uintptr_t id)
+{
+    if (id >= LXB_CSS_PROPERTY__LAST_ENTRY) {
+        return NULL;
+    }
+
+    return lxb_css_property_data[id].initial;
+}
+
+void *
+lxb_css_property_destroy(lxb_css_memory_t *memory, void *style,
+                         lxb_css_property_type_t type, bool self_destroy)
+{
+    const lxb_css_entry_data_t *data;
+
+    data = lxb_css_property_by_id(type);
+    if (data == NULL) {
+        return style;
+    }
+
+    return data->destroy(memory, style, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_serialize(const void *style, lxb_css_property_type_t type,
+                           lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_entry_data_t *data;
+
+    data = lxb_css_property_by_id(type);
+    if (data == NULL) {
+        return LXB_STATUS_ERROR_NOT_EXISTS;
+    }
+
+    return data->serialize(style, cb, ctx);
+}
+
+lxb_status_t
+lxb_css_property_serialize_str(const void *style, lxb_css_property_type_t type,
+                               lexbor_mraw_t *mraw, lexbor_str_t *str)
+{
+    const lxb_css_entry_data_t *data;
+
+    data = lxb_css_property_by_id(type);
+    if (data == NULL) {
+        return LXB_STATUS_ERROR_NOT_EXISTS;
+    }
+
+    return lxb_css_serialize_str_handler(style, str, mraw, data->serialize);
+}
+
+lxb_status_t
+lxb_css_property_serialize_name(const void *style, lxb_css_property_type_t type,
+                                lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_entry_data_t *data;
+
+    switch (type) {
+        case LXB_CSS_PROPERTY__UNDEF:
+            return lxb_css_property__undef_serialize_name(style, cb, ctx);
+
+        case LXB_CSS_PROPERTY__CUSTOM:
+            return lxb_css_property__custom_serialize_name(style, cb, ctx);
+
+        default:
+            break;
+    }
+
+    data = lxb_css_property_by_id(type);
+    if (data == NULL) {
+        return LXB_STATUS_ERROR_NOT_EXISTS;
+    }
+
+    return cb(data->name, data->length, ctx);
+}
+
+lxb_status_t
+lxb_css_property_serialize_name_str(const void *style, lxb_css_property_type_t type,
+                                    lexbor_mraw_t *mraw, lexbor_str_t *str)
+{
+    const lxb_css_entry_data_t *data;
+
+    switch (type) {
+        case LXB_CSS_PROPERTY__UNDEF:
+            return lxb_css_serialize_str_handler(style, str, mraw,
+                                       lxb_css_property__undef_serialize_name);
+
+        case LXB_CSS_PROPERTY__CUSTOM:
+            return lxb_css_serialize_str_handler(style, str, mraw,
+                                      lxb_css_property__custom_serialize_name);
+
+        default:
+            break;
+    }
+
+    data = lxb_css_property_by_id(type);
+    if (data == NULL) {
+        return LXB_STATUS_ERROR_NOT_EXISTS;
+    }
+
+    if (str->data == NULL) {
+        lexbor_str_init(str, mraw, data->length);
+        if (str->data == NULL) {
+            return LXB_STATUS_ERROR_MEMORY_ALLOCATION;
+        }
+    }
+
+    (void) lexbor_str_append(str, mraw, data->name, data->length);
+
+    return LXB_STATUS_OK;
+}
+
+/* _undef. */
+
+void *
+lxb_css_property__undef_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property__undef_t));
+}
+
+void *
+lxb_css_property__undef_destroy(lxb_css_memory_t *memory,
+                                void *style, bool self_destroy)
+{
+    if (style == NULL) {
+        return NULL;
+    }
+
+    if (self_destroy) {
+        return lexbor_mraw_free(memory->mraw, style);
+    }
+
+    return style;
+}
+
+lxb_status_t
+lxb_css_property__undef_serialize(const void *style,
+                                  lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property__undef_t *undef = style;
+
+    return cb(undef->value.data, undef->value.length, ctx);
+}
+
+lxb_status_t
+lxb_css_property__undef_serialize_name(const void *style,
+                                       lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property__undef_t *undef = style;
+    const lxb_css_entry_data_t *data;
+
+    if (undef->type == LXB_CSS_PROPERTY__UNDEF) {
+        return LXB_STATUS_OK;
+    }
+
+    data = lxb_css_property_by_id(undef->type);
+    if (data == NULL) {
+        return LXB_STATUS_ERROR_NOT_EXISTS;
+    }
+
+    return cb(data->name, data->length, ctx);
+}
+
+lxb_status_t
+lxb_css_property__undef_serialize_value(const void *style,
+                                        lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property__undef_t *undef = style;
+
+    if (undef->type == LXB_CSS_PROPERTY__UNDEF) {
+        return cb(undef->value.data, undef->value.length, ctx);
+    }
+
+    return LXB_STATUS_OK;
+}
+
+/* _custom. */
+
+void *
+lxb_css_property__custom_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property__custom_t));
+}
+
+void *
+lxb_css_property__custom_destroy(lxb_css_memory_t *memory,
+                                 void *style, bool self_destroy)
+{
+    if (style == NULL) {
+        return NULL;
+    }
+
+    if (self_destroy) {
+        return lexbor_mraw_free(memory->mraw, style);
+    }
+
+    return style;
+}
+
+lxb_status_t
+lxb_css_property__custom_serialize(const void *style,
+                                   lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property__custom_t *custom = style;
+
+    if (custom->value.data == NULL) {
+        return LXB_STATUS_OK;
+    }
+
+    return cb(custom->value.data, custom->value.length, ctx);
+}
+
+lxb_status_t
+lxb_css_property__custom_serialize_name(const void *style,
+                                        lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property__custom_t *custom = style;
+
+    return cb(custom->name.data, custom->name.length, ctx);
+}
+
+lxb_status_t
+lxb_css_property__custom_serialize_value(const void *style,
+                                         lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property__custom_t *custom = style;
+
+    if (custom->value.data == NULL) {
+        return LXB_STATUS_OK;
+    }
+
+    return cb(custom->value.data, custom->value.length, ctx);
+}
+
+/* Display. */
+
+void *
+lxb_css_property_display_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_display_t));
+}
+
+void *
+lxb_css_property_display_destroy(lxb_css_memory_t *memory,
+                                 void *property, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, property, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_display_serialize(const void *property,
+                                   lexbor_serialize_cb_f cb, void *ctx)
+{
+    lxb_status_t status;
+    const lxb_css_data_t *data;
+    const lxb_css_property_display_t *display = property;
+
+    static const lexbor_str_t str_ws = lexbor_str(" ");
+
+    data = lxb_css_value_by_id(display->a);
+    if (data == NULL) {
+        return LXB_STATUS_ERROR_NOT_EXISTS;
+    }
+
+    lexbor_serialize_write(cb, data->name, data->length, ctx, status);
+
+    if (display->b == LXB_CSS_PROPERTY__UNDEF) {
+        return LXB_STATUS_OK;
+    }
+
+    lexbor_serialize_write(cb, str_ws.data, str_ws.length, ctx, status);
+
+    data = lxb_css_value_by_id(display->b);
+    if (data == NULL) {
+        return LXB_STATUS_ERROR_NOT_EXISTS;
+    }
+
+    lexbor_serialize_write(cb, data->name, data->length, ctx, status);
+
+    if (display->c == LXB_CSS_PROPERTY__UNDEF) {
+        return LXB_STATUS_OK;
+    }
+
+    lexbor_serialize_write(cb, str_ws.data, str_ws.length, ctx, status);
+
+    data = lxb_css_value_by_id(display->c);
+    if (data == NULL) {
+        return LXB_STATUS_ERROR_NOT_EXISTS;
+    }
+
+    lexbor_serialize_write(cb, data->name, data->length, ctx, status);
+
+    return LXB_STATUS_OK;
+}
+
+/* Order. */
+
+void *
+lxb_css_property_order_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_order_t));
+}
+
+void *
+lxb_css_property_order_destroy(lxb_css_memory_t *memory,
+                               void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_order_serialize(const void *style,
+                                 lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_value_integer_type_sr(style, cb, ctx);
+}
+
+/* Visibility. */
+
+void *
+lxb_css_property_visibility_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_visibility_t));
+}
+
+void *
+lxb_css_property_visibility_destroy(lxb_css_memory_t *memory,
+                                    void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_visibility_serialize(const void *style,
+                                      lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_visibility_t *vb = style;
+
+    return lxb_css_value_serialize(vb->type, cb, ctx);
+}
+
+/* Width. */
+
+void *
+lxb_css_property_width_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_width_t));
+}
+
+void *
+lxb_css_property_width_destroy(lxb_css_memory_t *memory,
+                               void *property, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, property, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_width_serialize(const void *property,
+                                 lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_width_t *width = property;
+
+    switch (width->type) {
+        case LXB_CSS_VALUE__LENGTH:
+        case LXB_CSS_VALUE__NUMBER:
+            return lxb_css_value_length_sr(&width->u.length, cb, ctx);
+
+        case LXB_CSS_VALUE__PERCENTAGE:
+            return lxb_css_value_percentage_sr(&width->u.percentage, cb, ctx);
+
+        case LXB_CSS_VALUE__UNDEF:
+            /* FIXME: ???? */
+            break;
+
+        default:
+            return lxb_css_value_serialize(width->type, cb, ctx);
+    }
+
+    return LXB_STATUS_OK;
+}
+
+/* Height. */
+
+void *
+lxb_css_property_height_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_height_t));
+}
+
+void *
+lxb_css_property_height_destroy(lxb_css_memory_t *memory,
+                                void *property, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, property, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_height_serialize(const void *property,
+                                  lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_property_width_serialize(property, cb, ctx);
+}
+
+/* Box-sizing. */
+
+void *
+lxb_css_property_box_sizing_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_box_sizing_t));
+}
+
+void *
+lxb_css_property_box_sizing_destroy(lxb_css_memory_t *memory,
+                                    void *property, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, property, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_box_sizing_serialize(const void *property,
+                                      lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_box_sizing_t *bsize = property;
+
+    return lxb_css_value_serialize(bsize->type, cb, ctx);
+}
+
+/* Min-width. */
+
+void *
+lxb_css_property_min_width_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_min_width_t));
+}
+
+void *
+lxb_css_property_min_width_destroy(lxb_css_memory_t *memory,
+                                   void *property, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, property, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_min_width_serialize(const void *property,
+                                     lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_property_width_serialize(property, cb, ctx);
+}
+
+/* Min-height. */
+
+void *
+lxb_css_property_min_height_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_min_height_t));
+}
+
+void *
+lxb_css_property_min_height_destroy(lxb_css_memory_t *memory,
+                                    void *property, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, property, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_min_height_serialize(const void *property,
+                                      lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_property_width_serialize(property, cb, ctx);
+}
+
+/* Max-width. */
+
+void *
+lxb_css_property_max_width_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_max_width_t));
+}
+
+void *
+lxb_css_property_max_width_destroy(lxb_css_memory_t *memory,
+                                   void *property, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, property, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_max_width_serialize(const void *property,
+                                     lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_property_width_serialize(property, cb, ctx);
+}
+
+/* Max-height. */
+
+void *
+lxb_css_property_max_height_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_max_height_t));
+}
+
+void *
+lxb_css_property_max_height_destroy(lxb_css_memory_t *memory,
+                                    void *property, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, property, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_max_height_serialize(const void *property,
+                                      lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_property_width_serialize(property, cb, ctx);
+}
+
+/* Margin. */
+
+void *
+lxb_css_property_margin_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_margin_t));
+}
+
+void *
+lxb_css_property_margin_destroy(lxb_css_memory_t *memory,
+                                void *property, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, property, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_margin_serialize(const void *property,
+                                  lexbor_serialize_cb_f cb, void *ctx)
+{
+    lxb_status_t status;
+    const lxb_css_property_margin_t *margin = property;
+
+    static const lexbor_str_t str_ws = lexbor_str(" ");
+
+    /* Top. */
+
+    status = lxb_css_value_length_percentage_sr(&margin->top, cb, ctx);
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    if (margin->right.type == LXB_CSS_VALUE__UNDEF) {
+        return LXB_STATUS_OK;
+    }
+
+    /* Right. */
+
+    lexbor_serialize_write(cb, str_ws.data, str_ws.length, ctx, status);
+
+    status = lxb_css_value_length_percentage_sr(&margin->right, cb, ctx);
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    if (margin->bottom.type == LXB_CSS_VALUE__UNDEF) {
+        return LXB_STATUS_OK;
+    }
+
+    /* Bottom. */
+
+    lexbor_serialize_write(cb, str_ws.data, str_ws.length, ctx, status);
+
+    status = lxb_css_value_length_percentage_sr(&margin->bottom, cb, ctx);
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    if (margin->left.type == LXB_CSS_VALUE__UNDEF) {
+        return LXB_STATUS_OK;
+    }
+
+    /* Left. */
+
+    lexbor_serialize_write(cb, str_ws.data, str_ws.length, ctx, status);
+
+    return lxb_css_value_length_percentage_sr(&margin->left, cb, ctx);
+}
+
+/* Margin-top. */
+
+void *
+lxb_css_property_margin_top_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_margin_top_t));
+}
+
+void *
+lxb_css_property_margin_top_destroy(lxb_css_memory_t *memory,
+                                    void *property, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, property, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_margin_top_serialize(const void *property,
+                                      lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_value_length_percentage_sr(property, cb, ctx);
+}
+
+/* Margin-right. */
+
+void *
+lxb_css_property_margin_right_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_margin_right_t));
+}
+
+void *
+lxb_css_property_margin_right_destroy(lxb_css_memory_t *memory,
+                                      void *property, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, property, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_margin_right_serialize(const void *property,
+                                        lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_value_length_percentage_sr(property, cb, ctx);
+}
+
+/* Margin-bottom. */
+
+void *
+lxb_css_property_margin_bottom_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_margin_bottom_t));
+}
+
+void *
+lxb_css_property_margin_bottom_destroy(lxb_css_memory_t *memory,
+                                       void *property, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, property, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_margin_bottom_serialize(const void *property,
+                                         lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_value_length_percentage_sr(property, cb, ctx);
+}
+
+/* Margin-left. */
+
+void *
+lxb_css_property_margin_left_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_margin_left_t));
+}
+
+void *
+lxb_css_property_margin_left_destroy(lxb_css_memory_t *memory,
+                                     void *property, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, property, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_margin_left_serialize(const void *property,
+                                       lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_value_length_percentage_sr(property, cb, ctx);
+}
+
+/* Padding. */
+
+void *
+lxb_css_property_padding_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_padding_t));
+}
+
+void *
+lxb_css_property_padding_destroy(lxb_css_memory_t *memory,
+                                 void *property, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, property, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_padding_serialize(const void *property,
+                                   lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_property_margin_serialize(property, cb, ctx);
+}
+
+/* Padding-top. */
+
+void *
+lxb_css_property_padding_top_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_padding_top_t));
+}
+
+void *
+lxb_css_property_padding_top_destroy(lxb_css_memory_t *memory,
+                                     void *property, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, property, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_padding_top_serialize(const void *property,
+                                       lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_value_length_percentage_sr(property, cb, ctx);
+}
+
+/* Padding-right. */
+
+void *
+lxb_css_property_padding_right_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_padding_right_t));
+}
+
+void *
+lxb_css_property_padding_right_destroy(lxb_css_memory_t *memory,
+                                       void *property, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, property, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_padding_right_serialize(const void *property,
+                                         lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_value_length_percentage_sr(property, cb, ctx);
+}
+
+/* Padding-bottom. */
+
+void *
+lxb_css_property_padding_bottom_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_padding_bottom_t));
+}
+
+void *
+lxb_css_property_padding_bottom_destroy(lxb_css_memory_t *memory,
+                                        void *property, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, property, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_padding_bottom_serialize(const void *property,
+                                          lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_value_length_percentage_sr(property, cb, ctx);
+}
+
+/* Padding-left. */
+
+void *
+lxb_css_property_padding_left_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_padding_left_t));
+}
+
+void *
+lxb_css_property_padding_left_destroy(lxb_css_memory_t *memory,
+                                      void *property, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, property, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_padding_left_serialize(const void *property,
+                                        lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_value_length_percentage_sr(property, cb, ctx);
+}
+
+/* Border. */
+
+void *
+lxb_css_property_border_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_border_t));
+}
+
+void *
+lxb_css_property_border_destroy(lxb_css_memory_t *memory,
+                                void *property, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, property, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_border_serialize(const void *property,
+                                  lexbor_serialize_cb_f cb, void *ctx)
+{
+    bool ws_print;
+    lxb_status_t status;
+    const lxb_css_property_border_t *border = property;
+
+    static const lexbor_str_t str_ws = lexbor_str(" ");
+
+    ws_print = false;
+
+    if (border->width.type != LXB_CSS_VALUE__UNDEF) {
+        status = lxb_css_value_length_type_sr(&border->width, cb, ctx);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+
+        ws_print = true;
+    }
+
+    if (border->style != LXB_CSS_VALUE__UNDEF) {
+        if (ws_print) {
+            lexbor_serialize_write(cb, str_ws.data, str_ws.length, ctx, status);
+        }
+
+        status = lxb_css_value_serialize(border->style, cb, ctx);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+
+        ws_print = true;
+    }
+
+    if (border->color.type != LXB_CSS_VALUE__UNDEF) {
+        if (ws_print) {
+            lexbor_serialize_write(cb, str_ws.data, str_ws.length, ctx, status);
+        }
+
+        return lxb_css_value_color_serialize(&border->color, cb, ctx);
+    }
+
+    return LXB_STATUS_OK;
+}
+
+/* Border-top. */
+
+void *
+lxb_css_property_border_top_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_border_top_t));
+}
+
+void *
+lxb_css_property_border_top_destroy(lxb_css_memory_t *memory,
+                                    void *property, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, property, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_border_top_serialize(const void *property,
+                                      lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_property_border_serialize(property, cb, ctx);
+}
+
+/* Border-right. */
+
+void *
+lxb_css_property_border_right_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_border_right_t));
+}
+
+void *
+lxb_css_property_border_right_destroy(lxb_css_memory_t *memory,
+                                      void *property, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, property, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_border_right_serialize(const void *property,
+                                        lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_property_border_serialize(property, cb, ctx);
+}
+
+/* Border-bottom. */
+
+void *
+lxb_css_property_border_bottom_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_border_bottom_t));
+}
+
+void *
+lxb_css_property_border_bottom_destroy(lxb_css_memory_t *memory,
+                                       void *property, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, property, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_border_bottom_serialize(const void *property,
+                                         lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_property_border_serialize(property, cb, ctx);
+}
+
+/* Border-left. */
+
+void *
+lxb_css_property_border_left_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_border_left_t));
+}
+
+void *
+lxb_css_property_border_left_destroy(lxb_css_memory_t *memory,
+                                     void *property, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, property, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_border_left_serialize(const void *property,
+                                       lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_property_border_serialize(property, cb, ctx);
+}
+
+void *
+lxb_css_property_border_top_color_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_border_top_color_t));
+}
+
+void *
+lxb_css_property_border_top_color_destroy(lxb_css_memory_t *memory,
+                                          void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_border_top_color_serialize(const void *style,
+                                            lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_value_color_serialize(style, cb, ctx);
+}
+
+void *
+lxb_css_property_border_right_color_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_border_right_color_t));
+}
+
+void *
+lxb_css_property_border_right_color_destroy(lxb_css_memory_t *memory,
+                                            void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_border_right_color_serialize(const void *style,
+                                              lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_value_color_serialize(style, cb, ctx);
+}
+
+void *
+lxb_css_property_border_bottom_color_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_border_bottom_color_t));
+}
+
+void *
+lxb_css_property_border_bottom_color_destroy(lxb_css_memory_t *memory,
+                                             void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_border_bottom_color_serialize(const void *style,
+                                               lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_value_color_serialize(style, cb, ctx);
+}
+
+void *
+lxb_css_property_border_left_color_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_border_left_color_t));
+}
+
+void *
+lxb_css_property_border_left_color_destroy(lxb_css_memory_t *memory,
+                                           void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_border_left_color_serialize(const void *style,
+                                             lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_value_color_serialize(style, cb, ctx);
+}
+
+void *
+lxb_css_property_background_color_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_background_color_t));
+}
+
+void *
+lxb_css_property_background_color_destroy(lxb_css_memory_t *memory,
+                                          void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_background_color_serialize(const void *style,
+                                            lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_value_color_serialize(style, cb, ctx);
+}
+
+/* Color. */
+
+void *
+lxb_css_property_color_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_color_t));
+}
+
+void *
+lxb_css_property_color_destroy(lxb_css_memory_t *memory,
+                               void *property, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, property, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_color_serialize(const void *property,
+                                 lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_value_color_serialize(property, cb, ctx);
+}
+
+void *
+lxb_css_property_opacity_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_opacity_t));
+}
+
+void *
+lxb_css_property_opacity_destroy(lxb_css_memory_t *memory,
+                                 void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_opacity_serialize(const void *style,
+                                   lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_value_number_percentage_sr(style, cb, ctx);
+}
+
+void *
+lxb_css_property_position_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_position_t));
+}
+
+void *
+lxb_css_property_position_destroy(lxb_css_memory_t *memory,
+                                  void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_position_serialize(const void *style,
+                                    lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_position_t *position = style;
+
+    return lxb_css_value_serialize(position->type, cb, ctx);
+}
+
+void *
+lxb_css_property_top_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_top_t));
+}
+
+void *
+lxb_css_property_top_destroy(lxb_css_memory_t *memory,
+                             void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_top_serialize(const void *style,
+                               lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_value_length_percentage_sr(style, cb, ctx);
+}
+
+void *
+lxb_css_property_right_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_right_t));
+}
+
+void *
+lxb_css_property_right_destroy(lxb_css_memory_t *memory,
+                               void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_right_serialize(const void *style,
+                                 lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_property_top_serialize(style, cb, ctx);
+}
+
+void *
+lxb_css_property_bottom_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_bottom_t));
+}
+
+void *
+lxb_css_property_bottom_destroy(lxb_css_memory_t *memory,
+                                void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_bottom_serialize(const void *style,
+                                  lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_property_top_serialize(style, cb, ctx);
+}
+
+void *
+lxb_css_property_left_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_left_t));
+}
+
+void *
+lxb_css_property_left_destroy(lxb_css_memory_t *memory,
+                              void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_left_serialize(const void *style,
+                                lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_property_top_serialize(style, cb, ctx);
+}
+
+void *
+lxb_css_property_inset_block_start_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_inset_block_start_t));
+}
+
+void *
+lxb_css_property_inset_block_start_destroy(lxb_css_memory_t *memory,
+                                           void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_inset_block_start_serialize(const void *style,
+                                             lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_property_top_serialize(style, cb, ctx);
+}
+
+void *
+lxb_css_property_inset_inline_start_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_inset_inline_start_t));
+}
+
+void *
+lxb_css_property_inset_inline_start_destroy(lxb_css_memory_t *memory,
+                                            void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_inset_inline_start_serialize(const void *style,
+                                              lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_property_top_serialize(style, cb, ctx);
+}
+
+void *
+lxb_css_property_inset_block_end_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_inset_block_end_t));
+}
+
+void *
+lxb_css_property_inset_block_end_destroy(lxb_css_memory_t *memory,
+                                         void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_inset_block_end_serialize(const void *style,
+                                           lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_property_top_serialize(style, cb, ctx);
+}
+
+void *
+lxb_css_property_inset_inline_end_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_inset_inline_end_t));
+}
+
+void *
+lxb_css_property_inset_inline_end_destroy(lxb_css_memory_t *memory,
+                                          void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_inset_inline_end_serialize(const void *style,
+                                            lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_property_top_serialize(style, cb, ctx);
+}
+
+/* Text-transform. */
+
+LXB_API void *
+lxb_css_property_text_transform_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_text_transform_t));
+}
+
+LXB_API void *
+lxb_css_property_text_transform_destroy(lxb_css_memory_t *memory,
+                                        void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_text_transform_serialize(const void *style,
+                                          lexbor_serialize_cb_f cb, void *ctx)
+{
+    bool ws_print;
+    lxb_status_t status;
+    const lxb_css_property_text_transform_t *tt = style;
+
+    static const lexbor_str_t str_ws = lexbor_str(" ");
+
+    ws_print = false;
+
+    if (tt->type_case != LXB_CSS_VALUE__UNDEF) {
+        status = lxb_css_value_serialize(tt->type_case, cb, ctx);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+
+        ws_print = true;
+    }
+
+    if (tt->full_width != LXB_CSS_VALUE__UNDEF) {
+        if (ws_print) {
+            lexbor_serialize_write(cb, str_ws.data, str_ws.length, ctx, status);
+        }
+
+        status = lxb_css_value_serialize(tt->full_width, cb, ctx);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+
+        ws_print = true;
+    }
+
+    if (tt->full_size_kana != LXB_CSS_VALUE__UNDEF) {
+        if (ws_print) {
+            lexbor_serialize_write(cb, str_ws.data, str_ws.length, ctx, status);
+        }
+
+        return lxb_css_value_serialize(tt->full_size_kana, cb, ctx);
+    }
+
+    return LXB_STATUS_OK;
+}
+
+/* Text-align. */
+
+LXB_API void *
+lxb_css_property_text_align_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_text_align_t));
+}
+
+LXB_API void *
+lxb_css_property_text_align_destroy(lxb_css_memory_t *memory,
+                                    void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_text_align_serialize(const void *style,
+                                      lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_text_align_t *ta = style;
+
+    return lxb_css_value_serialize(ta->type, cb, ctx);
+}
+
+/* Text-align-all. */
+
+LXB_API void *
+lxb_css_property_text_align_all_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_text_align_all_t));
+}
+
+LXB_API void *
+lxb_css_property_text_align_all_destroy(lxb_css_memory_t *memory,
+                                        void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_text_align_all_serialize(const void *style,
+                                          lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_text_align_all_t *taa = style;
+
+    return lxb_css_value_serialize(taa->type, cb, ctx);
+}
+
+/* Text-align-last. */
+
+LXB_API void *
+lxb_css_property_text_align_last_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_text_align_last_t));
+}
+
+LXB_API void *
+lxb_css_property_text_align_last_destroy(lxb_css_memory_t *memory,
+                                         void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_text_align_last_serialize(const void *style,
+                                           lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_text_align_last_t *tal = style;
+
+    return lxb_css_value_serialize(tal->type, cb, ctx);
+}
+
+/* Text-justify. */
+
+LXB_API void *
+lxb_css_property_text_justify_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_text_justify_t));
+}
+
+LXB_API void *
+lxb_css_property_text_justify_destroy(lxb_css_memory_t *memory,
+                                      void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_text_justify_serialize(const void *style,
+                                        lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_text_justify_t *tj = style;
+
+    return lxb_css_value_serialize(tj->type, cb, ctx);
+}
+
+/* Text-indent. */
+
+LXB_API void *
+lxb_css_property_text_indent_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_text_indent_t));
+}
+
+LXB_API void *
+lxb_css_property_text_indent_destroy(lxb_css_memory_t *memory,
+                                     void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_text_indent_serialize(const void *style,
+                                       lexbor_serialize_cb_f cb, void *ctx)
+{
+    lxb_status_t status;
+    const lxb_css_property_text_indent_t *ti = style;
+
+    static const lexbor_str_t str_ws = lexbor_str(" ");
+
+    if (ti->type == LXB_CSS_VALUE__LENGTH) {
+        status = lxb_css_value_length_percentage_sr(&ti->length, cb, ctx);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+    }
+    else if (ti->type != LXB_CSS_VALUE__UNDEF) {
+        status = lxb_css_value_serialize(ti->type, cb, ctx);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+    }
+
+    if (ti->hanging != LXB_CSS_VALUE__UNDEF) {
+        lexbor_serialize_write(cb, str_ws.data, str_ws.length, ctx, status);
+
+        status = lxb_css_value_serialize(ti->hanging, cb, ctx);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+    }
+
+    if (ti->each_line != LXB_CSS_VALUE__UNDEF) {
+        lexbor_serialize_write(cb, str_ws.data, str_ws.length, ctx, status);
+
+        return lxb_css_value_serialize(ti->each_line, cb, ctx);
+    }
+
+    return LXB_STATUS_OK;
+}
+
+/* White-space. */
+
+LXB_API void *
+lxb_css_property_white_space_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_white_space_t));
+}
+
+LXB_API void *
+lxb_css_property_white_space_destroy(lxb_css_memory_t *memory,
+                                     void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_white_space_serialize(const void *style,
+                                       lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_white_space_t *ws = style;
+
+    return lxb_css_value_serialize(ws->type, cb, ctx);
+}
+
+/* Tab-size. */
+
+LXB_API void *
+lxb_css_property_tab_size_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_tab_size_t));
+}
+
+LXB_API void *
+lxb_css_property_tab_size_destroy(lxb_css_memory_t *memory,
+                                  void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_tab_size_serialize(const void *style,
+                                    lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_value_number_length_sr(style, cb, ctx);
+}
+
+/* Word-break. */
+
+LXB_API void *
+lxb_css_property_word_break_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_word_break_t));
+}
+
+LXB_API void *
+lxb_css_property_word_break_destroy(lxb_css_memory_t *memory,
+                                    void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_word_break_serialize(const void *style,
+                                      lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_word_break_t *wb = style;
+
+    return lxb_css_value_serialize(wb->type, cb, ctx);
+}
+
+/* Line-break. */
+
+LXB_API void *
+lxb_css_property_line_break_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_line_break_t));
+}
+
+LXB_API void *
+lxb_css_property_line_break_destroy(lxb_css_memory_t *memory,
+                                    void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_line_break_serialize(const void *style,
+                                      lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_line_break_t *lb = style;
+
+    return lxb_css_value_serialize(lb->type, cb, ctx);
+}
+
+/* Hyphens. */
+
+LXB_API void *
+lxb_css_property_hyphens_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_hyphens_t));
+}
+
+LXB_API void *
+lxb_css_property_hyphens_destroy(lxb_css_memory_t *memory,
+                                 void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_hyphens_serialize(const void *style,
+                                   lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_hyphens_t *hpns = style;
+
+    return lxb_css_value_serialize(hpns->type, cb, ctx);
+}
+
+/* Overflow-wrap. */
+
+LXB_API void *
+lxb_css_property_overflow_wrap_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_overflow_wrap_t));
+}
+
+LXB_API void *
+lxb_css_property_overflow_wrap_destroy(lxb_css_memory_t *memory,
+                                       void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_overflow_wrap_serialize(const void *style,
+                                         lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_overflow_wrap_t *ow = style;
+
+    return lxb_css_value_serialize(ow->type, cb, ctx);
+}
+
+/* Word-wrap. */
+
+LXB_API void *
+lxb_css_property_word_wrap_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_word_wrap_t));
+}
+
+LXB_API void *
+lxb_css_property_word_wrap_destroy(lxb_css_memory_t *memory,
+                                   void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_word_wrap_serialize(const void *style,
+                                     lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_word_wrap_t *ww = style;
+
+    return lxb_css_value_serialize(ww->type, cb, ctx);
+}
+
+/* Word-spacing. */
+
+LXB_API void *
+lxb_css_property_word_spacing_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_word_spacing_t));
+}
+
+LXB_API void *
+lxb_css_property_word_spacing_destroy(lxb_css_memory_t *memory,
+                                      void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_word_spacing_serialize(const void *style,
+                                        lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_value_length_type_sr(style, cb, ctx);
+}
+
+/* Letter-spacing. */
+
+LXB_API void *
+lxb_css_property_letter_spacing_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_letter_spacing_t));
+}
+
+LXB_API void *
+lxb_css_property_letter_spacing_destroy(lxb_css_memory_t *memory,
+                                        void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_letter_spacing_serialize(const void *style,
+                                          lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_value_length_type_sr(style, cb, ctx);
+}
+
+/* Hanging-punctuation. */
+
+LXB_API void *
+lxb_css_property_hanging_punctuation_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_hanging_punctuation_t));
+}
+
+LXB_API void *
+lxb_css_property_hanging_punctuation_destroy(lxb_css_memory_t *memory,
+                                             void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_hanging_punctuation_serialize(const void *style,
+                                               lexbor_serialize_cb_f cb, void *ctx)
+{
+    bool ws_print;
+    lxb_status_t status;
+    const lxb_css_property_hanging_punctuation_t *hp = style;
+
+    static const lexbor_str_t str_ws = lexbor_str(" ");
+
+    ws_print = false;
+
+    if (hp->type_first != LXB_CSS_VALUE__UNDEF) {
+        status = lxb_css_value_serialize(hp->type_first, cb, ctx);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+
+        ws_print = true;
+    }
+
+    if (hp->force_allow != LXB_CSS_VALUE__UNDEF) {
+        if (ws_print) {
+            lexbor_serialize_write(cb, str_ws.data, str_ws.length, ctx, status);
+        }
+
+        status = lxb_css_value_serialize(hp->force_allow, cb, ctx);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+
+        ws_print = true;
+    }
+
+    if (hp->last != LXB_CSS_VALUE__UNDEF) {
+        if (ws_print) {
+            lexbor_serialize_write(cb, str_ws.data, str_ws.length, ctx, status);
+        }
+
+        return lxb_css_value_serialize(hp->last, cb, ctx);
+    }
+
+    return LXB_STATUS_OK;
+}
+
+/* Font-family. */
+
+void *
+lxb_css_property_font_family_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_font_family_t));
+}
+
+void *
+lxb_css_property_font_family_destroy(lxb_css_memory_t *memory,
+                                     void *style, bool self_destroy)
+{
+    lxb_css_property_font_family_t *ff = style;
+    lxb_css_property_family_name_t *name, *next;
+
+    name = ff->first;
+
+    while (name != NULL) {
+        next = name->next;
+
+        if (!name->generic) {
+            (void) lexbor_str_destroy(&name->u.str, memory->mraw, false);
+        }
+
+        lexbor_mraw_free(memory->mraw, name);
+
+        name = next;
+    }
+
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_font_family_serialize(const void *style,
+                                       lexbor_serialize_cb_f cb, void *ctx)
+{
+    lxb_status_t status;
+    const lxb_css_property_font_family_t *ff = style;
+    const lxb_css_property_family_name_t *name;
+
+    static const lexbor_str_t str_comma = lexbor_str(", ");
+
+    name = ff->first;
+
+    while (name != NULL) {
+        if (name->generic) {
+            status = lxb_css_value_serialize(name->u.type, cb, ctx);
+        }
+        else {
+            status = lxb_css_syntax_ident_or_string_serialize(name->u.str.data,
+                                                              name->u.str.length,
+                                                              cb, ctx);
+        }
+
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+
+        name = name->next;
+
+        if (name != NULL) {
+            lexbor_serialize_write(cb, str_comma.data, str_comma.length,
+                                   ctx, status);
+        }
+    }
+
+    return LXB_STATUS_OK;
+}
+
+/* Font-weight. */
+
+void *
+lxb_css_property_font_weight_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_font_weight_t));
+}
+
+void *
+lxb_css_property_font_weight_destroy(lxb_css_memory_t *memory,
+                                     void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_font_weight_serialize(const void *style,
+                                       lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_value_number_type_sr(style, cb, ctx);
+}
+
+/* Font-stretch. */
+
+void *
+lxb_css_property_font_stretch_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_font_stretch_t));
+}
+
+void *
+lxb_css_property_font_stretch_destroy(lxb_css_memory_t *memory,
+                                      void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_font_stretch_serialize(const void *style,
+                                        lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_value_percentage_type_sr(style, cb, ctx);
+}
+
+/* Font-style. */
+
+void *
+lxb_css_property_font_style_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_font_style_t));
+}
+
+void *
+lxb_css_property_font_style_destroy(lxb_css_memory_t *memory,
+                                    void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+lxb_status_t
+lxb_css_property_font_style_serialize(const void *style,
+                                      lexbor_serialize_cb_f cb, void *ctx)
+{
+    lxb_status_t status;
+    const lxb_css_property_font_style_t *fs = style;
+
+    static const lexbor_str_t str_ws = lexbor_str(" ");
+
+    status = lxb_css_value_serialize(fs->type, cb, ctx);
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    if (fs->angle.unit != (lxb_css_unit_angle_t) LXB_CSS_UNIT__UNDEF) {
+        lexbor_serialize_write(cb, str_ws.data, str_ws.length, ctx, status);
+
+        status = lxb_css_value_angle_sr(&fs->angle, cb, ctx);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+    }
+
+    return LXB_STATUS_OK;
+}
+
+/* Font-size. */
+
+LXB_API void *
+lxb_css_property_font_size_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_font_size_t));
+}
+
+LXB_API void *
+lxb_css_property_font_size_destroy(lxb_css_memory_t *memory,
+                                   void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_font_size_serialize(const void *style,
+                                     lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_value_length_percentage_type_sr(style, cb, ctx);
+}
+
+/* Float-reference. */
+
+LXB_API void *
+lxb_css_property_float_reference_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_float_reference_t));
+}
+
+LXB_API void *
+lxb_css_property_float_reference_destroy(lxb_css_memory_t *memory,
+                                         void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_float_reference_serialize(const void *style,
+                                           lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_float_reference_t *fr = style;
+
+    return lxb_css_value_serialize(fr->type, cb, ctx);
+}
+
+/* Float. */
+
+LXB_API void *
+lxb_css_property_float_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_float_t));
+}
+
+LXB_API void *
+lxb_css_property_float_destroy(lxb_css_memory_t *memory,
+                               void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_float_serialize(const void *style,
+                                 lexbor_serialize_cb_f cb, void *ctx)
+{
+    lxb_status_t status;
+    const lxb_css_property_float_t *flt = style;
+
+    static const lexbor_str_t str_o = lexbor_str("(");
+    static const lexbor_str_t str_cm = lexbor_str(", ");
+    static const lexbor_str_t str_c = lexbor_str(")");
+
+    status = lxb_css_value_serialize(flt->type, cb, ctx);
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    if (flt->length.type != LXB_CSS_VALUE__LENGTH) {
+        return LXB_STATUS_OK;
+    }
+
+    lexbor_serialize_write(cb, str_o.data, str_o.length, ctx, status);
+
+    status = lxb_css_value_length_sr(&flt->length.length, cb, ctx);
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    if (flt->snap_type == LXB_CSS_VALUE__UNDEF) {
+        return cb(str_c.data, str_c.length, ctx);
+    }
+
+    lexbor_serialize_write(cb, str_cm.data, str_cm.length, ctx, status);
+
+    status = lxb_css_value_serialize(flt->snap_type, cb, ctx);
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    return cb(str_c.data, str_c.length, ctx);
+}
+
+/* Clear. */
+
+LXB_API void *
+lxb_css_property_clear_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_clear_t));
+}
+
+LXB_API void *
+lxb_css_property_clear_destroy(lxb_css_memory_t *memory,
+                               void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_clear_serialize(const void *style,
+                                 lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_clear_t *cls = style;
+
+    return lxb_css_value_serialize(cls->type, cb, ctx);
+}
+
+/* Float-defer. */
+
+LXB_API void *
+lxb_css_property_float_defer_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_float_defer_t));
+}
+
+LXB_API void *
+lxb_css_property_float_defer_destroy(lxb_css_memory_t *memory,
+                                     void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_float_defer_serialize(const void *style,
+                                       lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_float_defer_t *def = style;
+
+    if (def->type == LXB_CSS_FLOAT_DEFER__INTEGER) {
+        return lxb_css_value_integer_sr(&def->integer, cb, ctx);
+    }
+
+    return lxb_css_value_serialize(def->type, cb, ctx);
+}
+
+/* Float-offset. */
+
+LXB_API void *
+lxb_css_property_float_offset_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_float_offset_t));
+}
+
+LXB_API void *
+lxb_css_property_float_offset_destroy(lxb_css_memory_t *memory,
+                                      void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_float_offset_serialize(const void *style,
+                                        lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_value_length_percentage_sr(style, cb, ctx);
+}
+
+/* Wrap-flow. */
+
+LXB_API void *
+lxb_css_property_wrap_flow_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_wrap_flow_t));
+}
+
+LXB_API void *
+lxb_css_property_wrap_flow_destroy(lxb_css_memory_t *memory,
+                                   void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_wrap_flow_serialize(const void *style,
+                                     lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_wrap_flow_t *wf = style;
+
+    return lxb_css_value_serialize(wf->type, cb, ctx);
+}
+
+/* Wrap-through. */
+
+LXB_API void *
+lxb_css_property_wrap_through_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_wrap_through_t));
+}
+
+LXB_API void *
+lxb_css_property_wrap_through_destroy(lxb_css_memory_t *memory,
+                                      void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_wrap_through_serialize(const void *style,
+                                        lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_wrap_through_t *wt = style;
+
+    return lxb_css_value_serialize(wt->type, cb, ctx);
+}
+
+/* Flex-direction. */
+
+LXB_API void *
+lxb_css_property_flex_direction_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_flex_direction_t));
+}
+
+LXB_API void *
+lxb_css_property_flex_direction_destroy(lxb_css_memory_t *memory,
+                                        void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_flex_direction_serialize(const void *style,
+                                          lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_flex_direction_t *fd = style;
+
+    return lxb_css_value_serialize(fd->type, cb, ctx);
+}
+
+/* Flex-wrap. */
+
+LXB_API void *
+lxb_css_property_flex_wrap_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_flex_wrap_t));
+}
+
+LXB_API void *
+lxb_css_property_flex_wrap_destroy(lxb_css_memory_t *memory,
+                                   void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_flex_wrap_serialize(const void *style,
+                                     lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_flex_wrap_t *fw = style;
+
+    return lxb_css_value_serialize(fw->type, cb, ctx);
+}
+
+/* Flex-flow. */
+
+LXB_API void *
+lxb_css_property_flex_flow_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_flex_flow_t));
+}
+
+LXB_API void *
+lxb_css_property_flex_flow_destroy(lxb_css_memory_t *memory,
+                                   void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_flex_flow_serialize(const void *style,
+                                     lexbor_serialize_cb_f cb, void *ctx)
+{
+    lxb_status_t status;
+    const lxb_css_property_flex_flow_t *ff = style;
+
+    static const lexbor_str_t str_ws = lexbor_str(" ");
+
+    if (ff->type_direction != LXB_CSS_VALUE__UNDEF) {
+        status = lxb_css_value_serialize(ff->type_direction, cb, ctx);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+    }
+
+    if (ff->wrap != LXB_CSS_VALUE__UNDEF) {
+        if (ff->type_direction != LXB_CSS_VALUE__UNDEF) {
+            lexbor_serialize_write(cb, str_ws.data, str_ws.length, ctx, status);
+        }
+
+        return lxb_css_value_serialize(ff->wrap, cb, ctx);
+    }
+
+    return LXB_STATUS_OK;
+}
+
+/* Flex. */
+
+LXB_API void *
+lxb_css_property_flex_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_flex_t));
+}
+
+LXB_API void *
+lxb_css_property_flex_destroy(lxb_css_memory_t *memory,
+                              void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_flex_serialize(const void *style,
+                                lexbor_serialize_cb_f cb, void *ctx)
+{
+    lxb_status_t status;
+    const lxb_css_property_flex_t *flex = style;
+
+    static const lexbor_str_t str_ws = lexbor_str(" ");
+
+    if (flex->type != LXB_CSS_VALUE__UNDEF) {
+        return lxb_css_value_serialize(flex->type, cb, ctx);
+    }
+
+    if (flex->grow.type != LXB_CSS_VALUE__UNDEF) {
+        status = lxb_css_value_number_sr(&flex->grow.number, cb, ctx);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+
+        if (flex->shrink.type != LXB_CSS_VALUE__UNDEF) {
+            lexbor_serialize_write(cb, str_ws.data, str_ws.length, ctx, status);
+
+            status = lxb_css_value_number_sr(&flex->shrink.number, cb, ctx);
+            if (status != LXB_STATUS_OK) {
+                return status;
+            }
+        }
+    }
+
+    if (flex->basis.type == LXB_CSS_VALUE__UNDEF) {
+        return LXB_STATUS_OK;
+    }
+
+    if (flex->grow.type != LXB_CSS_VALUE__UNDEF) {
+        lexbor_serialize_write(cb, str_ws.data, str_ws.length, ctx, status);
+    }
+
+    return lxb_css_property_flex_basis_serialize(&flex->basis, cb, ctx);
+}
+
+/* Flex-grow. */
+
+LXB_API void *
+lxb_css_property_flex_grow_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_flex_grow_t));
+}
+
+LXB_API void *
+lxb_css_property_flex_grow_destroy(lxb_css_memory_t *memory,
+                                   void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_flex_grow_serialize(const void *style,
+                                     lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_value_number_type_sr(style, cb, ctx);
+}
+
+/* Flex-shrink. */
+
+LXB_API void *
+lxb_css_property_flex_shrink_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_flex_shrink_t));
+}
+
+LXB_API void *
+lxb_css_property_flex_shrink_destroy(lxb_css_memory_t *memory,
+                                     void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_flex_shrink_serialize(const void *style,
+                                       lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_value_number_type_sr(style, cb, ctx);
+}
+
+/* Flex-basis. */
+
+LXB_API void *
+lxb_css_property_flex_basis_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_flex_basis_t));
+}
+
+LXB_API void *
+lxb_css_property_flex_basis_destroy(lxb_css_memory_t *memory,
+                                    void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_flex_basis_serialize(const void *style,
+                                      lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_property_width_serialize(style, cb, ctx);
+}
+
+/* Justify-content. */
+
+LXB_API void *
+lxb_css_property_justify_content_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_justify_content_t));
+}
+
+LXB_API void *
+lxb_css_property_justify_content_destroy(lxb_css_memory_t *memory,
+                                         void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_justify_content_serialize(const void *style,
+                                           lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_justify_content_t *jc = style;
+
+    return lxb_css_value_serialize(jc->type, cb, ctx);
+}
+
+/* Align-items. */
+
+LXB_API void *
+lxb_css_property_align_items_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_align_items_t));
+}
+
+LXB_API void *
+lxb_css_property_align_items_destroy(lxb_css_memory_t *memory,
+                                     void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_align_items_serialize(const void *style,
+                                       lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_align_items_t *ai = style;
+
+    return lxb_css_value_serialize(ai->type, cb, ctx);
+}
+
+/* Align-self. */
+
+LXB_API void *
+lxb_css_property_align_self_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_align_self_t));
+}
+
+LXB_API void *
+lxb_css_property_align_self_destroy(lxb_css_memory_t *memory,
+                                    void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_align_self_serialize(const void *style,
+                                      lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_align_self_t *as = style;
+
+    return lxb_css_value_serialize(as->type, cb, ctx);
+}
+
+/* Align-content. */
+
+LXB_API void *
+lxb_css_property_align_content_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_align_content_t));
+}
+
+LXB_API void *
+lxb_css_property_align_content_destroy(lxb_css_memory_t *memory,
+                                       void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_align_content_serialize(const void *style,
+                                         lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_align_content_t *ac = style;
+
+    return lxb_css_value_serialize(ac->type, cb, ctx);
+}
+
+/* Dominant-baseline. */
+
+LXB_API void *
+lxb_css_property_dominant_baseline_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_dominant_baseline_t));
+}
+
+LXB_API void *
+lxb_css_property_dominant_baseline_destroy(lxb_css_memory_t *memory,
+                                           void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_dominant_baseline_serialize(const void *style,
+                                             lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_dominant_baseline_t *db = style;
+
+    return lxb_css_value_serialize(db->type, cb, ctx);
+}
+
+/* Vertical-align. */
+
+LXB_API void *
+lxb_css_property_vertical_align_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_vertical_align_t));
+}
+
+LXB_API void *
+lxb_css_property_vertical_align_destroy(lxb_css_memory_t *memory,
+                                        void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_vertical_align_serialize(const void *style,
+                                          lexbor_serialize_cb_f cb, void *ctx)
+{
+    bool is;
+    lxb_status_t status;
+    const lxb_css_property_vertical_align_t *va = style;
+
+    static const lexbor_str_t str_ws = lexbor_str(" ");
+
+    is = false;
+
+    if (va->type != LXB_CSS_VALUE__UNDEF) {
+        status = lxb_css_value_serialize(va->type, cb, ctx);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+
+        is = true;
+    }
+
+    if (va->alignment.type != LXB_CSS_VALUE__UNDEF) {
+        if (is) {
+            lexbor_serialize_write(cb, str_ws.data, str_ws.length, ctx, status);
+        }
+
+        status = lxb_css_value_serialize(va->alignment.type, cb, ctx);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+
+        is = true;
+    }
+
+    if (va->shift.type != LXB_CSS_VALUE__UNDEF) {
+        if (is) {
+            lexbor_serialize_write(cb, str_ws.data, str_ws.length, ctx, status);
+        }
+
+        status = lxb_css_value_length_percentage_sr(&va->shift, cb, ctx);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+    }
+
+    return LXB_STATUS_OK;
+}
+
+/* Baseline-source. */
+
+LXB_API void *
+lxb_css_property_baseline_source_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_baseline_source_t));
+}
+
+LXB_API void *
+lxb_css_property_baseline_source_destroy(lxb_css_memory_t *memory,
+                                         void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_baseline_source_serialize(const void *style,
+                                           lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_baseline_source_t *bs = style;
+
+    return lxb_css_value_serialize(bs->type, cb, ctx);
+}
+
+/* Alignment-baseline. */
+
+LXB_API void *
+lxb_css_property_alignment_baseline_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_alignment_baseline_t));
+}
+
+LXB_API void *
+lxb_css_property_alignment_baseline_destroy(lxb_css_memory_t *memory,
+                                            void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_alignment_baseline_serialize(const void *style,
+                                              lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_alignment_baseline_t *ab = style;
+
+    return lxb_css_value_serialize(ab->type, cb, ctx);
+}
+
+/* Baseline-shift. */
+
+LXB_API void *
+lxb_css_property_baseline_shift_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_baseline_shift_t));
+}
+
+LXB_API void *
+lxb_css_property_baseline_shift_destroy(lxb_css_memory_t *memory,
+                                        void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_baseline_shift_serialize(const void *style,
+                                          lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_value_length_percentage_sr(style, cb, ctx);
+}
+
+/* Line-height. */
+
+LXB_API void *
+lxb_css_property_line_height_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_line_height_t));
+}
+
+LXB_API void *
+lxb_css_property_line_height_destroy(lxb_css_memory_t *memory,
+                                     void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_line_height_serialize(const void *style,
+                                       lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_value_number_length_percentage_type_sr(style, cb, ctx);
+}
+
+/* Z-index. */
+
+LXB_API void *
+lxb_css_property_z_index_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_property_z_index_t));
+}
+
+LXB_API void *
+lxb_css_property_z_index_destroy(lxb_css_memory_t *memory,
+                                 void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_z_index_serialize(const void *style,
+                                   lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_value_integer_type_sr(style, cb, ctx);
+}
+
+/* Direction. */
+
+LXB_API void *
+lxb_css_property_direction_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_direction_t));
+}
+
+LXB_API void *
+lxb_css_property_direction_destroy(lxb_css_memory_t *memory,
+                                   void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_direction_serialize(const void *style,
+                                     lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_direction_t *dr = style;
+
+    return lxb_css_value_serialize(dr->type, cb, ctx);
+}
+
+/* Unicode-bidi. */
+
+LXB_API void *
+lxb_css_property_unicode_bidi_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_unicode_bidi_t));
+}
+
+LXB_API void *
+lxb_css_property_unicode_bidi_destroy(lxb_css_memory_t *memory,
+                                      void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_unicode_bidi_serialize(const void *style,
+                                        lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_unicode_bidi_t *ub = style;
+
+    return lxb_css_value_serialize(ub->type, cb, ctx);
+}
+
+/* Writing-mode. */
+
+LXB_API void *
+lxb_css_property_writing_mode_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_writing_mode_t));
+}
+
+LXB_API void *
+lxb_css_property_writing_mode_destroy(lxb_css_memory_t *memory,
+                                      void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_writing_mode_serialize(const void *style,
+                                        lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_writing_mode_t *wm = style;
+
+    return lxb_css_value_serialize(wm->type, cb, ctx);
+}
+
+/* Text-orientation. */
+
+LXB_API void *
+lxb_css_property_text_orientation_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_text_orientation_t));
+}
+
+LXB_API void *
+lxb_css_property_text_orientation_destroy(lxb_css_memory_t *memory,
+                                          void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_text_orientation_serialize(const void *style,
+                                            lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_text_orientation_t *to = style;
+
+    return lxb_css_value_serialize(to->type, cb, ctx);
+}
+
+/* Text-combine-upright. */
+
+LXB_API void *
+lxb_css_property_text_combine_upright_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_text_combine_upright_t));
+}
+
+LXB_API void *
+lxb_css_property_text_combine_upright_destroy(lxb_css_memory_t *memory,
+                                              void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_text_combine_upright_serialize(const void *style,
+                                                lexbor_serialize_cb_f cb, void *ctx)
+{
+    lxb_status_t status;
+    const lxb_css_property_text_combine_upright_t *tcu = style;
+
+    static const lexbor_str_t str_ws = lexbor_str(" ");
+
+    if (tcu->type == LXB_CSS_TEXT_COMBINE_UPRIGHT_DIGITS) {
+        status = lxb_css_value_serialize(tcu->type, cb, ctx);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+
+        if (tcu->digits.num != 0) {
+            lexbor_serialize_write(cb, str_ws.data, str_ws.length, ctx, status);
+
+            return lxb_css_value_integer_sr(&tcu->digits, cb, ctx);
+        }
+
+        return LXB_STATUS_OK;
+    }
+
+    return lxb_css_value_serialize(tcu->type, cb, ctx);
+}
+
+/* Overflow-x. */
+
+LXB_API void *
+lxb_css_property_overflow_x_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_overflow_x_t));
+}
+
+LXB_API void *
+lxb_css_property_overflow_x_destroy(lxb_css_memory_t *memory,
+                                    void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_overflow_x_serialize(const void *style,
+                                      lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_overflow_x_t *ox = style;
+
+    return lxb_css_value_serialize(ox->type, cb, ctx);
+}
+
+/* Overflow-y. */
+
+LXB_API void *
+lxb_css_property_overflow_y_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_overflow_y_t));
+}
+
+LXB_API void *
+lxb_css_property_overflow_y_destroy(lxb_css_memory_t *memory,
+                                    void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_overflow_y_serialize(const void *style,
+                                      lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_overflow_y_t *oy = style;
+
+    return lxb_css_value_serialize(oy->type, cb, ctx);
+}
+
+/* Overflow-block. */
+
+LXB_API void *
+lxb_css_property_overflow_block_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_overflow_block_t));
+}
+
+LXB_API void *
+lxb_css_property_overflow_block_destroy(lxb_css_memory_t *memory,
+                                        void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_overflow_block_serialize(const void *style,
+                                          lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_overflow_block_t *ob = style;
+
+    return lxb_css_value_serialize(ob->type, cb, ctx);
+}
+
+/* Overflow-inline. */
+
+LXB_API void *
+lxb_css_property_overflow_inline_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_overflow_inline_t));
+}
+
+LXB_API void *
+lxb_css_property_overflow_inline_destroy(lxb_css_memory_t *memory,
+                                         void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_overflow_inline_serialize(const void *style,
+                                           lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_overflow_inline_t *oi = style;
+
+    return lxb_css_value_serialize(oi->type, cb, ctx);
+}
+
+/* Text-overflow. */
+
+LXB_API void *
+lxb_css_property_text_overflow_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_text_overflow_t));
+}
+
+LXB_API void *
+lxb_css_property_text_overflow_destroy(lxb_css_memory_t *memory,
+                                       void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_text_overflow_serialize(const void *style,
+                                         lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_text_overflow_t *to = style;
+
+    return lxb_css_value_serialize(to->type, cb, ctx);
+}
+
+/* Text-decoration-line. */
+
+LXB_API void *
+lxb_css_property_text_decoration_line_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_text_decoration_line_t));
+}
+
+LXB_API void *
+lxb_css_property_text_decoration_line_destroy(lxb_css_memory_t *memory,
+                                              void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_text_decoration_line_serialize(const void *style,
+                                                lexbor_serialize_cb_f cb, void *ctx)
+{
+    bool itis;
+    lxb_status_t status;
+    const lxb_css_property_text_decoration_line_t *tdl = style;
+
+    static const lexbor_str_t str_ws = lexbor_str(" ");
+
+    itis = false;
+
+    if (tdl->underline != LXB_CSS_VALUE__UNDEF) {
+        status = lxb_css_value_serialize(tdl->underline, cb, ctx);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+
+        itis = true;
+    }
+
+    if (tdl->overline != LXB_CSS_VALUE__UNDEF) {
+        if (itis) {
+            lexbor_serialize_write(cb, str_ws.data, str_ws.length, ctx, status);
+        }
+
+        status = lxb_css_value_serialize(tdl->overline, cb, ctx);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+
+        itis = true;
+    }
+
+    if (tdl->line_through != LXB_CSS_VALUE__UNDEF) {
+        if (itis) {
+            lexbor_serialize_write(cb, str_ws.data, str_ws.length, ctx, status);
+        }
+
+        status = lxb_css_value_serialize(tdl->line_through, cb, ctx);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+
+        itis = true;
+    }
+
+    if (tdl->blink != LXB_CSS_VALUE__UNDEF) {
+        if (itis) {
+            lexbor_serialize_write(cb, str_ws.data, str_ws.length, ctx, status);
+        }
+
+        return lxb_css_value_serialize(tdl->blink, cb, ctx);
+    }
+
+    if (itis) {
+        return LXB_STATUS_OK;
+    }
+
+    return lxb_css_value_serialize(tdl->type, cb, ctx);
+}
+
+/* Text-decoration-style. */
+
+LXB_API void *
+lxb_css_property_text_decoration_style_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_text_decoration_style_t));
+}
+
+LXB_API void *
+lxb_css_property_text_decoration_style_destroy(lxb_css_memory_t *memory,
+                                               void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_text_decoration_style_serialize(const void *style,
+                                                 lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_property_text_decoration_style_t *tds = style;
+
+    return lxb_css_value_serialize(tds->type, cb, ctx);
+}
+
+/* Text-decoration-color. */
+
+LXB_API void *
+lxb_css_property_text_decoration_color_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_text_decoration_color_t));
+}
+
+LXB_API void *
+lxb_css_property_text_decoration_color_destroy(lxb_css_memory_t *memory,
+                                               void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_text_decoration_color_serialize(const void *style,
+                                                 lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_property_color_serialize(style, cb, ctx);
+}
+
+/* Text-decoration. */
+
+LXB_API void *
+lxb_css_property_text_decoration_create(lxb_css_memory_t *memory)
+{
+    return lexbor_mraw_calloc(memory->mraw,
+                              sizeof(lxb_css_property_text_decoration_t));
+}
+
+LXB_API void *
+lxb_css_property_text_decoration_destroy(lxb_css_memory_t *memory,
+                                         void *style, bool self_destroy)
+{
+    return lxb_css_property__undef_destroy(memory, style, self_destroy);
+}
+
+LXB_API lxb_status_t
+lxb_css_property_text_decoration_serialize(const void *style,
+                                           lexbor_serialize_cb_f cb, void *ctx)
+{
+    bool itis;
+    lxb_status_t status;
+    const lxb_css_property_text_decoration_t *td = style;
+
+    static const lexbor_str_t str_ws = lexbor_str(" ");
+
+    itis = false;
+
+    if (td->line.type != LXB_CSS_VALUE__UNDEF
+        || td->line.underline != LXB_CSS_VALUE__UNDEF
+        || td->line.overline != LXB_CSS_VALUE__UNDEF
+        || td->line.line_through != LXB_CSS_VALUE__UNDEF
+        || td->line.blink != LXB_CSS_VALUE__UNDEF)
+    {
+        status = lxb_css_property_text_decoration_line_serialize(&td->line,
+                                                                 cb, ctx);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+
+        itis = true;
+    }
+
+    if (td->style.type != LXB_CSS_VALUE__UNDEF) {
+        if (itis) {
+            lexbor_serialize_write(cb, str_ws.data, str_ws.length, ctx, status);
+        }
+
+        status = lxb_css_property_text_decoration_style_serialize(&td->style,
+                                                                  cb, ctx);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+
+        itis = true;
+    }
+
+    if (td->color.type != LXB_CSS_VALUE__UNDEF) {
+        if (itis) {
+            lexbor_serialize_write(cb, str_ws.data, str_ws.length, ctx, status);
+        }
+
+        return lxb_css_property_text_decoration_color_serialize(&td->color,
+                                                                cb, ctx);
+    }
+
+    return LXB_STATUS_OK;
+}
diff --git a/ext/dom/lexbor/lexbor/css/property/const.h b/ext/dom/lexbor/lexbor/css/property/const.h
index 8ee24481c6a..4f90bc1c107 100644
--- a/ext/dom/lexbor/lexbor/css/property/const.h
+++ b/ext/dom/lexbor/lexbor/css/property/const.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2023 Alexander Borisov
+ * Copyright (C) 2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
diff --git a/ext/dom/lexbor/lexbor/css/property/res.h b/ext/dom/lexbor/lexbor/css/property/res.h
index 35cce195901..eb5b90304a0 100644
--- a/ext/dom/lexbor/lexbor/css/property/res.h
+++ b/ext/dom/lexbor/lexbor/css/property/res.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2023 Alexander Borisov
+ * Copyright (C) 2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
diff --git a/ext/dom/lexbor/lexbor/css/property/state.c b/ext/dom/lexbor/lexbor/css/property/state.c
new file mode 100644
index 00000000000..198ef145615
--- /dev/null
+++ b/ext/dom/lexbor/lexbor/css/property/state.c
@@ -0,0 +1,5343 @@
+/*
+ * Copyright (C) 2021-2026 Alexander Borisov
+ *
+ * Author: Alexander Borisov <borisov@lexbor.com>
+ */
+
+#include "lexbor/css/property.h"
+#include "lexbor/css/parser.h"
+#include "lexbor/css/rule.h"
+#include "lexbor/css/value.h"
+#include "lexbor/css/unit.h"
+#include "lexbor/css/property/state.h"
+#include "lexbor/css/property/res.h"
+
+
+#ifndef LEXBOR_DISABLE_INTERNAL_EXTERN
+    LXB_EXTERN const lxb_char_t lexbor_str_res_map_hex[256];
+    LXB_EXTERN const lxb_char_t lexbor_str_res_map_lowercase[256];
+#endif
+
+#include "lexbor/core/conv.h"
+
+
+#define lxb_css_property_state_check_token(parser, token)                     \
+    if ((token) == NULL) {                                                    \
+        return lxb_css_parser_memory_fail(parser);                            \
+    }
+
+#define lxb_css_property_state_get_type(parser, token, type)                  \
+    do {                                                                      \
+        lxb_css_syntax_parser_consume(parser);                                \
+                                                                              \
+        token = lxb_css_syntax_parser_token_wo_ws(parser);                    \
+        lxb_css_property_state_check_token(parser, token);                    \
+                                                                              \
+        if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {                      \
+            return lxb_css_parser_success(parser);                            \
+        }                                                                     \
+                                                                              \
+        type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data, \
+                                  lxb_css_syntax_token_ident(token)->length); \
+    }                                                                         \
+    while (false)
+
+#define LXB_CSS_PROPERTY_STATE_HEX_MASK(n)                                    \
+    ((((uint32_t) 1 << (32 - (n))) - 1) << (n))
+
+
+static bool
+lxb_css_property_state_color_rgba_old(lxb_css_parser_t *parser,
+                                      const lxb_css_syntax_token_t *token,
+                                      lxb_css_value_color_t *color);
+static bool
+lxb_css_property_state_color_hsla_old(lxb_css_parser_t *parser,
+                                      const lxb_css_syntax_token_t *token,
+                                      lxb_css_value_color_hsla_t *hsl);
+
+static bool
+lxb_css_property_state_length(lxb_css_parser_t *parser,
+                              const lxb_css_syntax_token_t *token,
+                              lxb_css_value_length_t *length)
+{
+    const lxb_css_data_t *unit;
+
+    switch (token->type) {
+        case LXB_CSS_SYNTAX_TOKEN_DIMENSION:
+            unit = lxb_css_unit_absolute_relative_by_name(lxb_css_syntax_token_dimension(token)->str.data,
+                                                          lxb_css_syntax_token_dimension(token)->str.length);
+            if (unit == NULL) {
+                return false;
+            }
+
+            length->num = lxb_css_syntax_token_dimension(token)->num.num;
+            length->is_float = lxb_css_syntax_token_dimension(token)->num.is_float;
+            length->unit = (lxb_css_unit_t) unit->unique;
+            break;
+
+        case LXB_CSS_SYNTAX_TOKEN_NUMBER:
+            if (lxb_css_syntax_token_number(token)->num != 0) {
+                return false;
+            }
+
+            length->num = lxb_css_syntax_token_number(token)->num;
+            length->is_float = lxb_css_syntax_token_number(token)->is_float;
+            length->unit = LXB_CSS_UNIT__UNDEF;
+            break;
+
+        default:
+            return false;
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return true;
+}
+
+static bool
+lxb_css_property_state_length_percentage(lxb_css_parser_t *parser,
+                                         const lxb_css_syntax_token_t *token,
+                                         lxb_css_value_length_percentage_t *lp)
+{
+    const lxb_css_data_t *unit;
+
+    switch (token->type) {
+        case LXB_CSS_SYNTAX_TOKEN_DIMENSION:
+            unit = lxb_css_unit_absolute_relative_by_name(lxb_css_syntax_token_dimension(token)->str.data,
+                                                          lxb_css_syntax_token_dimension(token)->str.length);
+            if (unit == NULL) {
+                return false;
+            }
+
+            lp->type = LXB_CSS_VALUE__LENGTH;
+            lp->u.length.num = lxb_css_syntax_token_dimension(token)->num.num;
+            lp->u.length.is_float = lxb_css_syntax_token_dimension(token)->num.is_float;
+            lp->u.length.unit = (lxb_css_unit_t) unit->unique;
+            break;
+
+        case LXB_CSS_SYNTAX_TOKEN_NUMBER:
+            if (lxb_css_syntax_token_number(token)->num != 0) {
+                return false;
+            }
+
+            lp->type = LXB_CSS_VALUE__NUMBER;
+            lp->u.length.num = lxb_css_syntax_token_number(token)->num;
+            lp->u.length.is_float = lxb_css_syntax_token_number(token)->is_float;
+            lp->u.length.unit = LXB_CSS_UNIT__UNDEF;
+            break;
+
+        case LXB_CSS_SYNTAX_TOKEN_PERCENTAGE:
+            lp->type = LXB_CSS_VALUE__PERCENTAGE;
+            lp->u.percentage.num = lxb_css_syntax_token_percentage(token)->num;
+            lp->u.percentage.is_float = lxb_css_syntax_token_percentage(token)->is_float;
+            break;
+
+        default:
+            return false;
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return true;
+}
+
+static bool
+lxb_css_property_state_number_length_percentage(lxb_css_parser_t *parser,
+                                                const lxb_css_syntax_token_t *token,
+                                                lxb_css_value_number_length_percentage_t *nlp)
+{
+    const lxb_css_data_t *unit;
+
+    switch (token->type) {
+        case LXB_CSS_SYNTAX_TOKEN_DIMENSION:
+            unit = lxb_css_unit_absolute_relative_by_name(lxb_css_syntax_token_dimension(token)->str.data,
+                                                          lxb_css_syntax_token_dimension(token)->str.length);
+            if (unit == NULL) {
+                return false;
+            }
+
+            nlp->type = LXB_CSS_VALUE__LENGTH;
+            nlp->u.length.num = lxb_css_syntax_token_dimension(token)->num.num;
+            nlp->u.length.is_float = lxb_css_syntax_token_dimension(token)->num.is_float;
+            nlp->u.length.unit = (lxb_css_unit_t) unit->unique;
+            break;
+
+        case LXB_CSS_SYNTAX_TOKEN_NUMBER:
+            nlp->type = LXB_CSS_VALUE__NUMBER;
+            nlp->u.number.num = lxb_css_syntax_token_number(token)->num;
+            nlp->u.number.is_float = lxb_css_syntax_token_number(token)->is_float;
+            break;
+
+        case LXB_CSS_SYNTAX_TOKEN_PERCENTAGE:
+            nlp->type = LXB_CSS_VALUE__PERCENTAGE;
+            nlp->u.percentage.num = lxb_css_syntax_token_percentage(token)->num;
+            nlp->u.percentage.is_float = lxb_css_syntax_token_percentage(token)->is_float;
+            break;
+
+        default:
+            return false;
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return true;
+}
+
+static bool
+lxb_css_property_state_number_length(lxb_css_parser_t *parser,
+                                     const lxb_css_syntax_token_t *token,
+                                     lxb_css_value_number_length_t *nl)
+{
+    const lxb_css_data_t *unit;
+
+    switch (token->type) {
+        case LXB_CSS_SYNTAX_TOKEN_DIMENSION:
+            unit = lxb_css_unit_absolute_relative_by_name(lxb_css_syntax_token_dimension(token)->str.data,
+                                                          lxb_css_syntax_token_dimension(token)->str.length);
+            if (unit == NULL) {
+                return false;
+            }
+
+            nl->type = LXB_CSS_VALUE__LENGTH;
+            nl->u.length.num = lxb_css_syntax_token_dimension(token)->num.num;
+            nl->u.length.is_float = lxb_css_syntax_token_dimension(token)->num.is_float;
+            nl->u.length.unit = (lxb_css_unit_t) unit->unique;
+            break;
+
+        case LXB_CSS_SYNTAX_TOKEN_NUMBER:
+            nl->type = LXB_CSS_VALUE__NUMBER;
+            nl->u.number.num = lxb_css_syntax_token_number(token)->num;
+            nl->u.number.is_float = lxb_css_syntax_token_number(token)->is_float;
+            break;
+
+        default:
+            return false;
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return true;
+}
+
+static bool
+lxb_css_property_state_number(lxb_css_parser_t *parser,
+                              const lxb_css_syntax_token_t *token,
+                              lxb_css_value_number_t *number)
+{
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_NUMBER) {
+        return false;
+    }
+
+    number->num = lxb_css_syntax_token_number(token)->num;
+    number->is_float = lxb_css_syntax_token_number(token)->is_float;
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return true;
+}
+
+static bool
+lxb_css_property_state_integer(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token,
+                               lxb_css_value_integer_t *intg)
+{
+    long ln;
+    double num;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_NUMBER) {
+        return false;
+    }
+
+    num = lxb_css_syntax_token_number(token)->num;
+    ln = lexbor_conv_double_to_long(num);
+
+    num = num - (double) ln;
+
+    if (num < 0.0 || num > 0.0) {
+        return false;
+    }
+
+    intg->num = ln;
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return true;
+}
+
+static bool
+lxb_css_property_state_percentage(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token,
+                                  lxb_css_value_percentage_t *perc)
+{
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_PERCENTAGE) {
+        return false;
+    }
+
+    perc->num = lxb_css_syntax_token_percentage(token)->num;
+    perc->is_float = lxb_css_syntax_token_percentage(token)->is_float;
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return true;
+}
+
+static bool
+lxb_css_property_state_number_percentage_none(lxb_css_parser_t *parser,
+                                              const lxb_css_syntax_token_t *token,
+                                              lxb_css_value_number_percentage_t *np)
+{
+    double num;
+    lxb_css_value_type_t type;
+
+    if (token->type == LXB_CSS_SYNTAX_TOKEN_NUMBER) {
+        np->type = LXB_CSS_VALUE__NUMBER;
+    }
+    else if (token->type == LXB_CSS_SYNTAX_TOKEN_PERCENTAGE) {
+        np->type = LXB_CSS_VALUE__PERCENTAGE;
+    }
+    else if (token->type == LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                     lxb_css_syntax_token_ident(token)->length);
+        if (type != LXB_CSS_VALUE_NONE) {
+            return false;
+        }
+
+        np->type = LXB_CSS_VALUE_NONE;
+
+        lxb_css_syntax_parser_consume(parser);
+
+        return true;
+    }
+    else {
+        return false;
+    }
+
+    num = lxb_css_syntax_token_number(token)->num;
+
+    np->u.number.num = num;
+    np->u.number.is_float = lxb_css_syntax_token_number(token)->is_float;
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return true;
+}
+
+static bool
+lxb_css_property_state_percentage_none(lxb_css_parser_t *parser,
+                                       const lxb_css_syntax_token_t *token,
+                                       lxb_css_value_percentage_type_t *np)
+{
+    double num;
+    lxb_css_value_type_t type;
+
+    if (token->type == LXB_CSS_SYNTAX_TOKEN_PERCENTAGE) {
+        np->type = LXB_CSS_VALUE__PERCENTAGE;
+    }
+    else if (token->type == LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                     lxb_css_syntax_token_ident(token)->length);
+        if (type != LXB_CSS_VALUE_NONE) {
+            return false;
+        }
+
+        np->type = LXB_CSS_VALUE_NONE;
+
+        lxb_css_syntax_parser_consume(parser);
+
+        return true;
+    }
+    else {
+        return false;
+    }
+
+    num = lxb_css_syntax_token_number(token)->num;
+
+    np->percentage.num = num;
+    np->percentage.is_float = lxb_css_syntax_token_number(token)->is_float;
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return true;
+}
+
+static bool
+lxb_css_property_state_number_percentage(lxb_css_parser_t *parser,
+                                         const lxb_css_syntax_token_t *token,
+                                         lxb_css_value_number_percentage_t *np)
+{
+    double num;
+
+    if (token->type == LXB_CSS_SYNTAX_TOKEN_NUMBER) {
+        np->type = LXB_CSS_VALUE__NUMBER;
+    }
+    else if (token->type == LXB_CSS_SYNTAX_TOKEN_PERCENTAGE) {
+        np->type = LXB_CSS_VALUE__PERCENTAGE;
+    }
+    else {
+        return false;
+    }
+
+    num = lxb_css_syntax_token_number(token)->num;
+
+    np->u.number.num = num;
+    np->u.number.is_float = lxb_css_syntax_token_number(token)->is_float;
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return true;
+}
+
+static bool
+lxb_css_property_state_angle(lxb_css_parser_t *parser,
+                             const lxb_css_syntax_token_t *token,
+                             lxb_css_value_angle_t *angle)
+{
+    const lxb_css_data_t *unit;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_DIMENSION) {
+        return false;
+    }
+
+    unit = lxb_css_unit_angle_by_name(lxb_css_syntax_token_dimension(token)->str.data,
+                                      lxb_css_syntax_token_dimension(token)->str.length);
+    if (unit == NULL) {
+        return false;
+    }
+
+    angle->num = lxb_css_syntax_token_dimension(token)->num.num;
+    angle->is_float = lxb_css_syntax_token_dimension(token)->num.is_float;
+    angle->unit = (lxb_css_unit_angle_t) unit->unique;
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return true;
+}
+
+bool
+lxb_css_property_state_width_handler(lxb_css_parser_t *parser,
+                                     const lxb_css_syntax_token_t *token,
+                                     lxb_css_property_width_t *width)
+{
+    lxb_css_value_type_t type;
+
+    if (token->type == LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                     lxb_css_syntax_token_ident(token)->length);
+        switch (type) {
+            case LXB_CSS_VALUE_AUTO:
+            case LXB_CSS_VALUE_MIN_CONTENT:
+            case LXB_CSS_VALUE_MAX_CONTENT:
+                width->type = type;
+                break;
+
+            default:
+                return false;
+        }
+
+        lxb_css_syntax_parser_consume(parser);
+
+        return true;
+    }
+
+    return lxb_css_property_state_length_percentage(parser, token,
+                                   (lxb_css_value_length_percentage_t *)width);
+}
+
+static bool
+lxb_css_property_state_hue(lxb_css_parser_t *parser,
+                           const lxb_css_syntax_token_t *token,
+                           lxb_css_value_hue_t *hue)
+{
+    const lxb_css_data_t *unit;
+
+    switch (token->type) {
+        case LXB_CSS_SYNTAX_TOKEN_DIMENSION:
+            unit = lxb_css_unit_angle_by_name(lxb_css_syntax_token_dimension(token)->str.data,
+                                              lxb_css_syntax_token_dimension(token)->str.length);
+            if (unit == NULL) {
+                return false;
+            }
+
+            hue->type = LXB_CSS_VALUE__ANGLE;
+            hue->u.angle.num = lxb_css_syntax_token_dimension(token)->num.num;
+            hue->u.angle.is_float = lxb_css_syntax_token_dimension(token)->num.is_float;
+            hue->u.angle.unit = (lxb_css_unit_angle_t) unit->unique;
+            break;
+
+        case LXB_CSS_SYNTAX_TOKEN_NUMBER:
+            hue->type = LXB_CSS_VALUE__NUMBER;
+            hue->u.number.num = lxb_css_syntax_token_number(token)->num;
+            hue->u.number.is_float = lxb_css_syntax_token_number(token)->is_float;
+            break;
+
+        default:
+            return false;
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return true;
+}
+
+lxb_inline bool
+lxb_css_property_state_hue_none(lxb_css_parser_t *parser,
+                                const lxb_css_syntax_token_t *token,
+                                lxb_css_value_hue_t *hue)
+{
+    lxb_css_value_type_t type;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_property_state_hue(parser, token, hue);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    if (type != LXB_CSS_VALUE_NONE) {
+        return false;
+    }
+
+    hue->type = LXB_CSS_VALUE_NONE;
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return true;
+}
+
+static bool
+lxb_css_property_state_color_hex(lxb_css_parser_t *parser,
+                                 const lxb_css_syntax_token_t *token,
+                                 lxb_css_value_color_t *color)
+{
+    size_t length;
+    uint32_t chex;
+    lxb_char_t ch;
+    const lxb_char_t *end, *p;
+    lxb_css_value_color_hex_rgba_t *rgba;
+
+    length = token->types.hash.length;
+
+    if (length > 8) {
+        return false;
+    }
+
+    p = token->types.hash.data;
+    end = p + length;
+
+    chex = 0;
+
+    while (p < end) {
+        ch = lexbor_str_res_map_lowercase[lexbor_str_res_map_hex[*p]];
+
+        if (ch == 0xff) {
+            return false;
+        }
+
+        chex = chex << 4 | ch;
+
+        p++;
+    }
+
+    rgba = &color->u.hex.rgba;
+
+    switch (length) {
+        case 3:
+            rgba->r = chex >> 8;
+            rgba->g = chex >> 4 & ~LXB_CSS_PROPERTY_STATE_HEX_MASK(4);
+            rgba->b = chex & ~LXB_CSS_PROPERTY_STATE_HEX_MASK(4);
+            rgba->a = 0xff;
+
+            color->u.hex.type = LXB_CSS_PROPERTY_COLOR_HEX_TYPE_3;
+            break;
+
+        case 4:
+            rgba->r = chex >> 12;
+            rgba->g = chex >> 8 & ~LXB_CSS_PROPERTY_STATE_HEX_MASK(4);
+            rgba->b = chex >> 4 & ~LXB_CSS_PROPERTY_STATE_HEX_MASK(4);
+            rgba->a = chex & ~LXB_CSS_PROPERTY_STATE_HEX_MASK(4);
+
+            color->u.hex.type = LXB_CSS_PROPERTY_COLOR_HEX_TYPE_4;
+            break;
+
+        case 6:
+            rgba->r = chex >> 16;
+            rgba->g = chex >> 8 & ~LXB_CSS_PROPERTY_STATE_HEX_MASK(8);
+            rgba->b = chex & ~LXB_CSS_PROPERTY_STATE_HEX_MASK(8);
+            rgba->a = 0xff;
+
+            color->u.hex.type = LXB_CSS_PROPERTY_COLOR_HEX_TYPE_6;
+            break;
+
+        case 8:
+            rgba->r = chex >> 24;
+            rgba->g = chex >> 16 & ~LXB_CSS_PROPERTY_STATE_HEX_MASK(8);
+            rgba->b = chex >> 8 & ~LXB_CSS_PROPERTY_STATE_HEX_MASK(8);
+            rgba->a = chex & ~LXB_CSS_PROPERTY_STATE_HEX_MASK(8);
+
+            color->u.hex.type = LXB_CSS_PROPERTY_COLOR_HEX_TYPE_8;
+            break;
+
+        default:
+            return false;
+    }
+
+    color->type = LXB_CSS_COLOR_HEX;
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return true;
+}
+
+static bool
+lxb_css_property_state_color_rgba(lxb_css_parser_t *parser,
+                                  lxb_css_value_color_t *color)
+{
+    bool res;
+    lxb_css_color_type_t type;
+    lxb_css_value_color_rgba_t *rgb;
+    const lxb_css_syntax_token_t *token;
+
+    rgb = &color->u.rgb;
+
+    lxb_css_syntax_parser_consume(parser);
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    res = lxb_css_property_state_number_percentage_none(parser, token, &rgb->r);
+    if (res == false) {
+        return false;
+    }
+
+    type = rgb->r.type;
+
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    if (token->type == LXB_CSS_SYNTAX_TOKEN_COMMA) {
+        /* Deprecated format. */
+
+        if (type == LXB_CSS_VALUE_NONE) {
+            return false;
+        }
+
+        lxb_css_syntax_parser_consume(parser);
+        token = lxb_css_syntax_parser_token_wo_ws(parser);
+        lxb_css_property_state_check_token(parser, token);
+
+        rgb->old = true;
+
+        return lxb_css_property_state_color_rgba_old(parser, token, color);
+    }
+
+    res = lxb_css_property_state_number_percentage_none(parser, token, &rgb->g);
+    if (res == false) {
+        return false;
+    }
+
+    if (type != rgb->g.type) {
+        if (type == LXB_CSS_VALUE_NONE) {
+            type = rgb->g.type;
+        }
+        else if (rgb->g.type != LXB_CSS_VALUE_NONE) {
+            return false;
+        }
+    }
+
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    res = lxb_css_property_state_number_percentage_none(parser, token, &rgb->b);
+    if (res == false) {
+        return false;
+    }
+
+    if (type != rgb->b.type && type != LXB_CSS_VALUE_NONE
+        && rgb->b.type != LXB_CSS_VALUE_NONE)
+    {
+            return false;
+    }
+
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    if (token->type == LXB_CSS_SYNTAX_TOKEN_DELIM) {
+        if (lxb_css_syntax_token_delim(token)->character != '/') {
+            return false;
+        }
+
+        lxb_css_syntax_parser_consume(parser);
+        token = lxb_css_syntax_parser_token_wo_ws(parser);
+        lxb_css_property_state_check_token(parser, token);
+    }
+    else if (token->type == LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS) {
+        lxb_css_syntax_parser_consume(parser);
+        return true;
+    }
+    else {
+        return false;
+    }
+
+    res = lxb_css_property_state_number_percentage_none(parser, token, &rgb->a);
+    if (res == false) {
+        return false;
+    }
+
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS) {
+        return false;
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return true;
+}
+
+static bool
+lxb_css_property_state_color_rgba_old(lxb_css_parser_t *parser,
+                                      const lxb_css_syntax_token_t *token,
+                                      lxb_css_value_color_t *color)
+{
+    bool res;
+    lxb_css_value_color_rgba_t *rgb;
+
+    rgb = &color->u.rgb;
+
+    res = lxb_css_property_state_number_percentage(parser, token, &rgb->g);
+    if (res == false) {
+        return false;
+    }
+
+    if (rgb->r.type != rgb->g.type) {
+        return false;
+    }
+
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_COMMA) {
+        return false;
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    res = lxb_css_property_state_number_percentage(parser, token, &rgb->b);
+    if (res == false) {
+        return false;
+    }
+
+    if (rgb->r.type != rgb->b.type) {
+        return false;
+    }
+
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    if (token->type == LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS) {
+        lxb_css_syntax_parser_consume(parser);
+        return true;
+    }
+    else if (token->type != LXB_CSS_SYNTAX_TOKEN_COMMA) {
+        return false;
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    res = lxb_css_property_state_number_percentage(parser, token, &rgb->a);
+    if (res == false) {
+        return false;
+    }
+
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS) {
+        return false;
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return true;
+}
+
+static bool
+lxb_css_property_state_color_hsla(lxb_css_parser_t *parser,
+                                  lxb_css_value_color_t *color)
+{
+    bool res;
+    lxb_css_value_color_hsla_t *hsl;
+    const lxb_css_syntax_token_t *token;
+
+    lxb_css_syntax_parser_consume(parser);
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    hsl = &color->u.hsl;
+
+    res = lxb_css_property_state_hue_none(parser, token, &hsl->h);
+    if (res == false) {
+        return false;
+    }
+
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    if (token->type == LXB_CSS_SYNTAX_TOKEN_COMMA) {
+        /* Deprecated format. */
+
+        if (hsl->h.type == LXB_CSS_VALUE_NONE) {
+            return false;
+        }
+
+        lxb_css_syntax_parser_consume(parser);
+        token = lxb_css_syntax_parser_token_wo_ws(parser);
+        lxb_css_property_state_check_token(parser, token);
+
+        hsl->old = true;
+
+        return lxb_css_property_state_color_hsla_old(parser, token, hsl);
+    }
+
+    res = lxb_css_property_state_percentage_none(parser, token, &hsl->s);
+    if (res == false) {
+        return false;
+    }
+
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    res = lxb_css_property_state_percentage_none(parser, token, &hsl->l);
+    if (res == false) {
+        return false;
+    }
+
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    if (token->type == LXB_CSS_SYNTAX_TOKEN_DELIM) {
+        if (lxb_css_syntax_token_delim(token)->character != '/') {
+            return false;
+        }
+
+        lxb_css_syntax_parser_consume(parser);
+        token = lxb_css_syntax_parser_token_wo_ws(parser);
+        lxb_css_property_state_check_token(parser, token);
+    }
+    else if (token->type == LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS) {
+        lxb_css_syntax_parser_consume(parser);
+        return true;
+    }
+
+    res = lxb_css_property_state_number_percentage_none(parser, token, &hsl->a);
+    if (res == false) {
+        return false;
+    }
+
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS) {
+        return false;
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return true;
+}
+
+static bool
+lxb_css_property_state_color_hsla_old(lxb_css_parser_t *parser,
+                                      const lxb_css_syntax_token_t *token,
+                                      lxb_css_value_color_hsla_t *hsl)
+{
+    bool res;
+
+    res = lxb_css_property_state_percentage(parser, token, &hsl->s.percentage);
+    if (res == false) {
+        return false;
+    }
+
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_COMMA) {
+        return false;
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    res = lxb_css_property_state_percentage(parser, token, &hsl->l.percentage);
+    if (res == false) {
+        return false;
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    if (token->type == LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS) {
+        goto done;
+    }
+    else if (token->type != LXB_CSS_SYNTAX_TOKEN_COMMA) {
+        return false;
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    res = lxb_css_property_state_number_percentage(parser, token, &hsl->a);
+    if (res == false) {
+        return false;
+    }
+
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS) {
+        return false;
+    }
+
+done:
+
+    lxb_css_syntax_parser_consume(parser);
+
+    hsl->s.type = LXB_CSS_VALUE__PERCENTAGE;
+    hsl->l.type = LXB_CSS_VALUE__PERCENTAGE;
+
+    return true;
+}
+
+static bool
+lxb_css_property_state_color_lab(lxb_css_parser_t *parser,
+                                 lxb_css_value_color_t *color)
+{
+    bool res;
+    lxb_css_value_color_lab_t *lab;
+    const lxb_css_syntax_token_t *token;
+
+    lab = &color->u.lab;
+
+    lxb_css_syntax_parser_consume(parser);
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    res = lxb_css_property_state_number_percentage_none(parser, token, &lab->l);
+    if (res == false) {
+        return false;
+    }
+
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    res = lxb_css_property_state_number_percentage_none(parser, token, &lab->a);
+    if (res == false) {
+        return false;
+    }
+
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    res = lxb_css_property_state_number_percentage_none(parser, token, &lab->b);
+    if (res == false) {
+        return false;
+    }
+
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    if (token->type == LXB_CSS_SYNTAX_TOKEN_DELIM) {
+        if (lxb_css_syntax_token_delim(token)->character != '/') {
+            return false;
+        }
+
+        lxb_css_syntax_parser_consume(parser);
+        token = lxb_css_syntax_parser_token_wo_ws(parser);
+        lxb_css_property_state_check_token(parser, token);
+    }
+    else if (token->type == LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS) {
+        lxb_css_syntax_parser_consume(parser);
+        return true;
+    }
+    else {
+        return false;
+    }
+
+    res = lxb_css_property_state_number_percentage_none(parser, token,
+                                                        &lab->alpha);
+    if (res == false) {
+        return false;
+    }
+
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS) {
+        return false;
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return true;
+}
+
+static bool
+lxb_css_property_state_color_lch(lxb_css_parser_t *parser,
+                                 lxb_css_value_color_t *color)
+{
+    bool res;
+    lxb_css_value_color_lch_t *lch;
+    const lxb_css_syntax_token_t *token;
+
+    lch = &color->u.lch;
+
+    lxb_css_syntax_parser_consume(parser);
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    res = lxb_css_property_state_number_percentage_none(parser, token, &lch->l);
+    if (res == false) {
+        return false;
+    }
+
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    res = lxb_css_property_state_number_percentage_none(parser, token, &lch->c);
+    if (res == false) {
+        return false;
+    }
+
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    res = lxb_css_property_state_hue_none(parser, token, &lch->h);
+    if (res == false) {
+        return false;
+    }
+
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    if (token->type == LXB_CSS_SYNTAX_TOKEN_DELIM) {
+        if (lxb_css_syntax_token_delim(token)->character != '/') {
+            return false;
+        }
+
+        lxb_css_syntax_parser_consume(parser);
+        token = lxb_css_syntax_parser_token_wo_ws(parser);
+        lxb_css_property_state_check_token(parser, token);
+    }
+    else if (token->type == LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS) {
+        lxb_css_syntax_parser_consume(parser);
+        return true;
+    }
+    else {
+        return false;
+    }
+
+    res = lxb_css_property_state_number_percentage_none(parser, token, &lch->a);
+    if (res == false) {
+        return false;
+    }
+
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS) {
+        return false;
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return true;
+}
+
+/*
+ * Return:
+ *     true  and status always LXB_STATUS_OK — token consumed, ok.
+ *     false and status != LXB_STATUS_OK     — token consumed, not ok.
+ *     false and status == LXB_STATUS_OK     — token not consumed, not ok.
+ */
+static bool
+lxb_css_property_state_color_handler(lxb_css_parser_t *parser,
+                                     const lxb_css_syntax_token_t *token,
+                                     lxb_css_value_color_t *color,
+                                     lxb_status_t *status)
+{
+    bool res;
+    lxb_css_value_type_t type;
+
+    *status = LXB_STATUS_OK;
+
+    switch (token->type) {
+        case LXB_CSS_SYNTAX_TOKEN_HASH:
+            color->type = LXB_CSS_VALUE_HEX;
+
+            return lxb_css_property_state_color_hex(parser, token, color);
+
+        case LXB_CSS_SYNTAX_TOKEN_FUNCTION:
+            type = lxb_css_value_by_name(lxb_css_syntax_token_function(token)->data,
+                                         lxb_css_syntax_token_function(token)->length);
+            color->type = type;
+
+            switch (type) {
+                /* <color> */
+                case LXB_CSS_VALUE_RGB:
+                case LXB_CSS_VALUE_RGBA:
+                    res = lxb_css_property_state_color_rgba(parser, color);
+                    break;
+
+                case LXB_CSS_VALUE_HSL:
+                case LXB_CSS_VALUE_HSLA:
+                case LXB_CSS_VALUE_HWB:
+                    res = lxb_css_property_state_color_hsla(parser, color);
+                    break;
+
+                case LXB_CSS_VALUE_LAB:
+                case LXB_CSS_VALUE_OKLAB:
+                    res = lxb_css_property_state_color_lab(parser, color);
+                    break;
+
+                case LXB_CSS_VALUE_LCH:
+                case LXB_CSS_VALUE_OKLCH:
+                    res = lxb_css_property_state_color_lch(parser, color);
+                    break;
+
+                case LXB_CSS_VALUE_COLOR:
+                default:
+                    *status = LXB_STATUS_OK;
+                    return false;
+            }
+
+            if (!res) {
+                *status = LXB_STATUS_ERROR_UNEXPECTED_DATA;
+            }
+
+            return res;
+
+        case LXB_CSS_SYNTAX_TOKEN_IDENT:
+            type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                         lxb_css_syntax_token_ident(token)->length);
+            switch (type) {
+                /* <color> */
+                case LXB_CSS_VALUE_CURRENTCOLOR:
+                /* <system-color> */
+                case LXB_CSS_VALUE_CANVAS:
+                case LXB_CSS_VALUE_CANVASTEXT:
+                case LXB_CSS_VALUE_LINKTEXT:
+                case LXB_CSS_VALUE_VISITEDTEXT:
+                case LXB_CSS_VALUE_ACTIVETEXT:
+                case LXB_CSS_VALUE_BUTTONFACE:
+                case LXB_CSS_VALUE_BUTTONTEXT:
+                case LXB_CSS_VALUE_BUTTONBORDER:
+                case LXB_CSS_VALUE_FIELD:
+                case LXB_CSS_VALUE_FIELDTEXT:
+                case LXB_CSS_VALUE_HIGHLIGHT:
+                case LXB_CSS_VALUE_HIGHLIGHTTEXT:
+                case LXB_CSS_VALUE_SELECTEDITEM:
+                case LXB_CSS_VALUE_SELECTEDITEMTEXT:
+                case LXB_CSS_VALUE_MARK:
+                case LXB_CSS_VALUE_MARKTEXT:
+                case LXB_CSS_VALUE_GRAYTEXT:
+                case LXB_CSS_VALUE_ACCENTCOLOR:
+                case LXB_CSS_VALUE_ACCENTCOLORTEXT:
+                /* <absolute-color-base> */
+                case LXB_CSS_VALUE_TRANSPARENT:
+                /* <named-color> */
+                case LXB_CSS_VALUE_ALICEBLUE:
+                case LXB_CSS_VALUE_ANTIQUEWHITE:
+                case LXB_CSS_VALUE_AQUA:
+                case LXB_CSS_VALUE_AQUAMARINE:
+                case LXB_CSS_VALUE_AZURE:
+                case LXB_CSS_VALUE_BEIGE:
+                case LXB_CSS_VALUE_BISQUE:
+                case LXB_CSS_VALUE_BLACK:
+                case LXB_CSS_VALUE_BLANCHEDALMOND:
+                case LXB_CSS_VALUE_BLUE:
+                case LXB_CSS_VALUE_BLUEVIOLET:
+                case LXB_CSS_VALUE_BROWN:
+                case LXB_CSS_VALUE_BURLYWOOD:
+                case LXB_CSS_VALUE_CADETBLUE:
+                case LXB_CSS_VALUE_CHARTREUSE:
+                case LXB_CSS_VALUE_CHOCOLATE:
+                case LXB_CSS_VALUE_CORAL:
+                case LXB_CSS_VALUE_CORNFLOWERBLUE:
+                case LXB_CSS_VALUE_CORNSILK:
+                case LXB_CSS_VALUE_CRIMSON:
+                case LXB_CSS_VALUE_CYAN:
+                case LXB_CSS_VALUE_DARKBLUE:
+                case LXB_CSS_VALUE_DARKCYAN:
+                case LXB_CSS_VALUE_DARKGOLDENROD:
+                case LXB_CSS_VALUE_DARKGRAY:
+                case LXB_CSS_VALUE_DARKGREEN:
+                case LXB_CSS_VALUE_DARKGREY:
+                case LXB_CSS_VALUE_DARKKHAKI:
+                case LXB_CSS_VALUE_DARKMAGENTA:
+                case LXB_CSS_VALUE_DARKOLIVEGREEN:
+                case LXB_CSS_VALUE_DARKORANGE:
+                case LXB_CSS_VALUE_DARKORCHID:
+                case LXB_CSS_VALUE_DARKRED:
+                case LXB_CSS_VALUE_DARKSALMON:
+                case LXB_CSS_VALUE_DARKSEAGREEN:
+                case LXB_CSS_VALUE_DARKSLATEBLUE:
+                case LXB_CSS_VALUE_DARKSLATEGRAY:
+                case LXB_CSS_VALUE_DARKSLATEGREY:
+                case LXB_CSS_VALUE_DARKTURQUOISE:
+                case LXB_CSS_VALUE_DARKVIOLET:
+                case LXB_CSS_VALUE_DEEPPINK:
+                case LXB_CSS_VALUE_DEEPSKYBLUE:
+                case LXB_CSS_VALUE_DIMGRAY:
+                case LXB_CSS_VALUE_DIMGREY:
+                case LXB_CSS_VALUE_DODGERBLUE:
+                case LXB_CSS_VALUE_FIREBRICK:
+                case LXB_CSS_VALUE_FLORALWHITE:
+                case LXB_CSS_VALUE_FORESTGREEN:
+                case LXB_CSS_VALUE_FUCHSIA:
+                case LXB_CSS_VALUE_GAINSBORO:
+                case LXB_CSS_VALUE_GHOSTWHITE:
+                case LXB_CSS_VALUE_GOLD:
+                case LXB_CSS_VALUE_GOLDENROD:
+                case LXB_CSS_VALUE_GRAY:
+                case LXB_CSS_VALUE_GREEN:
+                case LXB_CSS_VALUE_GREENYELLOW:
+                case LXB_CSS_VALUE_GREY:
+                case LXB_CSS_VALUE_HONEYDEW:
+                case LXB_CSS_VALUE_HOTPINK:
+                case LXB_CSS_VALUE_INDIANRED:
+                case LXB_CSS_VALUE_INDIGO:
+                case LXB_CSS_VALUE_IVORY:
+                case LXB_CSS_VALUE_KHAKI:
+                case LXB_CSS_VALUE_LAVENDER:
+                case LXB_CSS_VALUE_LAVENDERBLUSH:
+                case LXB_CSS_VALUE_LAWNGREEN:
+                case LXB_CSS_VALUE_LEMONCHIFFON:
+                case LXB_CSS_VALUE_LIGHTBLUE:
+                case LXB_CSS_VALUE_LIGHTCORAL:
+                case LXB_CSS_VALUE_LIGHTCYAN:
+                case LXB_CSS_VALUE_LIGHTGOLDENRODYELLOW:
+                case LXB_CSS_VALUE_LIGHTGRAY:
+                case LXB_CSS_VALUE_LIGHTGREEN:
+                case LXB_CSS_VALUE_LIGHTGREY:
+                case LXB_CSS_VALUE_LIGHTPINK:
+                case LXB_CSS_VALUE_LIGHTSALMON:
+                case LXB_CSS_VALUE_LIGHTSEAGREEN:
+                case LXB_CSS_VALUE_LIGHTSKYBLUE:
+                case LXB_CSS_VALUE_LIGHTSLATEGRAY:
+                case LXB_CSS_VALUE_LIGHTSLATEGREY:
+                case LXB_CSS_VALUE_LIGHTSTEELBLUE:
+                case LXB_CSS_VALUE_LIGHTYELLOW:
+                case LXB_CSS_VALUE_LIME:
+                case LXB_CSS_VALUE_LIMEGREEN:
+                case LXB_CSS_VALUE_LINEN:
+                case LXB_CSS_VALUE_MAGENTA:
+                case LXB_CSS_VALUE_MAROON:
+                case LXB_CSS_VALUE_MEDIUMAQUAMARINE:
+                case LXB_CSS_VALUE_MEDIUMBLUE:
+                case LXB_CSS_VALUE_MEDIUMORCHID:
+                case LXB_CSS_VALUE_MEDIUMPURPLE:
+                case LXB_CSS_VALUE_MEDIUMSEAGREEN:
+                case LXB_CSS_VALUE_MEDIUMSLATEBLUE:
+                case LXB_CSS_VALUE_MEDIUMSPRINGGREEN:
+                case LXB_CSS_VALUE_MEDIUMTURQUOISE:
+                case LXB_CSS_VALUE_MEDIUMVIOLETRED:
+                case LXB_CSS_VALUE_MIDNIGHTBLUE:
+                case LXB_CSS_VALUE_MINTCREAM:
+                case LXB_CSS_VALUE_MISTYROSE:
+                case LXB_CSS_VALUE_MOCCASIN:
+                case LXB_CSS_VALUE_NAVAJOWHITE:
+                case LXB_CSS_VALUE_NAVY:
+                case LXB_CSS_VALUE_OLDLACE:
+                case LXB_CSS_VALUE_OLIVE:
+                case LXB_CSS_VALUE_OLIVEDRAB:
+                case LXB_CSS_VALUE_ORANGE:
+                case LXB_CSS_VALUE_ORANGERED:
+                case LXB_CSS_VALUE_ORCHID:
+                case LXB_CSS_VALUE_PALEGOLDENROD:
+                case LXB_CSS_VALUE_PALEGREEN:
+                case LXB_CSS_VALUE_PALETURQUOISE:
+                case LXB_CSS_VALUE_PALEVIOLETRED:
+                case LXB_CSS_VALUE_PAPAYAWHIP:
+                case LXB_CSS_VALUE_PEACHPUFF:
+                case LXB_CSS_VALUE_PERU:
+                case LXB_CSS_VALUE_PINK:
+                case LXB_CSS_VALUE_PLUM:
+                case LXB_CSS_VALUE_POWDERBLUE:
+                case LXB_CSS_VALUE_PURPLE:
+                case LXB_CSS_VALUE_REBECCAPURPLE:
+                case LXB_CSS_VALUE_RED:
+                case LXB_CSS_VALUE_ROSYBROWN:
+                case LXB_CSS_VALUE_ROYALBLUE:
+                case LXB_CSS_VALUE_SADDLEBROWN:
+                case LXB_CSS_VALUE_SALMON:
+                case LXB_CSS_VALUE_SANDYBROWN:
+                case LXB_CSS_VALUE_SEAGREEN:
+                case LXB_CSS_VALUE_SEASHELL:
+                case LXB_CSS_VALUE_SIENNA:
+                case LXB_CSS_VALUE_SILVER:
+                case LXB_CSS_VALUE_SKYBLUE:
+                case LXB_CSS_VALUE_SLATEBLUE:
+                case LXB_CSS_VALUE_SLATEGRAY:
+                case LXB_CSS_VALUE_SLATEGREY:
+                case LXB_CSS_VALUE_SNOW:
+                case LXB_CSS_VALUE_SPRINGGREEN:
+                case LXB_CSS_VALUE_STEELBLUE:
+                case LXB_CSS_VALUE_TAN:
+                case LXB_CSS_VALUE_TEAL:
+                case LXB_CSS_VALUE_THISTLE:
+                case LXB_CSS_VALUE_TOMATO:
+                case LXB_CSS_VALUE_TURQUOISE:
+                case LXB_CSS_VALUE_VIOLET:
+                case LXB_CSS_VALUE_WHEAT:
+                case LXB_CSS_VALUE_WHITE:
+                case LXB_CSS_VALUE_WHITESMOKE:
+                case LXB_CSS_VALUE_YELLOW:
+                case LXB_CSS_VALUE_YELLOWGREEN:
+                    color->type = type;
+                    break;
+
+                default:
+                    return false;
+            }
+
+            break;
+
+        default:
+            return false;
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return true;
+}
+
+bool
+lxb_css_property_state__undef(lxb_css_parser_t *parser,
+                              const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_parser_failed(parser);
+}
+
+bool
+lxb_css_property_state__custom(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_status_t status;
+    lxb_css_rule_declaration_t *declar = ctx;
+    lxb_css_property__custom_t *custom = declar->u.custom;
+
+    (void) lexbor_str_init(&custom->value, parser->memory->mraw, 0);
+    if (custom->value.data == NULL) {
+        return lxb_css_parser_memory_fail(parser);
+    }
+
+    while (token != NULL && token->type != LXB_CSS_SYNTAX_TOKEN__END) {
+        status = lxb_css_syntax_token_serialize_str(token, &custom->value,
+                                                    parser->memory->mraw);
+        if (status != LXB_STATUS_OK) {
+            return lxb_css_parser_memory_fail(parser);
+        }
+
+        lxb_css_syntax_parser_consume(parser);
+        token = lxb_css_syntax_parser_token(parser);
+    }
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_display(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_property_display_t *display;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    display = declar->u.display;
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+
+    switch (type) {
+        /* <display-outside> */
+        case LXB_CSS_DISPLAY_BLOCK:
+        case LXB_CSS_DISPLAY_INLINE:
+        case LXB_CSS_DISPLAY_RUN_IN:
+            display->a = type;
+            goto inside_listitem;
+
+        /* <display-inside> */
+        case LXB_CSS_DISPLAY_FLOW:
+        case LXB_CSS_DISPLAY_FLOW_ROOT:
+            display->a = type;
+            goto outside_listitem;
+
+        case LXB_CSS_DISPLAY_TABLE:
+        case LXB_CSS_DISPLAY_FLEX:
+        case LXB_CSS_DISPLAY_GRID:
+        case LXB_CSS_DISPLAY_RUBY:
+            display->a = type;
+            goto outside;
+
+        /* <display-internal> */
+        case LXB_CSS_DISPLAY_LIST_ITEM:
+            display->a = type;
+            goto listitem_only;
+
+        /* <display-internal> */
+        case LXB_CSS_DISPLAY_TABLE_ROW_GROUP:
+        case LXB_CSS_DISPLAY_TABLE_HEADER_GROUP:
+        case LXB_CSS_DISPLAY_TABLE_FOOTER_GROUP:
+        case LXB_CSS_DISPLAY_TABLE_ROW:
+        case LXB_CSS_DISPLAY_TABLE_CELL:
+        case LXB_CSS_DISPLAY_TABLE_COLUMN_GROUP:
+        case LXB_CSS_DISPLAY_TABLE_COLUMN:
+        case LXB_CSS_DISPLAY_TABLE_CAPTION:
+        case LXB_CSS_DISPLAY_RUBY_BASE:
+        case LXB_CSS_DISPLAY_RUBY_TEXT:
+        case LXB_CSS_DISPLAY_RUBY_BASE_CONTAINER:
+        case LXB_CSS_DISPLAY_RUBY_TEXT_CONTAINER:
+        /* <display-box> */
+        case LXB_CSS_DISPLAY_CONTENTS:
+        case LXB_CSS_DISPLAY_NONE:
+        /* <display-legacy> */
+        case LXB_CSS_DISPLAY_INLINE_BLOCK:
+        case LXB_CSS_DISPLAY_INLINE_TABLE:
+        case LXB_CSS_DISPLAY_INLINE_FLEX:
+        case LXB_CSS_DISPLAY_INLINE_GRID:
+            display->a = type;
+            goto done;
+
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+            display->a = type;
+            goto done;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+inside_listitem:
+
+    lxb_css_property_state_get_type(parser, token, type);
+
+    switch (type) {
+        /* <display-inside> */
+        case LXB_CSS_DISPLAY_FLOW:
+        case LXB_CSS_DISPLAY_FLOW_ROOT:
+            display->b = type;
+            break;
+
+        case LXB_CSS_DISPLAY_TABLE:
+        case LXB_CSS_DISPLAY_FLEX:
+        case LXB_CSS_DISPLAY_GRID:
+        case LXB_CSS_DISPLAY_RUBY:
+            display->b = type;
+            goto done;
+
+        case LXB_CSS_DISPLAY_LIST_ITEM:
+            display->b = type;
+            goto flow_only;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+listitem:
+
+    lxb_css_property_state_get_type(parser, token, type);
+
+    if (type == LXB_CSS_DISPLAY_LIST_ITEM) {
+        display->c = type;
+        goto done;
+    }
+
+    return lxb_css_parser_failed(parser);
+
+outside:
+
+    lxb_css_property_state_get_type(parser, token, type);
+
+    switch (type) {
+        /* <display-outside> */
+        case LXB_CSS_DISPLAY_BLOCK:
+        case LXB_CSS_DISPLAY_INLINE:
+        case LXB_CSS_DISPLAY_RUN_IN:
+            if (display->b == LXB_CSS_PROPERTY__UNDEF) {
+                display->b = type;
+            }
+            else {
+                display->c = type;
+            }
+
+            goto done;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+outside_listitem:
+
+    lxb_css_property_state_get_type(parser, token, type);
+
+    switch (type) {
+        /* <display-outside> */
+        case LXB_CSS_DISPLAY_BLOCK:
+        case LXB_CSS_DISPLAY_INLINE:
+        case LXB_CSS_DISPLAY_RUN_IN:
+            display->b = type;
+            goto listitem;
+
+        case LXB_CSS_DISPLAY_LIST_ITEM:
+            display->b = type;
+            goto outside;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+listitem_only:
+
+    lxb_css_property_state_get_type(parser, token, type);
+
+    switch (type) {
+        /* <display-outside> */
+        case LXB_CSS_DISPLAY_BLOCK:
+        case LXB_CSS_DISPLAY_INLINE:
+        case LXB_CSS_DISPLAY_RUN_IN:
+            display->b = type;
+            break;
+
+        /* <display-listitem> */
+        case LXB_CSS_DISPLAY_FLOW:
+        case LXB_CSS_DISPLAY_FLOW_ROOT:
+            display->b = type;
+            goto outside;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+flow_only:
+
+    lxb_css_property_state_get_type(parser, token, type);
+
+    switch (type) {
+        /* <display-listitem> */
+        case LXB_CSS_DISPLAY_FLOW:
+        case LXB_CSS_DISPLAY_FLOW_ROOT:
+            display->c = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+done:
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_order(lxb_css_parser_t *parser,
+                             const lxb_css_syntax_token_t *token, void *ctx)
+{
+    bool res;
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    res = lxb_css_property_state_integer(parser, token,
+                                         &declar->u.order->integer);
+    if (res) {
+        declar->u.order->type = LXB_CSS_ORDER__INTEGER;
+
+        return lxb_css_parser_success(parser);
+    }
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+            declar->u.order->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_visibility(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_VISIBILITY_VISIBLE:
+        case LXB_CSS_VISIBILITY_HIDDEN:
+        case LXB_CSS_VISIBILITY_COLLAPSE:
+            declar->u.visibility->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_width(lxb_css_parser_t *parser,
+                             const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type == LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                     lxb_css_syntax_token_ident(token)->length);
+        switch (type) {
+            case LXB_CSS_VALUE_INITIAL:
+            case LXB_CSS_VALUE_INHERIT:
+            case LXB_CSS_VALUE_UNSET:
+            case LXB_CSS_VALUE_REVERT:
+            case LXB_CSS_VALUE_AUTO:
+            case LXB_CSS_VALUE_MIN_CONTENT:
+            case LXB_CSS_VALUE_MAX_CONTENT:
+                declar->u.width->type = type;
+                break;
+
+            default:
+                return lxb_css_parser_failed(parser);
+        }
+
+        lxb_css_syntax_parser_consume(parser);
+
+        return lxb_css_parser_success(parser);
+    }
+
+    if (!lxb_css_property_state_length_percentage(parser, token,
+                                                  declar->u.user))
+    {
+        return lxb_css_parser_failed(parser);
+    }
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_height(lxb_css_parser_t *parser,
+                              const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_width(parser, token, ctx);
+}
+
+bool
+lxb_css_property_state_box_sizing(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        case LXB_CSS_VALUE_CONTENT_BOX:
+        case LXB_CSS_VALUE_BORDER_BOX:
+            declar->u.box_sizing->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_min_width(lxb_css_parser_t *parser,
+                                 const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_width(parser, token, ctx);
+}
+
+bool
+lxb_css_property_state_min_height(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_width(parser, token, ctx);
+}
+
+bool
+lxb_css_property_state_max_width(lxb_css_parser_t *parser,
+                                 const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type == LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                     lxb_css_syntax_token_ident(token)->length);
+        switch (type) {
+            case LXB_CSS_VALUE_INITIAL:
+            case LXB_CSS_VALUE_INHERIT:
+            case LXB_CSS_VALUE_UNSET:
+            case LXB_CSS_VALUE_REVERT:
+            case LXB_CSS_VALUE_NONE:
+            case LXB_CSS_VALUE_MIN_CONTENT:
+            case LXB_CSS_VALUE_MAX_CONTENT:
+                declar->u.width->type = type;
+                break;
+
+            default:
+                return lxb_css_parser_failed(parser);
+        }
+
+        lxb_css_syntax_parser_consume(parser);
+
+        return lxb_css_parser_success(parser);
+    }
+
+    if (!lxb_css_property_state_length_percentage(parser, token,
+                                                  declar->u.user))
+    {
+        return lxb_css_parser_failed(parser);
+    }
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_max_height(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_max_width(parser, token, ctx);
+}
+
+static bool
+lxb_css_property_state_mp(lxb_css_parser_t *parser,
+                          const lxb_css_syntax_token_t *token,
+                          lxb_css_rule_declaration_t *declar, bool with_auto)
+{
+    unsigned int state;
+    lxb_css_value_type_t type;
+    lxb_css_property_margin_top_t *top;
+
+    state = 1;
+
+next:
+
+    switch (state) {
+        case 1:
+            top = &declar->u.margin->top;
+            break;
+
+        case 2:
+            top = &declar->u.margin->right;
+            break;
+
+        case 3:
+            top = &declar->u.margin->bottom;
+            break;
+
+        case 4:
+            top = &declar->u.margin->left;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    if (token->type == LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                     lxb_css_syntax_token_ident(token)->length);
+        switch (type) {
+            case LXB_CSS_VALUE_INITIAL:
+            case LXB_CSS_VALUE_INHERIT:
+            case LXB_CSS_VALUE_UNSET:
+            case LXB_CSS_VALUE_REVERT:
+                top->type = type;
+                break;
+
+            case LXB_CSS_VALUE_AUTO:
+                if (with_auto) {
+                    top->type = type;
+                    break;
+                }
+
+                /* Fall through. */
+
+            default:
+                return lxb_css_parser_failed(parser);
+        }
+
+        lxb_css_syntax_parser_consume(parser);
+    }
+    else if (!lxb_css_property_state_length_percentage(parser, token,
+                                    (lxb_css_value_length_percentage_t *) top))
+    {
+        return lxb_css_parser_failed(parser);
+    }
+
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    if (token->type == LXB_CSS_SYNTAX_TOKEN__END) {
+        return lxb_css_parser_success(parser);
+    }
+
+    state++;
+
+    goto next;
+}
+
+static bool
+lxb_css_property_state_mp_top(lxb_css_parser_t *parser,
+                              const lxb_css_syntax_token_t *token,
+                              lxb_css_rule_declaration_t *declar, bool with_auto)
+{
+    lxb_css_value_type_t type;
+
+    if (token->type == LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                     lxb_css_syntax_token_ident(token)->length);
+        switch (type) {
+            case LXB_CSS_VALUE_INITIAL:
+            case LXB_CSS_VALUE_INHERIT:
+            case LXB_CSS_VALUE_UNSET:
+            case LXB_CSS_VALUE_REVERT:
+                declar->u.margin_top->type = type;
+                break;
+
+            case LXB_CSS_VALUE_AUTO:
+                if (with_auto) {
+                    declar->u.margin_top->type = type;
+                    break;
+                }
+
+                /* Fall through. */
+
+            default:
+                return lxb_css_parser_failed(parser);
+        }
+
+        lxb_css_syntax_parser_consume(parser);
+
+        return lxb_css_parser_success(parser);
+    }
+
+    if (!lxb_css_property_state_length_percentage(parser, token,
+                                                  declar->u.user))
+    {
+        return lxb_css_parser_failed(parser);
+    }
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_margin(lxb_css_parser_t *parser,
+                              const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_mp(parser, token, ctx, true);
+}
+
+bool
+lxb_css_property_state_margin_top(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_mp_top(parser, token, ctx, true);
+}
+
+bool
+lxb_css_property_state_margin_right(lxb_css_parser_t *parser,
+                                    const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_mp_top(parser, token, ctx, true);
+}
+
+bool
+lxb_css_property_state_margin_bottom(lxb_css_parser_t *parser,
+                                     const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_mp_top(parser, token, ctx, true);
+}
+
+bool
+lxb_css_property_state_margin_left(lxb_css_parser_t *parser,
+                                   const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_mp_top(parser, token, ctx, true);
+}
+
+bool
+lxb_css_property_state_padding(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_mp(parser, token, ctx, false);
+}
+
+bool
+lxb_css_property_state_padding_top(lxb_css_parser_t *parser,
+                                   const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_mp_top(parser, token, ctx, false);
+}
+
+bool
+lxb_css_property_state_padding_right(lxb_css_parser_t *parser,
+                                     const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_mp_top(parser, token, ctx, false);
+}
+
+bool
+lxb_css_property_state_padding_bottom(lxb_css_parser_t *parser,
+                                      const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_mp_top(parser, token, ctx, false);
+}
+
+bool
+lxb_css_property_state_padding_left(lxb_css_parser_t *parser,
+                                    const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_mp_top(parser, token, ctx, false);
+}
+
+static bool
+lxb_css_property_state_line_width_style_color(lxb_css_parser_t *parser,
+                                              const lxb_css_syntax_token_t *token,
+                                              lxb_css_property_border_t *border)
+{
+    lxb_status_t status;
+    lxb_css_value_type_t type;
+    const lxb_css_data_t *unit;
+    lxb_css_value_length_t *length;
+    lxb_css_syntax_token_string_t *str;
+
+    switch (token->type) {
+        case LXB_CSS_SYNTAX_TOKEN_DIMENSION:
+            if (border->width.type != LXB_CSS_VALUE__UNDEF) {
+                return false;
+            }
+
+            str = &lxb_css_syntax_token_dimension(token)->str;
+
+            unit = lxb_css_unit_absolute_relative_by_name(str->data,
+                                                          str->length);
+            if (unit == NULL) {
+                return false;
+            }
+
+            length = &border->width.length;
+
+            border->width.type = LXB_CSS_VALUE__LENGTH;
+            length->num = lxb_css_syntax_token_dimension(token)->num.num;
+            length->is_float = lxb_css_syntax_token_dimension(token)->num.is_float;
+            length->unit = (lxb_css_unit_t) unit->unique;
+            break;
+
+        case LXB_CSS_SYNTAX_TOKEN_NUMBER:
+            if (border->width.type != LXB_CSS_VALUE__UNDEF) {
+                return false;
+            }
+
+            length = &border->width.length;
+
+            border->width.type = LXB_CSS_VALUE__NUMBER;
+            length->num = lxb_css_syntax_token_number(token)->num;
+            length->is_float = lxb_css_syntax_token_number(token)->is_float;
+            break;
+
+        case LXB_CSS_SYNTAX_TOKEN_IDENT:
+            type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                         lxb_css_syntax_token_ident(token)->length);
+            switch (type) {
+                case LXB_CSS_VALUE_THIN:
+                case LXB_CSS_VALUE_MEDIUM:
+                case LXB_CSS_VALUE_THICK:
+                    if (border->width.type != LXB_CSS_VALUE__UNDEF) {
+                        return false;
+                    }
+
+                    border->width.type = type;
+                    break;
+
+                case LXB_CSS_VALUE_NONE:
+                case LXB_CSS_VALUE_HIDDEN:
+                case LXB_CSS_VALUE_DOTTED:
+                case LXB_CSS_VALUE_DASHED:
+                case LXB_CSS_VALUE_SOLID:
+                case LXB_CSS_VALUE_DOUBLE:
+                case LXB_CSS_VALUE_GROOVE:
+                case LXB_CSS_VALUE_RIDGE:
+                case LXB_CSS_VALUE_INSET:
+                case LXB_CSS_VALUE_OUTSET:
+                    if (border->style != LXB_CSS_VALUE__UNDEF) {
+                        return false;
+                    }
+
+                    border->style = type;
+                    break;
+
+                default:
+                    goto color;
+            }
+
+            break;
+
+        default:
+            goto color;
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return true;
+
+color:
+
+    if (border->color.type != LXB_CSS_VALUE__UNDEF) {
+        return false;
+    }
+
+    return lxb_css_property_state_color_handler(parser, token, &border->color,
+                                                &status);
+}
+
+bool
+lxb_css_property_state_border(lxb_css_parser_t *parser,
+                              const lxb_css_syntax_token_t *token, void *ctx)
+{
+    bool res;
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type == LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                     lxb_css_syntax_token_ident(token)->length);
+        switch (type) {
+            case LXB_CSS_VALUE_INITIAL:
+            case LXB_CSS_VALUE_INHERIT:
+            case LXB_CSS_VALUE_UNSET:
+            case LXB_CSS_VALUE_REVERT:
+                declar->u.border->style = type;
+
+                lxb_css_syntax_parser_consume(parser);
+                return lxb_css_parser_success(parser);
+
+            default:
+                break;
+        }
+    }
+
+    res = lxb_css_property_state_line_width_style_color(parser, token,
+                                                        declar->u.border);
+    if (!res) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    if (token->type == LXB_CSS_SYNTAX_TOKEN__END) {
+        return lxb_css_parser_success(parser);
+    }
+
+    res = lxb_css_property_state_line_width_style_color(parser, token,
+                                                        declar->u.border);
+    if (!res) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    if (token->type == LXB_CSS_SYNTAX_TOKEN__END) {
+        return lxb_css_parser_success(parser);
+    }
+
+    res = lxb_css_property_state_line_width_style_color(parser, token,
+                                                        declar->u.border);
+    if (!res) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_border_top(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_border(parser, token, ctx);
+}
+
+bool
+lxb_css_property_state_border_right(lxb_css_parser_t *parser,
+                                    const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_border(parser, token, ctx);
+}
+
+bool
+lxb_css_property_state_border_bottom(lxb_css_parser_t *parser,
+                                     const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_border(parser, token, ctx);
+}
+
+bool
+lxb_css_property_state_border_left(lxb_css_parser_t *parser,
+                                   const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_border(parser, token, ctx);
+}
+
+bool
+lxb_css_property_state_border_top_color(lxb_css_parser_t *parser,
+                                        const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_color(parser, token, ctx);
+}
+
+bool
+lxb_css_property_state_border_right_color(lxb_css_parser_t *parser,
+                                          const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_color(parser, token, ctx);
+}
+
+bool
+lxb_css_property_state_border_bottom_color(lxb_css_parser_t *parser,
+                                           const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_color(parser, token, ctx);
+}
+
+bool
+lxb_css_property_state_border_left_color(lxb_css_parser_t *parser,
+                                         const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_color(parser, token, ctx);
+}
+
+bool
+lxb_css_property_state_background_color(lxb_css_parser_t *parser,
+                                        const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_color(parser, token, ctx);
+}
+
+bool
+lxb_css_property_state_color(lxb_css_parser_t *parser,
+                             const lxb_css_syntax_token_t *token, void *ctx)
+{
+    bool res;
+    lxb_status_t status;
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type == LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                     lxb_css_syntax_token_ident(token)->length);
+        switch (type) {
+            /* Global. */
+            case LXB_CSS_VALUE_INITIAL:
+            case LXB_CSS_VALUE_INHERIT:
+            case LXB_CSS_VALUE_UNSET:
+            case LXB_CSS_VALUE_REVERT:
+                declar->u.color->type = type;
+
+                lxb_css_syntax_parser_consume(parser);
+                return lxb_css_parser_success(parser);
+
+            default:
+                break;
+        }
+    }
+
+    res = lxb_css_property_state_color_handler(parser, token,
+                                    (lxb_css_value_color_t *) declar->u.color,
+                                    &status);
+    if (!res) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_opacity(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token, void *ctx)
+{
+    bool res;
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+    lxb_css_property_opacity_t *opacity = declar->u.opacity;
+
+    res = lxb_css_property_state_number_percentage(parser, token,
+                                (lxb_css_value_number_percentage_t *) opacity);
+    if (res) {
+        return lxb_css_parser_success(parser);
+    }
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+            opacity->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_position(lxb_css_parser_t *parser,
+                                const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_POSITION_STATIC:
+        case LXB_CSS_POSITION_RELATIVE:
+        case LXB_CSS_POSITION_ABSOLUTE:
+        case LXB_CSS_POSITION_STICKY:
+        case LXB_CSS_POSITION_FIXED:
+            declar->u.position->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_top(lxb_css_parser_t *parser,
+                           const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_mp_top(parser, token, ctx, true);
+}
+
+bool
+lxb_css_property_state_right(lxb_css_parser_t *parser,
+                             const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_top(parser, token, ctx);
+}
+
+bool
+lxb_css_property_state_bottom(lxb_css_parser_t *parser,
+                              const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_top(parser, token, ctx);
+}
+
+bool
+lxb_css_property_state_left(lxb_css_parser_t *parser,
+                            const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_top(parser, token, ctx);
+}
+
+bool
+lxb_css_property_state_inset_block_start(lxb_css_parser_t *parser,
+                                         const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_top(parser, token, ctx);
+}
+
+bool
+lxb_css_property_state_inset_inline_start(lxb_css_parser_t *parser,
+                                          const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_top(parser, token, ctx);
+}
+
+bool
+lxb_css_property_state_inset_block_end(lxb_css_parser_t *parser,
+                                       const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_top(parser, token, ctx);
+}
+
+bool
+lxb_css_property_state_inset_inline_end(lxb_css_parser_t *parser,
+                                        const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_top(parser, token, ctx);
+}
+
+bool
+lxb_css_property_state_text_transform(lxb_css_parser_t *parser,
+                                      const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+    lxb_css_property_text_transform_t *tt;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    tt = declar->u.text_transform;
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_TEXT_TRANSFORM_NONE:
+            tt->type_case = type;
+            break;
+
+        case LXB_CSS_TEXT_TRANSFORM_CAPITALIZE:
+        case LXB_CSS_TEXT_TRANSFORM_UPPERCASE:
+        case LXB_CSS_TEXT_TRANSFORM_LOWERCASE:
+            tt->type_case = type;
+            goto next;
+
+        case LXB_CSS_TEXT_TRANSFORM_FULL_WIDTH:
+            tt->full_width = type;
+            goto next;
+
+        case LXB_CSS_TEXT_TRANSFORM_FULL_SIZE_KANA:
+            tt->full_size_kana = type;
+            goto next;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+
+next:
+
+    lxb_css_syntax_parser_consume(parser);
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_success(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+
+    switch (type) {
+        case LXB_CSS_TEXT_TRANSFORM_CAPITALIZE:
+        case LXB_CSS_TEXT_TRANSFORM_UPPERCASE:
+        case LXB_CSS_TEXT_TRANSFORM_LOWERCASE:
+            if (tt->type_case != LXB_CSS_VALUE__UNDEF) {
+                return lxb_css_parser_failed(parser);
+            }
+
+            tt->type_case = type;
+            goto next;
+
+        case LXB_CSS_TEXT_TRANSFORM_FULL_WIDTH:
+            if (tt->full_width != LXB_CSS_VALUE__UNDEF) {
+                return lxb_css_parser_failed(parser);
+            }
+
+            tt->full_width = type;
+            goto next;
+
+        case LXB_CSS_TEXT_TRANSFORM_FULL_SIZE_KANA:
+            if (tt->full_size_kana != LXB_CSS_VALUE__UNDEF) {
+                return lxb_css_parser_failed(parser);
+            }
+
+            tt->full_size_kana = type;
+            goto next;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+}
+
+bool
+lxb_css_property_state_text_align(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_TEXT_ALIGN_START:
+        case LXB_CSS_TEXT_ALIGN_END:
+        case LXB_CSS_TEXT_ALIGN_LEFT:
+        case LXB_CSS_TEXT_ALIGN_RIGHT:
+        case LXB_CSS_TEXT_ALIGN_CENTER:
+        case LXB_CSS_TEXT_ALIGN_JUSTIFY:
+        case LXB_CSS_TEXT_ALIGN_MATCH_PARENT:
+        case LXB_CSS_TEXT_ALIGN_JUSTIFY_ALL:
+            declar->u.text_align->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_text_align_all(lxb_css_parser_t *parser,
+                                      const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_TEXT_ALIGN_ALL_START:
+        case LXB_CSS_TEXT_ALIGN_ALL_END:
+        case LXB_CSS_TEXT_ALIGN_ALL_LEFT:
+        case LXB_CSS_TEXT_ALIGN_ALL_RIGHT:
+        case LXB_CSS_TEXT_ALIGN_ALL_CENTER:
+        case LXB_CSS_TEXT_ALIGN_ALL_JUSTIFY:
+        case LXB_CSS_TEXT_ALIGN_ALL_MATCH_PARENT:
+            declar->u.text_align_all->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_text_align_last(lxb_css_parser_t *parser,
+                                       const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_TEXT_ALIGN_LAST_AUTO:
+        case LXB_CSS_TEXT_ALIGN_LAST_START:
+        case LXB_CSS_TEXT_ALIGN_LAST_END:
+        case LXB_CSS_TEXT_ALIGN_LAST_LEFT:
+        case LXB_CSS_TEXT_ALIGN_LAST_RIGHT:
+        case LXB_CSS_TEXT_ALIGN_LAST_CENTER:
+        case LXB_CSS_TEXT_ALIGN_LAST_JUSTIFY:
+        case LXB_CSS_TEXT_ALIGN_LAST_MATCH_PARENT:
+            declar->u.text_align_last->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_text_justify(lxb_css_parser_t *parser,
+                                    const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_TEXT_JUSTIFY_AUTO:
+        case LXB_CSS_TEXT_JUSTIFY_NONE:
+        case LXB_CSS_TEXT_JUSTIFY_INTER_WORD:
+        case LXB_CSS_TEXT_JUSTIFY_INTER_CHARACTER:
+            declar->u.text_justify->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_text_indent(lxb_css_parser_t *parser,
+                                   const lxb_css_syntax_token_t *token, void *ctx)
+{
+    bool res;
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+    lxb_css_property_text_indent_t *text_indent;
+
+    text_indent = declar->u.text_indent;
+
+    res = lxb_css_property_state_length_percentage(parser, token,
+                                                   &text_indent->length);
+    if (res) {
+        token = lxb_css_syntax_parser_token_wo_ws(parser);
+        lxb_css_property_state_check_token(parser, token);
+
+        text_indent->type = LXB_CSS_VALUE__LENGTH;
+    }
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        if (!res) {
+            return lxb_css_parser_failed(parser);
+        }
+
+        return lxb_css_parser_success(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+            if (res) {
+                return lxb_css_parser_failed(parser);
+            }
+
+            text_indent->type = type;
+            break;
+
+        /* Local. */
+        case LXB_CSS_TEXT_INDENT_HANGING:
+            text_indent->hanging = type;
+            goto next;
+
+        case LXB_CSS_TEXT_INDENT_EACH_LINE:
+            text_indent->each_line = type;
+            goto next;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+
+next:
+
+    lxb_css_syntax_parser_consume(parser);
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    res = lxb_css_property_state_length_percentage(parser, token,
+                                                   &text_indent->length);
+    if (res) {
+        if (text_indent->type != LXB_CSS_VALUE__UNDEF) {
+            return lxb_css_parser_failed(parser);
+        }
+
+        token = lxb_css_syntax_parser_token_wo_ws(parser);
+        lxb_css_property_state_check_token(parser, token);
+
+        text_indent->type = LXB_CSS_VALUE__LENGTH;
+    }
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        if (text_indent->type == LXB_CSS_VALUE__UNDEF) {
+            return lxb_css_parser_failed(parser);
+        }
+
+        return lxb_css_parser_success(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+
+    switch (type) {
+        case LXB_CSS_TEXT_INDENT_HANGING:
+            if (text_indent->hanging != LXB_CSS_VALUE__UNDEF) {
+                return lxb_css_parser_failed(parser);
+            }
+
+            text_indent->hanging = type;
+            goto next;
+
+        case LXB_CSS_TEXT_INDENT_EACH_LINE:
+            if (text_indent->each_line != LXB_CSS_VALUE__UNDEF) {
+                return lxb_css_parser_failed(parser);
+            }
+
+            text_indent->each_line = type;
+            goto next;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+}
+
+bool
+lxb_css_property_state_white_space(lxb_css_parser_t *parser,
+                                   const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_WHITE_SPACE_NORMAL:
+        case LXB_CSS_WHITE_SPACE_PRE:
+        case LXB_CSS_WHITE_SPACE_NOWRAP:
+        case LXB_CSS_WHITE_SPACE_PRE_WRAP:
+        case LXB_CSS_WHITE_SPACE_BREAK_SPACES:
+        case LXB_CSS_WHITE_SPACE_PRE_LINE:
+            declar->u.white_space->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_tab_size(lxb_css_parser_t *parser,
+                                const lxb_css_syntax_token_t *token, void *ctx)
+{
+    bool res;
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    res = lxb_css_property_state_number_length(parser, token,
+                         (lxb_css_value_number_length_t *) declar->u.tab_size);
+    if (res) {
+        return lxb_css_parser_success(parser);
+    }
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+            declar->u.tab_size->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_word_break(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_WORD_BREAK_NORMAL:
+        case LXB_CSS_WORD_BREAK_KEEP_ALL:
+        case LXB_CSS_WORD_BREAK_BREAK_ALL:
+        case LXB_CSS_WORD_BREAK_BREAK_WORD:
+            declar->u.word_break->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_line_break(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_LINE_BREAK_AUTO:
+        case LXB_CSS_LINE_BREAK_LOOSE:
+        case LXB_CSS_LINE_BREAK_NORMAL:
+        case LXB_CSS_LINE_BREAK_STRICT:
+        case LXB_CSS_LINE_BREAK_ANYWHERE:
+            declar->u.line_break->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_hyphens(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_HYPHENS_NONE:
+        case LXB_CSS_HYPHENS_MANUAL:
+        case LXB_CSS_HYPHENS_AUTO:
+            declar->u.hyphens->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_overflow_wrap(lxb_css_parser_t *parser,
+                                     const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_OVERFLOW_WRAP_NORMAL:
+        case LXB_CSS_OVERFLOW_WRAP_BREAK_WORD:
+        case LXB_CSS_OVERFLOW_WRAP_ANYWHERE:
+            declar->u.overflow_wrap->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_word_wrap(lxb_css_parser_t *parser,
+                                 const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_overflow_wrap(parser, token, ctx);
+}
+
+bool
+lxb_css_property_state_word_spacing(lxb_css_parser_t *parser,
+                                    const lxb_css_syntax_token_t *token, void *ctx)
+{
+    bool res;
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    res = lxb_css_property_state_length(parser, token,
+                                        &declar->u.word_spacing->length);
+    if (res) {
+        declar->u.word_spacing->type = LXB_CSS_VALUE__LENGTH;
+
+        return lxb_css_parser_success(parser);
+    }
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_WORD_SPACING_NORMAL:
+            declar->u.word_spacing->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_letter_spacing(lxb_css_parser_t *parser,
+                                      const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_word_spacing(parser, token, ctx);
+}
+
+bool
+lxb_css_property_state_hanging_punctuation(lxb_css_parser_t *parser,
+                                           const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+    lxb_css_property_hanging_punctuation_t *hp;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    hp = declar->u.hanging_punctuation;
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+            /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+            /* Local. */
+        case LXB_CSS_HANGING_PUNCTUATION_NONE:
+            hp->type_first = type;
+            break;
+
+        case LXB_CSS_HANGING_PUNCTUATION_FIRST:
+            hp->type_first = type;
+            goto next;
+
+        case LXB_CSS_HANGING_PUNCTUATION_FORCE_END:
+        case LXB_CSS_HANGING_PUNCTUATION_ALLOW_END:
+            hp->force_allow = type;
+            goto next;
+
+        case LXB_CSS_HANGING_PUNCTUATION_LAST:
+            hp->last = type;
+            goto next;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+
+next:
+
+    lxb_css_syntax_parser_consume(parser);
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_success(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+
+    switch (type) {
+        case LXB_CSS_HANGING_PUNCTUATION_FIRST:
+            if (hp->type_first != LXB_CSS_VALUE__UNDEF) {
+                return lxb_css_parser_failed(parser);
+            }
+
+            hp->type_first = type;
+            goto next;
+
+        case LXB_CSS_HANGING_PUNCTUATION_FORCE_END:
+        case LXB_CSS_HANGING_PUNCTUATION_ALLOW_END:
+            if (hp->force_allow != LXB_CSS_VALUE__UNDEF) {
+                return lxb_css_parser_failed(parser);
+            }
+
+            hp->force_allow = type;
+            goto next;
+
+        case LXB_CSS_HANGING_PUNCTUATION_LAST:
+            if (hp->last != LXB_CSS_VALUE__UNDEF) {
+                return lxb_css_parser_failed(parser);
+            }
+
+            hp->last = type;
+            goto next;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+}
+
+bool
+lxb_css_property_state_font_family(lxb_css_parser_t *parser,
+                                   const lxb_css_syntax_token_t *token, void *ctx)
+{
+    size_t length;
+    const lxb_char_t *data;
+    lexbor_str_t *str;
+    lexbor_mraw_t *mraw;
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+    lxb_css_property_font_family_t *ff;
+    lxb_css_property_family_name_t *name;
+
+    mraw = parser->memory->mraw;
+    ff = declar->u.font_family;
+
+    while (token != NULL) {
+        name = lexbor_mraw_alloc(mraw, sizeof(lxb_css_property_family_name_t));
+        if (name == NULL) {
+            return lxb_css_parser_memory_fail(parser);
+        }
+
+        if (token->type == LXB_CSS_SYNTAX_TOKEN_IDENT) {
+            data = lxb_css_syntax_token_ident(token)->data;
+            length = lxb_css_syntax_token_ident(token)->length;
+
+            type = lxb_css_value_by_name(data, length);
+            if (type != LXB_CSS_VALUE__UNDEF) {
+                name->generic = true;
+                name->u.type = type;
+
+                goto next;
+            }
+        }
+        else if (token->type == LXB_CSS_SYNTAX_TOKEN_STRING) {
+            data = lxb_css_syntax_token_string(token)->data;
+            length = lxb_css_syntax_token_string(token)->length;
+        }
+        else {
+            return lxb_css_parser_failed(parser);
+        }
+
+        name->generic = false;
+
+        str = &name->u.str;
+
+        (void) lexbor_str_init(str, mraw, length);
+        if (name->u.str.data == NULL) {
+            return lxb_css_parser_memory_fail(parser);
+        }
+
+        memcpy(str->data, data, length);
+
+        str->data[length] = '\0';
+        str->length = length;
+
+    next:
+
+        if (ff->first == NULL) {
+            ff->first = name;
+        }
+        else {
+            ff->last->next = name;
+        }
+
+        name->next = NULL;
+        name->prev = ff->last;
+        ff->last = name;
+
+        lxb_css_syntax_parser_consume(parser);
+        token = lxb_css_syntax_parser_token_wo_ws(parser);
+        lxb_css_property_state_check_token(parser, token);
+
+        if (token->type != LXB_CSS_SYNTAX_TOKEN_COMMA) {
+            if (token->type == LXB_CSS_SYNTAX_TOKEN__END) {
+                return lxb_css_parser_success(parser);
+            }
+
+            return lxb_css_parser_failed(parser);
+        }
+
+        lxb_css_syntax_parser_consume(parser);
+        token = lxb_css_syntax_parser_token_wo_ws(parser);
+    }
+
+    lxb_css_property_state_check_token(parser, token);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_font_weight(lxb_css_parser_t *parser,
+                                   const lxb_css_syntax_token_t *token, void *ctx)\
+{
+    bool res;
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+    lxb_css_property_font_weight_t *fw = declar->u.font_weight;
+
+    res = lxb_css_property_state_number(parser, token, &fw->number);
+
+    if (res) {
+        if (fw->number.num < 1 || fw->number.num > 1000) {
+            return lxb_css_parser_failed(parser);
+        }
+
+        fw->type = LXB_CSS_FONT_WEIGHT__NUMBER;
+        return lxb_css_parser_success(parser);
+    }
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_FONT_WEIGHT_NORMAL:
+        case LXB_CSS_FONT_WEIGHT_BOLD:
+        case LXB_CSS_FONT_WEIGHT_BOLDER:
+        case LXB_CSS_FONT_WEIGHT_LIGHTER:
+            fw->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_font_stretch(lxb_css_parser_t *parser,
+                                    const lxb_css_syntax_token_t *token, void *ctx)
+{
+    bool res;
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+    lxb_css_property_font_stretch_t *fs = declar->u.font_stretch;
+
+    res = lxb_css_property_state_percentage(parser, token, &fs->percentage);
+
+    if (res) {
+        if (fs->percentage.num < 0) {
+            return lxb_css_parser_failed(parser);
+        }
+
+        fs->type = LXB_CSS_FONT_STRETCH__PERCENTAGE;
+        return lxb_css_parser_success(parser);
+    }
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_FONT_STRETCH_NORMAL:
+        case LXB_CSS_FONT_STRETCH_ULTRA_CONDENSED:
+        case LXB_CSS_FONT_STRETCH_EXTRA_CONDENSED:
+        case LXB_CSS_FONT_STRETCH_CONDENSED:
+        case LXB_CSS_FONT_STRETCH_SEMI_CONDENSED:
+        case LXB_CSS_FONT_STRETCH_SEMI_EXPANDED:
+        case LXB_CSS_FONT_STRETCH_EXPANDED:
+        case LXB_CSS_FONT_STRETCH_EXTRA_EXPANDED:
+        case LXB_CSS_FONT_STRETCH_ULTRA_EXPANDED:
+            fs->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_font_style(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token, void *ctx)
+{
+    bool res;
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+    lxb_css_property_font_style_t *fs = declar->u.font_style;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+            /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+            /* Local. */
+        case LXB_CSS_FONT_STYLE_NORMAL:
+        case LXB_CSS_FONT_STYLE_ITALIC:
+            fs->type = type;
+            break;
+
+        case LXB_CSS_FONT_STYLE_OBLIQUE:
+            fs->type = type;
+
+            lxb_css_syntax_parser_consume(parser);
+            token = lxb_css_syntax_parser_token_wo_ws(parser);
+            lxb_css_property_state_check_token(parser, token);
+
+            res = lxb_css_property_state_angle(parser, token, &fs->angle);
+
+            if (res) {
+                if (fs->angle.num < -90 || fs->angle.num > 90) {
+                    return lxb_css_parser_failed(parser);
+                }
+
+                return lxb_css_parser_success(parser);
+            }
+            else {
+                fs->angle.unit = (lxb_css_unit_angle_t) LXB_CSS_UNIT__UNDEF;
+            }
+
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_font_size(lxb_css_parser_t *parser,
+                                 const lxb_css_syntax_token_t *token, void *ctx)
+{
+    bool res;
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+    lxb_css_property_font_size_t *fs = declar->u.font_size;
+
+    res = lxb_css_property_state_length_percentage(parser, token, &fs->length);
+
+    if (res) {
+        if (fs->length.u.length.num < 0) {
+            return lxb_css_parser_failed(parser);
+        }
+
+        fs->type = LXB_CSS_FONT_SIZE__LENGTH;
+
+        return lxb_css_parser_success(parser);
+    }
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_FONT_SIZE_XX_SMALL:
+        case LXB_CSS_FONT_SIZE_X_SMALL:
+        case LXB_CSS_FONT_SIZE_SMALL:
+        case LXB_CSS_FONT_SIZE_MEDIUM:
+        case LXB_CSS_FONT_SIZE_LARGE:
+        case LXB_CSS_FONT_SIZE_X_LARGE:
+        case LXB_CSS_FONT_SIZE_XX_LARGE:
+        case LXB_CSS_FONT_SIZE_XXX_LARGE:
+        case LXB_CSS_FONT_SIZE_MATH:
+        case LXB_CSS_FONT_SIZE_LARGER:
+        case LXB_CSS_FONT_SIZE_SMALLER:
+            fs->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_float_reference(lxb_css_parser_t *parser,
+                                       const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_FLOAT_REFERENCE_INLINE:
+        case LXB_CSS_FLOAT_REFERENCE_COLUMN:
+        case LXB_CSS_FLOAT_REFERENCE_REGION:
+        case LXB_CSS_FLOAT_REFERENCE_PAGE:
+            declar->u.float_reference->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_float(lxb_css_parser_t *parser,
+                             const lxb_css_syntax_token_t *token, void *ctx)
+{
+    bool res;
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+    lxb_css_property_float_t *fp = declar->u.floatp;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        if (token->type == LXB_CSS_SYNTAX_TOKEN_FUNCTION) {
+            goto snap;
+        }
+
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_FLOAT_BLOCK_START:
+        case LXB_CSS_FLOAT_BLOCK_END:
+        case LXB_CSS_FLOAT_INLINE_START:
+        case LXB_CSS_FLOAT_INLINE_END:
+        case LXB_CSS_FLOAT_SNAP_BLOCK:
+        case LXB_CSS_FLOAT_SNAP_INLINE:
+        case LXB_CSS_FLOAT_LEFT:
+        case LXB_CSS_FLOAT_RIGHT:
+        case LXB_CSS_FLOAT_TOP:
+        case LXB_CSS_FLOAT_BOTTOM:
+        case LXB_CSS_FLOAT_NONE:
+            fp->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+
+snap:
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_function(token)->data,
+                                 lxb_css_syntax_token_function(token)->length);
+
+    if (type != LXB_CSS_FLOAT_SNAP_BLOCK
+        && type != LXB_CSS_FLOAT_SNAP_INLINE)
+    {
+        return lxb_css_parser_failed(parser);
+    }
+
+    fp->type = type;
+
+    lxb_css_syntax_parser_consume(parser);
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    res = lxb_css_property_state_length(parser, token, &fp->length.length);
+    if (!res) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    fp->length.type = LXB_CSS_VALUE__LENGTH;
+
+    lxb_css_syntax_parser_consume(parser);
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_COMMA) {
+        if (token->type == LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS) {
+            fp->snap_type = LXB_CSS_VALUE__UNDEF;
+
+            lxb_css_syntax_parser_consume(parser);
+            return lxb_css_parser_success(parser);
+        }
+
+        return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        case LXB_CSS_FLOAT_START:
+        case LXB_CSS_FLOAT_END:
+            if (fp->type != LXB_CSS_FLOAT_SNAP_BLOCK) {
+                return lxb_css_parser_failed(parser);
+            }
+
+            fp->snap_type = type;
+            break;
+
+        case LXB_CSS_FLOAT_LEFT:
+        case LXB_CSS_FLOAT_RIGHT:
+            if (fp->type != LXB_CSS_FLOAT_SNAP_INLINE) {
+                return lxb_css_parser_failed(parser);
+            }
+
+            fp->snap_type = type;
+            break;
+
+        case LXB_CSS_FLOAT_NEAR:
+            fp->snap_type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    if (token->type == LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS) {
+        lxb_css_syntax_parser_consume(parser);
+
+        return lxb_css_parser_success(parser);
+    }
+
+    return lxb_css_parser_failed(parser);
+}
+
+bool
+lxb_css_property_state_clear(lxb_css_parser_t *parser,
+                             const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_CLEAR_INLINE_START:
+        case LXB_CSS_CLEAR_INLINE_END:
+        case LXB_CSS_CLEAR_BLOCK_START:
+        case LXB_CSS_CLEAR_BLOCK_END:
+        case LXB_CSS_CLEAR_LEFT:
+        case LXB_CSS_CLEAR_RIGHT:
+        case LXB_CSS_CLEAR_TOP:
+        case LXB_CSS_CLEAR_BOTTOM:
+        case LXB_CSS_CLEAR_NONE:
+            declar->u.clear->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_float_defer(lxb_css_parser_t *parser,
+                                   const lxb_css_syntax_token_t *token, void *ctx)
+{
+    bool res;
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+    lxb_css_property_float_defer_t *fd = declar->u.float_defer;
+
+    res = lxb_css_property_state_integer(parser, token, &fd->integer);
+    if (res) {
+        fd->type = LXB_CSS_FLOAT_DEFER__INTEGER;
+
+        return lxb_css_parser_success(parser);
+    }
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_FLOAT_DEFER_LAST:
+        case LXB_CSS_FLOAT_DEFER_NONE:
+            fd->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_float_offset(lxb_css_parser_t *parser,
+                                    const lxb_css_syntax_token_t *token, void *ctx)
+{
+    bool res;
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+    lxb_css_property_float_offset_t *fo = declar->u.float_offset;
+
+    res = lxb_css_property_state_length_percentage(parser, token,
+                                     (lxb_css_value_length_percentage_t *) fo);
+    if (res) {
+        return lxb_css_parser_success(parser);
+    }
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+            fo->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_wrap_flow(lxb_css_parser_t *parser,
+                                 const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_WRAP_FLOW_AUTO:
+        case LXB_CSS_WRAP_FLOW_BOTH:
+        case LXB_CSS_WRAP_FLOW_START:
+        case LXB_CSS_WRAP_FLOW_END:
+        case LXB_CSS_WRAP_FLOW_MINIMUM:
+        case LXB_CSS_WRAP_FLOW_MAXIMUM:
+        case LXB_CSS_WRAP_FLOW_CLEAR:
+            declar->u.wrap_flow->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_wrap_through(lxb_css_parser_t *parser,
+                                    const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_WRAP_THROUGH_WRAP:
+        case LXB_CSS_WRAP_THROUGH_NONE:
+            declar->u.wrap_through->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_flex_direction(lxb_css_parser_t *parser,
+                                      const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_FLEX_DIRECTION_ROW:
+        case LXB_CSS_FLEX_DIRECTION_ROW_REVERSE:
+        case LXB_CSS_FLEX_DIRECTION_COLUMN:
+        case LXB_CSS_FLEX_DIRECTION_COLUMN_REVERSE:
+            declar->u.flex_direction->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_flex_wrap(lxb_css_parser_t *parser,
+                                 const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+            /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+            /* Local. */
+        case LXB_CSS_FLEX_WRAP_NOWRAP:
+        case LXB_CSS_FLEX_WRAP_WRAP:
+        case LXB_CSS_FLEX_WRAP_WRAP_REVERSE:
+            declar->u.flex_wrap->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_flex_flow(lxb_css_parser_t *parser,
+                                 const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+    lxb_css_property_flex_flow_t *ff = declar->u.flex_flow;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_FLEX_DIRECTION_ROW:
+        case LXB_CSS_FLEX_DIRECTION_ROW_REVERSE:
+        case LXB_CSS_FLEX_DIRECTION_COLUMN:
+        case LXB_CSS_FLEX_DIRECTION_COLUMN_REVERSE:
+            ff->type_direction = type;
+            goto direction;
+
+        case LXB_CSS_FLEX_WRAP_NOWRAP:
+        case LXB_CSS_FLEX_WRAP_WRAP:
+        case LXB_CSS_FLEX_WRAP_WRAP_REVERSE:
+            ff->wrap = type;
+            goto wrap;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+direction:
+
+    lxb_css_syntax_parser_consume(parser);
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_success(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        case LXB_CSS_FLEX_WRAP_NOWRAP:
+        case LXB_CSS_FLEX_WRAP_WRAP:
+        case LXB_CSS_FLEX_WRAP_WRAP_REVERSE:
+            ff->wrap = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    goto done;
+
+wrap:
+
+    lxb_css_syntax_parser_consume(parser);
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_success(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        case LXB_CSS_FLEX_DIRECTION_ROW:
+        case LXB_CSS_FLEX_DIRECTION_ROW_REVERSE:
+        case LXB_CSS_FLEX_DIRECTION_COLUMN:
+        case LXB_CSS_FLEX_DIRECTION_COLUMN_REVERSE:
+            ff->type_direction = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+done:
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+lxb_inline bool
+lxb_css_property_state_flex_grow_shrink(lxb_css_parser_t *parser,
+                                        const lxb_css_syntax_token_t *token,
+                                        lxb_css_property_flex_t *flex)
+{
+    bool res;
+
+    res = lxb_css_property_state_number(parser, token, &flex->grow.number);
+    if (!res) {
+        return false;
+    }
+
+    flex->grow.type = LXB_CSS_FLEX_GROW__NUMBER;
+
+    lxb_css_syntax_parser_consume(parser);
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    res = lxb_css_property_state_number(parser, token, &flex->shrink.number);
+    if (res) {
+        flex->shrink.type = LXB_CSS_FLEX_SHRINK__NUMBER;
+    }
+
+    return true;
+}
+
+lxb_inline bool
+lxb_css_property_state_flex_grow_basis(lxb_css_parser_t *parser,
+                                       const lxb_css_syntax_token_t *token,
+                                       lxb_css_property_flex_t *flex)
+{
+    bool res;
+    lxb_css_value_type_t type;
+
+    res = lxb_css_property_state_width_handler(parser, token,
+                               (lxb_css_property_flex_basis_t *) &flex->basis);
+    if (res) {
+        return true;
+    }
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return false;
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+
+    if (type == LXB_CSS_FLEX_BASIS_CONTENT) {
+        flex->basis.type = type;
+
+        lxb_css_syntax_parser_consume(parser);
+        return true;
+    }
+
+    return false;
+}
+
+bool
+lxb_css_property_state_flex(lxb_css_parser_t *parser,
+                            const lxb_css_syntax_token_t *token, void *ctx)
+{
+    bool res;
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+    lxb_css_property_flex_t *flex = declar->u.flex;
+
+    res = lxb_css_property_state_flex_grow_shrink(parser, token, flex);
+
+    if (res) {
+        token = lxb_css_syntax_parser_token_wo_ws(parser);
+        lxb_css_property_state_check_token(parser, token);
+
+        res = lxb_css_property_state_flex_grow_basis(parser, token, flex);
+
+        if (!res && token->type != LXB_CSS_SYNTAX_TOKEN__END) {
+            flex->basis.type = LXB_CSS_VALUE__NUMBER;
+            flex->basis.u.length.num = flex->grow.number.num;
+            flex->basis.u.length.unit = LXB_CSS_UNIT__UNDEF;
+            flex->basis.u.length.is_float = flex->grow.number.is_float;
+
+            flex->grow.type = LXB_CSS_VALUE__UNDEF;
+
+            if (flex->shrink.type != LXB_CSS_VALUE__UNDEF) {
+                flex->grow = flex->shrink;
+                flex->shrink.type = LXB_CSS_VALUE__UNDEF;
+
+                goto try_shrink_last;
+            }
+
+            res = lxb_css_property_state_flex_grow_shrink(parser, token, flex);
+            if (!res) {
+                return lxb_css_parser_failed(parser);
+            }
+        }
+
+        return lxb_css_parser_success(parser);
+    }
+    else {
+        res = lxb_css_property_state_flex_grow_basis(parser, token, flex);
+
+        if (res) {
+            token = lxb_css_syntax_parser_token_wo_ws(parser);
+            lxb_css_property_state_check_token(parser, token);
+
+            (void) lxb_css_property_state_flex_grow_shrink(parser, token, flex);
+
+            return lxb_css_parser_success(parser);
+        }
+    }
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_FLEX_NONE:
+            flex->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+
+try_shrink_last:
+
+    res = lxb_css_property_state_number(parser, token, &flex->shrink.number);
+    if (res) {
+        flex->shrink.type = LXB_CSS_FLEX_SHRINK__NUMBER;
+    }
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_flex_grow(lxb_css_parser_t *parser,
+                                 const lxb_css_syntax_token_t *token, void *ctx)
+{
+    bool res;
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+    lxb_css_property_flex_grow_t *fg = declar->u.flex_grow;
+
+    res = lxb_css_property_state_number(parser, token, &fg->number);
+    if (res) {
+        if (fg->number.num < 0) {
+            return lxb_css_parser_failed(parser);
+        }
+
+        fg->type = LXB_CSS_FLEX_GROW__NUMBER;
+
+        return lxb_css_parser_success(parser);
+    }
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+            fg->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_flex_shrink(lxb_css_parser_t *parser,
+                                   const lxb_css_syntax_token_t *token, void *ctx)
+{
+    bool res;
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+    lxb_css_property_flex_grow_t *fs = declar->u.flex_shrink;
+
+    res = lxb_css_property_state_number(parser, token, &fs->number);
+    if (res) {
+        if (fs->number.num < 0) {
+            return lxb_css_parser_failed(parser);
+        }
+
+        fs->type = LXB_CSS_FLEX_SHRINK__NUMBER;
+
+        return lxb_css_parser_success(parser);
+    }
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+            fs->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_flex_basis(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token, void *ctx)
+{
+    bool res;
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+    lxb_css_property_flex_basis_t *fb = declar->u.flex_basis;
+
+    res = lxb_css_property_state_width_handler(parser, token,
+                                               (lxb_css_property_width_t *) fb);
+    if (res) {
+        return lxb_css_parser_success(parser);
+    }
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        case LXB_CSS_FLEX_BASIS_CONTENT:
+            fb->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_justify_content(lxb_css_parser_t *parser,
+                                       const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_JUSTIFY_CONTENT_FLEX_START:
+        case LXB_CSS_JUSTIFY_CONTENT_FLEX_END:
+        case LXB_CSS_JUSTIFY_CONTENT_CENTER:
+        case LXB_CSS_JUSTIFY_CONTENT_SPACE_BETWEEN:
+        case LXB_CSS_JUSTIFY_CONTENT_SPACE_AROUND:
+            declar->u.justify_content->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_align_items(lxb_css_parser_t *parser,
+                                   const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_ALIGN_ITEMS_FLEX_START:
+        case LXB_CSS_ALIGN_ITEMS_FLEX_END:
+        case LXB_CSS_ALIGN_ITEMS_CENTER:
+        case LXB_CSS_ALIGN_ITEMS_BASELINE:
+        case LXB_CSS_ALIGN_ITEMS_STRETCH:
+            declar->u.align_items->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_align_self(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_ALIGN_SELF_AUTO:
+        case LXB_CSS_ALIGN_SELF_FLEX_START:
+        case LXB_CSS_ALIGN_SELF_FLEX_END:
+        case LXB_CSS_ALIGN_SELF_CENTER:
+        case LXB_CSS_ALIGN_SELF_BASELINE:
+        case LXB_CSS_ALIGN_SELF_STRETCH:
+            declar->u.align_self->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_align_content(lxb_css_parser_t *parser,
+                                     const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_ALIGN_CONTENT_FLEX_START:
+        case LXB_CSS_ALIGN_CONTENT_FLEX_END:
+        case LXB_CSS_ALIGN_CONTENT_CENTER:
+        case LXB_CSS_ALIGN_CONTENT_SPACE_BETWEEN:
+        case LXB_CSS_ALIGN_CONTENT_SPACE_AROUND:
+        case LXB_CSS_ALIGN_CONTENT_STRETCH:
+            declar->u.align_content->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_dominant_baseline(lxb_css_parser_t *parser,
+                                         const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_DOMINANT_BASELINE_AUTO:
+        case LXB_CSS_DOMINANT_BASELINE_TEXT_BOTTOM:
+        case LXB_CSS_DOMINANT_BASELINE_ALPHABETIC:
+        case LXB_CSS_DOMINANT_BASELINE_IDEOGRAPHIC:
+        case LXB_CSS_DOMINANT_BASELINE_MIDDLE:
+        case LXB_CSS_DOMINANT_BASELINE_CENTRAL:
+        case LXB_CSS_DOMINANT_BASELINE_MATHEMATICAL:
+        case LXB_CSS_DOMINANT_BASELINE_HANGING:
+        case LXB_CSS_DOMINANT_BASELINE_TEXT_TOP:
+            declar->u.dominant_baseline->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_alignment_baseline_h(lxb_css_parser_t *parser,
+                                            const lxb_css_syntax_token_t *token,
+                                            lxb_css_property_alignment_baseline_t *ab)
+{
+    lxb_css_value_type_t type;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return false;
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        case LXB_CSS_ALIGNMENT_BASELINE_BASELINE:
+        case LXB_CSS_ALIGNMENT_BASELINE_TEXT_BOTTOM:
+        case LXB_CSS_ALIGNMENT_BASELINE_ALPHABETIC:
+        case LXB_CSS_ALIGNMENT_BASELINE_IDEOGRAPHIC:
+        case LXB_CSS_ALIGNMENT_BASELINE_MIDDLE:
+        case LXB_CSS_ALIGNMENT_BASELINE_CENTRAL:
+        case LXB_CSS_ALIGNMENT_BASELINE_MATHEMATICAL:
+        case LXB_CSS_ALIGNMENT_BASELINE_TEXT_TOP:
+            ab->type = type;
+
+            lxb_css_syntax_parser_consume(parser);
+            return true;
+
+        default:
+            return false;
+    }
+}
+
+bool
+lxb_css_property_state_baseline_shift_h(lxb_css_parser_t *parser,
+                                        const lxb_css_syntax_token_t *token,
+                                        lxb_css_property_baseline_shift_t *bs)
+{
+    bool res;
+    lxb_css_value_type_t type;
+
+    res = lxb_css_property_state_length_percentage(parser, token, bs);
+
+    if (res) {
+        return true;
+    }
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return false;
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        case LXB_CSS_BASELINE_SHIFT_SUB:
+        case LXB_CSS_BASELINE_SHIFT_SUPER:
+        case LXB_CSS_BASELINE_SHIFT_TOP:
+        case LXB_CSS_BASELINE_SHIFT_CENTER:
+        case LXB_CSS_BASELINE_SHIFT_BOTTOM:
+            bs->type = type;
+
+            lxb_css_syntax_parser_consume(parser);
+            return true;
+
+        default:
+            return false;
+    }
+}
+
+bool
+lxb_css_property_state_vertical_align(lxb_css_parser_t *parser,
+                                      const lxb_css_syntax_token_t *token, void *ctx)
+{
+    bool res;
+    uint8_t maps;
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+    lxb_css_property_vertical_align_t *va = declar->u.vertical_align;
+
+    maps = 0;
+
+again:
+
+    res = lxb_css_property_state_alignment_baseline_h(parser, token,
+                                                      &va->alignment);
+    if (res) {
+        if (maps & 1 << 1) {
+            return lxb_css_parser_failed(parser);
+        }
+
+        maps |= 1 << 1;
+
+        token = lxb_css_syntax_parser_token_wo_ws(parser);
+        lxb_css_property_state_check_token(parser, token);
+
+        res = lxb_css_property_state_baseline_shift_h(parser, token,
+                                                      &va->shift);
+        if (res) {
+            if (maps & 1 << 2) {
+                return lxb_css_parser_failed(parser);
+            }
+
+            maps |= 1 << 2;
+
+            token = lxb_css_syntax_parser_token_wo_ws(parser);
+            lxb_css_property_state_check_token(parser, token);
+        }
+    }
+    else {
+        res = lxb_css_property_state_baseline_shift_h(parser, token,
+                                                      &va->shift);
+        if (res) {
+            if (maps & 1 << 2) {
+                return lxb_css_parser_failed(parser);
+            }
+
+            maps |= 1 << 2;
+
+            token = lxb_css_syntax_parser_token_wo_ws(parser);
+            lxb_css_property_state_check_token(parser, token);
+
+            res = lxb_css_property_state_alignment_baseline_h(parser, token,
+                                                              &va->alignment);
+            if (res) {
+                if (maps & 1 << 1) {
+                    return lxb_css_parser_failed(parser);
+                }
+
+                maps |= 1 << 1;
+
+                token = lxb_css_syntax_parser_token_wo_ws(parser);
+                lxb_css_property_state_check_token(parser, token);
+            }
+        }
+    }
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        if (maps != 0) {
+            return lxb_css_parser_success(parser);
+        }
+
+        return lxb_css_parser_failed(parser);
+    }
+
+    if (maps & 1 << 3) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_VERTICAL_ALIGN_FIRST:
+        case LXB_CSS_VERTICAL_ALIGN_LAST:
+            va->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    lxb_css_property_state_check_token(parser, token);
+
+    maps = 1 << 3;
+
+    goto again;
+}
+
+bool
+lxb_css_property_state_baseline_source(lxb_css_parser_t *parser,
+                                       const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_BASELINE_SOURCE_AUTO:
+        case LXB_CSS_BASELINE_SOURCE_FIRST:
+        case LXB_CSS_BASELINE_SOURCE_LAST:
+            declar->u.baseline_source->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_alignment_baseline(lxb_css_parser_t *parser,
+                                          const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_ALIGNMENT_BASELINE_BASELINE:
+        case LXB_CSS_ALIGNMENT_BASELINE_TEXT_BOTTOM:
+        case LXB_CSS_ALIGNMENT_BASELINE_ALPHABETIC:
+        case LXB_CSS_ALIGNMENT_BASELINE_IDEOGRAPHIC:
+        case LXB_CSS_ALIGNMENT_BASELINE_MIDDLE:
+        case LXB_CSS_ALIGNMENT_BASELINE_CENTRAL:
+        case LXB_CSS_ALIGNMENT_BASELINE_MATHEMATICAL:
+        case LXB_CSS_ALIGNMENT_BASELINE_TEXT_TOP:
+            declar->u.alignment_baseline->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_baseline_shift(lxb_css_parser_t *parser,
+                                      const lxb_css_syntax_token_t *token, void *ctx)
+{
+    bool res;
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    res = lxb_css_property_state_length_percentage(parser, token,
+                                                   declar->u.baseline_shift);
+    if (res) {
+        return lxb_css_parser_success(parser);
+    }
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_BASELINE_SHIFT_SUB:
+        case LXB_CSS_BASELINE_SHIFT_SUPER:
+        case LXB_CSS_BASELINE_SHIFT_TOP:
+        case LXB_CSS_BASELINE_SHIFT_CENTER:
+        case LXB_CSS_BASELINE_SHIFT_BOTTOM:
+            declar->u.baseline_shift->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_line_height(lxb_css_parser_t *parser,
+                                   const lxb_css_syntax_token_t *token, void *ctx)
+{
+    bool res;
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    res = lxb_css_property_state_number_length_percentage(parser, token,
+                                                          declar->u.line_height);
+    if (res) {
+        return lxb_css_parser_success(parser);
+    }
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_LINE_HEIGHT_NORMAL:
+            declar->u.line_height->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_z_index(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token, void *ctx)
+{
+    bool res;
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    res = lxb_css_property_state_integer(parser, token,
+                                         &declar->u.z_index->integer);
+    if (res) {
+        declar->u.z_index->type = LXB_CSS_VALUE__INTEGER;
+        return lxb_css_parser_success(parser);
+    }
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_Z_INDEX_AUTO:
+            declar->u.line_height->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_direction(lxb_css_parser_t *parser,
+                                 const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_DIRECTION_LTR:
+        case LXB_CSS_DIRECTION_RTL:
+            declar->u.direction->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_unicode_bidi(lxb_css_parser_t *parser,
+                                    const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_UNICODE_BIDI_NORMAL:
+        case LXB_CSS_UNICODE_BIDI_EMBED:
+        case LXB_CSS_UNICODE_BIDI_ISOLATE:
+        case LXB_CSS_UNICODE_BIDI_BIDI_OVERRIDE:
+        case LXB_CSS_UNICODE_BIDI_ISOLATE_OVERRIDE:
+        case LXB_CSS_UNICODE_BIDI_PLAINTEXT:
+            declar->u.unicode_bidi->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_writing_mode(lxb_css_parser_t *parser,
+                                    const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_WRITING_MODE_HORIZONTAL_TB:
+        case LXB_CSS_WRITING_MODE_VERTICAL_RL:
+        case LXB_CSS_WRITING_MODE_VERTICAL_LR:
+        case LXB_CSS_WRITING_MODE_SIDEWAYS_RL:
+        case LXB_CSS_WRITING_MODE_SIDEWAYS_LR:
+            declar->u.writing_mode->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_text_orientation(lxb_css_parser_t *parser,
+                                        const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_TEXT_ORIENTATION_MIXED:
+        case LXB_CSS_TEXT_ORIENTATION_UPRIGHT:
+        case LXB_CSS_TEXT_ORIENTATION_SIDEWAYS:
+            declar->u.text_orientation->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_text_combine_upright(lxb_css_parser_t *parser,
+                                            const lxb_css_syntax_token_t *token, void *ctx)
+{
+    bool res;
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+    lxb_css_property_text_combine_upright_t *tcu = declar->u.text_combine_upright;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_TEXT_COMBINE_UPRIGHT_NONE:
+        case LXB_CSS_TEXT_COMBINE_UPRIGHT_ALL:
+            tcu->type = type;
+            break;
+
+        case LXB_CSS_TEXT_COMBINE_UPRIGHT_DIGITS:
+            tcu->type = type;
+
+            lxb_css_syntax_parser_consume(parser);
+            token = lxb_css_syntax_parser_token_wo_ws(parser);
+            lxb_css_property_state_check_token(parser, token);
+
+            res = lxb_css_property_state_integer(parser, token,
+                                                 &tcu->digits);
+            if (res) {
+                if (tcu->digits.num != 2 && tcu->digits.num != 4) {
+                    return lxb_css_parser_failed(parser);
+                }
+            }
+
+            return lxb_css_parser_success(parser);
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_overflow_x(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_OVERFLOW_X_VISIBLE:
+        case LXB_CSS_OVERFLOW_X_HIDDEN:
+        case LXB_CSS_OVERFLOW_X_CLIP:
+        case LXB_CSS_OVERFLOW_X_SCROLL:
+        case LXB_CSS_OVERFLOW_X_AUTO:
+            declar->u.overflow_x->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_overflow_y(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_overflow_x(parser, token, ctx);
+}
+
+bool
+lxb_css_property_state_overflow_block(lxb_css_parser_t *parser,
+                                      const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_overflow_x(parser, token, ctx);
+}
+
+bool
+lxb_css_property_state_overflow_inline(lxb_css_parser_t *parser,
+                                       const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_overflow_x(parser, token, ctx);
+}
+
+bool
+lxb_css_property_state_text_overflow(lxb_css_parser_t *parser,
+                                     const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_TEXT_OVERFLOW_CLIP:
+        case LXB_CSS_TEXT_OVERFLOW_ELLIPSIS:
+            declar->u.text_overflow->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+lxb_status_t
+lxb_css_property_state_text_decoration_line_h(lxb_css_parser_t *parser,
+                                              const lxb_css_syntax_token_t *token,
+                                              lxb_css_property_text_decoration_line_t *tdl)
+{
+    lxb_css_value_type_t type;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return LXB_STATUS_NEXT;
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        case LXB_CSS_TEXT_DECORATION_LINE_NONE:
+            tdl->type = type;
+
+            lxb_css_syntax_parser_consume(parser);
+            return LXB_STATUS_OK;
+
+        default:
+            goto first;
+    }
+
+next:
+
+    lxb_css_syntax_parser_consume(parser);
+    token = lxb_css_syntax_parser_token_wo_ws(parser);
+    if (token == NULL) {
+        return LXB_STATUS_ERROR_MEMORY_ALLOCATION;
+    }
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return LXB_STATUS_OK;
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+
+first:
+
+    switch (type) {
+        case LXB_CSS_TEXT_DECORATION_LINE_UNDERLINE:
+            if (tdl->underline != LXB_CSS_VALUE__UNDEF) {
+                return LXB_STATUS_STOP;
+            }
+
+            tdl->underline = type;
+            goto next;
+
+        case LXB_CSS_TEXT_DECORATION_LINE_OVERLINE:
+            if (tdl->overline != LXB_CSS_VALUE__UNDEF) {
+                return LXB_STATUS_STOP;
+            }
+
+            tdl->overline = type;
+            goto next;
+
+        case LXB_CSS_TEXT_DECORATION_LINE_LINE_THROUGH:
+            if (tdl->line_through != LXB_CSS_VALUE__UNDEF) {
+                return LXB_STATUS_STOP;
+            }
+
+            tdl->line_through = type;
+            goto next;
+
+        case LXB_CSS_TEXT_DECORATION_LINE_BLINK:
+            if (tdl->blink != LXB_CSS_VALUE__UNDEF) {
+                return LXB_STATUS_STOP;
+            }
+
+            tdl->blink = type;
+            goto next;
+
+        default:
+            if (tdl->underline != LXB_CSS_VALUE__UNDEF
+                || tdl->overline != LXB_CSS_VALUE__UNDEF
+                || tdl->line_through != LXB_CSS_VALUE__UNDEF
+                || tdl->blink != LXB_CSS_VALUE__UNDEF)
+            {
+                return LXB_STATUS_OK;
+            }
+
+            return LXB_STATUS_NEXT;
+    }
+}
+
+bool
+lxb_css_property_state_text_decoration_line(lxb_css_parser_t *parser,
+                                            const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_status_t status;
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+    lxb_css_property_text_decoration_line_t *tdl = declar->u.text_decoration_line;
+
+    status = lxb_css_property_state_text_decoration_line_h(parser, token, tdl);
+
+    if (status == LXB_STATUS_OK) {
+        return lxb_css_parser_success(parser);
+    }
+    else if (status == LXB_STATUS_STOP) {
+        return lxb_css_parser_failed(parser);
+    }
+    else if (status != LXB_STATUS_NEXT) {
+        return lxb_css_parser_memory_fail(parser);
+    }
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+            tdl->type = type;
+
+            lxb_css_syntax_parser_consume(parser);
+            return lxb_css_parser_success(parser);
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+}
+
+bool
+lxb_css_property_state_text_decoration_style_h(lxb_css_parser_t *parser,
+                            const lxb_css_syntax_token_t *token,
+                            lxb_css_property_text_decoration_style_t *tds)
+{
+    lxb_css_value_type_t type;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return false;
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        case LXB_CSS_TEXT_DECORATION_STYLE_SOLID:
+        case LXB_CSS_TEXT_DECORATION_STYLE_DOUBLE:
+        case LXB_CSS_TEXT_DECORATION_STYLE_DOTTED:
+        case LXB_CSS_TEXT_DECORATION_STYLE_DASHED:
+        case LXB_CSS_TEXT_DECORATION_STYLE_WAVY:
+            tds->type = type;
+
+            lxb_css_syntax_parser_consume(parser);
+            return true;
+
+        default:
+            return false;
+    }
+}
+
+bool
+lxb_css_property_state_text_decoration_style(lxb_css_parser_t *parser,
+                                             const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+        /* Local. */
+        case LXB_CSS_TEXT_DECORATION_STYLE_SOLID:
+        case LXB_CSS_TEXT_DECORATION_STYLE_DOUBLE:
+        case LXB_CSS_TEXT_DECORATION_STYLE_DOTTED:
+        case LXB_CSS_TEXT_DECORATION_STYLE_DASHED:
+        case LXB_CSS_TEXT_DECORATION_STYLE_WAVY:
+            declar->u.text_decoration_style->type = type;
+            break;
+
+        default:
+            return lxb_css_parser_failed(parser);
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_parser_success(parser);
+}
+
+bool
+lxb_css_property_state_text_decoration_color(lxb_css_parser_t *parser,
+                                             const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_property_state_color(parser, token, ctx);
+}
+
+bool
+lxb_css_property_state_text_decoration(lxb_css_parser_t *parser,
+                                       const lxb_css_syntax_token_t *token, void *ctx)
+{
+    bool res, line, style, color;
+    lxb_status_t status;
+    lxb_css_value_type_t type;
+    lxb_css_rule_declaration_t *declar = ctx;
+    lxb_css_property_text_decoration_t *td = declar->u.text_decoration;
+
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT) {
+        goto lsc;
+    }
+
+    type = lxb_css_value_by_name(lxb_css_syntax_token_ident(token)->data,
+                                 lxb_css_syntax_token_ident(token)->length);
+    switch (type) {
+        /* Global. */
+        case LXB_CSS_VALUE_INITIAL:
+        case LXB_CSS_VALUE_INHERIT:
+        case LXB_CSS_VALUE_UNSET:
+        case LXB_CSS_VALUE_REVERT:
+            td->line.type = type;
+
+            lxb_css_syntax_parser_consume(parser);
+            return lxb_css_parser_success(parser);
+
+        default:
+            break;
+    }
+
+lsc:
+
+    line = false;
+    style = false;
+    color = false;
+
+    for (size_t i = 0; i < 3; i++) {
+        if (!line) {
+            status = lxb_css_property_state_text_decoration_line_h(parser, token,
+                                                                   &td->line);
+            if (status == LXB_STATUS_OK) {
+                token = lxb_css_syntax_parser_token_wo_ws(parser);
+                lxb_css_property_state_check_token(parser, token);
+
+                line = true;
+            }
+            else if (status == LXB_STATUS_STOP) {
+                return lxb_css_parser_failed(parser);
+            }
+            else if (status != LXB_STATUS_NEXT) {
+                return lxb_css_parser_memory_fail(parser);
+            }
+        }
+
+        if (!style) {
+            res = lxb_css_property_state_text_decoration_style_h(parser, token,
+                                                                 &td->style);
+            if (res) {
+                token = lxb_css_syntax_parser_token_wo_ws(parser);
+                lxb_css_property_state_check_token(parser, token);
+
+                style = true;
+            }
+        }
+
+        if (!color) {
+            res = lxb_css_property_state_color_handler(parser, token,
+                                         (lxb_css_value_color_t *) &td->color,
+                                         &status);
+            if (res) {
+                token = lxb_css_syntax_parser_token_wo_ws(parser);
+                lxb_css_property_state_check_token(parser, token);
+
+                color = true;
+            }
+            else {
+                if (status != LXB_STATUS_OK) {
+                    return lxb_css_parser_failed(parser);
+                }
+            }
+        }
+    }
+
+    if (!line && !style && !color) {
+        return lxb_css_parser_failed(parser);
+    }
+
+    return lxb_css_parser_success(parser);
+}
diff --git a/ext/dom/lexbor/lexbor/css/property/types.h b/ext/dom/lexbor/lexbor/css/property/types.h
new file mode 100644
index 00000000000..3a23f125a69
--- /dev/null
+++ b/ext/dom/lexbor/lexbor/css/property/types.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2025 Alexander Borisov
+ *
+ * Author: Alexander Borisov <borisov@lexbor.com>
+ */
+
+/*
+ * Caution!
+ * This file generated by the script "utils/lexbor/css/names.py"!
+ * Do not change this file!
+ */
+
+
+#ifndef LXB_CSS_PROPERTY_TYPES_H
+#define LXB_CSS_PROPERTY_TYPES_H
+
+
+
+
+
+#endif /* LXB_CSS_PROPERTY_TYPES_H */
diff --git a/ext/dom/lexbor/lexbor/css/rule.c b/ext/dom/lexbor/lexbor/css/rule.c
new file mode 100644
index 00000000000..5ee938730ea
--- /dev/null
+++ b/ext/dom/lexbor/lexbor/css/rule.c
@@ -0,0 +1,598 @@
+/*
+ * Copyright (C) 2021-2026 Alexander Borisov
+ *
+ * Author: Alexander Borisov <borisov@lexbor.com>
+ */
+
+#include "lexbor/css/rule.h"
+#include "lexbor/css/parser.h"
+#include "lexbor/core/serialize.h"
+#include "lexbor/css/stylesheet.h"
+#include "lexbor/css/selectors/selectors.h"
+
+
+void *
+lxb_css_rule_destroy(lxb_css_rule_t *rule, bool self_destroy)
+{
+    switch (rule->type) {
+        case LXB_CSS_RULE_LIST:
+            return lxb_css_rule_list_destroy(lxb_css_rule_list(rule),
+                                             self_destroy);
+        case LXB_CSS_RULE_AT_RULE:
+            return lxb_css_rule_at_destroy(lxb_css_rule_at(rule),
+                                           self_destroy);
+        case LXB_CSS_RULE_STYLE:
+            return lxb_css_rule_style_destroy(lxb_css_rule_style(rule),
+                                              self_destroy);
+        case LXB_CSS_RULE_BAD_STYLE:
+            return lxb_css_rule_bad_style_destroy(lxb_css_rule_bad_style(rule),
+                                                  self_destroy);
+        case LXB_CSS_RULE_DECLARATION:
+            return lxb_css_rule_declaration_destroy(lxb_css_rule_declaration(rule),
+                                                    self_destroy);
+        case LXB_CSS_RULE_DECLARATION_LIST:
+            return lxb_css_rule_declaration_list_destroy(lxb_css_rule_declaration_list(rule),
+                                                         self_destroy);
+        case LXB_CSS_RULE_STYLESHEET:
+        case LXB_CSS_RULE_UNDEF:
+            return NULL;
+    }
+
+    return NULL;
+}
+
+lxb_status_t
+lxb_css_rule_serialize(const lxb_css_rule_t *rule,
+                       lexbor_serialize_cb_f cb, void *ctx)
+{
+    switch (rule->type) {
+        case LXB_CSS_RULE_LIST:
+            return lxb_css_rule_list_serialize(lxb_css_rule_list(rule), cb, ctx);
+
+        case LXB_CSS_RULE_AT_RULE:
+            return lxb_css_rule_at_serialize(lxb_css_rule_at(rule), cb, ctx);
+
+        case LXB_CSS_RULE_STYLE:
+            return lxb_css_rule_style_serialize(lxb_css_rule_style(rule),
+                                                cb, ctx);
+        case LXB_CSS_RULE_BAD_STYLE:
+            return lxb_css_rule_bad_style_serialize(lxb_css_rule_bad_style(rule),
+                                                    cb, ctx);
+        case LXB_CSS_RULE_DECLARATION:
+            return lxb_css_rule_declaration_serialize(lxb_css_rule_declaration(rule),
+                                                      cb, ctx);
+        case LXB_CSS_RULE_DECLARATION_LIST:
+            return lxb_css_rule_declaration_list_serialize(lxb_css_rule_declaration_list(rule),
+                                                           cb, ctx);
+        case LXB_CSS_RULE_STYLESHEET:
+        case LXB_CSS_RULE_UNDEF:
+            break;
+    }
+
+    return LXB_STATUS_ERROR_WRONG_ARGS;
+}
+
+lxb_status_t
+lxb_css_rule_serialize_chain(const lxb_css_rule_t *rule,
+                             lexbor_serialize_cb_f cb, void *ctx)
+{
+    lxb_status_t status;
+
+    static const lxb_char_t ws_str[] = "\n";
+
+    status = lxb_css_rule_serialize(rule, cb, ctx);
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    rule = rule->next;
+
+    while (rule != NULL) {
+        lexbor_serialize_write(cb, ws_str, (sizeof(ws_str) - 1), ctx, status);
+
+        status = lxb_css_rule_serialize(rule, cb, ctx);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+
+        rule = rule->next;
+    }
+
+    return LXB_STATUS_OK;
+}
+
+lxb_css_rule_list_t *
+lxb_css_rule_list_destroy(lxb_css_rule_list_t *list, bool self_destroy)
+{
+    lxb_css_rule_t *rule, *next, *parent;
+    lxb_css_rule_t *child_rule;
+    lxb_css_memory_t *memory;
+    lxb_css_rule_at_t *at;
+    lxb_css_rule_style_t *style;
+    lxb_css_rule_bad_style_t *bad;
+    lxb_css_rule_list_t *sub_list;
+    lxb_css_rule_declaration_list_t *declr_list;
+
+    if (list == NULL) {
+        return NULL;
+    }
+
+    rule = list->first;
+    memory = lxb_css_rule(list)->memory;
+
+    while (rule != NULL) {
+        child_rule = NULL;
+
+        switch (rule->type) {
+            case LXB_CSS_RULE_LIST:
+                sub_list = lxb_css_rule_list(rule);
+
+                if (sub_list->first != NULL) {
+                    child_rule = sub_list->first;
+
+                    sub_list->first = NULL;
+                    sub_list->last = NULL;
+                }
+                break;
+
+            case LXB_CSS_RULE_STYLE:
+                style = lxb_css_rule_style(rule);
+
+                if (style->child != NULL) {
+                    child_rule = lxb_css_rule(style->child);
+                    style->child = NULL;
+                }
+                break;
+
+            case LXB_CSS_RULE_BAD_STYLE:
+                bad = lxb_css_rule_bad_style(rule);
+
+                if (bad->child != NULL) {
+                    child_rule = lxb_css_rule(bad->child);
+                    bad->child = NULL;
+                }
+                break;
+
+            case LXB_CSS_RULE_AT_RULE:
+                at = lxb_css_rule_at(rule);
+
+                if (at->type == LXB_CSS_AT_RULE_MEDIA) {
+                    if (at->u.media != NULL && at->u.media->block != NULL) {
+                        child_rule = lxb_css_rule(at->u.media->block);
+                        at->u.media->block = NULL;
+                    }
+                }
+                else if (at->type == LXB_CSS_AT_RULE__UNDEF) {
+                    if (at->u.undef != NULL && at->u.undef->block != NULL) {
+                        child_rule = lxb_css_rule(at->u.undef->block);
+                        at->u.undef->block = NULL;
+                    }
+                }
+                else if (at->type == LXB_CSS_AT_RULE__CUSTOM) {
+                    if (at->u.custom != NULL && at->u.custom->block != NULL) {
+                        child_rule = lxb_css_rule(at->u.custom->block);
+                        at->u.custom->block = NULL;
+                    }
+                }
+                else if (at->type == LXB_CSS_AT_RULE_FONT_FACE) {
+                    if (at->u.font_face != NULL && at->u.font_face->block != NULL) {
+                        child_rule = lxb_css_rule(at->u.font_face->block);
+                        at->u.font_face->block = NULL;
+                    }
+                }
+                break;
+
+            case LXB_CSS_RULE_DECLARATION_LIST:
+                declr_list = lxb_css_rule_declaration_list(rule);
+
+                if (declr_list->first != NULL) {
+                    child_rule = declr_list->first;
+
+                    declr_list->first = NULL;
+                    declr_list->last = NULL;
+                }
+                break;
+
+            default:
+                break;
+        }
+
+        if (child_rule != NULL) {
+            rule = child_rule;
+            continue;
+        }
+
+        next = rule->next;
+        parent = rule->parent;
+
+        (void) lxb_css_rule_destroy(rule, true);
+
+        if (next != NULL) {
+            rule = next;
+        }
+        else {
+            if (parent == lxb_css_rule(list)) {
+                break;
+            }
+
+            rule = parent;
+        }
+    }
+
+    if (self_destroy) {
+        return lexbor_mraw_free(memory->tree, list);
+    }
+
+    list->first = NULL;
+    list->last = NULL;
+
+    return list;
+}
+
+lxb_status_t
+lxb_css_rule_list_serialize(const lxb_css_rule_list_t *list,
+                            lexbor_serialize_cb_f cb, void *ctx)
+{
+    lxb_status_t status;
+    lxb_css_rule_t *rule;
+
+    static const lxb_char_t nl_str[] = "\n";
+
+    rule = list->first;
+
+    if (rule == NULL) {
+        return LXB_STATUS_OK;
+    }
+
+    status = lxb_css_rule_serialize(rule, cb, ctx);
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    rule = rule->next;
+
+    while (rule != NULL) {
+        lexbor_serialize_write(cb, nl_str, (sizeof(nl_str) - 1), ctx, status);
+
+        status = lxb_css_rule_serialize(rule, cb, ctx);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+
+        rule = rule->next;
+    }
+
+    return LXB_STATUS_OK;
+}
+
+lxb_css_rule_at_t *
+lxb_css_rule_at_destroy(lxb_css_rule_at_t *at, bool self_destroy)
+{
+    lxb_css_memory_t *memory = lxb_css_rule(at)->memory;
+
+    switch (at->type) {
+        case LXB_CSS_AT_RULE__UNDEF:
+            (void) lxb_css_at_rule__undef_destroy(memory, at->u.undef, true);
+            break;
+
+        case LXB_CSS_AT_RULE_MEDIA:
+            (void) lxb_css_at_rule_media_destroy(memory, at->u.media, true);
+            break;
+
+        case LXB_CSS_AT_RULE_NAMESPACE:
+            (void) lxb_css_at_rule_namespace_destroy(memory, at->u.ns, true);
+            break;
+
+        case LXB_CSS_AT_RULE__LAST_ENTRY:
+            break;
+    }
+
+    if (self_destroy) {
+        return lexbor_mraw_free(memory->tree, at);
+    }
+
+    return at;
+}
+
+lxb_status_t
+lxb_css_rule_at_serialize(const lxb_css_rule_at_t *at, lexbor_serialize_cb_f cb,
+                          void *ctx)
+{
+    lxb_status_t status;
+    const lxb_css_at_rule__undef_t *undef;
+    const lxb_css_at_rule__custom_t *custom;
+    const lxb_css_entry_at_rule_data_t *data, *undata;
+
+    static const lxb_char_t at_str[] = "@";
+
+    data = lxb_css_at_rule_by_id(at->type);
+    if (data == NULL) {
+        return LXB_STATUS_ERROR_NOT_EXISTS;
+    }
+
+    lexbor_serialize_write(cb, at_str, (sizeof(at_str) - 1), ctx, status);
+
+    if (at->type == LXB_CSS_AT_RULE__UNDEF) {
+        undef = at->u.undef;
+
+        undata = lxb_css_at_rule_by_id(undef->type);
+        if (undata == NULL) {
+            return LXB_STATUS_ERROR_NOT_EXISTS;
+        }
+
+        lexbor_serialize_write(cb, undata->name, undata->length, ctx, status);
+    }
+    else if (at->type == LXB_CSS_AT_RULE__CUSTOM) {
+        custom = at->u.custom;
+
+        lexbor_serialize_write(cb, custom->name.data,
+                               custom->name.length, ctx, status);
+    }
+    else {
+        lexbor_serialize_write(cb, data->name, data->length, ctx, status);
+    }
+
+    return data->serialize(at->u.user, cb, ctx);
+}
+
+lxb_status_t
+lxb_css_rule_at_serialize_name(const lxb_css_rule_at_t *at,
+                               lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_at_rule_serialize_name(at->u.user, at->type, cb, ctx);
+}
+
+lxb_css_rule_style_t *
+lxb_css_rule_style_destroy(lxb_css_rule_style_t *style, bool self_destroy)
+{
+    lxb_css_memory_t *memory = lxb_css_rule(style)->memory;
+
+    lxb_css_selector_list_destroy(style->selector);
+    (void) lxb_css_rule_declaration_list_destroy(style->declarations, true);
+    (void) lxb_css_rule_list_destroy(style->child, true);
+
+    style->selector = NULL;
+    style->declarations = NULL;
+    style->child = NULL;
+
+    if (self_destroy) {
+        return lexbor_mraw_free(memory->tree, style);
+    }
+
+    return style;
+}
+
+lxb_status_t
+lxb_css_rule_style_serialize(const lxb_css_rule_style_t *style,
+                             lexbor_serialize_cb_f cb, void *ctx)
+{
+    lxb_status_t status;
+
+    static const lxb_char_t lc_str[] = " {";
+    static const lxb_char_t rc_str[] = "}";
+    static const lxb_char_t cm_str[] = "; ";
+
+    status = lxb_css_selector_serialize_list_chain(style->selector, cb, ctx);
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    if (style->declarations != NULL) {
+        lexbor_serialize_write(cb, lc_str, (sizeof(lc_str) - 1), ctx, status);
+
+        status = lxb_css_rule_declaration_list_serialize(style->declarations,
+                                                         cb, ctx);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+
+        if (style->child == NULL) {
+            lexbor_serialize_write(cb, rc_str, (sizeof(rc_str) - 1),
+                                   ctx, status);
+        }
+    }
+
+    if (style->child != NULL && style->child->first != NULL) {
+        lexbor_serialize_write(cb, cm_str, (sizeof(cm_str) - 1), ctx, status);
+
+        status = lxb_css_rule_list_serialize(style->child, cb, ctx);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+    }
+
+    if (style->declarations != NULL) {
+        lexbor_serialize_write(cb, rc_str, (sizeof(rc_str) - 1), ctx, status);
+    }
+
+    return LXB_STATUS_OK;
+}
+
+lxb_css_rule_bad_style_t *
+lxb_css_rule_bad_style_destroy(lxb_css_rule_bad_style_t *bad, bool self_destroy)
+{
+    lxb_css_memory_t *memory = lxb_css_rule(bad)->memory;
+
+    (void) lexbor_str_destroy(&bad->selectors, memory->mraw, false);
+    bad->declarations = lxb_css_rule_declaration_list_destroy(bad->declarations,
+                                                              true);
+    bad->child = lxb_css_rule_list_destroy(bad->child, true);
+
+    if (self_destroy) {
+        return lexbor_mraw_free(memory->tree, bad);
+    }
+
+    return bad;
+}
+
+lxb_status_t
+lxb_css_rule_bad_style_serialize(const lxb_css_rule_bad_style_t *bad,
+                                 lexbor_serialize_cb_f cb, void *ctx)
+{
+    lxb_status_t status;
+
+    static const lxb_char_t lc_str[] = "{";
+    static const lxb_char_t rc_str[] = "}";
+
+    if (bad->selectors.data != NULL) {
+        lexbor_serialize_write(cb, bad->selectors.data, bad->selectors.length,
+                               ctx, status);
+    }
+
+    if (bad->declarations != NULL) {
+        lexbor_serialize_write(cb, lc_str, (sizeof(lc_str) - 1), ctx, status);
+
+        status = lxb_css_rule_declaration_list_serialize(bad->declarations,
+                                                         cb, ctx);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+
+        return cb(rc_str, (sizeof(rc_str) - 1), ctx);
+    }
+
+    return LXB_STATUS_OK;
+}
+
+lxb_css_rule_declaration_list_t *
+lxb_css_rule_declaration_list_destroy(lxb_css_rule_declaration_list_t *list,
+                                      bool self_destroy)
+{
+    lxb_css_rule_t *declr, *next;
+
+    if (list == NULL) {
+        return NULL;
+    }
+
+    declr = list->first;
+
+    while (declr != NULL) {
+        next = declr->next;
+        (void) lxb_css_rule_destroy(declr, true);
+        declr = next;
+    }
+
+    if (self_destroy) {
+        return lexbor_mraw_free(lxb_css_rule(list)->memory->tree, list);
+    }
+
+    list->first = NULL;
+    list->last = NULL;
+
+    return list;
+}
+
+lxb_status_t
+lxb_css_rule_declaration_list_serialize(const lxb_css_rule_declaration_list_t *list,
+                                        lexbor_serialize_cb_f cb, void *ctx)
+{
+    lxb_status_t status;
+    const lxb_css_rule_t *declr;
+
+    static const lxb_char_t sm_str[] = "; ";
+
+    declr = list->first;
+
+    if (declr == NULL) {
+        return LXB_STATUS_OK;
+    }
+
+    status = lxb_css_rule_serialize(declr, cb, ctx);
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    declr = declr->next;
+
+    while (declr != NULL) {
+        lexbor_serialize_write(cb, sm_str, (sizeof(sm_str) - 1), ctx, status);
+
+        status = lxb_css_rule_serialize(declr, cb, ctx);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+
+        declr = declr->next;
+    }
+
+    return LXB_STATUS_OK;
+}
+
+lxb_css_rule_declaration_t *
+lxb_css_rule_declaration_destroy(lxb_css_rule_declaration_t *declr,
+                                 bool self_destroy)
+{
+    lxb_css_memory_t *memory = lxb_css_rule(declr)->memory;
+
+    if (declr->u.user != NULL) {
+        declr->u.user = lxb_css_property_destroy(memory, declr->u.user,
+                                                 declr->type, true);
+    }
+
+    if (self_destroy) {
+        return lexbor_mraw_free(memory->tree, declr);
+    }
+
+    return declr;
+}
+
+lxb_status_t
+lxb_css_rule_declaration_serialize(const lxb_css_rule_declaration_t *declaration,
+                                   lexbor_serialize_cb_f cb, void *ctx)
+{
+    lxb_status_t status;
+    const lxb_css_entry_data_t *data, *undata;
+    const lxb_css_property__undef_t *undef;
+    const lxb_css_property__custom_t *custom;
+
+    static const lxb_char_t cl_str[] = ": ";
+    static const lxb_char_t imp_str[] = " !important";
+
+    data = lxb_css_property_by_id(declaration->type);
+    if (data == NULL) {
+        return LXB_STATUS_ERROR_NOT_EXISTS;
+    }
+
+    if (declaration->type == LXB_CSS_PROPERTY__UNDEF) {
+        undef = declaration->u.undef;
+
+        if (undef->type > LXB_CSS_PROPERTY__CUSTOM) {
+            undata = lxb_css_property_by_id(undef->type);
+            if (undata == NULL) {
+                return LXB_STATUS_ERROR_NOT_EXISTS;
+            }
+
+            lexbor_serialize_write(cb, undata->name, undata->length, ctx, status);
+            lexbor_serialize_write(cb, cl_str, (sizeof(cl_str) - 1), ctx, status);
+        }
+    }
+    else if (declaration->type == LXB_CSS_PROPERTY__CUSTOM) {
+        custom = declaration->u.custom;
+
+        lexbor_serialize_write(cb, custom->name.data, custom->name.length,
+                               ctx, status);
+        lexbor_serialize_write(cb, cl_str, (sizeof(cl_str) - 1), ctx, status);
+    }
+    else {
+        lexbor_serialize_write(cb, data->name, data->length, ctx, status);
+        lexbor_serialize_write(cb, cl_str, (sizeof(cl_str) - 1), ctx, status);
+    }
+
+    status = data->serialize(declaration->u.user, cb, ctx);
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    if (declaration->important && declaration->type != LXB_CSS_PROPERTY__UNDEF) {
+        lexbor_serialize_write(cb, imp_str, (sizeof(imp_str) - 1), ctx, status);
+    }
+
+    return LXB_STATUS_OK;
+}
+
+lxb_status_t
+lxb_css_rule_declaration_serialize_name(const lxb_css_rule_declaration_t *declr,
+                                        lexbor_serialize_cb_f cb, void *ctx)
+{
+    return lxb_css_property_serialize_name(declr->u.user, declr->type, cb, ctx);
+}
diff --git a/ext/dom/lexbor/lexbor/css/rule.h b/ext/dom/lexbor/lexbor/css/rule.h
index bd191f9b651..d192a0161cc 100644
--- a/ext/dom/lexbor/lexbor/css/rule.h
+++ b/ext/dom/lexbor/lexbor/css/rule.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021-2023 Alexander Borisov
+ * Copyright (C) 2021-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -46,9 +46,6 @@ struct lxb_css_rule {
     lxb_css_rule_t      *prev;
     lxb_css_rule_t      *parent;

-    const lxb_char_t    *begin;
-    const lxb_char_t    *end;
-
     lxb_css_memory_t    *memory;
     size_t              ref_count;
 };
@@ -68,10 +65,15 @@ struct lxb_css_rule_at {
     union {
         lxb_css_at_rule__undef_t    *undef;
         lxb_css_at_rule__custom_t   *custom;
+        lxb_css_at_rule_font_face_t *font_face;
         lxb_css_at_rule_media_t     *media;
         lxb_css_at_rule_namespace_t *ns;
         void                        *user;
     } u;
+
+    size_t         name_begin;
+    size_t         prelude_begin;
+    size_t         prelude_end;
 };

 struct lxb_css_rule_style {
@@ -79,6 +81,10 @@ struct lxb_css_rule_style {

     lxb_css_selector_list_t         *selector;
     lxb_css_rule_declaration_list_t *declarations;
+    lxb_css_rule_list_t             *child;
+
+    size_t                          prelude_begin;
+    size_t                          prelude_end;
 };

 struct lxb_css_rule_bad_style {
@@ -86,6 +92,10 @@ struct lxb_css_rule_bad_style {

     lexbor_str_t                    selectors;
     lxb_css_rule_declaration_list_t *declarations;
+    lxb_css_rule_list_t             *child;
+
+    size_t                          prelude_begin;
+    size_t                          prelude_end;
 };

 struct lxb_css_rule_declaration_list {
@@ -97,6 +107,16 @@ struct lxb_css_rule_declaration_list {
     size_t         count;
 };

+typedef struct {
+    size_t name_begin;
+    size_t name_end;
+    size_t value_begin;
+    size_t value_end;
+    size_t important_begin;
+    size_t important_end;
+}
+lxb_css_rule_declaration_offset_t;
+
 struct lxb_css_rule_declaration {
     lxb_css_rule_t rule;
     uintptr_t      type;
@@ -204,7 +224,9 @@ struct lxb_css_rule_declaration {
         void                                     *user;
     } u;

-    bool            important;
+    lxb_css_rule_declaration_offset_t offset;
+
+    bool                              important;
 };


diff --git a/ext/dom/lexbor/lexbor/css/selectors/base.h b/ext/dom/lexbor/lexbor/css/selectors/base.h
index 279c1e5f68c..3151f74b04e 100644
--- a/ext/dom/lexbor/lexbor/css/selectors/base.h
+++ b/ext/dom/lexbor/lexbor/css/selectors/base.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021-2024 Alexander Borisov
+ * Copyright (C) 2021-2025 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -16,7 +16,7 @@ extern "C" {


 #define LXB_CSS_SELECTORS_VERSION_MAJOR 1
-#define LXB_CSS_SELECTORS_VERSION_MINOR 1
+#define LXB_CSS_SELECTORS_VERSION_MINOR 3
 #define LXB_CSS_SELECTORS_VERSION_PATCH 0

 #define LXB_CSS_SELECTORS_VERSION_STRING                                       \
diff --git a/ext/dom/lexbor/lexbor/css/selectors/pseudo_const.h b/ext/dom/lexbor/lexbor/css/selectors/pseudo_const.h
index 2b19f188814..9fa5bb2177c 100644
--- a/ext/dom/lexbor/lexbor/css/selectors/pseudo_const.h
+++ b/ext/dom/lexbor/lexbor/css/selectors/pseudo_const.h
@@ -69,15 +69,16 @@ typedef enum {
     LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_HAS              = 0x0003,
     LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_IS               = 0x0004,
     LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_LANG             = 0x0005,
-    LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NOT              = 0x0006,
-    LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_CHILD        = 0x0007,
-    LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_COL          = 0x0008,
-    LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_CHILD   = 0x0009,
-    LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_COL     = 0x000a,
-    LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_OF_TYPE = 0x000b,
-    LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_OF_TYPE      = 0x000c,
-    LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_WHERE            = 0x000d,
-    LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION__LAST_ENTRY      = 0x000e
+    LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_LEXBOR_CONTAINS  = 0x0006,
+    LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NOT              = 0x0007,
+    LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_CHILD        = 0x0008,
+    LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_COL          = 0x0009,
+    LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_CHILD   = 0x000a,
+    LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_COL     = 0x000b,
+    LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_OF_TYPE = 0x000c,
+    LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_OF_TYPE      = 0x000d,
+    LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_WHERE            = 0x000e,
+    LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION__LAST_ENTRY      = 0x000f
 }
 lxb_css_selector_pseudo_class_function_id_t;

diff --git a/ext/dom/lexbor/lexbor/css/selectors/pseudo_res.h b/ext/dom/lexbor/lexbor/css/selectors/pseudo_res.h
index 5ae6e048064..10825740606 100644
--- a/ext/dom/lexbor/lexbor/css/selectors/pseudo_res.h
+++ b/ext/dom/lexbor/lexbor/css/selectors/pseudo_res.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020-2021 Alexander Borisov
+ * Copyright (C) 2020-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -68,60 +68,64 @@ static const lxb_css_selectors_pseudo_data_func_t lxb_css_selectors_pseudo_data_
 {
     {(lxb_char_t *) "#undef", 6, LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION__UNDEF,
      false, LXB_CSS_SELECTOR_COMBINATOR_CLOSE,
-     {.state = lxb_css_selectors_state_pseudo_class_function__undef, .block = NULL,
-      .failed = lxb_css_state_failed, .end = lxb_css_selectors_state_function_end}, false, false},
+     {.value = lxb_css_selectors_state_pseudo_class_function__undef,
+      .cb.failed = lxb_css_state_failed, .cb.end = lxb_css_selectors_state_function_end}, false, false},
     {(lxb_char_t *) "current", 7, LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_CURRENT,
      false, LXB_CSS_SELECTOR_COMBINATOR_CLOSE,
-     {.state = lxb_css_selectors_state_pseudo_class_function_current, .block = NULL,
-      .failed = lxb_css_state_failed, .end = lxb_css_selectors_state_function_end}, false, true},
+     {.value = lxb_css_selectors_state_pseudo_class_function_current,
+      .cb.failed = lxb_css_state_failed, .cb.end = lxb_css_selectors_state_function_end}, false, true},
     {(lxb_char_t *) "dir", 3, LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_DIR,
      false, LXB_CSS_SELECTOR_COMBINATOR_CLOSE,
-     {.state = lxb_css_selectors_state_pseudo_class_function_dir, .block = NULL,
-      .failed = lxb_css_state_failed, .end = lxb_css_selectors_state_function_end}, false, false},
+     {.value = lxb_css_selectors_state_pseudo_class_function_dir,
+      .cb.failed = lxb_css_state_failed, .cb.end = lxb_css_selectors_state_function_end}, false, false},
     {(lxb_char_t *) "has", 3, LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_HAS,
      false, LXB_CSS_SELECTOR_COMBINATOR_DESCENDANT,
-     {.state = lxb_css_selectors_state_pseudo_class_function_has, .block = NULL,
-      .failed = lxb_css_state_failed, .end = lxb_css_selectors_state_function_forgiving_relative}, true, true},
+     {.value = lxb_css_selectors_state_pseudo_class_function_has,
+      .cb.failed = lxb_css_state_failed, .cb.end = lxb_css_selectors_state_function_forgiving_relative}, true, true},
     {(lxb_char_t *) "is", 2, LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_IS,
      false, LXB_CSS_SELECTOR_COMBINATOR_CLOSE,
-     {.state = lxb_css_selectors_state_pseudo_class_function_is, .block = NULL,
-      .failed = lxb_css_state_failed, .end = lxb_css_selectors_state_function_forgiving}, true, true},
+     {.value = lxb_css_selectors_state_pseudo_class_function_is,
+      .cb.failed = lxb_css_state_failed, .cb.end = lxb_css_selectors_state_function_forgiving}, true, true},
     {(lxb_char_t *) "lang", 4, LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_LANG,
      false, LXB_CSS_SELECTOR_COMBINATOR_CLOSE,
-     {.state = lxb_css_selectors_state_pseudo_class_function_lang, .block = NULL,
-      .failed = lxb_css_state_failed, .end = lxb_css_selectors_state_function_end}, false, false},
+     {.value = lxb_css_selectors_state_pseudo_class_function_lang,
+      .cb.failed = lxb_css_state_failed, .cb.end = lxb_css_selectors_state_function_end}, false, false},
+    {(lxb_char_t *) "lexbor-contains", 15, LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_LEXBOR_CONTAINS,
+     false, LXB_CSS_SELECTOR_COMBINATOR_CLOSE,
+     {.value = lxb_css_selectors_state_pseudo_class_function_lexbor_contains,
+      .cb.failed = lxb_css_state_failed, .cb.end = lxb_css_selectors_state_function_end}, false, false},
     {(lxb_char_t *) "not", 3, LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NOT,
      false, LXB_CSS_SELECTOR_COMBINATOR_CLOSE,
-     {.state = lxb_css_selectors_state_pseudo_class_function_not, .block = NULL,
-      .failed = lxb_css_state_failed, .end = lxb_css_selectors_state_function_end}, false, true},
+     {.value = lxb_css_selectors_state_pseudo_class_function_not,
+      .cb.failed = lxb_css_state_failed, .cb.end = lxb_css_selectors_state_function_end}, false, true},
     {(lxb_char_t *) "nth-child", 9, LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_CHILD,
      false, LXB_CSS_SELECTOR_COMBINATOR_CLOSE,
-     {.state = lxb_css_selectors_state_pseudo_class_function_nth_child, .block = NULL,
-      .failed = lxb_css_state_failed, .end = lxb_css_selectors_state_function_end}, false, true},
+     {.value = lxb_css_selectors_state_pseudo_class_function_nth_child,
+      .cb.failed = lxb_css_state_failed, .cb.end = lxb_css_selectors_state_function_end}, false, true},
     {(lxb_char_t *) "nth-col", 7, LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_COL,
      false, LXB_CSS_SELECTOR_COMBINATOR_CLOSE,
-     {.state = lxb_css_selectors_state_pseudo_class_function_nth_col, .block = NULL,
-      .failed = lxb_css_state_failed, .end = lxb_css_selectors_state_function_end}, false, false},
+     {.value = lxb_css_selectors_state_pseudo_class_function_nth_col,
+      .cb.failed = lxb_css_state_failed, .cb.end = lxb_css_selectors_state_function_end}, false, false},
     {(lxb_char_t *) "nth-last-child", 14, LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_CHILD,
      false, LXB_CSS_SELECTOR_COMBINATOR_CLOSE,
-     {.state = lxb_css_selectors_state_pseudo_class_function_nth_last_child, .block = NULL,
-      .failed = lxb_css_state_failed, .end = lxb_css_selectors_state_function_end}, false, true},
+     {.value = lxb_css_selectors_state_pseudo_class_function_nth_last_child,
+      .cb.failed = lxb_css_state_failed, .cb.end = lxb_css_selectors_state_function_end}, false, true},
     {(lxb_char_t *) "nth-last-col", 12, LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_COL,
      false, LXB_CSS_SELECTOR_COMBINATOR_CLOSE,
-     {.state = lxb_css_selectors_state_pseudo_class_function_nth_last_col, .block = NULL,
-      .failed = lxb_css_state_failed, .end = lxb_css_selectors_state_function_end}, false, false},
+     {.value = lxb_css_selectors_state_pseudo_class_function_nth_last_col,
+      .cb.failed = lxb_css_state_failed, .cb.end = lxb_css_selectors_state_function_end}, false, false},
     {(lxb_char_t *) "nth-last-of-type", 16, LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_OF_TYPE,
      false, LXB_CSS_SELECTOR_COMBINATOR_CLOSE,
-     {.state = lxb_css_selectors_state_pseudo_class_function_nth_last_of_type, .block = NULL,
-      .failed = lxb_css_state_failed, .end = lxb_css_selectors_state_function_end}, false, false},
+     {.value = lxb_css_selectors_state_pseudo_class_function_nth_last_of_type,
+      .cb.failed = lxb_css_state_failed, .cb.end = lxb_css_selectors_state_function_end}, false, false},
     {(lxb_char_t *) "nth-of-type", 11, LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_OF_TYPE,
      false, LXB_CSS_SELECTOR_COMBINATOR_CLOSE,
-     {.state = lxb_css_selectors_state_pseudo_class_function_nth_of_type, .block = NULL,
-      .failed = lxb_css_state_failed, .end = lxb_css_selectors_state_function_end}, false, false},
+     {.value = lxb_css_selectors_state_pseudo_class_function_nth_of_type,
+      .cb.failed = lxb_css_state_failed, .cb.end = lxb_css_selectors_state_function_end}, false, false},
     {(lxb_char_t *) "where", 5, LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_WHERE,
      false, LXB_CSS_SELECTOR_COMBINATOR_CLOSE,
-     {.state = lxb_css_selectors_state_pseudo_class_function_where, .block = NULL,
-      .failed = lxb_css_state_failed, .end = lxb_css_selectors_state_function_forgiving}, true, true}
+     {.value = lxb_css_selectors_state_pseudo_class_function_where,
+      .cb.failed = lxb_css_state_failed, .cb.end = lxb_css_selectors_state_function_forgiving}, true, true}
 };

 static const lxb_css_selectors_pseudo_data_t lxb_css_selectors_pseudo_data_pseudo_element[LXB_CSS_SELECTOR_PSEUDO_ELEMENT__LAST_ENTRY] =
@@ -145,8 +149,8 @@ static const lxb_css_selectors_pseudo_data_func_t lxb_css_selectors_pseudo_data_
 {
     {(lxb_char_t *) "#undef", 6, LXB_CSS_SELECTOR_PSEUDO_ELEMENT_FUNCTION__UNDEF,
      false, LXB_CSS_SELECTOR_COMBINATOR_CLOSE,
-     {.state = lxb_css_selectors_state_pseudo_element_function__undef, .block = NULL,
-      .failed = lxb_css_state_failed, .end = lxb_css_selectors_state_function_end}, false, false}
+     {.value = lxb_css_selectors_state_pseudo_element_function__undef,
+      .cb.failed = lxb_css_state_failed, .cb.end = lxb_css_selectors_state_function_end}, false, false}
 };

 static const lexbor_shs_entry_t lxb_css_selectors_pseudo_class_shs[79] =
@@ -232,46 +236,50 @@ static const lexbor_shs_entry_t lxb_css_selectors_pseudo_class_shs[79] =
     {NULL, NULL, 0, 0}
 };

-static const lexbor_shs_entry_t lxb_css_selectors_pseudo_class_function_shs[39] =
+static const lexbor_shs_entry_t lxb_css_selectors_pseudo_class_function_shs[43] =
 {
-    {NULL, NULL, 38, 0},
+    {NULL, NULL, 42, 0},
+    {"nth-last-of-type", (void *) &lxb_css_selectors_pseudo_data_pseudo_class_function[LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_OF_TYPE], 16, 0},
     {NULL, NULL, 0, 0},
-    {"current", (void *) &lxb_css_selectors_pseudo_data_pseudo_class_function[LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_CURRENT], 7, 0},
     {NULL, NULL, 0, 0},
-    {"dir", (void *) &lxb_css_selectors_pseudo_data_pseudo_class_function[LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_DIR], 3, 0},
     {NULL, NULL, 0, 0},
     {NULL, NULL, 0, 0},
+    {"not", (void *) &lxb_css_selectors_pseudo_data_pseudo_class_function[LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NOT], 3, 0},
     {NULL, NULL, 0, 0},
-    {"is", (void *) &lxb_css_selectors_pseudo_data_pseudo_class_function[LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_IS], 2, 0},
     {NULL, NULL, 0, 0},
     {NULL, NULL, 0, 0},
     {NULL, NULL, 0, 0},
     {NULL, NULL, 0, 0},
     {NULL, NULL, 0, 0},
-    {"nth-child", (void *) &lxb_css_selectors_pseudo_data_pseudo_class_function[LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_CHILD], 9, 0},
     {NULL, NULL, 0, 0},
+    {"has", (void *) &lxb_css_selectors_pseudo_data_pseudo_class_function[LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_HAS], 3, 0},
     {NULL, NULL, 0, 0},
     {NULL, NULL, 0, 0},
     {NULL, NULL, 0, 0},
-    {"nth-last-child", (void *) &lxb_css_selectors_pseudo_data_pseudo_class_function[LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_CHILD], 14, 0},
     {NULL, NULL, 0, 0},
     {NULL, NULL, 0, 0},
+    {"nth-col", (void *) &lxb_css_selectors_pseudo_data_pseudo_class_function[LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_COL], 7, 0},
     {NULL, NULL, 0, 0},
-    {"where", (void *) &lxb_css_selectors_pseudo_data_pseudo_class_function[LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_WHERE], 5, 0},
+    {"lexbor-contains", (void *) &lxb_css_selectors_pseudo_data_pseudo_class_function[LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_LEXBOR_CONTAINS], 15, 0},
+    {NULL, NULL, 0, 0},
+    {"is", (void *) &lxb_css_selectors_pseudo_data_pseudo_class_function[LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_IS], 2, 0},
+    {"nth-last-col", (void *) &lxb_css_selectors_pseudo_data_pseudo_class_function[LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_COL], 12, 0},
+    {"current", (void *) &lxb_css_selectors_pseudo_data_pseudo_class_function[LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_CURRENT], 7, 0},
     {NULL, NULL, 0, 0},
     {NULL, NULL, 0, 0},
-    {"nth-col", (void *) &lxb_css_selectors_pseudo_data_pseudo_class_function[LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_COL], 7, 0},
     {"lang", (void *) &lxb_css_selectors_pseudo_data_pseudo_class_function[LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_LANG], 4, 0},
-    {"has", (void *) &lxb_css_selectors_pseudo_data_pseudo_class_function[LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_HAS], 3, 0},
     {NULL, NULL, 0, 0},
     {NULL, NULL, 0, 0},
-    {"nth-last-col", (void *) &lxb_css_selectors_pseudo_data_pseudo_class_function[LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_COL], 12, 0},
-    {"nth-of-type", (void *) &lxb_css_selectors_pseudo_data_pseudo_class_function[LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_OF_TYPE], 11, 0},
+    {"nth-child", (void *) &lxb_css_selectors_pseudo_data_pseudo_class_function[LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_CHILD], 9, 0},
     {NULL, NULL, 0, 0},
     {NULL, NULL, 0, 0},
     {NULL, NULL, 0, 0},
-    {"not", (void *) &lxb_css_selectors_pseudo_data_pseudo_class_function[LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NOT], 3, 0},
-    {"nth-last-of-type", (void *) &lxb_css_selectors_pseudo_data_pseudo_class_function[LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_OF_TYPE], 16, 0},
+    {NULL, NULL, 0, 0},
+    {"nth-last-child", (void *) &lxb_css_selectors_pseudo_data_pseudo_class_function[LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_CHILD], 14, 0},
+    {"nth-of-type", (void *) &lxb_css_selectors_pseudo_data_pseudo_class_function[LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_OF_TYPE], 11, 0},
+    {NULL, NULL, 0, 0},
+    {"dir", (void *) &lxb_css_selectors_pseudo_data_pseudo_class_function[LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_DIR], 3, 0},
+    {"where", (void *) &lxb_css_selectors_pseudo_data_pseudo_class_function[LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_WHERE], 5, 0},
     {NULL, NULL, 0, 0}
 };

diff --git a/ext/dom/lexbor/lexbor/css/selectors/pseudo_state.c b/ext/dom/lexbor/lexbor/css/selectors/pseudo_state.c
index f40b089d130..263ca52f35e 100644
--- a/ext/dom/lexbor/lexbor/css/selectors/pseudo_state.c
+++ b/ext/dom/lexbor/lexbor/css/selectors/pseudo_state.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020-2022 Alexander Borisov
+ * Copyright (C) 2020-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -27,10 +27,9 @@ lxb_css_selectors_state_pseudo_of_back(lxb_css_parser_t *parser,


 static const lxb_css_syntax_cb_components_t lxb_css_selectors_comp = {
-    .state = lxb_css_selectors_state_complex_list,
-    .block = NULL,
-    .failed = lxb_css_state_failed,
-    .end = lxb_css_selectors_state_pseudo_of_end
+    .prelude = lxb_css_selectors_state_complex_list,
+    .cb.failed = lxb_css_state_failed,
+    .cb.end = lxb_css_selectors_state_pseudo_of_end
 };


@@ -182,6 +181,117 @@ lxb_css_selectors_state_pseudo_element_function__undef(lxb_css_parser_t *parser,
     return true;
 }

+bool
+lxb_css_selectors_state_pseudo_class_function_lexbor_contains(lxb_css_parser_t *parser,
+                                const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_selectors_t *selectors;
+    lxb_css_selector_t *selector;
+    lxb_css_selector_contains_t *contains;
+    lexbor_str_t *str;
+    const lxb_char_t *data;
+    size_t length;
+
+    selectors = parser->selectors;
+    selector = selectors->list_last->last;
+
+again:
+
+    switch (token->type) {
+        case LXB_CSS_SYNTAX_TOKEN_STRING:
+            data = token->types.string.data;
+            length = token->types.string.length;
+            break;
+
+        case LXB_CSS_SYNTAX_TOKEN_IDENT:
+            data = token->types.ident.data;
+            length = token->types.ident.length;
+            break;
+
+        case LXB_CSS_SYNTAX_TOKEN_WHITESPACE:
+            lxb_css_syntax_parser_consume(parser);
+            lxb_css_parser_token_status_m(parser, token);
+            goto again;
+
+        default:
+            lxb_css_parser_unexpected_data(parser, token);
+            return lxb_css_parser_failed(parser);
+    }
+
+    contains = lexbor_mraw_alloc(parser->memory->mraw,
+                            sizeof(lxb_css_selector_contains_t));
+    if (contains == NULL) {
+        return lxb_css_parser_memory_fail(parser);
+    }
+
+    contains->insensitive = false;
+    str = &contains->str;
+
+    str->data = lexbor_mraw_alloc(parser->memory->mraw,
+                                  sizeof(lexbor_str_t));
+    if (str->data == NULL) {
+        return lxb_css_parser_memory_fail(parser);
+    }
+
+    memcpy(str->data, data, length + 1);
+
+    str->length = length;
+    str->data[length] = '\0';
+
+    selector->u.pseudo.data = contains;
+
+again_end:
+
+    lxb_css_syntax_parser_consume(parser);
+    lxb_css_parser_token_status_m(parser, token);
+
+    switch (token->type) {
+        case LXB_CSS_SYNTAX_TOKEN__END:
+            break;
+
+        case LXB_CSS_SYNTAX_TOKEN_WHITESPACE:
+            goto again_end;
+
+        case LXB_CSS_SYNTAX_TOKEN_IDENT:
+            data = token->types.ident.data;
+            length = token->types.ident.length;
+
+            if (length == 1 && (*data == 'i' || *data == 'I')) {
+                contains->insensitive = true;
+
+                lxb_css_syntax_parser_consume(parser);
+                lxb_css_parser_token_status_m(parser, token);
+
+                if (token->type == LXB_CSS_SYNTAX_TOKEN_WHITESPACE) {
+                    lxb_css_syntax_parser_consume(parser);
+                    lxb_css_parser_token_status_m(parser, token);
+                }
+
+                if (token->type != LXB_CSS_SYNTAX_TOKEN__END) {
+                    goto failed;
+                }
+
+                break;
+            }
+            /* Fall through. */
+
+        default:
+            goto failed;
+    }
+
+    parser->selectors->list = NULL;
+
+    return lxb_css_parser_success(parser);
+
+failed:
+
+    lexbor_mraw_free(parser->memory->mraw, contains->str.data);
+    lexbor_mraw_free(parser->memory->mraw, contains);
+
+    lxb_css_parser_unexpected_data(parser, token);
+    return lxb_css_parser_failed(parser);
+}
+
 static bool
 lxb_css_selectors_state_pseudo_anb(lxb_css_parser_t *parser,
                                    const lxb_css_syntax_token_t *token,
@@ -268,10 +378,14 @@ lxb_css_selectors_state_pseudo_of_begin(lxb_css_parser_t *parser,
                 return lxb_css_parser_memory_fail(parser);
             }

-            rule = lxb_css_syntax_parser_components_push(parser, token,
+            rule = lxb_css_syntax_parser_components_push(parser,
+                                                         &lxb_css_selectors_comp,
                                                          lxb_css_selectors_state_pseudo_of_back,
-                                                         &lxb_css_selectors_comp, list,
-                                                         LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS);
+                                                         list, LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS);
+//            rule = lxb_css_syntax_parser_components_push(parser, token,
+//                                                         lxb_css_selectors_state_pseudo_of_back,
+//                                                         &lxb_css_selectors_comp, list,
+//                                                         LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS);
             if (rule == NULL) {
                 lexbor_mraw_free(parser->memory->mraw,
                                  list->last->u.pseudo.data);
diff --git a/ext/dom/lexbor/lexbor/css/selectors/pseudo_state.h b/ext/dom/lexbor/lexbor/css/selectors/pseudo_state.h
index 5c5a31f9458..652e455f1f1 100644
--- a/ext/dom/lexbor/lexbor/css/selectors/pseudo_state.h
+++ b/ext/dom/lexbor/lexbor/css/selectors/pseudo_state.h
@@ -77,6 +77,10 @@ LXB_API bool
 lxb_css_selectors_state_pseudo_element_function__undef(lxb_css_parser_t *parser,
     const lxb_css_syntax_token_t *token, void *ctx);

+LXB_API bool
+lxb_css_selectors_state_pseudo_class_function_lexbor_contains(lxb_css_parser_t *parser,
+    const lxb_css_syntax_token_t *token, void *ctx);
+

 #ifdef __cplusplus
 } /* extern "C" */
diff --git a/ext/dom/lexbor/lexbor/css/selectors/selector.c b/ext/dom/lexbor/lexbor/css/selectors/selector.c
index e8bf96ba88c..160d19fa45a 100644
--- a/ext/dom/lexbor/lexbor/css/selectors/selector.c
+++ b/ext/dom/lexbor/lexbor/css/selectors/selector.c
@@ -638,11 +638,45 @@ lxb_css_selector_serialize_class(lxb_css_selector_t *selector,
     return LXB_STATUS_OK;
 }

+static lxb_status_t
+lxb_css_selector_serialize_escape_write(lxb_char_t *p, lxb_char_t *end,
+                                        lexbor_serialize_cb_f cb, void *ctx)
+{
+    lxb_char_t *begin;
+    lxb_status_t status;
+
+    begin = p;
+
+    lxb_css_selector_serialize_write("\"", 1);
+
+    while (p < end) {
+        if (*p == '"') {
+            if (begin < p) {
+                lxb_css_selector_serialize_write(begin, p - begin);
+            }
+
+            lxb_css_selector_serialize_write("\\000022", 7);
+
+            begin = p + 1;
+        }
+
+        p++;
+    }
+
+    if (begin < p) {
+        lxb_css_selector_serialize_write(begin, p - begin);
+    }
+
+    lxb_css_selector_serialize_write("\"", 1);
+
+    return LXB_STATUS_OK;
+}
+
 static lxb_status_t
 lxb_css_selector_serialize_attribute(lxb_css_selector_t *selector,
                                      lexbor_serialize_cb_f cb, void *ctx)
 {
-    lxb_char_t *p, *begin, *end;
+    lxb_char_t *p, *end;
     lxb_status_t status;
     lxb_css_selector_attribute_t *attr;

@@ -686,30 +720,11 @@ lxb_css_selector_serialize_attribute(lxb_css_selector_t *selector,
     p = attr->value.data;
     end = attr->value.data + attr->value.length;

-    begin = p;
-
-    lxb_css_selector_serialize_write("\"", 1);
-
-    while (p < end) {
-        if (*p == '"') {
-            if (begin < p) {
-                lxb_css_selector_serialize_write(begin, p - begin);
-            }
-
-            lxb_css_selector_serialize_write("\\000022", 7);
-
-            begin = p + 1;
-        }
-
-        p++;
-    }
-
-    if (begin < p) {
-        lxb_css_selector_serialize_write(begin, p - begin);
+    status = lxb_css_selector_serialize_escape_write(p, end, cb, ctx);
+    if (status != LXB_STATUS_OK) {
+        return status;
     }

-    lxb_css_selector_serialize_write("\"", 1);
-
     if (attr->modifier != LXB_CSS_SELECTOR_MODIFIER_UNSET) {
         switch (attr->modifier) {
             case LXB_CSS_SELECTOR_MODIFIER_I:
@@ -740,7 +755,9 @@ lxb_css_selector_serialize_pseudo_class_function(lxb_css_selector_t *selector,
                                                  lexbor_serialize_cb_f cb, void *ctx)
 {
     lxb_status_t status;
+    lxb_char_t *p, *end;
     lxb_css_selector_pseudo_t *pseudo;
+    lxb_css_selector_contains_t *contains;
     const lxb_css_selectors_pseudo_data_func_t *pfunc;

     pseudo = &selector->u.pseudo;
@@ -789,6 +806,22 @@ lxb_css_selector_serialize_pseudo_class_function(lxb_css_selector_t *selector,
                                                            cb, ctx);
             break;

+        case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_LEXBOR_CONTAINS:
+            contains = pseudo->data;
+            p = contains->str.data;
+            end = p + contains->str.length;
+
+            status = lxb_css_selector_serialize_escape_write(p, end, cb, ctx);
+            if (status != LXB_STATUS_OK) {
+                return status;
+            }
+
+            if (contains->insensitive) {
+                lxb_css_selector_serialize_write(" i", 2);
+            }
+
+            break;
+
         default:
             status = LXB_STATUS_OK;
             break;
diff --git a/ext/dom/lexbor/lexbor/css/selectors/selector.h b/ext/dom/lexbor/lexbor/css/selectors/selector.h
index 52dbabc7ba5..1862c868c8c 100644
--- a/ext/dom/lexbor/lexbor/css/selectors/selector.h
+++ b/ext/dom/lexbor/lexbor/css/selectors/selector.h
@@ -80,6 +80,12 @@ typedef struct {
 }
 lxb_css_selector_anb_of_t;

+typedef struct {
+    lexbor_str_t str;
+    bool         insensitive;
+}
+lxb_css_selector_contains_t;
+
 struct lxb_css_selector {
     lxb_css_selector_type_t       type;
     lxb_css_selector_combinator_t combinator;
diff --git a/ext/dom/lexbor/lexbor/css/selectors/selectors.c b/ext/dom/lexbor/lexbor/css/selectors/selectors.c
index 52537873ef0..77586f4a65c 100644
--- a/ext/dom/lexbor/lexbor/css/selectors/selectors.c
+++ b/ext/dom/lexbor/lexbor/css/selectors/selectors.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020-2022 Alexander Borisov
+ * Copyright (C) 2020-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -20,59 +20,51 @@ lxb_css_selectors_components_end(lxb_css_parser_t *parser,


 static const lxb_css_syntax_cb_components_t lxb_css_selectors_complex_list_cb = {
-    .state = lxb_css_selectors_state_complex_list,
-    .block = NULL,
-    .failed = lxb_css_state_failed,
-    .end = lxb_css_selectors_components_end
+    .prelude = lxb_css_selectors_state_complex_list,
+    .cb.failed = lxb_css_state_failed,
+    .cb.end = lxb_css_selectors_components_end
 };

 static const lxb_css_syntax_cb_components_t lxb_css_selectors_compound_list_cb = {
-    .state = lxb_css_selectors_state_compound_list,
-    .block = NULL,
-    .failed = lxb_css_state_failed,
-    .end = lxb_css_selectors_components_end
+    .prelude = lxb_css_selectors_state_compound_list,
+    .cb.failed = lxb_css_state_failed,
+    .cb.end = lxb_css_selectors_components_end
 };

 static const lxb_css_syntax_cb_components_t lxb_css_selectors_simple_list_cb = {
-    .state = lxb_css_selectors_state_simple_list,
-    .block = NULL,
-    .failed = lxb_css_state_failed,
-    .end = lxb_css_selectors_components_end
+    .prelude = lxb_css_selectors_state_simple_list,
+    .cb.failed = lxb_css_state_failed,
+    .cb.end = lxb_css_selectors_components_end
 };

 static const lxb_css_syntax_cb_components_t lxb_css_selectors_relative_list_cb = {
-    .state = lxb_css_selectors_state_relative_list,
-    .block = NULL,
-    .failed = lxb_css_state_failed,
-    .end = lxb_css_selectors_components_end
+    .prelude = lxb_css_selectors_state_relative_list,
+    .cb.failed = lxb_css_state_failed,
+    .cb.end = lxb_css_selectors_components_end
 };

 static const lxb_css_syntax_cb_components_t lxb_css_selectors_complex_cb = {
-    .state = lxb_css_selectors_state_complex,
-    .block = NULL,
-    .failed = lxb_css_state_failed,
-    .end = lxb_css_selectors_components_end
+    .prelude = lxb_css_selectors_state_complex,
+    .cb.failed = lxb_css_state_failed,
+    .cb.end = lxb_css_selectors_components_end
 };

 static const lxb_css_syntax_cb_components_t lxb_css_selectors_compound_cb = {
-    .state = lxb_css_selectors_state_compound,
-    .block = NULL,
-    .failed = lxb_css_state_failed,
-    .end = lxb_css_selectors_components_end
+    .prelude = lxb_css_selectors_state_compound,
+    .cb.failed = lxb_css_state_failed,
+    .cb.end = lxb_css_selectors_components_end
 };

 static const lxb_css_syntax_cb_components_t lxb_css_selectors_simple_cb = {
-    .state = lxb_css_selectors_state_simple,
-    .block = NULL,
-    .failed = lxb_css_state_failed,
-    .end = lxb_css_selectors_components_end
+    .prelude = lxb_css_selectors_state_simple,
+    .cb.failed = lxb_css_state_failed,
+    .cb.end = lxb_css_selectors_components_end
 };

 static const lxb_css_syntax_cb_components_t lxb_css_selectors_relative_cb = {
-    .state = lxb_css_selectors_state_relative,
-    .block = NULL,
-    .failed = lxb_css_state_failed,
-    .end = lxb_css_selectors_components_end
+    .prelude = lxb_css_selectors_state_relative,
+    .cb.failed = lxb_css_state_failed,
+    .cb.end = lxb_css_selectors_components_end
 };


@@ -170,9 +162,7 @@ lxb_css_selectors_parse_relative_list(lxb_css_parser_t *parser,
 }

 static lxb_status_t
-lxb_css_selectors_parse_prepare(lxb_css_parser_t *parser,
-                                lxb_css_memory_t *memory,
-                                lxb_css_selectors_t *selectors)
+lxb_css_selectors_parse_prepare(lxb_css_parser_t *parser)
 {
     if (parser->stage != LXB_CSS_PARSER_CLEAN) {
         if (parser->stage == LXB_CSS_PARSER_RUN) {
@@ -185,12 +175,6 @@ lxb_css_selectors_parse_prepare(lxb_css_parser_t *parser,
     parser->tkz->with_comment = false;
     parser->stage = LXB_CSS_PARSER_RUN;

-    parser->old_memory = parser->memory;
-    parser->old_selectors = parser->selectors;
-
-    parser->memory = memory;
-    parser->selectors = selectors;
-
     return LXB_STATUS_OK;
 }

@@ -203,8 +187,7 @@ lxb_css_selectors_parse_process(lxb_css_parser_t *parser,

     lxb_css_parser_buffer_set(parser, data, length);

-    rule = lxb_css_syntax_parser_components_push(parser, NULL, NULL,
-                                                 components, NULL,
+    rule = lxb_css_syntax_parser_components_push(parser, components, NULL, NULL,
                                                  LXB_CSS_SYNTAX_TOKEN_UNDEF);
     if (rule == NULL) {
         return NULL;
@@ -222,9 +205,6 @@ static void
 lxb_css_selectors_parse_finish(lxb_css_parser_t *parser)
 {
     parser->stage = LXB_CSS_PARSER_END;
-
-    parser->memory = parser->old_memory;
-    parser->selectors = parser->old_selectors;
 }

 static lxb_css_selector_list_t *
@@ -232,41 +212,45 @@ lxb_css_selectors_parse_list(lxb_css_parser_t *parser,
                              const lxb_css_syntax_cb_components_t *components,
                              const lxb_char_t *data, size_t length)
 {
-    lxb_css_memory_t *memory;
-    lxb_css_selectors_t *selectors;
+    bool my_mem, my_selectors;
     lxb_css_selector_list_t *list;

-    memory = parser->memory;
-    selectors = parser->selectors;
+    my_mem = false;
+    my_selectors = false;

-    if (selectors == NULL) {
-        selectors = lxb_css_selectors_create();
-        parser->status = lxb_css_selectors_init(selectors);
+    if (parser->selectors == NULL) {
+        parser->selectors = lxb_css_selectors_create();
+        parser->status = lxb_css_selectors_init(parser->selectors);

         if (parser->status != LXB_STATUS_OK) {
-            (void) lxb_css_selectors_destroy(selectors, true);
+            (void) lxb_css_selectors_destroy(parser->selectors, true);
             return NULL;
         }
+
+        my_selectors = true;
     }
     else {
-        lxb_css_selectors_clean(selectors);
+        lxb_css_selectors_clean(parser->selectors);
     }

-    if (memory == NULL) {
-        memory = lxb_css_memory_create();
-        parser->status = lxb_css_memory_init(memory, 256);
+    if (parser->memory == NULL) {
+        parser->memory = lxb_css_memory_create();
+        parser->status = lxb_css_memory_init(parser->memory, 256);

         if (parser->status != LXB_STATUS_OK) {
-            if (selectors != parser->selectors) {
-                (void) lxb_css_selectors_destroy(selectors, true);
+            if (my_selectors) {
+                parser->selectors = lxb_css_selectors_destroy(parser->selectors,
+                                                              true);
             }

-            (void) lxb_css_memory_destroy(memory, true);
+            (void) lxb_css_memory_destroy(parser->memory, true);
             return NULL;
         }
+
+        my_mem = true;
     }

-    parser->status = lxb_css_selectors_parse_prepare(parser, memory, selectors);
+    parser->status = lxb_css_selectors_parse_prepare(parser);
     if (parser->status != LXB_STATUS_OK) {
         list = NULL;
         goto end;
@@ -278,12 +262,12 @@ lxb_css_selectors_parse_list(lxb_css_parser_t *parser,

 end:

-    if (list == NULL && memory != parser->memory) {
-        (void) lxb_css_memory_destroy(memory, true);
+    if (list == NULL && my_mem) {
+        parser->memory = lxb_css_memory_destroy(parser->memory, true);
     }

-    if (selectors != parser->selectors) {
-        (void) lxb_css_selectors_destroy(selectors, true);
+    if (my_selectors) {
+        parser->selectors = lxb_css_selectors_destroy(parser->selectors, true);
     }

     return list;
diff --git a/ext/dom/lexbor/lexbor/css/selectors/state.c b/ext/dom/lexbor/lexbor/css/selectors/state.c
index 873e7d31cfd..1f0a391ac29 100644
--- a/ext/dom/lexbor/lexbor/css/selectors/state.c
+++ b/ext/dom/lexbor/lexbor/css/selectors/state.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020-2022 Alexander Borisov
+ * Copyright (C) 2020-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -1557,8 +1557,8 @@ lxb_css_selectors_state_pseudo_class_function(lxb_css_parser_t *parser,
     selectors->comb_default = func->combinator;
     selectors->parent = selector;

-    rule = lxb_css_syntax_parser_function_push(parser, token, success,
-                                               &func->cb, selectors->list_last);
+    rule = lxb_css_syntax_consume_function(parser, token, &func->cb,
+                                           success, selectors->list_last);
     if (rule == NULL) {
         goto failed;
     }
@@ -1663,8 +1663,8 @@ lxb_css_selectors_state_pseudo_element_function(lxb_css_parser_t *parser,
     selectors->comb_default = func->combinator;
     selectors->parent = selector;

-    rule = lxb_css_syntax_parser_function_push(parser, token, success,
-                                               &func->cb, selectors->list_last);
+    rule = lxb_css_syntax_consume_function(parser, token, &func->cb,
+                                           success, selectors->list_last);
     if (rule == NULL) {
         (void) lxb_css_parser_memory_fail(parser);
         return parser->status;
@@ -1711,7 +1711,7 @@ lxb_css_selectors_state_function_end(lxb_css_parser_t *parser,
     lxb_css_selectors_t *selectors = parser->selectors;

     if (token->type == LXB_CSS_SYNTAX_TOKEN__EOF) {
-        (void) lxb_css_log_format(parser->log, LXB_CSS_LOG_ERROR,
+        (void) lxb_css_log_format(parser->log, LXB_CSS_LOG_SYNTAX_ERROR,
                                   "%s. End Of File in pseudo function",
                                   lxb_css_selectors_module_name);
     }
@@ -1737,7 +1737,7 @@ lxb_css_selectors_state_function_end(lxb_css_parser_t *parser,
         return LXB_STATUS_OK;
     }

-    (void) lxb_css_log_format(parser->log, LXB_CSS_LOG_ERROR,
+    (void) lxb_css_log_format(parser->log, LXB_CSS_LOG_SYNTAX_ERROR,
                               "%s. Pseudo function can't be empty: %S()",
                               lxb_css_selectors_module_name, &selector->name);

@@ -1783,7 +1783,7 @@ lxb_css_selectors_state_forgiving_cb(lxb_css_parser_t *parser,
     lxb_css_parser_set_ok(parser);

     if (token->type == LXB_CSS_SYNTAX_TOKEN__EOF) {
-        (void) lxb_css_log_format(parser->log, LXB_CSS_LOG_ERROR,
+        (void) lxb_css_log_format(parser->log, LXB_CSS_LOG_SYNTAX_ERROR,
                                   "%s. End Of File in pseudo function",
                                   lxb_css_selectors_module_name);
     }
@@ -1814,7 +1814,7 @@ lxb_css_selectors_state_forgiving_cb(lxb_css_parser_t *parser,
         return LXB_STATUS_OK;
     }

-    (void) lxb_css_log_format(parser->log, LXB_CSS_LOG_ERROR,
+    (void) lxb_css_log_format(parser->log, LXB_CSS_LOG_SYNTAX_ERROR,
                               "%s. Pseudo function can't be empty: %S()",
                               lxb_css_selectors_module_name, &selector->name);

diff --git a/ext/dom/lexbor/lexbor/css/state.c b/ext/dom/lexbor/lexbor/css/state.c
index 15a9614948f..dda5310a967 100644
--- a/ext/dom/lexbor/lexbor/css/state.c
+++ b/ext/dom/lexbor/lexbor/css/state.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021-2022 Alexander Borisov
+ * Copyright (C) 2021-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -9,6 +9,143 @@
 #include "lexbor/css/at_rule/state.h"


+static bool
+lxb_css_state_list_rules_next(lxb_css_parser_t *parser,
+                              const lxb_css_syntax_token_t *token, void *ctx);
+
+static lxb_status_t
+lxb_css_state_list_rules_end(lxb_css_parser_t *parser,
+                             const lxb_css_syntax_token_t *token,
+                             void *ctx, bool failed);
+
+static const lxb_css_syntax_cb_at_rule_t *
+lxb_css_state_at_rule_begin(lxb_css_parser_t *parser,
+                            const lxb_css_syntax_token_t *token, void *ctx,
+                            void **out_rule);
+
+static bool
+lxb_css_state_at_rule_prelude(lxb_css_parser_t *parser,
+                              const lxb_css_syntax_token_t *token,
+                              void *ctx);
+
+static lxb_status_t
+lxb_css_state_at_rule_prelude_end(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token,
+                                  void *ctx, bool failed);
+static bool
+lxb_css_state_at_rule_prelude_failed(lxb_css_parser_t *parser,
+                                     const lxb_css_syntax_token_t *token,
+                                     void *ctx);
+static lxb_status_t
+lxb_css_state_at_rule_end(lxb_css_parser_t *parser,
+                          const lxb_css_syntax_token_t *token,
+                          void *ctx, bool failed);
+
+static const lxb_css_syntax_cb_qualified_rule_t *
+lxb_css_state_qualified_rule_begin(lxb_css_parser_t *parser,
+                                   const lxb_css_syntax_token_t *token,
+                                   void *ctx, void **out_rule);
+
+static bool
+lxb_css_state_qualified_rule_prelude(lxb_css_parser_t *parser,
+                                     const lxb_css_syntax_token_t *token,
+                                     void *ctx);
+
+static lxb_status_t
+lxb_css_state_qualified_rule_prelude_end(lxb_css_parser_t *parser,
+                                         const lxb_css_syntax_token_t *token,
+                                         void *ctx, bool failed);
+
+static const lxb_css_syntax_cb_block_t *
+lxb_css_state_qualified_rule_block_begin(lxb_css_parser_t *parser,
+                                         const lxb_css_syntax_token_t *token,
+                                         void *ctx, void **out_rule);
+
+static bool
+lxb_css_state_qualified_rule_prelude_failed(lxb_css_parser_t *parser,
+                                            const lxb_css_syntax_token_t *token,
+                                            void *ctx);
+static lxb_status_t
+lxb_css_state_qualified_rule_end(lxb_css_parser_t *parser,
+                                 const lxb_css_syntax_token_t *token,
+                                 void *ctx, bool failed);
+static bool
+lxb_css_state_block_next(lxb_css_parser_t *parser,
+                         const lxb_css_syntax_token_t *token, void *ctx);
+
+static lxb_status_t
+lxb_css_state_block_end(lxb_css_parser_t *parser,
+                        const lxb_css_syntax_token_t *token,
+                        void *ctx, bool failed);
+
+static const lxb_css_syntax_cb_declarations_t *
+lxb_css_state_declarations_begin(lxb_css_parser_t *parser,
+                                 const lxb_css_syntax_token_t *token,
+                                 void *ctx, void **out_rule);
+
+static lxb_css_parser_state_f
+lxb_css_state_declaration_name(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token,
+                               void *ctx, void **out_rule);
+
+static lxb_status_t
+lxb_css_state_declaration_end(lxb_css_parser_t *parser,
+                              void *declarations, void *ctx,
+                              const lxb_css_syntax_token_t *token,
+                              lxb_css_syntax_declaration_offset_t *offset,
+                              bool important, bool failed);
+
+static lxb_status_t
+lxb_css_state_declarations_end(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token,
+                               void *ctx, bool failed);
+
+static bool
+lxb_css_state_declarations_bad(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token, void *ctx);
+
+
+static const lxb_css_syntax_cb_list_rules_t lxb_css_state_list_rules = {
+    .at_rule = lxb_css_state_at_rule_begin,
+    .qualified_rule = lxb_css_state_qualified_rule_begin,
+    .next = lxb_css_state_list_rules_next,
+    .cb.failed = lxb_css_state_failed,
+    .cb.end = lxb_css_state_list_rules_end
+};
+
+static const lxb_css_syntax_cb_at_rule_t lxb_css_state_at_rule = {
+    .prelude = lxb_css_state_at_rule_prelude,
+    .prelude_end = lxb_css_state_at_rule_prelude_end,
+    .block = lxb_css_state_at_rule_block_begin,
+    .cb.failed = lxb_css_state_at_rule_prelude_failed,
+    .cb.end = lxb_css_state_at_rule_end
+};
+
+static const lxb_css_syntax_cb_qualified_rule_t lxb_css_state_qualified_rule = {
+    .prelude = lxb_css_state_qualified_rule_prelude,
+    .prelude_end = lxb_css_state_qualified_rule_prelude_end,
+    .block = lxb_css_state_qualified_rule_block_begin,
+    .cb.failed = lxb_css_state_qualified_rule_prelude_failed,
+    .cb.end = lxb_css_state_qualified_rule_end
+};
+
+static const lxb_css_syntax_cb_block_t lxb_css_state_block = {
+    .at_rule = lxb_css_state_at_rule_begin,
+    .declarations = lxb_css_state_declarations_begin,
+    .qualified_rule = lxb_css_state_qualified_rule_begin,
+    .next = lxb_css_state_block_next,
+    .cb.failed = lxb_css_state_failed,
+    .cb.end = lxb_css_state_block_end,
+};
+
+static const lxb_css_syntax_cb_declarations_t lxb_css_state_declaration = {
+    .name = lxb_css_state_declaration_name,
+    .end = lxb_css_state_declaration_end,
+    .cb.failed = lxb_css_state_declarations_bad,
+    .cb.end = lxb_css_state_declarations_end
+};
+
+
 bool
 lxb_css_state_success(lxb_css_parser_t *parser,
                       const lxb_css_syntax_token_t *token, void *ctx)
@@ -49,3 +186,491 @@ lxb_css_state_stop(lxb_css_parser_t *parser,
 {
     return lxb_css_parser_stop(parser);
 }
+
+bool
+lxb_css_state_blank(lxb_css_parser_t *parser,
+                    const lxb_css_syntax_token_t *token, void *ctx)
+{
+    return lxb_css_parser_success(parser);
+}
+
+const lxb_css_syntax_cb_list_rules_t *
+lxb_css_state_cb_list_rules(void)
+{
+    return &lxb_css_state_list_rules;
+}
+
+const lxb_css_syntax_cb_at_rule_t *
+lxb_css_state_cb_at_rule(void)
+{
+    return &lxb_css_state_at_rule;
+}
+
+const lxb_css_syntax_cb_qualified_rule_t *
+lxb_css_state_cb_qualified_rule(void)
+{
+    return &lxb_css_state_qualified_rule;
+}
+
+const lxb_css_syntax_cb_block_t *
+lxb_css_state_cb_block(void)
+{
+    return &lxb_css_state_block;
+}
+
+const lxb_css_syntax_cb_declarations_t *
+lxb_css_state_cb_declarations(void)
+{
+    return &lxb_css_state_declaration;
+}
+
+static bool
+lxb_css_state_list_rules_next(lxb_css_parser_t *parser,
+                              const lxb_css_syntax_token_t *token, void *ctx)
+{
+    void *returned = lxb_css_syntax_returned(parser);
+    lxb_css_rule_list_t *list = ctx;
+
+    if (returned != NULL) {
+        lxb_css_rule_list_append(list, returned);
+    }
+
+    return lxb_css_parser_success(parser);
+}
+
+static lxb_status_t
+lxb_css_state_list_rules_end(lxb_css_parser_t *parser,
+                             const lxb_css_syntax_token_t *token,
+                             void *ctx, bool failed)
+{
+    lxb_css_rule_list_t *list = ctx;
+
+    lxb_css_syntax_set_return(parser, list);
+
+    return LXB_STATUS_OK;
+}
+
+static const lxb_css_syntax_cb_at_rule_t *
+lxb_css_state_at_rule_begin(lxb_css_parser_t *parser,
+                            const lxb_css_syntax_token_t *token, void *ctx,
+                            void **out_rule)
+{
+    lxb_css_rule_at_t *at;
+    const lxb_css_entry_at_rule_data_t *entry;
+
+    at = lxb_css_at_rule_create(parser, lxb_css_syntax_token_ident(token)->data,
+                                lxb_css_syntax_token_ident(token)->length,
+                                &entry);
+    if (at == NULL) {
+        return lxb_css_parser_memory_fail_null(parser);
+    }
+
+    *out_rule = at;
+
+    return entry->cbs;
+}
+
+static bool
+lxb_css_state_at_rule_prelude(lxb_css_parser_t *parser,
+                              const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_rule_at_t *at = ctx;
+
+    at->prelude_begin = token->offset;
+
+    while (token != NULL && token->type != LXB_CSS_SYNTAX_TOKEN__END) {
+        lxb_css_syntax_parser_consume(parser);
+        token = lxb_css_syntax_parser_token(parser);
+    }
+
+    return lxb_css_parser_success(parser);
+}
+
+static lxb_status_t
+lxb_css_state_at_rule_prelude_end(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token,
+                                  void *ctx, bool failed)
+{
+    lxb_status_t status;
+    lxb_css_rule_at_t *at = ctx;
+    lxb_css_at_rule__custom_t *custom;
+
+    at->prelude_end = token->offset;
+
+    custom = at->u.custom;
+
+    status = lxb_css_make_data(parser, &custom->prelude, at->prelude_begin,
+                               at->prelude_end);
+    if (status != LXB_STATUS_OK) {
+        return lxb_css_parser_memory_fail_status(parser);
+    }
+
+    return LXB_STATUS_OK;
+}
+
+const lxb_css_syntax_cb_block_t *
+lxb_css_state_at_rule_block_begin(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token,
+                                  void *ctx, void **out_rule)
+{
+    lxb_css_rule_list_t *list;
+
+    list = lxb_css_rule_list_create(parser->memory);
+    if (list == NULL) {
+        return lxb_css_parser_memory_fail_null(parser);
+    }
+
+    *out_rule = list;
+
+    return &lxb_css_state_block;
+}
+
+static bool
+lxb_css_state_at_rule_prelude_failed(lxb_css_parser_t *parser,
+                                     const lxb_css_syntax_token_t *token,
+                                     void *ctx)
+{
+    while (token != NULL && token->type != LXB_CSS_SYNTAX_TOKEN__END) {
+        lxb_css_syntax_parser_consume(parser);
+        token = lxb_css_syntax_parser_token(parser);
+    }
+
+    return lxb_css_parser_success(parser);
+}
+
+static lxb_status_t
+lxb_css_state_at_rule_end(lxb_css_parser_t *parser,
+                          const lxb_css_syntax_token_t *token,
+                          void *ctx, bool failed)
+{
+    lxb_css_rule_at_t *at = ctx;
+    lxb_css_rule_list_t *block = lxb_css_syntax_returned(parser);
+
+    at->u.custom->block = block;
+
+    lxb_css_syntax_set_return(parser, at);
+
+    return LXB_STATUS_OK;
+}
+
+static const lxb_css_syntax_cb_qualified_rule_t *
+lxb_css_state_qualified_rule_begin(lxb_css_parser_t *parser,
+                                   const lxb_css_syntax_token_t *token,
+                                   void *ctx, void **out_rule)
+{
+    lxb_css_rule_style_t *style;
+
+    style = lxb_css_rule_style_create(parser->memory);
+    if (style == NULL) {
+        return lxb_css_parser_memory_fail_null(parser);
+    }
+
+    *out_rule = style;
+
+    return &lxb_css_state_qualified_rule;
+}
+
+static bool
+lxb_css_state_qualified_rule_prelude(lxb_css_parser_t *parser,
+                                     const lxb_css_syntax_token_t *token,
+                                     void *ctx)
+{
+    lxb_css_rule_style_t *style = ctx;
+
+    lxb_css_selectors_clean(parser->selectors);
+    lxb_css_parser_state_set(parser, lxb_css_selectors_state_complex_list);
+
+    style->prelude_begin = token->offset;
+
+    return false;
+}
+
+static lxb_status_t
+lxb_css_state_qualified_rule_prelude_end(lxb_css_parser_t *parser,
+                                         const lxb_css_syntax_token_t *token,
+                                         void *ctx, bool failed)
+{
+    size_t begin;
+    lxb_status_t status;
+    lxb_css_rule_style_t *style = ctx;
+    lxb_css_rule_bad_style_t *bad;
+
+    if (!failed) {
+        style->selector = parser->selectors->list;
+        style->prelude_end = token->offset;
+
+        return LXB_STATUS_OK;
+    }
+
+    begin = style->prelude_begin;
+
+    (void) lxb_css_rule_style_destroy(style, true);
+
+    bad = lxb_css_rule_bad_style_create(parser->memory);
+    if (bad == NULL) {
+        return lxb_css_parser_memory_fail_status(parser);
+    }
+
+    bad->prelude_begin = begin;
+    bad->prelude_end = token->offset;
+
+    status = lxb_css_make_data(parser, &bad->selectors, bad->prelude_begin,
+                               bad->prelude_end);
+    if (status != LXB_STATUS_OK) {
+        return lxb_css_parser_memory_fail_status(parser);
+    }
+
+    lxb_css_parser_set_context(parser, bad);
+
+    return LXB_STATUS_OK;
+}
+
+static const lxb_css_syntax_cb_block_t *
+lxb_css_state_qualified_rule_block_begin(lxb_css_parser_t *parser,
+                                         const lxb_css_syntax_token_t *token,
+                                         void *ctx, void **out_rule)
+{
+    lxb_css_rule_list_t *list;
+
+    list = lxb_css_rule_list_create(parser->memory);
+    if (list == NULL) {
+        return lxb_css_parser_memory_fail_null(parser);
+    }
+
+    *out_rule = list;
+
+    return &lxb_css_state_block;
+}
+
+static bool
+lxb_css_state_qualified_rule_prelude_failed(lxb_css_parser_t *parser,
+                                            const lxb_css_syntax_token_t *token,
+                                            void *ctx)
+{
+    while (token != NULL && token->type != LXB_CSS_SYNTAX_TOKEN__END) {
+        lxb_css_syntax_parser_consume(parser);
+        token = lxb_css_syntax_parser_token(parser);
+    }
+
+    return lxb_css_parser_success(parser);
+}
+
+static lxb_status_t
+lxb_css_state_qualified_rule_end(lxb_css_parser_t *parser,
+                                 const lxb_css_syntax_token_t *token,
+                                 void *ctx, bool failed)
+{
+    lxb_css_rule_t *declrs;
+    lxb_css_rule_list_t *list;
+    lxb_css_rule_style_t *style;
+    lxb_css_rule_bad_style_t *bad;
+
+    list = lxb_css_syntax_returned(parser);
+
+    if (!failed) {
+        style = ctx;
+
+        if (list != NULL && list->first != NULL
+            && list->first->type == LXB_CSS_RULE_DECLARATION_LIST)
+        {
+            declrs = list->first;
+            style->declarations = lxb_css_rule_declaration_list(declrs);
+
+            declrs->parent = lxb_css_rule(style);
+
+            if (list->first == list->last) {
+                list->last = NULL;
+            }
+
+            if (declrs->next != NULL) {
+                declrs->next->prev = NULL;
+            }
+
+            list->first = declrs->next;
+            declrs->next = NULL;
+        }
+
+        style->child = list;
+
+        lxb_css_syntax_set_return(parser, style);
+    }
+    else {
+        bad = ctx;
+
+        if (list != NULL && list->first != NULL
+            && list->first->type == LXB_CSS_RULE_DECLARATION_LIST)
+        {
+            declrs = list->first;
+            bad->declarations = lxb_css_rule_declaration_list(declrs);
+
+            declrs->parent = lxb_css_rule(bad);
+
+            if (list->first == list->last) {
+                list->last = NULL;
+            }
+
+            if (declrs->next != NULL) {
+                declrs->next->prev = NULL;
+            }
+
+            list->first = declrs->next;
+            declrs->next = NULL;
+        }
+
+        bad->child = list;
+
+        lxb_css_syntax_set_return(parser, bad);
+    }
+
+    return LXB_STATUS_OK;
+}
+
+static bool
+lxb_css_state_block_next(lxb_css_parser_t *parser,
+                         const lxb_css_syntax_token_t *token, void *ctx)
+{
+    /* rule can be either a declaration list or an at rule.  */
+
+    lxb_css_rule_t *rule = lxb_css_syntax_returned(parser);
+    lxb_css_rule_list_t *list = ctx;
+
+    lxb_css_rule_list_append(list, rule);
+
+    return lxb_css_parser_success(parser);
+}
+
+static lxb_status_t
+lxb_css_state_block_end(lxb_css_parser_t *parser,
+                        const lxb_css_syntax_token_t *token,
+                        void *ctx, bool failed)
+{
+    lxb_css_rule_list_t *list = ctx;
+
+    lxb_css_syntax_set_return(parser, list);
+
+    return LXB_STATUS_OK;
+}
+
+static const lxb_css_syntax_cb_declarations_t *
+lxb_css_state_declarations_begin(lxb_css_parser_t *parser,
+                                 const lxb_css_syntax_token_t *token,
+                                 void *ctx, void **out_rule)
+{
+    lxb_css_rule_declaration_list_t *list;
+
+    list = lxb_css_rule_declaration_list_create(parser->memory);
+    if (list == NULL) {
+        return lxb_css_parser_memory_fail_null(parser);
+    }
+
+    *out_rule = list;
+
+    return &lxb_css_state_declaration;
+}
+
+static lxb_css_parser_state_f
+lxb_css_state_declaration_name(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token,
+                               void *ctx, void **out_rule)
+{
+    const lxb_css_entry_data_t *entry;
+    lxb_css_rule_declaration_t *declar;
+
+    declar = lxb_css_declaration_create(parser,
+                                        lxb_css_syntax_token_ident(token)->data,
+                                        lxb_css_syntax_token_ident(token)->length,
+                                        &entry);
+    if (declar == NULL) {
+        (void) lxb_css_parser_memory_fail_null(parser);
+        return NULL;
+    }
+
+    /* We present an original position. */
+
+    declar->offset.name_begin = token->offset;
+    declar->offset.name_end = token->offset
+                                + lxb_css_syntax_token_base(token)->length;
+    *out_rule = declar;
+
+    return entry->state;
+}
+
+static lxb_status_t
+lxb_css_state_declaration_end(lxb_css_parser_t *parser,
+                              void *declarations, void *ctx,
+                              const lxb_css_syntax_token_t *token,
+                              lxb_css_syntax_declaration_offset_t *offset,
+                              bool important, bool failed)
+{
+    lxb_status_t status;
+    lxb_css_property__undef_t *undef;
+    lxb_css_rule_declaration_t *declar = ctx;
+    lxb_css_rule_declaration_list_t *list = declarations;
+
+    declar->offset.value_begin = offset->value_begin;
+    declar->offset.value_end = offset->value_end;
+    declar->offset.important_begin = offset->important_begin;
+    declar->offset.important_end = offset->important_end;
+    declar->important = important;
+
+    if (failed) {
+        lxb_css_rule_declaration_destroy(declar, false);
+
+        undef = lxb_css_property__undef_create(parser->memory);
+        if (undef == NULL) {
+            return lxb_css_parser_memory_fail_status(parser);
+        }
+
+        undef->type = declar->type;
+
+        status = lxb_css_make_data(parser, &undef->value,
+                                   declar->offset.value_begin,
+                                   declar->offset.value_end);
+        if (status != LXB_STATUS_OK) {
+            return lxb_css_parser_memory_fail_status(parser);
+        }
+
+        declar->u.undef = undef;
+        declar->type = LXB_CSS_PROPERTY__UNDEF;
+    }
+
+    lxb_css_rule_declaration_list_append(list, lxb_css_rule(declar));
+
+    return LXB_STATUS_OK;
+}
+
+static lxb_status_t
+lxb_css_state_declarations_end(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token,
+                               void *ctx, bool failed)
+{
+    lxb_css_rule_declaration_list_t *list = ctx;
+
+    lxb_css_syntax_set_return(parser, list);
+
+    return LXB_STATUS_OK;
+}
+
+static bool
+lxb_css_state_declarations_bad(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token, void *ctx)
+{
+    lxb_css_rule_declaration_t *declar;
+
+    if (ctx == NULL) {
+        declar = lxb_css_rule_declaration_create(parser->memory);
+        if (declar == NULL) {
+            return lxb_css_parser_memory_fail(parser);
+        }
+
+        lxb_css_parser_current_rule(parser)->context = declar;
+        declar->type = LXB_CSS_PROPERTY__UNDEF;
+    }
+
+    while (token != NULL && token->type != LXB_CSS_SYNTAX_TOKEN__END) {
+        lxb_css_syntax_parser_consume(parser);
+        token = lxb_css_syntax_parser_token(parser);
+    }
+
+    return lxb_css_parser_success(parser);
+}
diff --git a/ext/dom/lexbor/lexbor/css/state.h b/ext/dom/lexbor/lexbor/css/state.h
index 0a2abd80363..6ecd5034392 100644
--- a/ext/dom/lexbor/lexbor/css/state.h
+++ b/ext/dom/lexbor/lexbor/css/state.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021-2022 Alexander Borisov
+ * Copyright (C) 2021-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -12,6 +12,7 @@ extern "C" {
 #endif

 #include "lexbor/css/base.h"
+#include "lexbor/css/syntax/syntax.h"


 LXB_API bool
@@ -26,6 +27,30 @@ LXB_API bool
 lxb_css_state_stop(lxb_css_parser_t *parser,
                    const lxb_css_syntax_token_t *token, void *ctx);

+LXB_API bool
+lxb_css_state_blank(lxb_css_parser_t *parser,
+                    const lxb_css_syntax_token_t *token, void *ctx);
+
+LXB_API const lxb_css_syntax_cb_list_rules_t *
+lxb_css_state_cb_list_rules(void);
+
+LXB_API const lxb_css_syntax_cb_at_rule_t *
+lxb_css_state_cb_at_rule(void);
+
+LXB_API const lxb_css_syntax_cb_qualified_rule_t *
+lxb_css_state_cb_qualified_rule(void);
+
+LXB_API const lxb_css_syntax_cb_block_t *
+lxb_css_state_cb_block(void);
+
+LXB_API const lxb_css_syntax_cb_declarations_t *
+lxb_css_state_cb_declarations(void);
+
+const lxb_css_syntax_cb_block_t *
+lxb_css_state_at_rule_block_begin(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token,
+                                  void *ctx, void **out_rule);
+

 #ifdef __cplusplus
 } /* extern "C" */
diff --git a/ext/dom/lexbor/lexbor/css/stylesheet.c b/ext/dom/lexbor/lexbor/css/stylesheet.c
new file mode 100644
index 00000000000..f03f145721c
--- /dev/null
+++ b/ext/dom/lexbor/lexbor/css/stylesheet.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2021-2026 Alexander Borisov
+ *
+ * Author: Alexander Borisov <borisov@lexbor.com>
+ */
+
+#include "lexbor/css/css.h"
+#include "lexbor/css/stylesheet.h"
+#include "lexbor/css/parser.h"
+#include "lexbor/css/at_rule.h"
+#include "lexbor/css/property.h"
+#include "lexbor/css/rule.h"
+#include "lexbor/css/state.h"
+#include "lexbor/css/selectors/selectors.h"
+#include "lexbor/css/selectors/state.h"
+
+
+lxb_css_stylesheet_t *
+lxb_css_stylesheet_create(lxb_css_memory_t *memory)
+{
+    lxb_status_t status;
+    lxb_css_stylesheet_t *stylesheet;
+
+    if (memory == NULL) {
+        memory = lxb_css_memory_create();
+        status = lxb_css_memory_init(memory, 1024);
+
+        if (status != LXB_STATUS_OK) {
+            (void) lxb_css_memory_destroy(memory, true);
+            return NULL;
+        }
+    }
+    else {
+        (void) lxb_css_memory_ref_inc(memory);
+    }
+
+    stylesheet = lexbor_mraw_calloc(memory->mraw, sizeof(lxb_css_stylesheet_t));
+    if (stylesheet == NULL) {
+        return NULL;
+    }
+
+    stylesheet->memory = memory;
+
+    return stylesheet;
+}
+
+lxb_css_stylesheet_t *
+lxb_css_stylesheet_destroy(lxb_css_stylesheet_t *sst, bool destroy_memory)
+{
+    if (sst == NULL) {
+        return NULL;
+    }
+
+    if (destroy_memory) {
+        (void) lxb_css_memory_ref_dec_destroy(sst->memory);
+        return NULL;
+    }
+
+    if (sst->root != NULL) {
+        (void) lxb_css_rule_destroy(sst->root, true);
+    }
+
+    (void) lexbor_mraw_free(sst->memory->mraw, sst);
+
+    return NULL;
+}
+
+lxb_status_t
+lxb_css_stylesheet_parse(lxb_css_stylesheet_t *sst, lxb_css_parser_t *parser,
+                         const lxb_char_t *data, size_t length)
+{
+    lxb_status_t status;
+    lxb_css_rule_list_t *list;
+    lxb_css_selectors_t selectors;
+
+    if (sst == NULL || parser == NULL) {
+        return LXB_STATUS_ERROR_WRONG_ARGS;
+    }
+
+    if (parser->selectors == NULL) {
+        status = lxb_css_selectors_init(&selectors);
+        if (status != LXB_STATUS_OK) {
+            return status;
+        }
+
+        parser->selectors = &selectors;
+    }
+    else {
+        lxb_css_selectors_clean(parser->selectors);
+    }
+
+    parser->memory = sst->memory;
+
+    list = lxb_css_syntax_parse_list_rules(parser,
+                                           lxb_css_state_cb_list_rules(),
+                                           data, length);
+
+    if (parser->selectors == &selectors) {
+        parser->selectors = lxb_css_selectors_destroy(&selectors, false);
+    }
+
+    if (list == NULL) {
+        sst->root = NULL;
+        return parser->status;
+    }
+
+    sst->root = &list->rule;
+
+    return LXB_STATUS_OK;
+}
diff --git a/ext/dom/lexbor/lexbor/css/stylesheet.h b/ext/dom/lexbor/lexbor/css/stylesheet.h
index 5f3e37d82e4..9d52f9897cc 100644
--- a/ext/dom/lexbor/lexbor/css/stylesheet.h
+++ b/ext/dom/lexbor/lexbor/css/stylesheet.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020-2023 Alexander Borisov
+ * Copyright (C) 2020-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -25,26 +25,62 @@ struct lxb_css_stylesheet {
     void                     *element; /* lxb_html_style_element_t * */
 };

+/*
+ * Create a new CSS stylesheet object.
+ *
+ * This function creates a stylesheet object which holds the parsed CSS rules.
+ *
+ * @param[in] memory  Optional. A memory pool to use for allocations.
+ *                    If NULL, a new internal memory pool is created/managed
+ *                    by the stylesheet.
+ *
+ * @return A new lxb_css_stylesheet_t * or NULL on failure.
+ */
 LXB_API lxb_css_stylesheet_t *
 lxb_css_stylesheet_create(lxb_css_memory_t *memory);

+/*
+ * Destroy a CSS stylesheet object.
+ *
+ * @param[in] sst             Optional. The stylesheet object to destroy.
+ *                            If NULL, the function returns NULL.
+ * @param[in] destroy_memory  If true, the memory pool attached to
+ *                            the stylesheet is also destroyed.
+ *
+ * @return Always NULL.
+ */
 LXB_API lxb_css_stylesheet_t *
 lxb_css_stylesheet_destroy(lxb_css_stylesheet_t *sst, bool destroy_memory);

-LXB_API lxb_css_stylesheet_t *
-lxb_css_stylesheet_parse(lxb_css_parser_t *parser,
-                         const lxb_char_t *data, size_t length);
-
+/*
+ * Parse CSS content into the stylesheet.
+ *
+ * This function takes CSS text and builds the rule tree in the stylesheet.
+ *
+ * The function returns an error only in extremely unforeseen circumstances,
+ * such as the inability to allocate memory for objects. Any broken CSS will
+ * not cause an error.
+ *
+ * Selectors note:
+ *   If the provided parser does not have an initialized selectors module, one
+ *   will be created temporarily for this call. For better performance when
+ *   parsing multiple stylesheets, initialize the selectors module in
+ *   the parser once:
+ *
+ *     lxb_css_parser_t *parser = lxb_css_parser_create();
+ *     lxb_css_parser_init(parser, NULL);
+ *     lxb_css_parser_selectors_init(parser);
+ *
+ * @param[in] sst     Required. The target stylesheet.
+ * @param[in] parser  Required. An initialized CSS parser.
+ * @param[in] data    Optional. The CSS text data.
+ * @param[in] length  Required. Length of the data in bytes.
+ *
+ * @return LXB_STATUS_OK on success, or an error code on failure.
+ */
 LXB_API lxb_status_t
-lxb_css_stylesheet_prepare(lxb_css_parser_t *parser, lxb_css_memory_t *memory,
-                           lxb_css_selectors_t *selectors);
-
-LXB_API lxb_css_stylesheet_t *
-lxb_css_stylesheet_process(lxb_css_parser_t *parser,
-                           const lxb_char_t *data, size_t length);
-
-LXB_API void
-lxb_css_stylesheet_finish(lxb_css_parser_t *parser);
+lxb_css_stylesheet_parse(lxb_css_stylesheet_t *sst, lxb_css_parser_t *parser,
+                         const lxb_char_t *data, size_t length);


 #ifdef __cplusplus
diff --git a/ext/dom/lexbor/lexbor/css/syntax/anb.c b/ext/dom/lexbor/lexbor/css/syntax/anb.c
index ffd1751cdab..d3f7c7bfe0a 100644
--- a/ext/dom/lexbor/lexbor/css/syntax/anb.c
+++ b/ext/dom/lexbor/lexbor/css/syntax/anb.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021-2022 Alexander Borisov
+ * Copyright (C) 2021-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -38,10 +38,9 @@ lxb_css_syntax_anb_state_ident_data(lxb_css_parser_t *parser,


 static const lxb_css_syntax_cb_pipe_t lxb_css_syntax_anb_pipe = {
-    .state = lxb_css_syntax_anb_state,
-    .block = NULL,
-    .failed = lxb_css_state_failed,
-    .end = lxb_css_syntax_anb_end
+    .prelude = lxb_css_syntax_anb_state,
+    .cb.failed = lxb_css_state_failed,
+    .cb.end = lxb_css_syntax_anb_end
 };


@@ -66,8 +65,8 @@ lxb_css_syntax_anb_parse(lxb_css_parser_t *parser,

     lxb_css_parser_buffer_set(parser, data, length);

-    rule = lxb_css_syntax_parser_pipe_push(parser, NULL,
-                                           &lxb_css_syntax_anb_pipe, &anb,
+    rule = lxb_css_syntax_parser_pipe_push(parser, &lxb_css_syntax_anb_pipe,
+                                           NULL, &anb,
                                            LXB_CSS_SYNTAX_TOKEN_UNDEF);
     if (rule == NULL) {
         return anb;
diff --git a/ext/dom/lexbor/lexbor/css/syntax/base.h b/ext/dom/lexbor/lexbor/css/syntax/base.h
index 3dc981ba3da..627fce4c7fa 100644
--- a/ext/dom/lexbor/lexbor/css/syntax/base.h
+++ b/ext/dom/lexbor/lexbor/css/syntax/base.h
@@ -17,7 +17,7 @@ extern "C" {


 #define LXB_CSS_SYNTAX_VERSION_MAJOR 1
-#define LXB_CSS_SYNTAX_VERSION_MINOR 3
+#define LXB_CSS_SYNTAX_VERSION_MINOR 4
 #define LXB_CSS_SYNTAX_VERSION_PATCH 0

 #define LXB_CSS_SYNTAX_VERSION_STRING                                          \
diff --git a/ext/dom/lexbor/lexbor/css/syntax/parser.c b/ext/dom/lexbor/lexbor/css/syntax/parser.c
index 5a3c7abf24f..7e7e973f75d 100644
--- a/ext/dom/lexbor/lexbor/css/syntax/parser.c
+++ b/ext/dom/lexbor/lexbor/css/syntax/parser.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020-2025 Alexander Borisov
+ * Copyright (C) 2020-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -11,14 +11,11 @@
 #include "lexbor/css/at_rule/state.h"


-static const lxb_css_syntax_token_t lxb_css_syntax_token_terminated =
-{
-    .types.terminated = {.begin = NULL, .length = 0, .user_id = 0},
-    .type = LXB_CSS_SYNTAX_TOKEN__END,
-    .offset = 0,
-    .cloned = false
-};
+static const lexbor_str_t lxb_css_err_rc = lexbor_str("Unexpected token in "
+                                                      "qualified rule: RC_BRACKET");

+static lxb_css_syntax_rule_t *
+lxb_css_syntax_parser_stack_pop(lxb_css_parser_t *parser);

 static const lxb_css_syntax_token_t *
 lxb_css_syntax_parser_list_rules(lxb_css_parser_t *parser,
@@ -35,28 +32,105 @@ lxb_css_syntax_parser_list_rules_qualified(lxb_css_parser_t *parser,
                                            const lxb_css_syntax_token_t *token,
                                            lxb_css_syntax_rule_t *rule);

-static bool
+static const lxb_css_syntax_token_t *
 lxb_css_syntax_parser_list_rules_back(lxb_css_parser_t *parser,
-                                      const lxb_css_syntax_token_t *token, void *ctx);
+                                      const lxb_css_syntax_token_t *token,
+                                      lxb_css_syntax_rule_t *rule);
+
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_at_begin(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token,
+                               lxb_css_syntax_rule_t *rule,
+                               lxb_css_parser_state_f back_state,
+                               lxb_css_syntax_begin_at_rule_f cb,
+                               bool nested);

 static const lxb_css_syntax_token_t *
 lxb_css_syntax_parser_at_rule(lxb_css_parser_t *parser,
                               const lxb_css_syntax_token_t *token,
                               lxb_css_syntax_rule_t *rule);

+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_at_block(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token,
+                               lxb_css_syntax_rule_t *rule);
+
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_at_prelude_end(lxb_css_parser_t *parser,
+                                     const lxb_css_syntax_token_t *token,
+                                     lxb_css_syntax_rule_t *rule);
+
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_at_prelude_end_consule_token(lxb_css_parser_t *parser,
+                                                   const lxb_css_syntax_token_t *token,
+                                                   lxb_css_syntax_rule_t *rule);
+
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_at_back_to_prelude(lxb_css_parser_t *parser,
+                                         const lxb_css_syntax_token_t *token,
+                                         lxb_css_syntax_rule_t *rule);
+
 static const lxb_css_syntax_token_t *
 lxb_css_syntax_parser_qualified_rule(lxb_css_parser_t *parser,
                                      const lxb_css_syntax_token_t *token,
                                      lxb_css_syntax_rule_t *rule);

 static const lxb_css_syntax_token_t *
-lxb_css_syntax_parser_declarations(lxb_css_parser_t *parser,
-                                   const lxb_css_syntax_token_t *token,
-                                   lxb_css_syntax_rule_t *rule);
+lxb_css_syntax_parser_qualified_rule_block(lxb_css_parser_t *parser,
+                                           const lxb_css_syntax_token_t *token,
+                                           lxb_css_syntax_rule_t *rule);
+
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_qualified_prelude_end(lxb_css_parser_t *parser,
+                                            const lxb_css_syntax_token_t *token,
+                                            lxb_css_syntax_rule_t *rule);
+
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_qualified_back_to_prelude(lxb_css_parser_t *parser,
+                                                const lxb_css_syntax_token_t *token,
+                                                lxb_css_syntax_rule_t *rule);
+
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_block_begin(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token,
+                                  lxb_css_syntax_rule_t *rule,
+                                  lxb_css_parser_state_f back_state,
+                                  lxb_css_syntax_begin_block_f cb);
+
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_block(lxb_css_parser_t *parser,
+                            const lxb_css_syntax_token_t *token,
+                            lxb_css_syntax_rule_t *rule);
+
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_block_at(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token,
+                               lxb_css_syntax_rule_t *rule);
+
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_block_declarations(lxb_css_parser_t *parser,
+                                         const lxb_css_syntax_token_t *token,
+                                         lxb_css_syntax_rule_t *rule);
+
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_block_qualified(lxb_css_parser_t *parser,
+                                      const lxb_css_syntax_token_t *token,
+                                      lxb_css_syntax_rule_t *rule);
+
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_block_back(lxb_css_parser_t *parser,
+                                 const lxb_css_syntax_token_t *token,
+                                 lxb_css_syntax_rule_t *rule);
+
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_declarations_validate(lxb_css_parser_t *parser,
+                                            const lxb_css_syntax_token_t *token,
+                                            lxb_css_syntax_rule_t *rule);

-static bool
-lxb_css_syntax_parser_declarations_back(lxb_css_parser_t *parser,
-                                        const lxb_css_syntax_token_t *token, void *ctx);
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_declarations_begin(lxb_css_parser_t *parser,
+                                         const lxb_css_syntax_token_t *token,
+                                         lxb_css_syntax_rule_t *rule);

 static const lxb_css_syntax_token_t *
 lxb_css_syntax_parser_declarations_name(lxb_css_parser_t *parser,
@@ -69,40 +143,77 @@ lxb_css_syntax_parser_declarations_value(lxb_css_parser_t *parser,
                                          lxb_css_syntax_rule_t *rule);

 static const lxb_css_syntax_token_t *
-lxb_css_syntax_parser_declarations_next(lxb_css_parser_t *parser,
+lxb_css_syntax_parser_declarations_drop(lxb_css_parser_t *parser,
                                         const lxb_css_syntax_token_t *token,
                                         lxb_css_syntax_rule_t *rule);

 static const lxb_css_syntax_token_t *
-lxb_css_syntax_parser_declarations_drop(lxb_css_parser_t *parser,
+lxb_css_syntax_parser_declarations_next(lxb_css_parser_t *parser,
                                         const lxb_css_syntax_token_t *token,
                                         lxb_css_syntax_rule_t *rule);

+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_declaration_back_to_value(lxb_css_parser_t *parser,
+                                                const lxb_css_syntax_token_t *token,
+                                                lxb_css_syntax_rule_t *rule);
+
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_declaration_end(lxb_css_parser_t *parser,
+                                      const lxb_css_syntax_token_t *token,
+                                      lxb_css_syntax_rule_t *rule);
+
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_declaration_end_handler(lxb_css_parser_t *parser,
+                                              const lxb_css_syntax_token_t *token,
+                                              lxb_css_syntax_rule_t *rule,
+                                              bool skip_token);
+
 static const lxb_css_syntax_token_t *
 lxb_css_syntax_parser_declarations_end(lxb_css_parser_t *parser,
                                        const lxb_css_syntax_token_t *token,
                                        lxb_css_syntax_rule_t *rule);

+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_declarations_end_h(lxb_css_parser_t *parser,
+                                         const lxb_css_syntax_token_t *token,
+                                         lxb_css_syntax_rule_t *rule,
+                                         bool skip_token);
+
 static const lxb_css_syntax_token_t *
 lxb_css_syntax_parser_components(lxb_css_parser_t *parser,
                                  const lxb_css_syntax_token_t *token,
                                  lxb_css_syntax_rule_t *rule);

+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_components_back_to_value(lxb_css_parser_t *parser,
+                                               const lxb_css_syntax_token_t *token,
+                                               lxb_css_syntax_rule_t *rule);
+
 static const lxb_css_syntax_token_t *
 lxb_css_syntax_parser_function(lxb_css_parser_t *parser,
                                const lxb_css_syntax_token_t *token,
                                lxb_css_syntax_rule_t *rule);

 static const lxb_css_syntax_token_t *
-lxb_css_syntax_parser_block(lxb_css_parser_t *parser,
-                            const lxb_css_syntax_token_t *token,
-                            lxb_css_syntax_rule_t *rule);
+lxb_css_syntax_parser_function_back(lxb_css_parser_t *parser,
+                                    const lxb_css_syntax_token_t *token,
+                                    lxb_css_syntax_rule_t *rule);

 static const lxb_css_syntax_token_t *
 lxb_css_syntax_parser_pipe(lxb_css_parser_t *parser,
                            const lxb_css_syntax_token_t *token,
                            lxb_css_syntax_rule_t *rule);

+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_pipe_back(lxb_css_parser_t *parser,
+                                const lxb_css_syntax_token_t *token,
+                                lxb_css_syntax_rule_t *rule);
+
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_end_back(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token,
+                               lxb_css_syntax_rule_t *rule);
+

 lxb_inline const lxb_css_syntax_token_t *
 lxb_css_syntax_parser_failed(lxb_css_parser_t *parser, lxb_status_t status)
@@ -111,6 +222,31 @@ lxb_css_syntax_parser_failed(lxb_css_parser_t *parser, lxb_status_t status)
     return NULL;
 }

+lxb_inline const lxb_css_syntax_token_t *
+lxb_css_syntax_token_parser_do_phase_again(lxb_css_parser_t *parser)
+{
+    parser->fake_null = true;
+    return NULL;
+}
+
+lxb_inline const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_call_back(lxb_css_parser_t *parser,
+                                const lxb_css_syntax_token_t *token)
+{
+    lxb_css_syntax_rule_t *rules;
+
+    (void) lxb_css_syntax_parser_stack_pop(parser);
+
+    rules = parser->rules;
+
+    if (parser->rules <= parser->rules_begin) {
+        rules->state = lxb_css_state_stop;
+        return token;
+    }
+
+    return rules->back(parser, token, rules);
+}
+

 lxb_status_t
 lxb_css_syntax_parser_run(lxb_css_parser_t *parser)
@@ -177,369 +313,259 @@ lxb_css_syntax_parser_consume(lxb_css_parser_t *parser)

 lxb_css_syntax_rule_t *
 lxb_css_syntax_parser_list_rules_push(lxb_css_parser_t *parser,
-                                      const lxb_css_syntax_token_t *token,
-                                      lxb_css_parser_state_f state_back,
                                       const lxb_css_syntax_cb_list_rules_t *cb_rules,
-                                      void *ctx, bool top_level,
-                                      lxb_css_syntax_token_type_t stop)
+                                      lxb_css_parser_state_f back,
+                                      void *ctx, lxb_css_syntax_token_type_t stop)
 {
-    lxb_status_t status;
     lxb_css_syntax_rule_t *rule;

-    lxb_css_parser_offset_set(parser, token);
-
-    status = lxb_css_syntax_stack_expand(parser, 1);
-    if (status != LXB_STATUS_OK) {
-        parser->status = status;
-        return NULL;
+    if ((parser->rules + 1) >= parser->rules_end) {
+        parser->status = lxb_css_syntax_stack_expand(parser, 1);
+        if (parser->status != LXB_STATUS_OK) {
+            return NULL;
+        }
     }
-
-    parser->rules->state = lxb_css_state_success;
+
+    parser->rules->back_state = back;

     rule = ++parser->rules;

-    memset(rule, 0x00, sizeof(lxb_css_syntax_rule_t));
-
-    rule->phase = lxb_css_syntax_parser_list_rules;
-    rule->state = cb_rules->cb.state;
-    rule->state_back = state_back;
-    rule->back = lxb_css_syntax_parser_list_rules;
-    rule->cbx.list_rules = cb_rules;
-    rule->context = ctx;
-    rule->block_end = stop;
-    rule->top_level = top_level;
-
-    if (token != NULL) {
-        rule->u.list_rules.begin = token->offset;
-    }
-
-    parser->context = NULL;
+    *rule = (lxb_css_syntax_rule_t) {
+        .phase = lxb_css_syntax_parser_list_rules,
+        .state = lxb_css_state_blank,
+        .back = lxb_css_syntax_parser_list_rules_back,
+        .cbx.list_rules = cb_rules,
+        .context = ctx,
+        .block_end = stop
+    };

     return rule;
 }

 lxb_css_syntax_rule_t *
 lxb_css_syntax_parser_at_rule_push(lxb_css_parser_t *parser,
-                                   const lxb_css_syntax_token_t *token,
-                                   lxb_css_parser_state_f state_back,
                                    const lxb_css_syntax_cb_at_rule_t *at_rule,
-                                   void *ctx, lxb_css_syntax_token_type_t stop)
+                                   lxb_css_parser_state_f back, void *ctx,
+                                   lxb_css_syntax_token_type_t stop,
+                                   bool nested)
 {
-    lxb_status_t status;
-    lxb_css_syntax_at_rule_offset_t *at;
     lxb_css_syntax_rule_t *rule;

-    lxb_css_parser_offset_set(parser, token);
-
-    status = lxb_css_syntax_stack_expand(parser, 1);
-    if (status != LXB_STATUS_OK) {
-        parser->status = status;
-        return NULL;
+    if ((parser->rules + 1) >= parser->rules_end) {
+        parser->status = lxb_css_syntax_stack_expand(parser, 1);
+        if (parser->status != LXB_STATUS_OK) {
+            return NULL;
+        }
     }

-    parser->rules->state = lxb_css_state_success;
+    parser->rules->back_state = back;

     rule = ++parser->rules;

-    memset(rule, 0x00, sizeof(lxb_css_syntax_rule_t));
-
-    rule->phase = lxb_css_syntax_parser_at_rule;
-    rule->state = at_rule->state;
-    rule->state_back = state_back;
-    rule->back = lxb_css_syntax_parser_at_rule;
-    rule->cbx.at_rule = at_rule;
-    rule->context = ctx;
-    rule->block_end = stop;
-
-    if (token != NULL) {
-        at = &rule->u.at_rule;
-
-        at->name = token->offset;
-        at->prelude = token->offset + lxb_css_syntax_token_base(token)->length;
-    }
-
-    parser->context = NULL;
+    *rule = (lxb_css_syntax_rule_t) {
+        .phase = lxb_css_syntax_parser_at_rule,
+        .state = at_rule->prelude,
+        .back = lxb_css_syntax_parser_at_back_to_prelude,
+        .cbx.at_rule = at_rule,
+        .context = ctx,
+        .block_end = stop,
+        .nested = nested
+    };

     return rule;
 }

 lxb_css_syntax_rule_t *
 lxb_css_syntax_parser_qualified_push(lxb_css_parser_t *parser,
-                                     const lxb_css_syntax_token_t *token,
-                                     lxb_css_parser_state_f state_back,
                                      const lxb_css_syntax_cb_qualified_rule_t *qualified,
-                                     void *ctx, lxb_css_syntax_token_type_t stop)
+                                     lxb_css_parser_state_f back, void *ctx,
+                                     lxb_css_syntax_token_type_t stop,
+                                     bool nested)
 {
-    lxb_status_t status;
     lxb_css_syntax_rule_t *rule;

-    lxb_css_parser_offset_set(parser, token);
-
-    status = lxb_css_syntax_stack_expand(parser, 1);
-    if (status != LXB_STATUS_OK) {
-        parser->status = status;
-        return NULL;
+    if ((parser->rules + 1) >= parser->rules_end) {
+        parser->status = lxb_css_syntax_stack_expand(parser, 1);
+        if (parser->status != LXB_STATUS_OK) {
+            return NULL;
+        }
     }

-    parser->rules->state = lxb_css_state_success;
+    parser->rules->back_state = back;

     rule = ++parser->rules;

-    memset(rule, 0x00, sizeof(lxb_css_syntax_rule_t));
-
-    rule->phase = lxb_css_syntax_parser_qualified_rule;
-    rule->state = qualified->state;
-    rule->state_back = state_back;
-    rule->back = lxb_css_syntax_parser_qualified_rule;
-    rule->cbx.qualified_rule = qualified;
-    rule->context = ctx;
-    rule->block_end = stop;
-
-    if (token != NULL) {
-        rule->u.qualified.prelude = token->offset;
-    }
-
-    parser->context = NULL;
+    *rule = (lxb_css_syntax_rule_t) {
+        .phase = lxb_css_syntax_parser_qualified_rule,
+        .state = qualified->prelude,
+        .back = lxb_css_syntax_parser_qualified_back_to_prelude,
+        .cbx.qualified_rule = qualified,
+        .context = ctx,
+        .block_end = stop,
+        .nested = nested
+    };

     return rule;
 }

 lxb_css_syntax_rule_t *
-lxb_css_syntax_parser_declarations_push(lxb_css_parser_t *parser,
-                                        const lxb_css_syntax_token_t *token,
-                                        lxb_css_parser_state_f state_back,
-                                        const lxb_css_syntax_cb_declarations_t *declarations,
-                                        void *ctx, lxb_css_syntax_token_type_t stop)
+lxb_css_syntax_parser_block_push(lxb_css_parser_t *parser,
+                                 const lxb_css_syntax_cb_block_t *block,
+                                 lxb_css_parser_state_f back, void *ctx)
 {
-    lxb_status_t status;
     lxb_css_syntax_rule_t *rule;

-    lxb_css_parser_offset_set(parser, token);
-
-    status = lxb_css_syntax_stack_expand(parser, 1);
-    if (status != LXB_STATUS_OK) {
-        parser->status = status;
-        return NULL;
+    if ((parser->rules + 1) >= parser->rules_end) {
+        parser->status = lxb_css_syntax_stack_expand(parser, 1);
+        if (parser->status != LXB_STATUS_OK) {
+            return NULL;
+        }
     }

-    parser->rules->state = lxb_css_state_success;
+    parser->rules->back_state = back;

     rule = ++parser->rules;

-    memset(rule, 0x00, sizeof(lxb_css_syntax_rule_t));
-
-    rule->phase = lxb_css_syntax_parser_declarations;
-    rule->state = declarations->cb.state;
-    rule->state_back = state_back;
-    rule->back = lxb_css_syntax_parser_declarations;
-    rule->cbx.declarations = declarations;
-    rule->context = ctx;
-    rule->block_end = stop;
-
-    if (token != NULL) {
-        rule->u.declarations.begin = token->offset;
-    }
-
-    parser->context = NULL;
+    *rule = (lxb_css_syntax_rule_t) {
+        .phase = lxb_css_syntax_parser_block,
+        .state = lxb_css_state_blank,
+        .back = lxb_css_syntax_parser_block_back,
+        .cbx.block = block,
+        .context = ctx
+    };

     return rule;
 }

 lxb_css_syntax_rule_t *
-lxb_css_syntax_parser_components_push(lxb_css_parser_t *parser,
-                                      const lxb_css_syntax_token_t *token,
-                                      lxb_css_parser_state_f state_back,
-                                      const lxb_css_syntax_cb_components_t *comp,
-                                      void *ctx, lxb_css_syntax_token_type_t stop)
+lxb_css_syntax_parser_declarations_push(lxb_css_parser_t *parser,
+                                        const lxb_css_syntax_cb_declarations_t *declr,
+                                        lxb_css_parser_state_f back, void *ctx,
+                                        lxb_css_syntax_token_type_t stop,
+                                        bool name_validate, bool nested)
 {
-    lxb_status_t status;
     lxb_css_syntax_rule_t *rule;
+    lxb_css_syntax_state_f phase;

-    lxb_css_parser_offset_set(parser, token);
-
-    status = lxb_css_syntax_stack_expand(parser, 1);
-    if (status != LXB_STATUS_OK) {
-        parser->status = status;
-        return NULL;
+    if ((parser->rules + 1) >= parser->rules_end) {
+        parser->status = lxb_css_syntax_stack_expand(parser, 1);
+        if (parser->status != LXB_STATUS_OK) {
+            return NULL;
+        }
     }

-    parser->rules->state = lxb_css_state_success;
+    parser->rules->back_state = back;

     rule = ++parser->rules;

-    memset(rule, 0x00, sizeof(lxb_css_syntax_rule_t));
-
-    rule->phase = lxb_css_syntax_parser_components;
-    rule->state = comp->state;
-    rule->state_back = state_back;
-    rule->back = lxb_css_syntax_parser_components;
-    rule->cbx.components = comp;
-    rule->context = ctx;
-    rule->block_end = stop;
+    phase = (!name_validate) ? lxb_css_syntax_parser_declarations_begin
+                             : lxb_css_syntax_parser_declarations_validate;

-    parser->context = NULL;
+    *rule = (lxb_css_syntax_rule_t) {
+        .phase = phase,
+        .state = lxb_css_state_blank,
+        .back = lxb_css_syntax_parser_declaration_back_to_value,
+        .cbx.declarations = declr,
+        .context = ctx,
+        .block_end = stop,
+        .nested = nested
+    };

     return rule;
 }

 lxb_css_syntax_rule_t *
-lxb_css_syntax_parser_function_push(lxb_css_parser_t *parser,
-                                    const lxb_css_syntax_token_t *token,
-                                    lxb_css_parser_state_f state_back,
-                                    const lxb_css_syntax_cb_function_t *func,
-                                    void *ctx)
+lxb_css_syntax_parser_components_push(lxb_css_parser_t *parser,
+                                      const lxb_css_syntax_cb_components_t *comp,
+                                      lxb_css_parser_state_f back, void *ctx,
+                                      lxb_css_syntax_token_type_t stop)
 {
-    lxb_status_t status;
     lxb_css_syntax_rule_t *rule;

-    if (token == NULL || token->type != LXB_CSS_SYNTAX_TOKEN_FUNCTION) {
-        parser->status = LXB_STATUS_ERROR_WRONG_ARGS;
-        return NULL;
-    }
-
-    if (parser->rules > parser->rules_begin) {
-        rule = parser->rules;
-
-        if (rule->deep != 0
-            && parser->types_pos[-1] == LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS)
-        {
-            rule->deep--;
-            parser->types_pos--;
+    if ((parser->rules + 1) >= parser->rules_end) {
+        parser->status = lxb_css_syntax_stack_expand(parser, 1);
+        if (parser->status != LXB_STATUS_OK) {
+            return NULL;
         }
     }

-    parser->rules->state = lxb_css_state_success;
-
-    lxb_css_parser_offset_set(parser, token);
-
-    status = lxb_css_syntax_stack_expand(parser, 1);
-    if (status != LXB_STATUS_OK) {
-        parser->status = status;
-        return NULL;
-    }
+    parser->rules->back_state = back;

     rule = ++parser->rules;

-    memset(rule, 0x00, sizeof(lxb_css_syntax_rule_t));
-
-    rule->phase = lxb_css_syntax_parser_function;
-    rule->state = func->state;
-    rule->state_back = state_back;
-    rule->back = lxb_css_syntax_parser_function;
-    rule->cbx.func = func;
-    rule->context = ctx;
-
-    parser->context = NULL;
+    *rule = (lxb_css_syntax_rule_t) {
+        .phase = lxb_css_syntax_parser_components,
+        .state = comp->prelude,
+        .back = lxb_css_syntax_parser_components_back_to_value,
+        .cbx.components = comp,
+        .context = ctx,
+        .block_end = stop
+    };

     return rule;
 }

 lxb_css_syntax_rule_t *
-lxb_css_syntax_parser_block_push(lxb_css_parser_t *parser,
-                                 const lxb_css_syntax_token_t *token,
-                                 lxb_css_parser_state_f state_back,
-                                 const lxb_css_syntax_cb_block_t *block,
-                                 void *ctx)
+lxb_css_syntax_parser_function_push(lxb_css_parser_t *parser,
+                                    const lxb_css_syntax_cb_function_t *func,
+                                    lxb_css_parser_state_f back, void *ctx)
 {
-    lxb_status_t status;
     lxb_css_syntax_rule_t *rule;
-    lxb_css_syntax_token_type_t block_end;
-
-    if (token == NULL) {
-        parser->status = LXB_STATUS_ERROR_WRONG_ARGS;
-        return NULL;
-    }
-
-    switch (token->type) {
-        case LXB_CSS_SYNTAX_TOKEN_LS_BRACKET:
-            block_end = LXB_CSS_SYNTAX_TOKEN_RS_BRACKET;
-            break;
-
-        case LXB_CSS_SYNTAX_TOKEN_FUNCTION:
-        case LXB_CSS_SYNTAX_TOKEN_L_PARENTHESIS:
-            block_end = LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS;
-            break;
-
-        case LXB_CSS_SYNTAX_TOKEN_LC_BRACKET:
-            block_end = LXB_CSS_SYNTAX_TOKEN_RC_BRACKET;
-            break;

-        default:
-            parser->status = LXB_STATUS_ERROR_WRONG_ARGS;
+    if ((parser->rules + 1) >= parser->rules_end) {
+        parser->status = lxb_css_syntax_stack_expand(parser, 1);
+        if (parser->status != LXB_STATUS_OK) {
             return NULL;
-    }
-
-    if (parser->rules > parser->rules_begin) {
-        rule = parser->rules;
-
-        if (rule->deep != 0 && parser->types_pos[-1] == block_end) {
-            rule->deep--;
-            parser->types_pos--;
         }
     }

-    parser->rules->state = lxb_css_state_success;
-
-    lxb_css_parser_offset_set(parser, token);
-
-    status = lxb_css_syntax_stack_expand(parser, 1);
-    if (status != LXB_STATUS_OK) {
-        parser->status = status;
-        return NULL;
-    }
+    parser->rules->back_state = back;

     rule = ++parser->rules;

-    memset(rule, 0x00, sizeof(lxb_css_syntax_rule_t));
-
-    rule->phase = lxb_css_syntax_parser_block;
-    rule->state = block->state;
-    rule->state_back = state_back;
-    rule->back = lxb_css_syntax_parser_block;
-    rule->cbx.block = block;
-    rule->context = ctx;
-    rule->block_end = block_end;
-
-    parser->context = NULL;
+    *rule = (lxb_css_syntax_rule_t) {
+        .phase = lxb_css_syntax_parser_function,
+        .state = func->value,
+        .back = lxb_css_syntax_parser_function_back,
+        .cbx.func = func,
+        .context = ctx
+    };

     return rule;
 }

 lxb_css_syntax_rule_t *
 lxb_css_syntax_parser_pipe_push(lxb_css_parser_t *parser,
-                                lxb_css_parser_state_f state_back,
                                 const lxb_css_syntax_cb_pipe_t *pipe,
-                                void *ctx, lxb_css_syntax_token_type_t stop)
+                                lxb_css_parser_state_f back, void *ctx,
+                                lxb_css_syntax_token_type_t stop)
 {
-    lxb_status_t status;
     lxb_css_syntax_rule_t *rule;

-    status = lxb_css_syntax_stack_expand(parser, 1);
-    if (status != LXB_STATUS_OK) {
-        parser->status = status;
-        return NULL;
+    if ((parser->rules + 1) >= parser->rules_end) {
+        parser->status = lxb_css_syntax_stack_expand(parser, 1);
+        if (parser->status != LXB_STATUS_OK) {
+            return NULL;
+        }
     }

-    parser->rules->state = lxb_css_state_success;
+    parser->rules->back_state = back;

     rule = ++parser->rules;

-    memset(rule, 0x00, sizeof(lxb_css_syntax_rule_t));
-
-    rule->phase = lxb_css_syntax_parser_pipe;
-    rule->state = pipe->state;
-    rule->state_back = state_back;
-    rule->back = lxb_css_syntax_parser_pipe;
-    rule->cbx.pipe = pipe;
-    rule->context = ctx;
-    rule->block_end = stop;
-
-    parser->context = NULL;
+    *rule = (lxb_css_syntax_rule_t) {
+        .phase = lxb_css_syntax_parser_pipe,
+        .state = pipe->prelude,
+        .back = lxb_css_syntax_parser_pipe_back,
+        .cbx.pipe = pipe,
+        .context = ctx,
+        .block_end = stop
+    };

     return rule;
 }

-lxb_css_syntax_rule_t *
+static lxb_css_syntax_rule_t *
 lxb_css_syntax_parser_stack_pop(lxb_css_parser_t *parser)
 {
     return parser->rules--;
@@ -554,12 +580,16 @@ lxb_css_syntax_parser_list_rules(lxb_css_parser_t *parser,
         return token;
     }

+    rule->skip_consume = true;
+
 begin:

     rule->offset = token->offset + lxb_css_syntax_token_base(token)->length;

     switch (token->type) {
         case LXB_CSS_SYNTAX_TOKEN_WHITESPACE:
+        case LXB_CSS_SYNTAX_TOKEN_CDC:
+        case LXB_CSS_SYNTAX_TOKEN_CDO:
             lxb_css_syntax_token_consume(parser->tkz);

             token = lxb_css_syntax_token(parser->tkz);
@@ -577,22 +607,6 @@ lxb_css_syntax_parser_list_rules(lxb_css_parser_t *parser,
         case LXB_CSS_SYNTAX_TOKEN__EOF:
             goto done;

-        case LXB_CSS_SYNTAX_TOKEN_CDC:
-        case LXB_CSS_SYNTAX_TOKEN_CDO:
-            if (rule->top_level) {
-                lxb_css_syntax_token_consume(parser->tkz);
-
-                token = lxb_css_syntax_token(parser->tkz);
-                if (token == NULL) {
-                    return lxb_css_syntax_parser_failed(parser,
-                                                        parser->tkz->status);
-                }
-
-                goto begin;
-            }
-
-            /* fall through */
-
         default:
             if (rule->block_end == token->type && rule->deep == 0) {
                 goto done;
@@ -607,79 +621,136 @@ lxb_css_syntax_parser_list_rules(lxb_css_parser_t *parser,
 done:

     rule->phase = lxb_css_syntax_parser_end;
-    rule->skip_consume = true;

-    rule->u.list_rules.end = token->offset;
-
-    return &lxb_css_syntax_token_terminated;
+    return lxb_css_parser_token_end(parser, 0);
 }

+/*
+ * This code will be called before rule->state is called.
+ * Exclusively from the lxb_css_parser_run(...).
+ */
 static const lxb_css_syntax_token_t *
 lxb_css_syntax_parser_list_rules_at(lxb_css_parser_t *parser,
                                     const lxb_css_syntax_token_t *token,
                                     lxb_css_syntax_rule_t *rule)
 {
-    if (rule->state != lxb_css_state_success) {
-        return token;
-    }
+    const lxb_css_syntax_cb_list_rules_t *list_rules = rule->cbx.list_rules;

-    rule = lxb_css_syntax_parser_at_rule_push(parser, token,
-                                              lxb_css_syntax_parser_list_rules_back,
-                                              rule->cbx.list_rules->at_rule,
-                                              rule->context, rule->block_end);
-    if (rule == NULL) {
-        return NULL;
-    }
-
-    parser->fake_null = true;
-
-    return NULL;
+    return lxb_css_syntax_parser_at_begin(parser, token, rule, list_rules->next,
+                                          list_rules->at_rule, false);
 }

+/*
+ * This code will be called before rule->state is called.
+ * Exclusively from the lxb_css_parser_run(...).
+ */
 static const lxb_css_syntax_token_t *
 lxb_css_syntax_parser_list_rules_qualified(lxb_css_parser_t *parser,
                                            const lxb_css_syntax_token_t *token,
                                            lxb_css_syntax_rule_t *rule)
 {
-    if (rule->state != lxb_css_state_success) {
-        return token;
-    }
+    void *qualified_ctx;
+    lxb_css_syntax_rule_t *qualified;
+    lxb_css_syntax_begin_qualified_rule_f cb;
+    const lxb_css_syntax_cb_list_rules_t *list_rules;
+    const lxb_css_syntax_cb_qualified_rule_t *cb_qualified;

-    rule = lxb_css_syntax_parser_qualified_push(parser, token,
-                                                lxb_css_syntax_parser_list_rules_back,
-                                                rule->cbx.list_rules->qualified_rule,
-                                                rule->context, rule->block_end);
-    if (rule == NULL) {
-        return NULL;
+    qualified_ctx = NULL;
+    list_rules = rule->cbx.list_rules;
+    cb = list_rules->qualified_rule;
+
+    rule->skip_consume = false;
+
+    cb_qualified = cb(parser, token, rule->context, &qualified_ctx);
+    if (cb_qualified == NULL) {
+        return lxb_css_syntax_parser_failed(parser,
+                                            LXB_STATUS_ERROR_UNEXPECTED_DATA);
     }

-    parser->fake_null = true;
+    qualified = lxb_css_syntax_parser_qualified_push(parser, cb_qualified,
+                                                     list_rules->next,
+                                                     qualified_ctx,
+                                                     rule->block_end,
+                                                     false);
+    if (qualified == NULL) {
+        return lxb_css_syntax_parser_failed(parser,
+                                            LXB_STATUS_ERROR_MEMORY_ALLOCATION);
+    }

-    return NULL;
+    return lxb_css_syntax_token_parser_do_phase_again(parser);
 }

-static bool
+/*
+ * This code will be called before rule->state is called.
+ * Exclusively from the lxb_css_parser_run(...).
+ */
+static const lxb_css_syntax_token_t *
 lxb_css_syntax_parser_list_rules_back(lxb_css_parser_t *parser,
-                                      const lxb_css_syntax_token_t *token, void *ctx)
+                                      const lxb_css_syntax_token_t *token,
+                                      lxb_css_syntax_rule_t *rule)
 {
-    lxb_css_syntax_rule_t *rule;
+    rule->phase = lxb_css_syntax_parser_list_rules;
+    rule->state = rule->back_state;
+    rule->skip_consume = true;

-    if (token->type == LXB_CSS_SYNTAX_TOKEN__END) {
-        return lxb_css_parser_success(parser);
+    return token;
+}
+
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_at_begin(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token,
+                               lxb_css_syntax_rule_t *rule,
+                               lxb_css_parser_state_f back_state,
+                               lxb_css_syntax_begin_at_rule_f cb,
+                               bool nested)
+{
+    void *at_rule_ctx;
+    lxb_css_syntax_rule_t *at_rule;
+    const lxb_css_syntax_cb_at_rule_t *cb_at_rule;
+
+    at_rule_ctx = NULL;
+    rule->skip_consume = false;
+
+    cb_at_rule = cb(parser, token, rule->context, &at_rule_ctx);
+    if (cb_at_rule == NULL) {
+        return lxb_css_syntax_parser_failed(parser,
+                                            LXB_STATUS_ERROR_UNEXPECTED_DATA);
     }

-    rule = parser->rules;
-    rule->state = rule->cbx.list_rules->next;
+    at_rule = lxb_css_syntax_parser_at_rule_push(parser, cb_at_rule,
+                                                 back_state, at_rule_ctx,
+                                                 rule->block_end, nested);
+    if (at_rule == NULL) {
+        return lxb_css_syntax_parser_failed(parser,
+                                            LXB_STATUS_ERROR_MEMORY_ALLOCATION);
+    }
+
+    lxb_css_syntax_token_consume(parser->tkz);
+
+    token = lxb_css_syntax_token(parser->tkz);
+    if (token == NULL) {
+        return lxb_css_syntax_parser_failed(parser, parser->tkz->status);
+    }

-    return false;
+    if (token->type == LXB_CSS_SYNTAX_TOKEN_WHITESPACE) {
+        lxb_css_syntax_token_consume(parser->tkz);
+    }
+
+    return lxb_css_syntax_token_parser_do_phase_again(parser);
 }

+/*
+ * First call for this code will be called before rule->state is called.
+ * Exclusively from the lxb_css_parser_run(...).
+ * Rule -- lxb_css_syntax_rule_t with at_rule callbacks.
+ */
 static const lxb_css_syntax_token_t *
 lxb_css_syntax_parser_at_rule(lxb_css_parser_t *parser,
                               const lxb_css_syntax_token_t *token,
                               lxb_css_syntax_rule_t *rule)
 {
     lxb_status_t status;
+    const lxb_css_log_message_t *msg;

     if (rule->offset > token->offset) {
         return token;
@@ -688,7 +759,7 @@ lxb_css_syntax_parser_at_rule(lxb_css_parser_t *parser,
     rule->offset = token->offset + lxb_css_syntax_token_base(token)->length;

     if (rule->block_end == token->type && rule->deep == 0) {
-        rule->skip_ending = true;
+        rule->phase = lxb_css_syntax_parser_at_prelude_end;
         goto done;
     }

@@ -706,25 +777,11 @@ lxb_css_syntax_parser_at_rule(lxb_css_parser_t *parser,

         case LXB_CSS_SYNTAX_TOKEN_LC_BRACKET:
             if (rule->deep == 0) {
-                rule->phase = lxb_css_syntax_parser_start_block;
-
-                rule->u.at_rule.prelude_end = token->offset;
-                rule->u.at_rule.block = token->offset
-                    + lxb_css_syntax_token_base(token)->length;
-
+                rule->phase = lxb_css_syntax_parser_at_block;
+                rule->back = lxb_css_syntax_parser_end_back;
                 rule->skip_consume = true;

-                parser->block = rule->cbx.cb->block;
-
-                lxb_css_syntax_token_consume(parser->tkz);
-
-                token = lxb_css_syntax_token(parser->tkz);
-                if (token == NULL) {
-                    return lxb_css_syntax_parser_failed(parser,
-                                                        parser->tkz->status);
-                }
-
-                token = &lxb_css_syntax_token_terminated;
+                return lxb_css_parser_token_end(parser, token->offset);
             }

             status = lxb_css_parser_types_push(parser,
@@ -732,13 +789,25 @@ lxb_css_syntax_parser_at_rule(lxb_css_parser_t *parser,
             break;

         case LXB_CSS_SYNTAX_TOKEN_RC_BRACKET:
-            if (rule->deep != 0 && parser->types_pos[-1] == token->type) {
-                if (rule->deep == 1) {
-                    goto done;
+            if (rule->deep != 0) {
+                if (parser->types_pos[-1] == token->type) {
+                    parser->types_pos--;
+                    rule->deep--;
+                }
+            }
+            else {
+                msg = lxb_css_log_format(parser->log,
+                                         LXB_CSS_LOG_SYNTAX_ERROR,
+                                         "%S", &lxb_css_err_rc);
+                if (msg == NULL) {
+                    return lxb_css_syntax_parser_failed(parser,
+                                           LXB_STATUS_ERROR_MEMORY_ALLOCATION);
                 }

-                parser->types_pos--;
-                rule->deep--;
+                if (rule->nested) {
+                    rule->phase = lxb_css_syntax_parser_at_prelude_end;
+                    goto done;
+                }
             }

             return token;
@@ -754,12 +823,14 @@ lxb_css_syntax_parser_at_rule(lxb_css_parser_t *parser,

         case LXB_CSS_SYNTAX_TOKEN_SEMICOLON:
             if (rule->deep == 0) {
+                rule->phase = lxb_css_syntax_parser_at_prelude_end_consule_token;
                 goto done;
             }

             return token;

         case LXB_CSS_SYNTAX_TOKEN__EOF:
+            rule->phase = lxb_css_syntax_parser_at_prelude_end;
             goto done;

         default:
@@ -776,17 +847,91 @@ lxb_css_syntax_parser_at_rule(lxb_css_parser_t *parser,

 done:

-    rule->phase = lxb_css_syntax_parser_end;
     rule->skip_consume = true;

-    if (rule->u.at_rule.prelude_end != 0) {
-        rule->u.at_rule.block_end = token->offset;
+    return lxb_css_parser_token_end(parser, token->offset);
+}
+
+/*
+ * This code will be called before rule->state is called.
+ * Exclusively from the lxb_css_parser_run(...).
+ */
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_at_block(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token,
+                               lxb_css_syntax_rule_t *rule)
+{
+    lxb_status_t status;
+    const lxb_css_syntax_cb_at_rule_t *at_rule = rule->cbx.at_rule;
+
+    status = at_rule->prelude_end(parser, token, rule->context, rule->failed);
+    if (status != LXB_STATUS_OK) {
+        return lxb_css_syntax_parser_failed(parser, status);
     }
-    else {
-        rule->u.at_rule.prelude_end = token->offset;
+
+    return lxb_css_syntax_parser_block_begin(parser, token, rule,
+                                             at_rule->prelude, at_rule->block);
+}
+
+/*
+ * This code will be called before rule->state is called.
+ * Exclusively from the lxb_css_parser_run(...).
+ */
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_at_prelude_end(lxb_css_parser_t *parser,
+                                     const lxb_css_syntax_token_t *token,
+                                     lxb_css_syntax_rule_t *rule)
+{
+    lxb_status_t status;
+    const lxb_css_syntax_cb_at_rule_t *at_rule = rule->cbx.at_rule;
+
+    rule->phase = lxb_css_syntax_parser_end;
+    rule->state = lxb_css_state_success;
+
+    status = at_rule->prelude_end(parser, token, rule->context, rule->failed);
+    if (status != LXB_STATUS_OK) {
+        return lxb_css_syntax_parser_failed(parser, status);
     }

-    return &lxb_css_syntax_token_terminated;
+    return lxb_css_syntax_token_parser_do_phase_again(parser);
+}
+
+/*
+ * This code will be called before rule->state is called.
+ * Exclusively from the lxb_css_parser_run(...).
+ */
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_at_prelude_end_consule_token(lxb_css_parser_t *parser,
+                                                   const lxb_css_syntax_token_t *token,
+                                                   lxb_css_syntax_rule_t *rule)
+{
+    lxb_status_t status;
+    const lxb_css_syntax_cb_at_rule_t *at_rule = rule->cbx.at_rule;
+
+    rule->phase = lxb_css_syntax_parser_end_consume_token;
+
+    status = at_rule->prelude_end(parser, token, rule->context, rule->failed);
+    if (status != LXB_STATUS_OK) {
+        return lxb_css_syntax_parser_failed(parser, status);
+    }
+
+    return lxb_css_syntax_token_parser_do_phase_again(parser);
+}
+
+/*
+ * This code will be called before rule->state is called.
+ * Exclusively from the lxb_css_parser_run(...).
+ */
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_at_back_to_prelude(lxb_css_parser_t *parser,
+                                         const lxb_css_syntax_token_t *token,
+                                         lxb_css_syntax_rule_t *rule)
+{
+    rule->phase = lxb_css_syntax_parser_at_rule;
+    rule->state = rule->back_state;
+    rule->skip_consume = false;
+
+    return token;
 }

 static const lxb_css_syntax_token_t *
@@ -795,8 +940,7 @@ lxb_css_syntax_parser_qualified_rule(lxb_css_parser_t *parser,
                                      lxb_css_syntax_rule_t *rule)
 {
     lxb_status_t status;
-
-    /* It is necessary to avoid re-entry of the token into the phase. */
+    const lxb_css_log_message_t *msg;

     if (rule->offset > token->offset) {
         return token;
@@ -805,7 +949,6 @@ lxb_css_syntax_parser_qualified_rule(lxb_css_parser_t *parser,
     rule->offset = token->offset + lxb_css_syntax_token_base(token)->length;

     if (rule->block_end == token->type && rule->deep == 0) {
-        rule->skip_ending = true;
         goto done;
     }

@@ -823,25 +966,11 @@ lxb_css_syntax_parser_qualified_rule(lxb_css_parser_t *parser,

         case LXB_CSS_SYNTAX_TOKEN_LC_BRACKET:
             if (rule->deep == 0) {
-                rule->phase = lxb_css_syntax_parser_start_block;
-
-                rule->u.qualified.prelude_end = token->offset;
-                rule->u.qualified.block = token->offset
-                                    + lxb_css_syntax_token_base(token)->length;
-
+                rule->phase = lxb_css_syntax_parser_qualified_rule_block;
+                rule->back = lxb_css_syntax_parser_end_back;
                 rule->skip_consume = true;

-                parser->block = rule->cbx.cb->block;
-
-                lxb_css_syntax_token_consume(parser->tkz);
-
-                token = lxb_css_syntax_token(parser->tkz);
-                if (token == NULL) {
-                    return lxb_css_syntax_parser_failed(parser,
-                                                        parser->tkz->status);
-                }
-
-                token = &lxb_css_syntax_token_terminated;
+                return lxb_css_parser_token_end(parser, token->offset);
             }

             status = lxb_css_parser_types_push(parser,
@@ -849,13 +978,24 @@ lxb_css_syntax_parser_qualified_rule(lxb_css_parser_t *parser,
             break;

         case LXB_CSS_SYNTAX_TOKEN_RC_BRACKET:
-            if (rule->deep != 0 && parser->types_pos[-1] == token->type) {
-                if (rule->deep == 1) {
-                    goto done;
+            if (rule->deep != 0) {
+                if (parser->types_pos[-1] == token->type) {
+                    parser->types_pos--;
+                    rule->deep--;
+                }
+            }
+            else {
+                msg = lxb_css_log_format(parser->log,
+                                         LXB_CSS_LOG_SYNTAX_ERROR,
+                                         "%S", &lxb_css_err_rc);
+                if (msg == NULL) {
+                    return lxb_css_syntax_parser_failed(parser,
+                                        LXB_STATUS_ERROR_MEMORY_ALLOCATION);
                 }

-                parser->types_pos--;
-                rule->deep--;
+                if (rule->nested) {
+                    goto done;
+                }
             }

             return token;
@@ -868,7 +1008,7 @@ lxb_css_syntax_parser_qualified_rule(lxb_css_parser_t *parser,
             }

             return token;
-
+
         case LXB_CSS_SYNTAX_TOKEN__EOF:
             goto done;

@@ -886,23 +1026,113 @@ lxb_css_syntax_parser_qualified_rule(lxb_css_parser_t *parser,

 done:

-    rule->phase = lxb_css_syntax_parser_end;
+    rule->phase = lxb_css_syntax_parser_qualified_prelude_end;
     rule->skip_consume = true;

-    if (rule->u.qualified.block != 0) {
-        rule->u.qualified.block_end = token->offset;
+    return lxb_css_parser_token_end(parser, token->offset);
+}
+
+/*
+ * This code will be called before rule->state is called.
+ * Exclusively from the lxb_css_parser_run(...).
+ */
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_qualified_rule_block(lxb_css_parser_t *parser,
+                                           const lxb_css_syntax_token_t *token,
+                                           lxb_css_syntax_rule_t *rule)
+{
+    const lxb_css_syntax_cb_qualified_rule_t *qualified_rule;
+
+    qualified_rule = rule->cbx.qualified_rule;
+
+    parser->status = qualified_rule->prelude_end(parser, token,
+                                                 rule->context, rule->failed);
+    if (parser->status != LXB_STATUS_OK) {
+        return NULL;
     }
-    else {
-        rule->u.qualified.prelude_end = token->offset;
+
+    return lxb_css_syntax_parser_block_begin(parser, token, rule,
+                                             qualified_rule->prelude,
+                                             qualified_rule->block);
+}
+
+/*
+ * This code will be called before rule->state is called.
+ * Exclusively from the lxb_css_parser_run(...).
+ */
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_qualified_prelude_end(lxb_css_parser_t *parser,
+                                            const lxb_css_syntax_token_t *token,
+                                            lxb_css_syntax_rule_t *rule)
+{
+    const lxb_css_syntax_cb_qualified_rule_t *qualified_rule;
+
+    qualified_rule = rule->cbx.qualified_rule;
+
+    parser->status = qualified_rule->prelude_end(parser, token,
+                                                 rule->context, rule->failed);
+    if (parser->status != LXB_STATUS_OK) {
+        return NULL;
+    }
+
+    rule->phase = lxb_css_syntax_parser_end;
+    rule->state = lxb_css_state_success;
+
+    return lxb_css_syntax_token_parser_do_phase_again(parser);
+}
+
+/*
+ * This code will be called before rule->state is called.
+ * Exclusively from the lxb_css_parser_run(...).
+ */
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_qualified_back_to_prelude(lxb_css_parser_t *parser,
+                                                const lxb_css_syntax_token_t *token,
+                                                lxb_css_syntax_rule_t *rule)
+{
+    rule->phase = lxb_css_syntax_parser_qualified_rule;
+    rule->state = rule->back_state;
+    rule->skip_consume = false;
+
+    return token;
+}
+
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_block_begin(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token,
+                                  lxb_css_syntax_rule_t *rule,
+                                  lxb_css_parser_state_f back_state,
+                                  lxb_css_syntax_begin_block_f cb)
+{
+    void *block_ctx;
+    lxb_css_syntax_rule_t *block;
+    const lxb_css_syntax_cb_block_t *cb_block;
+
+    block_ctx = NULL;
+    rule->skip_consume = false;
+
+    cb_block = cb(parser, token, rule->context, &block_ctx);
+    if (cb_block == NULL) {
+        return lxb_css_syntax_parser_failed(parser,
+                                            LXB_STATUS_ERROR_UNEXPECTED_DATA);
+    }
+
+    block = lxb_css_syntax_parser_block_push(parser, cb_block, back_state,
+                                             block_ctx);
+    if (block == NULL) {
+        return lxb_css_syntax_parser_failed(parser,
+                                            LXB_STATUS_ERROR_MEMORY_ALLOCATION);
     }

-    return &lxb_css_syntax_token_terminated;
+    lxb_css_syntax_token_consume(parser->tkz);
+
+    return lxb_css_syntax_token_parser_do_phase_again(parser);
 }

 static const lxb_css_syntax_token_t *
-lxb_css_syntax_parser_declarations(lxb_css_parser_t *parser,
-                                   const lxb_css_syntax_token_t *token,
-                                   lxb_css_syntax_rule_t *rule)
+lxb_css_syntax_parser_block(lxb_css_parser_t *parser,
+                            const lxb_css_syntax_token_t *token,
+                            lxb_css_syntax_rule_t *rule)
 {
     if (rule->offset > token->offset) {
         return token;
@@ -912,11 +1142,6 @@ lxb_css_syntax_parser_declarations(lxb_css_parser_t *parser,

     rule->offset = token->offset + lxb_css_syntax_token_base(token)->length;

-    if (rule->block_end == token->type && rule->deep == 0) {
-        rule->skip_ending = true;
-        goto done;
-    }
-
     switch (token->type) {
         case LXB_CSS_SYNTAX_TOKEN_SEMICOLON:
         case LXB_CSS_SYNTAX_TOKEN_WHITESPACE:
@@ -930,93 +1155,221 @@ lxb_css_syntax_parser_declarations(lxb_css_parser_t *parser,

             goto begin;

-        case LXB_CSS_SYNTAX_TOKEN_IDENT:
-            rule->u.declarations.name_begin = token->offset;
-
-            if (lxb_css_syntax_tokenizer_lookup_colon(parser->tkz)) {
-                rule->phase = lxb_css_syntax_parser_declarations_name;
-                parser->block = rule->cbx.cb->block;
+        case LXB_CSS_SYNTAX_TOKEN_RC_BRACKET:
+            if (rule->deep == 0) {
+                rule->phase = lxb_css_syntax_parser_end_consume_token;
+                break;
+            }

-                return token;
+            if (parser->types_pos[-1] == token->type) {
+                parser->types_pos--;
+                rule->deep--;
             }

-            rule->state = rule->cbx.cb->failed;
-            rule->phase = lxb_css_syntax_parser_declarations_drop;
-            rule->failed = true;
+            return token;

+        case LXB_CSS_SYNTAX_TOKEN__EOF:
+            rule->phase = lxb_css_syntax_parser_end;
             break;

         case LXB_CSS_SYNTAX_TOKEN_AT_KEYWORD:
-            rule->u.declarations.name_begin = 0;
-
-            rule = lxb_css_syntax_parser_at_rule_push(parser, token,
-                             lxb_css_syntax_parser_declarations_back,
-                             rule->cbx.declarations->at_rule, rule->context,
-                             rule->block_end);
-            if (rule != NULL) {
-                parser->fake_null = true;
-            }
+            rule->phase = lxb_css_syntax_parser_block_at;
+            break;

-            return NULL;
+        case LXB_CSS_SYNTAX_TOKEN_IDENT:
+            if (lxb_css_syntax_tokenizer_lookup_colon(parser->tkz)) {
+                rule->phase = lxb_css_syntax_parser_block_declarations;
+                break;
+            }

-        case LXB_CSS_SYNTAX_TOKEN__EOF:
-            goto done;
+            /* Fall Through. */

         default:
-            rule->state = rule->cbx.cb->failed;
-            rule->phase = lxb_css_syntax_parser_declarations_drop;
-            rule->failed = true;
-
-            rule->u.declarations.name_begin = token->offset;
+            rule->phase = lxb_css_syntax_parser_block_qualified;
             break;
     }

-    parser->fake_null = true;
+    rule->skip_consume = true;

-    return NULL;
+    return lxb_css_parser_token_end(parser, 0);
+}

-done:
+/*
+ * This code will be called before rule->state is called.
+ * Exclusively from the lxb_css_parser_run(...).
+ */
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_block_at(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token,
+                               lxb_css_syntax_rule_t *rule)
+{
+    const lxb_css_syntax_cb_block_t *block = rule->cbx.block;

-    rule->phase = lxb_css_syntax_parser_end;
-    rule->state = lxb_css_state_success;
-    rule->skip_consume = true;
+    return lxb_css_syntax_parser_at_begin(parser, token, rule,
+                                          block->next, block->at_rule, true);
+}

-    rule->u.declarations.name_begin = 0;
-    rule->u.declarations.end = token->offset;
+/*
+ * This code will be called before rule->state is called.
+ * Exclusively from the lxb_css_parser_run(...).
+ */
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_block_declarations(lxb_css_parser_t *parser,
+                                         const lxb_css_syntax_token_t *token,
+                                         lxb_css_syntax_rule_t *rule)
+{
+    void *declr_ctx;
+    lxb_css_syntax_rule_t *declr_rule;
+    lxb_css_syntax_begin_declarations_f cb;
+    const lxb_css_syntax_cb_block_t *block;
+    const lxb_css_syntax_cb_declarations_t *cb_declr;

-    parser->fake_null = true;
+    declr_ctx = NULL;
+    block = rule->cbx.block;
+    cb = block->declarations;

-    return NULL;
+    rule->skip_consume = false;
+
+    cb_declr = cb(parser, token, rule->context, &declr_ctx);
+    if (cb_declr == NULL) {
+        return lxb_css_syntax_parser_failed(parser,
+                                            LXB_STATUS_ERROR_UNEXPECTED_DATA);
+    }
+
+    declr_rule = lxb_css_syntax_parser_declarations_push(parser, cb_declr,
+                                                         block->next, declr_ctx,
+                                                         LXB_CSS_SYNTAX_TOKEN_RC_BRACKET,
+                                                         false, true);
+    if (declr_rule == NULL) {
+        return lxb_css_syntax_parser_failed(parser,
+                                            LXB_STATUS_ERROR_MEMORY_ALLOCATION);
+    }
+
+    return lxb_css_syntax_token_parser_do_phase_again(parser);
 }

-static bool
-lxb_css_syntax_parser_declarations_back(lxb_css_parser_t *parser,
-                                        const lxb_css_syntax_token_t *token, void *ctx)
+/*
+ * This code will be called before rule->state is called.
+ * Exclusively from the lxb_css_parser_run(...).
+ */
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_block_qualified(lxb_css_parser_t *parser,
+                                      const lxb_css_syntax_token_t *token,
+                                      lxb_css_syntax_rule_t *rule)
 {
-    lxb_css_syntax_rule_t *rules = parser->rules;
+    void *qualified_ctx;
+    lxb_css_syntax_rule_t *qualified;
+    const lxb_css_syntax_cb_block_t *block;
+    lxb_css_syntax_begin_qualified_rule_f cb;
+    const lxb_css_syntax_cb_qualified_rule_t *cb_qualified;

-    rules->state = rules->cbx.declarations->cb.state;
+    qualified_ctx = NULL;
+    block = rule->cbx.block;
+    cb = block->qualified_rule;
+
+    rule->skip_consume = false;

-    return rules->state(parser, token, ctx);
+    cb_qualified = cb(parser, token, rule->context, &qualified_ctx);
+    if (cb_qualified == NULL) {
+        return lxb_css_syntax_parser_failed(parser,
+                                            LXB_STATUS_ERROR_UNEXPECTED_DATA);
+    }
+
+    qualified = lxb_css_syntax_parser_qualified_push(parser, cb_qualified,
+                                                     block->next, qualified_ctx,
+                                                     LXB_CSS_SYNTAX_TOKEN_SEMICOLON,
+                                                     true);
+    if (qualified == NULL) {
+        return lxb_css_syntax_parser_failed(parser,
+                                            LXB_STATUS_ERROR_MEMORY_ALLOCATION);
+    }
+
+    return lxb_css_syntax_token_parser_do_phase_again(parser);
 }

+/*
+ * This code will be called before rule->state is called.
+ * Exclusively from the lxb_css_parser_run(...).
+ */
 static const lxb_css_syntax_token_t *
-lxb_css_syntax_parser_declarations_name(lxb_css_parser_t *parser,
-                                        const lxb_css_syntax_token_t *token,
-                                        lxb_css_syntax_rule_t *rule)
+lxb_css_syntax_parser_block_back(lxb_css_parser_t *parser,
+                                 const lxb_css_syntax_token_t *token,
+                                 lxb_css_syntax_rule_t *rule)
 {
-    if (rule->offset > token->offset) {
-        return token;
+    rule->phase = lxb_css_syntax_parser_block;
+    rule->state = rule->back_state;
+    rule->skip_consume = true;
+
+    return token;
+}
+
+/*
+ * This code will be called before rule->state is called.
+ * Exclusively from the lxb_css_parser_run(...).
+ */
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_declarations_validate(lxb_css_parser_t *parser,
+                                            const lxb_css_syntax_token_t *token,
+                                            lxb_css_syntax_rule_t *rule)
+{
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_IDENT
+        || !lxb_css_syntax_tokenizer_lookup_colon(parser->tkz))
+    {
+        rule->phase = lxb_css_syntax_parser_declarations_drop;
+        rule->state = rule->cbx.cb->failed;
+        rule->begin = token->offset;
+        rule->context_old = rule->context;
+        rule->context = NULL;
+        rule->failed = true;
+
+        parser->offset.value_end = 0;
+
+        return lxb_css_syntax_token_parser_do_phase_again(parser);
     }

-    if (rule->state != lxb_css_state_success) {
-        rule->skip_consume = true;
+    return lxb_css_syntax_parser_declarations_begin(parser, token, rule);
+}
+
+/*
+ * This code will be called before rule->state is called.
+ * Exclusively from the lxb_css_parser_run(...).
+ */
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_declarations_begin(lxb_css_parser_t *parser,
+                                         const lxb_css_syntax_token_t *token,
+                                         lxb_css_syntax_rule_t *rule)
+{
+    void *declr_ctx;
+    lxb_css_syntax_declaration_name_f cb;

-        return &lxb_css_syntax_token_terminated;
+    declr_ctx = NULL;
+    cb = rule->cbx.declarations->name;
+
+    rule->state = cb(parser, token, rule->context, &declr_ctx);
+    if (rule->state == NULL) {
+        return lxb_css_syntax_parser_failed(parser,
+                                            LXB_STATUS_ERROR_UNEXPECTED_DATA);
     }

+    rule->phase = lxb_css_syntax_parser_declarations_name;
+    rule->context_old = rule->context;
+    rule->context = declr_ctx;
     rule->skip_consume = false;

+    lxb_css_syntax_token_consume(parser->tkz);
+
+    return lxb_css_syntax_token_parser_do_phase_again(parser);
+}
+
+/*
+ * This code will be called before rule->state is called.
+ * Exclusively from the lxb_css_parser_run(...).
+ */
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_declarations_name(lxb_css_parser_t *parser,
+                                        const lxb_css_syntax_token_t *token,
+                                        lxb_css_syntax_rule_t *rule)
+{
     /* 1. */

     if (token->type == LXB_CSS_SYNTAX_TOKEN_WHITESPACE) {
@@ -1049,8 +1402,6 @@ lxb_css_syntax_parser_declarations_name(lxb_css_parser_t *parser,
         return NULL;
     }

-    rule->u.declarations.name_end = token->offset;
-
     lxb_css_syntax_token_consume(parser->tkz);

     token = lxb_css_syntax_token(parser->tkz);
@@ -1069,12 +1420,12 @@ lxb_css_syntax_parser_declarations_name(lxb_css_parser_t *parser,
         }
     }

-    rule->u.declarations.value_begin = token->offset;
+    rule->begin = token->offset;
+    parser->offset.value_end = 0;

     /* 4. */

     rule->phase = lxb_css_syntax_parser_declarations_value;
-    rule->state = parser->block;

     return lxb_css_syntax_parser_declarations_value(parser, token, rule);
 }
@@ -1085,7 +1436,7 @@ lxb_css_syntax_parser_declarations_value(lxb_css_parser_t *parser,
                                          lxb_css_syntax_rule_t *rule)
 {
     bool imp;
-    uintptr_t before_important;
+    size_t offset;
     lxb_status_t status;

     if (rule->offset > token->offset) {
@@ -1097,7 +1448,6 @@ lxb_css_syntax_parser_declarations_value(lxb_css_parser_t *parser,
     rule->offset = token->offset + lxb_css_syntax_token_base(token)->length;

     if (rule->block_end == token->type && rule->deep == 0) {
-        rule->skip_ending = true;
         goto done;
     }

@@ -1115,7 +1465,7 @@ lxb_css_syntax_parser_declarations_value(lxb_css_parser_t *parser,
                 return token;
             }

-            before_important = token->offset;
+            parser->offset.value_end = token->offset;

             lxb_css_syntax_token_consume(parser->tkz);

@@ -1128,7 +1478,7 @@ lxb_css_syntax_parser_declarations_value(lxb_css_parser_t *parser,

             if (token->type == LXB_CSS_SYNTAX_TOKEN_DELIM) {
                 rule->important = true;
-                rule->u.declarations.before_important = before_important;
+                parser->offset.important_begin = token->offset;

                 lxb_css_syntax_token_consume(parser->tkz);

@@ -1138,6 +1488,10 @@ lxb_css_syntax_parser_declarations_value(lxb_css_parser_t *parser,
                 if (token == NULL) {
                     return lxb_css_syntax_parser_failed(parser, parser->tkz->status);
                 }
+
+                parser->offset.important_end = token->offset
+                    + lxb_css_syntax_token_base(token)->length;
+
                 lxb_css_syntax_token_consume(parser->tkz);

                 token = lxb_css_syntax_token(parser->tkz);
@@ -1155,6 +1509,10 @@ lxb_css_syntax_parser_declarations_value(lxb_css_parser_t *parser,
                     }
                 }
             }
+            else {
+                parser->offset.important_begin = 0;
+                parser->offset.important_end = 0;
+            }

             goto again;

@@ -1162,17 +1520,20 @@ lxb_css_syntax_parser_declarations_value(lxb_css_parser_t *parser,
             if (rule->deep == 0) {
                 rule->phase = lxb_css_syntax_parser_declarations_next;

-                rule->u.declarations.value_end = token->offset;
+                offset = token->offset;

-                lxb_css_syntax_token_consume(parser->tkz);
+                parser->offset.value_begin = rule->begin;
+                parser->offset.end = offset;

-                token = lxb_css_syntax_token(parser->tkz);
-                if (token == NULL) {
-                    return lxb_css_syntax_parser_failed(parser,
-                                                        parser->tkz->status);
+                if (parser->offset.value_end == 0) {
+                    parser->offset.value_end = offset;
+                    parser->offset.important_begin = 0;
+                    parser->offset.important_end = 0;
                 }

-                return &lxb_css_syntax_token_terminated;
+                lxb_css_syntax_token_consume(parser->tkz);
+
+                return lxb_css_parser_token_end(parser, offset);
             }

             return token;
@@ -1190,9 +1551,11 @@ lxb_css_syntax_parser_declarations_value(lxb_css_parser_t *parser,
                 return token;
             }

-            rule->u.declarations.before_important = token->offset;
             rule->important = true;

+            parser->offset.value_end = token->offset;
+            parser->offset.important_begin = token->offset;
+
             lxb_css_syntax_token_consume(parser->tkz);

             token = lxb_css_syntax_token(parser->tkz);
@@ -1200,6 +1563,9 @@ lxb_css_syntax_parser_declarations_value(lxb_css_parser_t *parser,
                 return lxb_css_syntax_parser_failed(parser, parser->tkz->status);
             }

+            parser->offset.important_end = token->offset
+                + lxb_css_syntax_token_base(token)->length;
+
             lxb_css_syntax_token_consume(parser->tkz);

             token = lxb_css_syntax_token(parser->tkz);
@@ -1262,177 +1628,304 @@ lxb_css_syntax_parser_declarations_value(lxb_css_parser_t *parser,

 done:

-    rule->phase = lxb_css_syntax_parser_declarations_end;
-    rule->skip_consume = true;
+    parser->offset.value_begin = rule->begin;
+    parser->offset.end = token->offset;
+
+    if (parser->offset.value_end == 0) {
+        parser->offset.value_end = token->offset;
+        parser->offset.important_begin = 0;
+        parser->offset.important_end = 0;
+    }

-    rule->u.declarations.value_end = token->offset;
-    rule->u.declarations.end = token->offset;
+    rule->phase = lxb_css_syntax_parser_declaration_end;
+    rule->skip_consume = true;

-    return &lxb_css_syntax_token_terminated;
+    return lxb_css_parser_token_end(parser, token->offset);
 }

 static const lxb_css_syntax_token_t *
-lxb_css_syntax_parser_declarations_next(lxb_css_parser_t *parser,
+lxb_css_syntax_parser_declarations_drop(lxb_css_parser_t *parser,
                                         const lxb_css_syntax_token_t *token,
                                         lxb_css_syntax_rule_t *rule)
 {
+    size_t offset;
     lxb_status_t status;
-    lxb_css_syntax_declarations_offset_t *decl;

-    if (rule->state != lxb_css_state_success) {
-        rule->skip_consume = true;
+    if (rule->offset > token->offset) {
+        return token;
+    }

-        return &lxb_css_syntax_token_terminated;
+    rule->offset = token->offset + lxb_css_syntax_token_base(token)->length;
+
+    if (rule->block_end == token->type && rule->deep == 0) {
+        goto done;
+    }
+
+    switch (token->type) {
+        case LXB_CSS_SYNTAX_TOKEN_SEMICOLON:
+            if (rule->deep == 0) {
+                rule->phase = lxb_css_syntax_parser_declarations_next;
+
+                offset = token->offset;
+
+                parser->offset.value_begin = rule->begin;
+                parser->offset.end = offset;
+
+                if (parser->offset.value_end == 0) {
+                    parser->offset.value_end = offset;
+                    parser->offset.important_begin = 0;
+                    parser->offset.important_end = 0;
+                }
+
+                lxb_css_syntax_token_consume(parser->tkz);
+
+                return lxb_css_parser_token_end(parser, offset);
+            }
+
+            return token;
+
+        case LXB_CSS_SYNTAX_TOKEN_LS_BRACKET:
+            status = lxb_css_parser_types_push(parser,
+                                               LXB_CSS_SYNTAX_TOKEN_RS_BRACKET);
+            break;
+
+        case LXB_CSS_SYNTAX_TOKEN_FUNCTION:
+        case LXB_CSS_SYNTAX_TOKEN_L_PARENTHESIS:
+            status = lxb_css_parser_types_push(parser,
+                                               LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS);
+            break;
+
+        case LXB_CSS_SYNTAX_TOKEN_LC_BRACKET:
+            status = lxb_css_parser_types_push(parser,
+                                               LXB_CSS_SYNTAX_TOKEN_RC_BRACKET);
+            break;
+
+        case LXB_CSS_SYNTAX_TOKEN_RC_BRACKET:
+            if (rule->deep == 0) {
+                if (rule->nested) {
+                    goto done;
+                }
+            }
+            else if (parser->types_pos[-1] == token->type) {
+                parser->types_pos--;
+                rule->deep--;
+            }
+
+            return token;
+
+        case LXB_CSS_SYNTAX_TOKEN_RS_BRACKET:
+        case LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS:
+            if (rule->deep != 0 && parser->types_pos[-1] == token->type) {
+                parser->types_pos--;
+                rule->deep--;
+            }
+
+            return token;
+
+        case LXB_CSS_SYNTAX_TOKEN__EOF:
+            goto done;
+
+        default:
+            return token;
     }

-    status = rule->cbx.declarations->declaration_end(parser, rule->context,
-                                                     rule->important,
-                                                     rule->failed);
     if (status != LXB_STATUS_OK) {
         return lxb_css_syntax_parser_failed(parser, status);
     }

-    rule->phase = lxb_css_syntax_parser_declarations;
-    rule->state = rule->cbx.cb->state;
+    rule->deep++;

-    rule->skip_consume = false;
-    rule->important = false;
-    rule->failed = false;
+    return token;
+
+done:
+
+    parser->offset.value_begin = rule->begin;
+    parser->offset.end = token->offset;

-    decl = &rule->u.declarations;
+    if (parser->offset.value_end == 0) {
+        parser->offset.value_end = token->offset;
+        parser->offset.important_begin = 0;
+        parser->offset.important_end = 0;
+    }

-    decl->name_begin = 0;
-    decl->name_end = 0;
-    decl->value_begin = 0;
-    decl->before_important = 0;
-    decl->value_end = 0;
+    rule->phase = lxb_css_syntax_parser_declaration_end;
+    rule->skip_consume = true;

-    return lxb_css_syntax_parser_declarations(parser, token, rule);
+    return lxb_css_parser_token_end(parser, token->offset);
 }

+/*
+ * This code will be called before rule->state is called.
+ * Exclusively from the lxb_css_parser_run(...).
+ */
 static const lxb_css_syntax_token_t *
-lxb_css_syntax_parser_declarations_drop(lxb_css_parser_t *parser,
+lxb_css_syntax_parser_declarations_next(lxb_css_parser_t *parser,
                                         const lxb_css_syntax_token_t *token,
                                         lxb_css_syntax_rule_t *rule)
 {
+    void *out_rule;
     lxb_status_t status;
+    lxb_css_syntax_declaration_name_f name;

-    /* It is necessary to avoid re-entry of the token into the phase. */
+    if (rule->state != lxb_css_state_success) {
+        rule->skip_consume = true;

-    if (rule->offset > token->offset) {
-        return token;
+        return lxb_css_parser_token_end(parser, token->offset);
     }

-    rule->offset = token->offset + lxb_css_syntax_token_base(token)->length;
-
-    if (rule->block_end == token->type && rule->deep == 0) {
-        rule->skip_ending = true;
-        goto done;
+    status = rule->cbx.declarations->end(parser, rule->context_old,
+                                         rule->context, token, &parser->offset,
+                                         rule->important, rule->failed);
+    if (status != LXB_STATUS_OK) {
+        return lxb_css_syntax_parser_failed(parser, status);
     }

-    switch (token->type) {
-        case LXB_CSS_SYNTAX_TOKEN_SEMICOLON:
-            if (rule->deep == 0) {
-                rule->phase = lxb_css_syntax_parser_declarations_next;
+begin:
+
+    switch (token->type) {
+        case LXB_CSS_SYNTAX_TOKEN_SEMICOLON:
+        case LXB_CSS_SYNTAX_TOKEN_WHITESPACE:
+            lxb_css_syntax_token_consume(parser->tkz);
+
+            token = lxb_css_syntax_token(parser->tkz);
+            if (token == NULL) {
+                return lxb_css_syntax_parser_failed(parser,
+                                                    parser->tkz->status);
+            }
+
+            goto begin;

-                rule->u.declarations.name_end = token->offset;
+        case LXB_CSS_SYNTAX_TOKEN__EOF:
+            rule->phase = lxb_css_syntax_parser_declarations_end;
+            break;

-                lxb_css_syntax_token_consume(parser->tkz);
+        case LXB_CSS_SYNTAX_TOKEN_IDENT:
+            if (lxb_css_syntax_tokenizer_lookup_colon(parser->tkz)) {
+                out_rule = NULL;
+                name = rule->cbx.declarations->name;
+                rule->skip_consume = true;

-                token = lxb_css_syntax_token(parser->tkz);
-                if (token == NULL) {
+                rule->state = name(parser, token, rule->context, &out_rule);
+                if (rule->state == NULL) {
                     return lxb_css_syntax_parser_failed(parser,
-                                                        parser->tkz->status);
+                                                        LXB_STATUS_ERROR_UNEXPECTED_DATA);
                 }

-                rule->skip_consume = true;
-
-                return &lxb_css_syntax_token_terminated;
-            }
+                rule->context = out_rule;

-            return token;
+                lxb_css_syntax_token_consume(parser->tkz);

-        case LXB_CSS_SYNTAX_TOKEN_LS_BRACKET:
-            status = lxb_css_parser_types_push(parser,
-                                               LXB_CSS_SYNTAX_TOKEN_RS_BRACKET);
-            break;
+                rule->phase = lxb_css_syntax_parser_declarations_name;
+                rule->context = out_rule;

-        case LXB_CSS_SYNTAX_TOKEN_FUNCTION:
-        case LXB_CSS_SYNTAX_TOKEN_L_PARENTHESIS:
-            status = lxb_css_parser_types_push(parser,
-                                               LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS);
-            break;
+                break;
+            }

-        case LXB_CSS_SYNTAX_TOKEN_LC_BRACKET:
-            status = lxb_css_parser_types_push(parser,
-                                               LXB_CSS_SYNTAX_TOKEN_RC_BRACKET);
-            break;
+            /* Fall through. */

-        case LXB_CSS_SYNTAX_TOKEN_RC_BRACKET:
-        case LXB_CSS_SYNTAX_TOKEN_RS_BRACKET:
-        case LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS:
-            if (rule->deep != 0 && parser->types_pos[-1] == token->type) {
-                parser->types_pos--;
-                rule->deep--;
+        default:
+            if (rule->nested) {
+                rule->phase = lxb_css_syntax_parser_declarations_end;
             }
+            else {
+                rule->phase = lxb_css_syntax_parser_declarations_drop;
+                rule->state = rule->cbx.cb->failed;
+                rule->begin = token->offset;
+                rule->context = NULL;
+                rule->failed = true;

-            return token;
-
-        case LXB_CSS_SYNTAX_TOKEN__EOF:
-            goto done;
+                parser->offset.value_end = 0;

-        default:
-            return token;
-    }
+                return lxb_css_syntax_token_parser_do_phase_again(parser);
+            }

-    if (status != LXB_STATUS_OK) {
-        return lxb_css_syntax_parser_failed(parser, status);
+            break;
     }

-    rule->deep++;
-
-    return token;
+    rule->skip_consume = false;
+    rule->important = false;
+    rule->failed = false;

-done:
+    return lxb_css_syntax_token_parser_do_phase_again(parser);
+}

-    rule->phase = lxb_css_syntax_parser_declarations_end;
-    rule->skip_consume = true;
+/*
+ * This code will be called before rule->state is called.
+ * Exclusively from the lxb_css_parser_run(...).
+ */
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_declaration_back_to_value(lxb_css_parser_t *parser,
+                                                const lxb_css_syntax_token_t *token,
+                                                lxb_css_syntax_rule_t *rule)
+{
+    rule->phase = lxb_css_syntax_parser_declarations_value;
+    rule->state = rule->back_state;
+    rule->skip_consume = false;

-    rule->u.declarations.name_end = token->offset;
-    rule->u.declarations.end = token->offset;
+    return token;
+}

-    return &lxb_css_syntax_token_terminated;
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_declaration_end(lxb_css_parser_t *parser,
+                                      const lxb_css_syntax_token_t *token,
+                                      lxb_css_syntax_rule_t *rule)
+{
+    return lxb_css_syntax_parser_declaration_end_handler(parser, token,
+                                                         rule, false);
 }

 static const lxb_css_syntax_token_t *
-lxb_css_syntax_parser_declarations_end(lxb_css_parser_t *parser,
-                                       const lxb_css_syntax_token_t *token,
-                                       lxb_css_syntax_rule_t *rule)
+lxb_css_syntax_parser_declaration_end_handler(lxb_css_parser_t *parser,
+                                              const lxb_css_syntax_token_t *token,
+                                              lxb_css_syntax_rule_t *rule,
+                                              bool skip_token)
 {
     lxb_status_t status;
-    lxb_css_syntax_rule_t *rules;

     if (rule->state != lxb_css_state_success) {
         rule->skip_consume = true;

-        return &lxb_css_syntax_token_terminated;
+        return lxb_css_parser_token_end(parser, token->offset);
     }

-    status = rule->cbx.declarations->declaration_end(parser, rule->context,
-                                                     rule->important,
-                                                     rule->failed);
+    status = rule->cbx.declarations->end(parser, rule->context_old,
+                                         rule->context, token, &parser->offset,
+                                         rule->important, rule->failed);
     if (status != LXB_STATUS_OK) {
         return lxb_css_syntax_parser_failed(parser, status);
     }

+    return lxb_css_syntax_parser_declarations_end_h(parser, token,
+                                                    rule, skip_token);
+}
+
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_declarations_end(lxb_css_parser_t *parser,
+                                       const lxb_css_syntax_token_t *token,
+                                       lxb_css_syntax_rule_t *rule)
+{
+    return lxb_css_syntax_parser_declarations_end_h(parser, token,
+                                                    rule, false);
+}
+
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_declarations_end_h(lxb_css_parser_t *parser,
+                                         const lxb_css_syntax_token_t *token,
+                                         lxb_css_syntax_rule_t *rule,
+                                         bool skip_token)
+{
+    lxb_status_t status;
+
     /* This code will be called exclusively from the lxb_css_parser_run(...). */

+    rule->context = rule->context_old;
+
     status = rule->cbx.cb->end(parser, token, rule->context, false);
     if (status != LXB_STATUS_OK) {
         return lxb_css_syntax_parser_failed(parser, status);
     }

-    if (!rule->skip_ending) {
+    if (skip_token) {
         lxb_css_syntax_token_consume(parser->tkz);

         token = lxb_css_syntax_token(parser->tkz);
@@ -1442,18 +1935,7 @@ lxb_css_syntax_parser_declarations_end(lxb_css_parser_t *parser,
         }
     }

-    (void) lxb_css_syntax_parser_stack_pop(parser);
-
-    rules = parser->rules;
-
-    if (parser->rules <= parser->rules_begin) {
-        rules->state = lxb_css_state_stop;
-        return token;
-    }
-
-    rules->phase = rules->back;
-
-    return rules->phase(parser, token, rules);
+    return lxb_css_syntax_parser_call_back(parser, token);
 }

 static const lxb_css_syntax_token_t *
@@ -1470,7 +1952,6 @@ lxb_css_syntax_parser_components(lxb_css_parser_t *parser,
     rule->offset = token->offset + lxb_css_syntax_token_base(token)->length;

     if (rule->block_end == token->type && rule->deep == 0) {
-        rule->skip_ending = true;
         goto done;
     }

@@ -1521,7 +2002,23 @@ lxb_css_syntax_parser_components(lxb_css_parser_t *parser,
     rule->phase = lxb_css_syntax_parser_end;
     rule->skip_consume = true;

-    return &lxb_css_syntax_token_terminated;
+    return lxb_css_parser_token_end(parser, token->offset);
+}
+
+/*
+ * This code will be called before rule->state is called.
+ * Exclusively from the lxb_css_parser_run(...).
+ */
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_components_back_to_value(lxb_css_parser_t *parser,
+                                               const lxb_css_syntax_token_t *token,
+                                               lxb_css_syntax_rule_t *rule)
+{
+    rule->phase = lxb_css_syntax_parser_components;
+    rule->state = rule->back_state;
+    rule->skip_consume = false;
+
+    return token;
 }

 static const lxb_css_syntax_token_t *
@@ -1555,16 +2052,16 @@ lxb_css_syntax_parser_function(lxb_css_parser_t *parser,
             break;

         case LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS:
-            if (rule->deep != 0) {
-                if (parser->types_pos[-1] == token->type) {
-                    parser->types_pos--;
-                    rule->deep--;
-                }
-            }
-            else {
+            if (rule->deep == 0)  {
+                rule->phase = lxb_css_syntax_parser_end_consume_token;
                 goto done;
             }

+            if (parser->types_pos[-1] == token->type) {
+                parser->types_pos--;
+                rule->deep--;
+            }
+
             return token;

         case LXB_CSS_SYNTAX_TOKEN_RC_BRACKET:
@@ -1577,6 +2074,7 @@ lxb_css_syntax_parser_function(lxb_css_parser_t *parser,
             return token;

         case LXB_CSS_SYNTAX_TOKEN__EOF:
+            rule->phase = lxb_css_syntax_parser_end;
             goto done;

         default:
@@ -1593,77 +2091,25 @@ lxb_css_syntax_parser_function(lxb_css_parser_t *parser,

 done:

-    rule->phase = lxb_css_syntax_parser_end;
     rule->skip_consume = true;

-    return &lxb_css_syntax_token_terminated;
+    return lxb_css_parser_token_end(parser, token->offset);
 }

+/*
+ * This code will be called before rule->state is called.
+ * Exclusively from the lxb_css_parser_run(...).
+ */
 static const lxb_css_syntax_token_t *
-lxb_css_syntax_parser_block(lxb_css_parser_t *parser,
-                            const lxb_css_syntax_token_t *token,
-                            lxb_css_syntax_rule_t *rule)
+lxb_css_syntax_parser_function_back(lxb_css_parser_t *parser,
+                                    const lxb_css_syntax_token_t *token,
+                                    lxb_css_syntax_rule_t *rule)
 {
-    lxb_status_t status;
-
-    if (rule->offset > token->offset) {
-        return token;
-    }
-
-    rule->offset = token->offset + lxb_css_syntax_token_base(token)->length;
-
-    if (rule->block_end == token->type && rule->deep == 0) {
-        goto done;
-    }
-
-    switch (token->type) {
-        case LXB_CSS_SYNTAX_TOKEN_LS_BRACKET:
-            status = lxb_css_parser_types_push(parser,
-                                               LXB_CSS_SYNTAX_TOKEN_RS_BRACKET);
-            break;
-
-        case LXB_CSS_SYNTAX_TOKEN_FUNCTION:
-        case LXB_CSS_SYNTAX_TOKEN_L_PARENTHESIS:
-            status = lxb_css_parser_types_push(parser,
-                                               LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS);
-            break;
-
-        case LXB_CSS_SYNTAX_TOKEN_LC_BRACKET:
-            status = lxb_css_parser_types_push(parser,
-                                               LXB_CSS_SYNTAX_TOKEN_RC_BRACKET);
-            break;
-
-        case LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS:
-        case LXB_CSS_SYNTAX_TOKEN_RS_BRACKET:
-        case LXB_CSS_SYNTAX_TOKEN_RC_BRACKET:
-            if (rule->deep != 0 && parser->types_pos[-1] == token->type) {
-                parser->types_pos--;
-                rule->deep--;
-            }
-
-            return token;
-
-        case LXB_CSS_SYNTAX_TOKEN__EOF:
-            goto done;
-
-        default:
-            return token;
-    }
-
-    if (status != LXB_STATUS_OK) {
-        return lxb_css_syntax_parser_failed(parser, status);
-    }
-
-    rule->deep++;
+    rule->phase = lxb_css_syntax_parser_function;
+    rule->state = rule->back_state;
+    rule->skip_consume = false;

     return token;
-
-done:
-
-    rule->phase = lxb_css_syntax_parser_end;
-    rule->skip_consume = true;
-
-    return &lxb_css_syntax_token_terminated;
 }

 static const lxb_css_syntax_token_t *
@@ -1677,31 +2123,41 @@ lxb_css_syntax_parser_pipe(lxb_css_parser_t *parser,
         rule->phase = lxb_css_syntax_parser_end;
         rule->skip_consume = true;

-        return &lxb_css_syntax_token_terminated;
+        return lxb_css_parser_token_end(parser, token->offset);
     }

     return token;
 }

-const lxb_css_syntax_token_t *
-lxb_css_syntax_parser_start_block(lxb_css_parser_t *parser,
-                                  const lxb_css_syntax_token_t *token,
-                                  lxb_css_syntax_rule_t *rule)
+/*
+ * This code will be called before rule->state is called.
+ * Exclusively from the lxb_css_parser_run(...).
+ */
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_pipe_back(lxb_css_parser_t *parser,
+                                const lxb_css_syntax_token_t *token,
+                                lxb_css_syntax_rule_t *rule)
 {
-    if (rule->state != lxb_css_state_success) {
-        rule->skip_consume = true;
-
-        return &lxb_css_syntax_token_terminated;
-    }
-
-    /* This code will be called exclusively from the lxb_css_parser_run(...). */
-
+    rule->phase = lxb_css_syntax_parser_pipe;
+    rule->state = rule->back_state;
     rule->skip_consume = false;

-    rule->phase = rule->back;
-    rule->state = parser->block;
+    return token;
+}
+
+/*
+ * This code will be called before rule->state is called.
+ * Exclusively from the lxb_css_parser_run(...).
+ */
+static const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_end_back(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token,
+                               lxb_css_syntax_rule_t *rule)
+{
+    rule->phase = lxb_css_syntax_parser_end;
+    rule->state = lxb_css_state_blank;

-    return rule->back(parser, token, rule);
+    return token;
 }

 const lxb_css_syntax_token_t *
@@ -1710,13 +2166,12 @@ lxb_css_syntax_parser_end(lxb_css_parser_t *parser,
                           lxb_css_syntax_rule_t *rule)
 {
     lxb_status_t status;
-    lxb_css_syntax_rule_t *rules;
     lxb_css_syntax_cb_base_t *base;

-    if (rule->state != lxb_css_state_success) {
-        rule->skip_consume = true;
+    rule->skip_consume = true;

-        return &lxb_css_syntax_token_terminated;
+    if (rule->state != lxb_css_state_success) {
+        return lxb_css_parser_token_end(parser, token->offset);
     }

     /* This code will be called exclusively from the lxb_css_parser_run(...). */
@@ -1728,27 +2183,43 @@ lxb_css_syntax_parser_end(lxb_css_parser_t *parser,
         return lxb_css_syntax_parser_failed(parser, status);
     }

-    if (!rule->skip_ending) {
-        lxb_css_syntax_token_consume(parser->tkz);
+    rule->skip_consume = false;

-        token = lxb_css_syntax_token(parser->tkz);
-        if (token == NULL) {
-            return lxb_css_syntax_parser_failed(parser,
-                                                parser->tkz->status);
-        }
+    return lxb_css_syntax_parser_call_back(parser, token);
+}
+
+const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_end_consume_token(lxb_css_parser_t *parser,
+                                        const lxb_css_syntax_token_t *token,
+                                        lxb_css_syntax_rule_t *rule)
+{
+    lxb_status_t status;
+    lxb_css_syntax_cb_base_t *base;
+
+    rule->skip_consume = true;
+
+    if (rule->state != lxb_css_state_success) {
+        return lxb_css_parser_token_end(parser, token->offset);
     }

-    (void) lxb_css_syntax_parser_stack_pop(parser);
+    /* This code will be called exclusively from the lxb_css_parser_run(...). */

-    rules = parser->rules;
+    base = rule->cbx.user;

-    if (parser->rules <= parser->rules_begin) {
-        rules->state = lxb_css_state_stop;
-        return token;
+    status = base->end(parser, token, rule->context, rule->failed);
+    if (status != LXB_STATUS_OK) {
+        return lxb_css_syntax_parser_failed(parser, status);
     }

-    rules->phase = rules->back;
-    rules->state = rule->state_back;
+    rule->skip_consume = false;
+
+    lxb_css_syntax_token_consume(parser->tkz);
+
+    token = lxb_css_syntax_token(parser->tkz);
+    if (token == NULL) {
+        return lxb_css_syntax_parser_failed(parser,
+                                            parser->tkz->status);
+    }

-    return rules->phase(parser, token, rules);
+    return lxb_css_syntax_parser_call_back(parser, token);
 }
diff --git a/ext/dom/lexbor/lexbor/css/syntax/parser.h b/ext/dom/lexbor/lexbor/css/syntax/parser.h
index f41d62f1ff8..2e7aff64450 100644
--- a/ext/dom/lexbor/lexbor/css/syntax/parser.h
+++ b/ext/dom/lexbor/lexbor/css/syntax/parser.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020-2025 Alexander Borisov
+ * Copyright (C) 2020-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -30,70 +30,63 @@ lxb_css_syntax_parser_consume(lxb_css_parser_t *parser);

 LXB_API lxb_css_syntax_rule_t *
 lxb_css_syntax_parser_list_rules_push(lxb_css_parser_t *parser,
-                                      const lxb_css_syntax_token_t *token,
-                                      lxb_css_parser_state_f state_back,
                                       const lxb_css_syntax_cb_list_rules_t *list_rules,
-                                      void *ctx, bool top_level,
-                                      lxb_css_syntax_token_type_t stop);
+                                      lxb_css_parser_state_f back,
+                                      void *ctx, lxb_css_syntax_token_type_t stop);

 LXB_API lxb_css_syntax_rule_t *
 lxb_css_syntax_parser_at_rule_push(lxb_css_parser_t *parser,
-                                   const lxb_css_syntax_token_t *token,
-                                   lxb_css_parser_state_f state_back,
                                    const lxb_css_syntax_cb_at_rule_t *at_rule,
-                                   void *ctx, lxb_css_syntax_token_type_t stop);
+                                   lxb_css_parser_state_f back,
+                                   void *ctx, lxb_css_syntax_token_type_t stop,
+                                   bool nested);

 LXB_API lxb_css_syntax_rule_t *
 lxb_css_syntax_parser_qualified_push(lxb_css_parser_t *parser,
-                                     const lxb_css_syntax_token_t *token,
-                                     lxb_css_parser_state_f state_back,
                                      const lxb_css_syntax_cb_qualified_rule_t *qualified,
-                                     void *ctx, lxb_css_syntax_token_type_t stop);
+                                     lxb_css_parser_state_f back,
+                                     void *ctx, lxb_css_syntax_token_type_t stop,
+                                     bool nested);
+
+LXB_API lxb_css_syntax_rule_t *
+lxb_css_syntax_parser_block_push(lxb_css_parser_t *parser,
+                                 const lxb_css_syntax_cb_block_t *block,
+                                 lxb_css_parser_state_f back, void *ctx);

 LXB_API lxb_css_syntax_rule_t *
 lxb_css_syntax_parser_declarations_push(lxb_css_parser_t *parser,
-                                        const lxb_css_syntax_token_t *token,
-                                        lxb_css_parser_state_f state_back,
-                                        const lxb_css_syntax_cb_declarations_t *declarations,
-                                        void *ctx, lxb_css_syntax_token_type_t stop);
+                                        const lxb_css_syntax_cb_declarations_t *declr,
+                                        lxb_css_parser_state_f back, void *ctx,
+                                        lxb_css_syntax_token_type_t stop,
+                                        bool name_validate, bool nested);

 LXB_API lxb_css_syntax_rule_t *
 lxb_css_syntax_parser_components_push(lxb_css_parser_t *parser,
-                                      const lxb_css_syntax_token_t *token,
-                                      lxb_css_parser_state_f state_back,
                                       const lxb_css_syntax_cb_components_t *comp,
+                                      lxb_css_parser_state_f back,
                                       void *ctx, lxb_css_syntax_token_type_t stop);

 LXB_API lxb_css_syntax_rule_t *
 lxb_css_syntax_parser_function_push(lxb_css_parser_t *parser,
-                                    const lxb_css_syntax_token_t *token,
-                                    lxb_css_parser_state_f state_back,
                                     const lxb_css_syntax_cb_function_t *func,
-                                    void *ctx);
-
-LXB_API lxb_css_syntax_rule_t *
-lxb_css_syntax_parser_block_push(lxb_css_parser_t *parser,
-                                 const lxb_css_syntax_token_t *token,
-                                 lxb_css_parser_state_f state_back,
-                                 const lxb_css_syntax_cb_block_t *block,
-                                 void *ctx);
+                                    lxb_css_parser_state_f back, void *ctx);

 LXB_API lxb_css_syntax_rule_t *
 lxb_css_syntax_parser_pipe_push(lxb_css_parser_t *parser,
-                                lxb_css_parser_state_f state_back,
                                 const lxb_css_syntax_cb_pipe_t *pipe,
-                                void *ctx, lxb_css_syntax_token_type_t stop);
-
-LXB_API const lxb_css_syntax_token_t *
-lxb_css_syntax_parser_start_block(lxb_css_parser_t *parser,
-                                  const lxb_css_syntax_token_t *token,
-                                  lxb_css_syntax_rule_t *rule);
+                                lxb_css_parser_state_f back, void *ctx,
+                                lxb_css_syntax_token_type_t stop);

 LXB_API const lxb_css_syntax_token_t *
 lxb_css_syntax_parser_end(lxb_css_parser_t *parser,
                           const lxb_css_syntax_token_t *token,
                           lxb_css_syntax_rule_t *rule);

+LXB_API const lxb_css_syntax_token_t *
+lxb_css_syntax_parser_end_consume_token(lxb_css_parser_t *parser,
+                                        const lxb_css_syntax_token_t *token,
+                                        lxb_css_syntax_rule_t *rule);
+

 #ifdef __cplusplus
 } /* extern "C" */
diff --git a/ext/dom/lexbor/lexbor/css/syntax/res.h b/ext/dom/lexbor/lexbor/css/syntax/res.h
index cd33446f81d..7fa2f8ba705 100644
--- a/ext/dom/lexbor/lexbor/css/syntax/res.h
+++ b/ext/dom/lexbor/lexbor/css/syntax/res.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018-2025 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -7,12 +7,9 @@
 #ifndef LEXBOR_CSS_SYNTAX_RES_H
 #define LEXBOR_CSS_SYNTAX_RES_H

-#ifdef LXB_CSS_SYNTAX_RES_NAME_MAP
-#ifndef LXB_CSS_SYNTAX_RES_NAME_MAP_ENABLED
-#define LXB_CSS_SYNTAX_RES_NAME_MAP_ENABLED
 #define LXB_CSS_SYNTAX_RES_NAME_START 0x01

-static const lxb_char_t lxb_css_syntax_res_name_map[256] =
+LXB_API const lxb_char_t lxb_css_syntax_res_name_map[256] =
 {
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -42,7 +39,4 @@ static const lxb_char_t lxb_css_syntax_res_name_map[256] =
     0x01, 0x01, 0x01, 0x01, 0x01
 };

-#endif /* LXB_CSS_SYNTAX_RES_NAME_MAP_ENABLED */
-#endif /* LXB_CSS_SYNTAX_RES_NAME_MAP */
-
 #endif /* LEXBOR_CSS_SYNTAX_RES_H */
diff --git a/ext/dom/lexbor/lexbor/css/syntax/state.c b/ext/dom/lexbor/lexbor/css/syntax/state.c
index 99cd30c1868..a93731e1123 100644
--- a/ext/dom/lexbor/lexbor/css/syntax/state.c
+++ b/ext/dom/lexbor/lexbor/css/syntax/state.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018-2025 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -14,12 +14,11 @@
 #include "lexbor/css/syntax/syntax.h"
 #include "lexbor/css/syntax/tokenizer/error.h"

-#define LXB_CSS_SYNTAX_RES_NAME_MAP
 #include "lexbor/css/syntax/res.h"

-#define LEXBOR_STR_RES_MAP_HEX
-#include "lexbor/core/str_res.h"
-
+#ifndef LEXBOR_DISABLE_INTERNAL_EXTERN
+    LXB_EXTERN const lxb_char_t lexbor_str_res_map_hex[256];
+#endif

 #define LXB_CSS_SYNTAX_ERROR_CODEPOINT 0x1FFFFF

@@ -1101,7 +1100,9 @@ lxb_css_syntax_state_consume_numeric(lxb_css_syntax_tokenizer_t *tkz,

     /* U+0030 DIGIT ZERO (0) and U+0039 DIGIT NINE (9) */
     do {
-        e_digit = (*data - 0x30) + e_digit * 0x0A;
+        if (e_digit < INT_MAX / 10) {
+            e_digit = (*data - 0x30) + e_digit * 0x0A;
+        }

         data += 1;

@@ -1523,7 +1524,7 @@ lxb_css_syntax_state_url(lxb_css_syntax_tokenizer_t *tkz,
                 lxb_css_syntax_tokenizer_error_add(tkz->parse_errors, data,
                                         LXB_CSS_SYNTAX_TOKENIZER_ERROR_EOINUR);

-                return lxb_css_syntax_state_string_set(tkz, token, data);
+                goto done;

             default:
                 if (*data >= 0x80) {
diff --git a/ext/dom/lexbor/lexbor/css/syntax/state_res.h b/ext/dom/lexbor/lexbor/css/syntax/state_res.h
index 2f6e2899fdc..e98909a5bff 100644
--- a/ext/dom/lexbor/lexbor/css/syntax/state_res.h
+++ b/ext/dom/lexbor/lexbor/css/syntax/state_res.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018-2025 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
diff --git a/ext/dom/lexbor/lexbor/css/syntax/syntax.c b/ext/dom/lexbor/lexbor/css/syntax/syntax.c
index b148d8a043c..f8a1e944df2 100644
--- a/ext/dom/lexbor/lexbor/css/syntax/syntax.c
+++ b/ext/dom/lexbor/lexbor/css/syntax/syntax.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018-2023 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -9,58 +9,315 @@

 #include "lexbor/core/str.h"

-#define LEXBOR_STR_RES_MAP_HEX
-#define LEXBOR_STR_RES_MAP_HEX_TO_CHAR_LOWERCASE
-#define LEXBOR_STR_RES_CHAR_TO_TWO_HEX_VALUE_LOWERCASE
-#define LEXBOR_STR_RES_ANSI_REPLACEMENT_CHARACTER
-#include "lexbor/core/str_res.h"
+#ifndef LEXBOR_DISABLE_INTERNAL_EXTERN
+    LXB_EXTERN const lxb_char_t lexbor_str_res_ansi_replacement_character[4];
+    LXB_EXTERN const lxb_char_t lexbor_str_res_map_hex[256];
+    LXB_EXTERN const lxb_char_t lexbor_str_res_map_hex_to_char_lowercase[17];
+    LXB_EXTERN const char *lexbor_str_res_char_to_two_hex_value_lowercase[257];
+    LXB_EXTERN const lxb_char_t lxb_css_syntax_res_name_map[256];
+#endif

-#define LXB_CSS_SYNTAX_RES_NAME_MAP
-#include "lexbor/css/syntax/res.h"
+static const lexbor_str_t lxb_css_syntax_str_ws = lexbor_str(" ");


-static const lexbor_str_t lxb_str_ws = lexbor_str(" ");
-
-
-lxb_status_t
+lxb_css_rule_list_t *
 lxb_css_syntax_parse_list_rules(lxb_css_parser_t *parser,
                                 const lxb_css_syntax_cb_list_rules_t *cb,
-                                const lxb_char_t *data, size_t length,
-                                void *ctx, bool top_level)
+                                const lxb_char_t *data, size_t length)
 {
-    lxb_status_t status;
+    lxb_css_rule_list_t *list;
     lxb_css_syntax_rule_t *rule;

     if (lxb_css_parser_is_running(parser)) {
         parser->status = LXB_STATUS_ERROR_WRONG_STAGE;
-        return parser->status;
+        return NULL;
     }

     lxb_css_parser_clean(parser);
-
     lxb_css_parser_buffer_set(parser, data, length);

-    rule = lxb_css_syntax_parser_list_rules_push(parser, NULL, NULL, cb,
-                                                 ctx, top_level,
+    list = lxb_css_rule_list_create(parser->memory);
+    if (list == NULL) {
+        parser->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
+        goto failed;
+    }
+
+    rule = lxb_css_syntax_parser_list_rules_push(parser, cb, NULL, list,
                                                  LXB_CSS_SYNTAX_TOKEN_UNDEF);
     if (rule == NULL) {
-        status = parser->status;
-        goto end;
+        goto failed;
+    }
+
+    parser->tkz->with_comment = false;
+    parser->stage = LXB_CSS_PARSER_RUN;
+
+    parser->status = lxb_css_syntax_parser_run(parser);
+    if (parser->status != LXB_STATUS_OK) {
+        goto failed;
+    }
+
+    parser->stage = LXB_CSS_PARSER_END;
+
+    return list;
+
+failed:
+
+    if (list != NULL) {
+        lxb_css_rule_list_destroy(list, true);
+    }
+
+    parser->stage = LXB_CSS_PARSER_END;
+
+    return NULL;
+}
+
+lxb_css_rule_declaration_list_t *
+lxb_css_syntax_parse_declarations(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_cb_declarations_t *cb,
+                                  const lxb_char_t *data, size_t length)
+{
+    lxb_css_rule_declaration_list_t *list;
+    lxb_css_syntax_rule_t *rule;
+
+    if (lxb_css_parser_is_running(parser)) {
+        parser->status = LXB_STATUS_ERROR_WRONG_STAGE;
+        return NULL;
+    }
+
+    lxb_css_parser_clean(parser);
+    lxb_css_parser_buffer_set(parser, data, length);
+
+    list = lxb_css_rule_declaration_list_create(parser->memory);
+    if (list == NULL) {
+        parser->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
+        goto failed;
+    }
+
+    rule = lxb_css_syntax_parser_declarations_push(parser, cb, NULL, list,
+                                                   LXB_CSS_SYNTAX_TOKEN_UNDEF,
+                                                   true, false);
+    if (rule == NULL) {
+        goto failed;
     }

     parser->tkz->with_comment = false;
     parser->stage = LXB_CSS_PARSER_RUN;

-    status = lxb_css_syntax_parser_run(parser);
-    if (status != LXB_STATUS_OK) {
-        /* Destroy StyleSheet. */
+    parser->status = lxb_css_syntax_parser_run(parser);
+    if (parser->status != LXB_STATUS_OK) {
+        goto failed;
     }

-end:
+    parser->stage = LXB_CSS_PARSER_END;
+
+    return list;
+
+failed:
+
+    if (list != NULL) {
+        lxb_css_rule_declaration_list_destroy(list, true);
+    }

     parser->stage = LXB_CSS_PARSER_END;

-    return status;
+    return NULL;
+}
+
+lxb_css_syntax_rule_t *
+lxb_css_syntax_consume_list_rules(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_cb_list_rules_t *list_rules,
+                                  lxb_css_parser_state_f back,
+                                  void *ctx, lxb_css_syntax_token_type_t stop)
+{
+    return lxb_css_syntax_parser_list_rules_push(parser, list_rules, back,
+                                                 ctx, stop);
+}
+
+lxb_css_syntax_rule_t *
+lxb_css_syntax_consume_at_rule(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token,
+                               const lxb_css_syntax_cb_at_rule_t *at_rule,
+                               lxb_css_parser_state_f back,
+                               void *ctx, lxb_css_syntax_token_type_t stop)
+{
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_AT_KEYWORD) {
+        return NULL;
+    }
+
+    if (parser->rules > parser->rules_begin && parser->rules->deep != 0
+        && parser->types_pos[-1] == LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS)
+    {
+        parser->types_pos -= 1;
+        parser->rules->deep -= 1;
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_syntax_parser_at_rule_push(parser, at_rule, back, ctx,
+                                              stop, false);
+}
+
+lxb_css_syntax_rule_t *
+lxb_css_syntax_consume_qualified_rule(lxb_css_parser_t *parser,
+                                      const lxb_css_syntax_token_t *token,
+                                      const lxb_css_syntax_cb_qualified_rule_t *qualified,
+                                      lxb_css_parser_state_f back,
+                                      void *ctx, lxb_css_syntax_token_type_t stop)
+{
+    lxb_css_syntax_token_type_t type;
+
+    if (parser->rules > parser->rules_begin && parser->rules->deep != 0) {
+        switch (token->type) {
+            case LXB_CSS_SYNTAX_TOKEN_LS_BRACKET:
+                type = LXB_CSS_SYNTAX_TOKEN_RS_BRACKET;
+                break;
+
+            case LXB_CSS_SYNTAX_TOKEN_FUNCTION:
+            case LXB_CSS_SYNTAX_TOKEN_L_PARENTHESIS:
+                type = LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS;
+                break;
+
+            case LXB_CSS_SYNTAX_TOKEN_LC_BRACKET:
+                type = LXB_CSS_SYNTAX_TOKEN_RC_BRACKET;
+                break;
+
+            default:
+                type = LXB_CSS_SYNTAX_TOKEN_UNDEF;
+                break;
+        }
+
+
+        if (parser->types_pos[-1] == type) {
+            parser->types_pos -= 1;
+            parser->rules->deep -= 1;
+        }
+    }
+
+    return lxb_css_syntax_parser_qualified_push(parser, qualified, back,
+                                                ctx, stop, false);
+}
+
+lxb_css_syntax_rule_t *
+lxb_css_syntax_consume_block(lxb_css_parser_t *parser,
+                             const lxb_css_syntax_token_t *token,
+                             const lxb_css_syntax_cb_block_t *block,
+                             lxb_css_parser_state_f back, void *ctx)
+{
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_LC_BRACKET) {
+        return NULL;
+    }
+
+    if (parser->rules > parser->rules_begin && parser->rules->deep != 0
+        && parser->types_pos[-1] == LXB_CSS_SYNTAX_TOKEN_RC_BRACKET)
+    {
+        parser->types_pos -= 1;
+        parser->rules->deep -= 1;
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_syntax_parser_block_push(parser, block, back, ctx);
+}
+
+lxb_css_syntax_rule_t *
+lxb_css_syntax_consume_declarations(lxb_css_parser_t *parser,
+                                    const lxb_css_syntax_token_t *token,
+                                    const lxb_css_syntax_cb_declarations_t *declr,
+                                    lxb_css_parser_state_f back, void *ctx,
+                                    lxb_css_syntax_token_type_t stop)
+{
+    lxb_css_syntax_token_type_t type;
+
+    if (parser->rules > parser->rules_begin && parser->rules->deep != 0) {
+        switch (token->type) {
+            case LXB_CSS_SYNTAX_TOKEN_LS_BRACKET:
+                type = LXB_CSS_SYNTAX_TOKEN_RS_BRACKET;
+                break;
+
+            case LXB_CSS_SYNTAX_TOKEN_FUNCTION:
+            case LXB_CSS_SYNTAX_TOKEN_L_PARENTHESIS:
+                type = LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS;
+                break;
+
+            case LXB_CSS_SYNTAX_TOKEN_LC_BRACKET:
+                type = LXB_CSS_SYNTAX_TOKEN_RC_BRACKET;
+                break;
+
+            default:
+                type = LXB_CSS_SYNTAX_TOKEN_UNDEF;
+                break;
+        }
+
+
+        if (parser->types_pos[-1] == type) {
+            parser->types_pos -= 1;
+            parser->rules->deep -= 1;
+        }
+    }
+
+    return lxb_css_syntax_parser_declarations_push(parser, declr, back,
+                                                   ctx, stop, true, false);
+}
+
+lxb_css_syntax_rule_t *
+lxb_css_syntax_consume_components(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token,
+                                  const lxb_css_syntax_cb_components_t *comp,
+                                  lxb_css_parser_state_f back,
+                                  void *ctx, lxb_css_syntax_token_type_t stop)
+{
+    lxb_css_syntax_token_type_t type;
+
+    if (parser->rules > parser->rules_begin && parser->rules->deep != 0) {
+        switch (token->type) {
+            case LXB_CSS_SYNTAX_TOKEN_LS_BRACKET:
+                type = LXB_CSS_SYNTAX_TOKEN_RS_BRACKET;
+                break;
+
+            case LXB_CSS_SYNTAX_TOKEN_FUNCTION:
+            case LXB_CSS_SYNTAX_TOKEN_L_PARENTHESIS:
+                type = LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS;
+                break;
+
+            case LXB_CSS_SYNTAX_TOKEN_LC_BRACKET:
+                type = LXB_CSS_SYNTAX_TOKEN_RC_BRACKET;
+                break;
+
+            default:
+                type = LXB_CSS_SYNTAX_TOKEN_UNDEF;
+                break;
+        }
+
+
+        if (parser->types_pos[-1] == type) {
+            parser->types_pos -= 1;
+            parser->rules->deep -= 1;
+        }
+    }
+
+    return lxb_css_syntax_parser_components_push(parser, comp, back, ctx, stop);
+}
+
+lxb_css_syntax_rule_t *
+lxb_css_syntax_consume_function(lxb_css_parser_t *parser,
+                                const lxb_css_syntax_token_t *token,
+                                const lxb_css_syntax_cb_function_t *func,
+                                lxb_css_parser_state_f back, void *ctx)
+{
+    if (token->type != LXB_CSS_SYNTAX_TOKEN_FUNCTION) {
+        return NULL;
+    }
+
+    if (parser->rules > parser->rules_begin && parser->rules->deep != 0
+        && parser->types_pos[-1] == LXB_CSS_SYNTAX_TOKEN_R_PARENTHESIS)
+    {
+        parser->types_pos -= 1;
+        parser->rules->deep -= 1;
+    }
+
+    lxb_css_syntax_parser_consume(parser);
+
+    return lxb_css_syntax_parser_function_push(parser, func, back, ctx);
 }

 lxb_status_t
@@ -69,22 +326,20 @@ lxb_css_syntax_stack_expand(lxb_css_parser_t *parser, size_t count)
     size_t length, cur_len, size;
     lxb_css_syntax_rule_t *p;

-    if ((parser->rules + count) >= parser->rules_end) {
-        cur_len = parser->rules - parser->rules_begin;
+    cur_len = parser->rules - parser->rules_begin;

-        length = cur_len + count + 1024;
-        size = length * sizeof(lxb_css_syntax_rule_t);
+    length = cur_len + count + 1024;
+    size = length * sizeof(lxb_css_syntax_rule_t);

-        p = lexbor_realloc(parser->rules_begin, size);
-        if (p == NULL) {
-            return LXB_STATUS_ERROR_MEMORY_ALLOCATION;
-        }
-
-        parser->rules_begin = p;
-        parser->rules_end = p + length;
-        parser->rules = p + cur_len;
+    p = lexbor_realloc(parser->rules_begin, size);
+    if (p == NULL) {
+        return LXB_STATUS_ERROR_MEMORY_ALLOCATION;
     }

+    parser->rules_begin = p;
+    parser->rules_end = p + length;
+    parser->rules = p + cur_len;
+
     return LXB_STATUS_OK;
 }

@@ -166,8 +421,9 @@ lxb_css_syntax_ident_serialize(const lxb_char_t *data, size_t length,
             data = ++p;

             if (p < end && lexbor_str_res_map_hex[*p] != 0xff) {
-                lexbor_serialize_write(cb, lxb_str_ws.data,
-                                       lxb_str_ws.length, ctx, status);
+                lexbor_serialize_write(cb, lxb_css_syntax_str_ws.data,
+                                       lxb_css_syntax_str_ws.length,
+                                       ctx, status);
             }

             continue;
@@ -231,8 +487,9 @@ lxb_css_syntax_string_serialize(const lxb_char_t *data, size_t length,
                     p++;

                     if (p < end && lexbor_str_res_map_hex[*p] != 0xff) {
-                        lexbor_serialize_write(cb, lxb_str_ws.data,
-                                               lxb_str_ws.length, ctx, status);
+                        lexbor_serialize_write(cb, lxb_css_syntax_str_ws.data,
+                                               lxb_css_syntax_str_ws.length,
+                                               ctx, status);
                     }

                     data = p;
diff --git a/ext/dom/lexbor/lexbor/css/syntax/syntax.h b/ext/dom/lexbor/lexbor/css/syntax/syntax.h
index 91ed9088f29..08e9c5c8618 100644
--- a/ext/dom/lexbor/lexbor/css/syntax/syntax.h
+++ b/ext/dom/lexbor/lexbor/css/syntax/syntax.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Alexander Borisov
+ * Copyright (C) 2022-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -12,6 +12,7 @@ extern "C" {
 #endif

 #include "lexbor/css/syntax/tokenizer.h"
+#include "lexbor/css/syntax/tokenizer.h"


 typedef struct lxb_css_syntax_rule lxb_css_syntax_rule_t;
@@ -21,124 +22,211 @@ typedef const lxb_css_syntax_token_t *
                           const lxb_css_syntax_token_t *token,
                           lxb_css_syntax_rule_t *rule);

-typedef lxb_status_t
-(*lxb_css_syntax_declaration_end_f)(lxb_css_parser_t *parser, void *ctx,
-                                    bool important, bool failed);
+
+typedef struct lxb_css_syntax_cb_base lxb_css_syntax_cb_base_t;
+typedef struct lxb_css_syntax_cb_list_rules lxb_css_syntax_cb_list_rules_t;
+typedef struct lxb_css_syntax_cb_at_rule lxb_css_syntax_cb_at_rule_t;
+typedef struct lxb_css_syntax_cb_qualified_rule lxb_css_syntax_cb_qualified_rule_t;
+typedef struct lxb_css_syntax_cb_block lxb_css_syntax_cb_block_t;
+typedef struct lxb_css_syntax_cb_declarations lxb_css_syntax_cb_declarations_t;
+typedef struct lxb_css_syntax_cb_function lxb_css_syntax_cb_function_t;
+typedef struct lxb_css_syntax_cb_components lxb_css_syntax_cb_components_t;
+typedef struct lxb_css_syntax_cb_pipe lxb_css_syntax_cb_pipe_t;
+
+typedef struct lxb_css_syntax_declaration_offset lxb_css_syntax_declaration_offset_t;

 typedef lxb_status_t
 (*lxb_css_syntax_cb_done_f)(lxb_css_parser_t *parser,
                             const lxb_css_syntax_token_t *token,
                             void *ctx, bool failed);

-typedef struct {
-    uintptr_t begin;
-    uintptr_t end;
-}
-lxb_css_syntax_list_rules_offset_t;
-
-typedef struct {
-    uintptr_t name;
-    uintptr_t prelude;
-    uintptr_t prelude_end;
-    uintptr_t block;
-    uintptr_t block_end;
-}
-lxb_css_syntax_at_rule_offset_t;
-
-typedef struct {
-    uintptr_t prelude;
-    uintptr_t prelude_end;
-    uintptr_t block;
-    uintptr_t block_end;
-}
-lxb_css_syntax_qualified_offset_t;
-
-typedef struct {
-    uintptr_t begin;
-    uintptr_t end;
-    uintptr_t name_begin;
-    uintptr_t name_end;
-    uintptr_t value_begin;
-    uintptr_t before_important;
-    uintptr_t value_end;
-}
-lxb_css_syntax_declarations_offset_t;
-
-typedef struct {
-    lxb_css_parser_state_f   state;
-    lxb_css_parser_state_f   block;
+typedef const lxb_css_syntax_cb_at_rule_t *
+(*lxb_css_syntax_begin_at_rule_f)(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token,
+                                  void *ctx, void **out_rule);
+
+typedef const lxb_css_syntax_cb_qualified_rule_t *
+(*lxb_css_syntax_begin_qualified_rule_f)(lxb_css_parser_t *parser,
+                                         const lxb_css_syntax_token_t *token,
+                                         void *ctx, void **out_rule);
+
+typedef const lxb_css_syntax_cb_block_t *
+(*lxb_css_syntax_begin_block_f)(lxb_css_parser_t *parser,
+                                const lxb_css_syntax_token_t *token,
+                                void *ctx, void **out_rule);
+
+typedef const lxb_css_syntax_cb_declarations_t *
+(*lxb_css_syntax_begin_declarations_f)(lxb_css_parser_t *parser,
+                                       const lxb_css_syntax_token_t *token,
+                                       void *ctx, void **out_rule);
+typedef lxb_css_parser_state_f
+(*lxb_css_syntax_declaration_name_f)(lxb_css_parser_t *parser,
+                                     const lxb_css_syntax_token_t *token,
+                                     void *ctx, void **out_rule);
+typedef lxb_status_t
+(*lxb_css_syntax_declaration_end_f)(lxb_css_parser_t *parser,
+                                    void *declaration, void *ctx,
+                                    const lxb_css_syntax_token_t *token,
+                                    lxb_css_syntax_declaration_offset_t *offset,
+                                    bool important, bool failed);
+
+struct lxb_css_syntax_cb_base {
     lxb_css_parser_state_f   failed;
     lxb_css_syntax_cb_done_f end;
-}
-lxb_css_syntax_cb_base_t;
+};

-typedef lxb_css_syntax_cb_base_t lxb_css_syntax_cb_pipe_t;
-typedef lxb_css_syntax_cb_base_t lxb_css_syntax_cb_block_t;
-typedef lxb_css_syntax_cb_base_t lxb_css_syntax_cb_function_t;
-typedef lxb_css_syntax_cb_base_t lxb_css_syntax_cb_components_t;
-typedef lxb_css_syntax_cb_base_t lxb_css_syntax_cb_at_rule_t;
-typedef lxb_css_syntax_cb_base_t lxb_css_syntax_cb_qualified_rule_t;
+struct lxb_css_syntax_cb_list_rules {
+    lxb_css_syntax_cb_base_t              cb;
+    lxb_css_parser_state_f                next;
+    lxb_css_syntax_begin_at_rule_f        at_rule;
+    lxb_css_syntax_begin_qualified_rule_f qualified_rule;
+};
+
+struct lxb_css_syntax_cb_at_rule {
+    lxb_css_syntax_cb_base_t     cb;
+    lxb_css_parser_state_f       prelude;
+    lxb_css_syntax_cb_done_f     prelude_end;
+    lxb_css_syntax_begin_block_f block;
+};
+
+struct lxb_css_syntax_cb_qualified_rule {
+    lxb_css_syntax_cb_base_t     cb;
+    lxb_css_parser_state_f       prelude;
+    lxb_css_syntax_cb_done_f     prelude_end;
+    lxb_css_syntax_begin_block_f block;
+};
+
+struct lxb_css_syntax_cb_block {
+    lxb_css_syntax_cb_base_t              cb;
+    lxb_css_parser_state_f                next;
+    lxb_css_syntax_begin_at_rule_f        at_rule;
+    lxb_css_syntax_begin_declarations_f   declarations;
+    lxb_css_syntax_begin_qualified_rule_f qualified_rule;
+};

-typedef struct {
+struct lxb_css_syntax_cb_declarations {
     lxb_css_syntax_cb_base_t          cb;
-    lxb_css_syntax_declaration_end_f  declaration_end;
-    const lxb_css_syntax_cb_at_rule_t *at_rule;
-}
-lxb_css_syntax_cb_declarations_t;
-
-typedef struct {
-    lxb_css_syntax_cb_base_t                 cb;
-    lxb_css_parser_state_f                   next;
-    const lxb_css_syntax_cb_at_rule_t        *at_rule;
-    const lxb_css_syntax_cb_qualified_rule_t *qualified_rule;
-}
-lxb_css_syntax_cb_list_rules_t;
+    lxb_css_syntax_declaration_name_f name;
+    lxb_css_syntax_declaration_end_f  end;
+};
+
+struct lxb_css_syntax_cb_function {
+    lxb_css_syntax_cb_base_t cb;
+    lxb_css_parser_state_f   value;
+};
+
+struct lxb_css_syntax_cb_components {
+    lxb_css_syntax_cb_base_t cb;
+    lxb_css_parser_state_f   prelude;
+};
+
+struct lxb_css_syntax_cb_pipe {
+    lxb_css_syntax_cb_base_t cb;
+    lxb_css_parser_state_f   prelude;
+};
+
+struct lxb_css_syntax_declaration_offset {
+    size_t value_begin;
+    size_t value_end;
+    size_t important_begin;
+    size_t important_end;
+    size_t end;
+};

 struct lxb_css_syntax_rule {
     lxb_css_syntax_state_f       phase;
     lxb_css_parser_state_f       state;
-    lxb_css_parser_state_f       state_back;
+
+    /*
+     * This callback will be called before rule->state is called.
+     * Exclusively from the lxb_css_parser_run(...).
+     */
     lxb_css_syntax_state_f       back;
+    lxb_css_parser_state_f       back_state;
+    void                         *context;
+    void                         *context_old;
+    void                         *returned;

     union {
         const lxb_css_syntax_cb_base_t           *cb;
         const lxb_css_syntax_cb_list_rules_t     *list_rules;
         const lxb_css_syntax_cb_at_rule_t        *at_rule;
         const lxb_css_syntax_cb_qualified_rule_t *qualified_rule;
-        const lxb_css_syntax_cb_declarations_t   *declarations;
         const lxb_css_syntax_cb_components_t     *components;
+        const lxb_css_syntax_cb_declarations_t   *declarations;
         const lxb_css_syntax_cb_function_t       *func;
         const lxb_css_syntax_cb_block_t          *block;
         const lxb_css_syntax_cb_pipe_t           *pipe;
         void                                     *user;
     } cbx;

-    void                        *context;
-
-    uintptr_t                   offset;
-    size_t                      deep;
-    lxb_css_syntax_token_type_t block_end;
-    bool                        skip_ending;
-    bool                        skip_consume;
-    bool                        important;
-    bool                        failed;
-    bool                        top_level;
-
-    union {
-        lxb_css_syntax_list_rules_offset_t   list_rules;
-        lxb_css_syntax_at_rule_offset_t      at_rule;
-        lxb_css_syntax_qualified_offset_t    qualified;
-        lxb_css_syntax_declarations_offset_t declarations;
-        void                                 *user;
-    } u;
+    size_t                       offset;
+    size_t                       deep;
+    size_t                       begin;
+    lxb_css_syntax_token_type_t  block_end;
+    bool                         nested;
+    bool                         skip_consume;
+    bool                         important;
+    bool                         failed;
 };


-LXB_API lxb_status_t
+LXB_API lxb_css_rule_list_t *
 lxb_css_syntax_parse_list_rules(lxb_css_parser_t *parser,
                                 const lxb_css_syntax_cb_list_rules_t *cb,
-                                const lxb_char_t *data, size_t length,
-                                void *ctx, bool top_level);
+                                const lxb_char_t *data, size_t length);
+
+LXB_API lxb_css_rule_declaration_list_t *
+lxb_css_syntax_parse_declarations(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_cb_declarations_t *cb,
+                                  const lxb_char_t *data, size_t length);
+
+LXB_API lxb_css_syntax_rule_t *
+lxb_css_syntax_consume_list_rules(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_cb_list_rules_t *list_rules,
+                                  lxb_css_parser_state_f back,
+                                  void *ctx, lxb_css_syntax_token_type_t stop);
+
+LXB_API lxb_css_syntax_rule_t *
+lxb_css_syntax_consume_at_rule(lxb_css_parser_t *parser,
+                               const lxb_css_syntax_token_t *token,
+                               const lxb_css_syntax_cb_at_rule_t *at_rule,
+                               lxb_css_parser_state_f back,
+                               void *ctx, lxb_css_syntax_token_type_t stop);
+
+LXB_API lxb_css_syntax_rule_t *
+lxb_css_syntax_consume_qualified_rule(lxb_css_parser_t *parser,
+                                      const lxb_css_syntax_token_t *token,
+                                      const lxb_css_syntax_cb_qualified_rule_t *qualified,
+                                      lxb_css_parser_state_f back,
+                                      void *ctx, lxb_css_syntax_token_type_t stop);
+
+LXB_API lxb_css_syntax_rule_t *
+lxb_css_syntax_consume_block(lxb_css_parser_t *parser,
+                             const lxb_css_syntax_token_t *token,
+                             const lxb_css_syntax_cb_block_t *block,
+                             lxb_css_parser_state_f back, void *ctx);
+
+LXB_API lxb_css_syntax_rule_t *
+lxb_css_syntax_consume_declarations(lxb_css_parser_t *parser,
+                                    const lxb_css_syntax_token_t *token,
+                                    const lxb_css_syntax_cb_declarations_t *declr,
+                                    lxb_css_parser_state_f back, void *ctx,
+                                    lxb_css_syntax_token_type_t stop);
+
+LXB_API lxb_css_syntax_rule_t *
+lxb_css_syntax_consume_components(lxb_css_parser_t *parser,
+                                  const lxb_css_syntax_token_t *token,
+                                  const lxb_css_syntax_cb_components_t *comp,
+                                  lxb_css_parser_state_f back,
+                                  void *ctx, lxb_css_syntax_token_type_t stop);
+
+LXB_API lxb_css_syntax_rule_t *
+lxb_css_syntax_consume_function(lxb_css_parser_t *parser,
+                                const lxb_css_syntax_token_t *token,
+                                const lxb_css_syntax_cb_function_t *func,
+                                lxb_css_parser_state_f back, void *ctx);
+

 LXB_API lxb_status_t
 lxb_css_syntax_stack_expand(lxb_css_parser_t *parser, size_t count);
@@ -159,6 +247,7 @@ LXB_API lxb_status_t
 lxb_css_syntax_ident_or_string_serialize(const lxb_char_t *data, size_t length,
                                          lexbor_serialize_cb_f cb, void *ctx);

+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
diff --git a/ext/dom/lexbor/lexbor/css/syntax/token.c b/ext/dom/lexbor/lexbor/css/syntax/token.c
index be1cc7809c4..ff53c4531e8 100644
--- a/ext/dom/lexbor/lexbor/css/syntax/token.c
+++ b/ext/dom/lexbor/lexbor/css/syntax/token.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018-2025 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -12,15 +12,12 @@
 #include "lexbor/css/parser.h"
 #include "lexbor/css/syntax/token.h"
 #include "lexbor/css/syntax/state.h"
-#include "lexbor/css/syntax/state_res.h"
-
-#define LXB_CSS_SYNTAX_TOKEN_RES_NAME_SHS_MAP
 #include "lexbor/css/syntax/token_res.h"

-#define LEXBOR_STR_RES_MAP_HEX
-#define LEXBOR_STR_RES_ANSI_REPLACEMENT_CHARACTER
-#include "lexbor/core/str_res.h"
-
+#ifndef LEXBOR_DISABLE_INTERNAL_EXTERN
+    LXB_EXTERN const lxb_char_t lexbor_str_res_ansi_replacement_character[4];
+    LXB_EXTERN const lxb_char_t lexbor_str_res_map_hex[256];
+#endif

 lxb_css_syntax_token_t *
 lxb_css_syntax_tokenizer_token(lxb_css_syntax_tokenizer_t *tkz);
diff --git a/ext/dom/lexbor/lexbor/css/syntax/token_res.h b/ext/dom/lexbor/lexbor/css/syntax/token_res.h
index 7a8e1c4d259..d5ee29cf3b2 100644
--- a/ext/dom/lexbor/lexbor/css/syntax/token_res.h
+++ b/ext/dom/lexbor/lexbor/css/syntax/token_res.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018-2025 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -7,10 +7,6 @@
 #ifndef LEXBOR_CSS_SYNTAX_TOKEN_RES_H
 #define LEXBOR_CSS_SYNTAX_TOKEN_RES_H

-
-#ifdef LXB_CSS_SYNTAX_TOKEN_RES_NAME_SHS_MAP
-#ifndef LXB_CSS_SYNTAX_TOKEN_RES_NAME_SHS_MAP_ENABLED
-#define LXB_CSS_SYNTAX_TOKEN_RES_NAME_SHS_MAP_ENABLED
 static const lexbor_shs_entry_t lxb_css_syntax_token_res_name_shs_map[136] =
 {
     {NULL, NULL, 135, 0}, {NULL, NULL, 0, 0},
@@ -83,8 +79,4 @@ static const lexbor_shs_entry_t lxb_css_syntax_token_res_name_shs_map[136] =
     {NULL, NULL, 0, 0}, {"semicolon", (void *) LXB_CSS_SYNTAX_TOKEN_SEMICOLON, 9, 0}
 };

-#endif /* LXB_CSS_SYNTAX_TOKEN_RES_NAME_SHS_MAP_ENABLED */
-#endif /* LXB_CSS_SYNTAX_TOKEN_RES_NAME_SHS_MAP */
-
-
 #endif /* LEXBOR_CSS_SYNTAX_TOKEN_RES_H */
diff --git a/ext/dom/lexbor/lexbor/css/syntax/tokenizer.c b/ext/dom/lexbor/lexbor/css/syntax/tokenizer.c
index 9eecac65754..a44b2c7194a 100644
--- a/ext/dom/lexbor/lexbor/css/syntax/tokenizer.c
+++ b/ext/dom/lexbor/lexbor/css/syntax/tokenizer.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018-2025 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -12,9 +12,10 @@

 #include "lexbor/core/array.h"

-#define LEXBOR_STR_RES_MAP_LOWERCASE
-#include "lexbor/core/str_res.h"

+#ifndef LEXBOR_DISABLE_INTERNAL_EXTERN
+    LXB_EXTERN const lxb_char_t lexbor_str_res_map_lowercase[256];
+#endif

 static const lxb_char_t lxb_css_syntax_tokenizer_important[] = "important";

@@ -297,7 +298,7 @@ lxb_css_syntax_tokenizer_lookup_important_ch(lxb_css_syntax_tokenizer_t *tkz,
 {
     static const size_t length = sizeof(lxb_css_syntax_tokenizer_important) - 1;

-    if (!(end - p >= length
+    if (!(lxb_size(end - p) >= length
            && lexbor_str_data_ncasecmp(p, lxb_css_syntax_tokenizer_important,
                                        length)))
     {
diff --git a/ext/dom/lexbor/lexbor/css/unit.c b/ext/dom/lexbor/lexbor/css/unit.c
new file mode 100644
index 00000000000..f3cc9c8ef28
--- /dev/null
+++ b/ext/dom/lexbor/lexbor/css/unit.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2021 Alexander Borisov
+ *
+ * Author: Alexander Borisov <borisov@lexbor.com>
+ */
+
+#include "lexbor/css/css.h"
+#include "lexbor/css/unit/res.h"
+
+
+const lxb_css_data_t *
+lxb_css_unit_absolute_relative_by_name(const lxb_char_t *name, size_t length)
+{
+    const lexbor_shs_entry_t *entry;
+
+    entry = lexbor_shs_entry_get_lower_static(lxb_css_unit_absolute_relative_shs,
+                                              name, length);
+    if (entry == NULL) {
+        return NULL;
+    }
+
+    return entry->value;
+}
+
+const lxb_css_data_t *
+lxb_css_unit_absolute_by_name(const lxb_char_t *name, size_t length)
+{
+    const lexbor_shs_entry_t *entry;
+
+    entry = lexbor_shs_entry_get_lower_static(lxb_css_unit_absolute_shs,
+                                              name, length);
+    if (entry == NULL) {
+        return NULL;
+    }
+
+    return entry->value;
+}
+
+const lxb_css_data_t *
+lxb_css_unit_relative_by_name(const lxb_char_t *name, size_t length)
+{
+    const lexbor_shs_entry_t *entry;
+
+    entry = lexbor_shs_entry_get_lower_static(lxb_css_unit_relative_shs,
+                                              name, length);
+    if (entry == NULL) {
+        return NULL;
+    }
+
+    return entry->value;
+}
+
+const lxb_css_data_t *
+lxb_css_unit_angle_by_name(const lxb_char_t *name, size_t length)
+{
+    const lexbor_shs_entry_t *entry;
+
+    entry = lexbor_shs_entry_get_lower_static(lxb_css_unit_angle_shs,
+                                              name, length);
+    if (entry == NULL) {
+        return NULL;
+    }
+
+    return entry->value;
+}
+
+const lxb_css_data_t *
+lxb_css_unit_frequency_by_name(const lxb_char_t *name, size_t length)
+{
+    const lexbor_shs_entry_t *entry;
+
+    entry = lexbor_shs_entry_get_lower_static(lxb_css_unit_frequency_shs,
+                                              name, length);
+    if (entry == NULL) {
+        return NULL;
+    }
+
+    return entry->value;
+}
+
+const lxb_css_data_t *
+lxb_css_unit_resolution_by_name(const lxb_char_t *name, size_t length)
+{
+    const lexbor_shs_entry_t *entry;
+
+    entry = lexbor_shs_entry_get_lower_static(lxb_css_unit_resolution_shs,
+                                              name, length);
+    if (entry == NULL) {
+        return NULL;
+    }
+
+    return entry->value;
+}
+
+const lxb_css_data_t *
+lxb_css_unit_duration_by_name(const lxb_char_t *name, size_t length)
+{
+    const lexbor_shs_entry_t *entry;
+
+    entry = lexbor_shs_entry_get_lower_static(lxb_css_unit_duration_shs,
+                                              name, length);
+    if (entry == NULL) {
+        return NULL;
+    }
+
+    return entry->value;
+}
+
+const lxb_css_data_t *
+lxb_css_unit_by_id(lxb_css_type_t id)
+{
+    return &lxb_css_unit_data[id];
+}
diff --git a/ext/dom/lexbor/lexbor/css/unit/const.h b/ext/dom/lexbor/lexbor/css/unit/const.h
index 9b7ba1c311b..9f5e515834e 100644
--- a/ext/dom/lexbor/lexbor/css/unit/const.h
+++ b/ext/dom/lexbor/lexbor/css/unit/const.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2023 Alexander Borisov
+ * Copyright (C) 2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
diff --git a/ext/dom/lexbor/lexbor/css/unit/res.h b/ext/dom/lexbor/lexbor/css/unit/res.h
index 4cca189b6f4..ac24503d1a6 100644
--- a/ext/dom/lexbor/lexbor/css/unit/res.h
+++ b/ext/dom/lexbor/lexbor/css/unit/res.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2023 Alexander Borisov
+ * Copyright (C) 2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
diff --git a/ext/dom/lexbor/lexbor/css/value.c b/ext/dom/lexbor/lexbor/css/value.c
new file mode 100644
index 00000000000..23e2472d625
--- /dev/null
+++ b/ext/dom/lexbor/lexbor/css/value.c
@@ -0,0 +1,678 @@
+/*
+ * Copyright (C) 2022-2026 Alexander Borisov
+ *
+ * Author: Alexander Borisov <borisov@lexbor.com>
+ */
+
+#include "lexbor/css/css.h"
+#include "lexbor/css/value/res.h"
+
+#include "lexbor/core/serialize.h"
+#include "lexbor/core/conv.h"
+
+
+#ifndef LEXBOR_DISABLE_INTERNAL_EXTERN
+    LXB_EXTERN const lxb_char_t lexbor_str_res_map_hex_to_char_lowercase[17];
+    LXB_EXTERN const char *lexbor_str_res_char_to_two_hex_value_lowercase[257];
+#endif
+
+static const lexbor_str_t lxb_css_value_str_ws = lexbor_str(" ");
+static const lexbor_str_t lxb_str_comma = lexbor_str(", ");
+static const lexbor_str_t lxb_str_alpha = lexbor_str(" / ");
+static const lexbor_str_t lxb_str_rp = lexbor_str(")");
+
+
+const lxb_css_data_t *
+lxb_css_value_by_id(uintptr_t id)
+{
+    if (id < LXB_CSS_VALUE__LAST_ENTRY) {
+        return &lxb_css_value_data[id];
+    }
+
+    return NULL;
+}
+
+lxb_css_value_type_t
+lxb_css_value_by_name(const lxb_char_t *name, size_t length)
+{
+    const lexbor_shs_entry_t *entry;
+
+    entry = lexbor_shs_entry_get_lower_static(lxb_css_value_shs, name, length);
+    if (entry == NULL) {
+        return LXB_CSS_VALUE__UNDEF;
+    }
+
+    return (lxb_css_value_type_t) (uintptr_t) entry->value;
+}
+
+lxb_status_t
+lxb_css_value_serialize(lxb_css_value_type_t type,
+                        lexbor_serialize_cb_f cb, void *ctx)
+{
+    const lxb_css_data_t *data;
+
+    if (type >= LXB_CSS_VALUE__LAST_ENTRY) {
+        return LXB_STATUS_ERROR_WRONG_ARGS;
+    }
+
+    data = &lxb_css_value_data[type];
+
+    return cb(data->name, data->length, ctx);
+}
+
+lxb_status_t
+lxb_css_value_percentage_sr(const lxb_css_value_percentage_t *percent,
+                               lexbor_serialize_cb_f cb, void *ctx)
+{
+    size_t length;
+    lxb_char_t buf[128];
+    lxb_status_t status;
+
+    static const lexbor_str_t str_per = lexbor_str("%");
+
+    /* FIXME: If length != sizeof(buf)? */
+    length = lexbor_conv_float_to_data(percent->num, buf, sizeof(buf));
+
+    lexbor_serialize_write(cb, buf, length, ctx, status);
+    lexbor_serialize_write(cb, str_per.data, str_per.length, ctx, status);
+
+    return LXB_STATUS_OK;
+}
+
+lxb_status_t
+lxb_css_value_length_sr(const lxb_css_value_length_t *len,
+                        lexbor_serialize_cb_f cb, void *ctx)
+{
+    size_t length;
+    lxb_char_t buf[128];
+    lxb_status_t status;
+    const lxb_css_data_t *unit;
+
+    /* FIXME: If length != sizeof(buf)? */
+    length = lexbor_conv_float_to_data(len->num, buf, sizeof(buf));
+
+    lexbor_serialize_write(cb, buf, length, ctx, status);
+
+    if (len->unit == LXB_CSS_UNIT__UNDEF) {
+        return LXB_STATUS_OK;
+    }
+
+    unit = lxb_css_unit_by_id(len->unit);
+    if (unit == NULL) {
+        return LXB_STATUS_OK;
+    }
+
+    lexbor_serialize_write(cb, unit->name, unit->length, ctx, status);
+
+    return LXB_STATUS_OK;
+}
+
+lxb_status_t
+lxb_css_value_number_sr(const lxb_css_value_number_t *number,
+                        lexbor_serialize_cb_f cb, void *ctx)
+{
+    size_t length;
+    lxb_char_t buf[128];
+    lxb_status_t status;
+
+    /* FIXME: If length != sizeof(buf)? */
+    length = lexbor_conv_float_to_data(number->num, buf, sizeof(buf));
+
+    lexbor_serialize_write(cb, buf, length, ctx, status);
+
+    return LXB_STATUS_OK;
+}
+
+lxb_status_t
+lxb_css_value_integer_sr(const lxb_css_value_integer_t *integer,
+                         lexbor_serialize_cb_f cb, void *ctx)
+{
+    size_t length;
+    lxb_char_t buf[128];
+    lxb_status_t status;
+
+    /* FIXME: If length != sizeof(buf)? */
+    length = lexbor_conv_long_to_data(integer->num, buf, sizeof(buf));
+
+    lexbor_serialize_write(cb, buf, length, ctx, status);
+
+    return LXB_STATUS_OK;
+}
+
+lxb_status_t
+lxb_css_value_length_percentage_sr(const lxb_css_value_length_percentage_t *lp,
+                                   lexbor_serialize_cb_f cb, void *ctx)
+{
+    switch (lp->type) {
+        case LXB_CSS_VALUE__LENGTH:
+        case LXB_CSS_VALUE__NUMBER:
+            return lxb_css_value_length_sr(&lp->u.length, cb, ctx);
+
+        case LXB_CSS_VALUE__PERCENTAGE:
+            return lxb_css_value_percentage_sr(&lp->u.percentage, cb, ctx);
+
+        case LXB_CSS_VALUE__UNDEF:
+            /* FIXME: ???? */
+            break;
+
+        default:
+            return lxb_css_value_serialize(lp->type, cb, ctx);
+    }
+
+    return LXB_STATUS_OK;
+}
+
+lxb_status_t
+lxb_css_value_number_length_sr(const lxb_css_value_number_length_t *nl,
+                               lexbor_serialize_cb_f cb, void *ctx)
+{
+    switch (nl->type) {
+        case LXB_CSS_VALUE__LENGTH:
+        case LXB_CSS_VALUE__NUMBER:
+            return lxb_css_value_length_sr(&nl->u.length, cb, ctx);
+
+        default:
+            return lxb_css_value_serialize(nl->type, cb, ctx);
+    }
+
+    return LXB_STATUS_OK;
+}
+
+lxb_status_t
+lxb_css_value_number_percentage_sr(const lxb_css_value_number_percentage_t *np,
+                                   lexbor_serialize_cb_f cb, void *ctx)
+{
+    switch (np->type) {
+        case LXB_CSS_VALUE__NUMBER:
+            return lxb_css_value_number_sr(&np->u.number, cb, ctx);
+
+        case LXB_CSS_VALUE__PERCENTAGE:
+            return lxb_css_value_percentage_sr(&np->u.percentage, cb, ctx);
+
+        case LXB_CSS_VALUE__UNDEF:
+            /* FIXME: ???? */
+            break;
+
+        default:
+            return lxb_css_value_serialize(np->type, cb, ctx);
+    }
+
+    return LXB_STATUS_OK;
+}
+
+lxb_status_t
+lxb_css_value_length_type_sr(const lxb_css_value_length_type_t *lt,
+                             lexbor_serialize_cb_f cb, void *ctx)
+{
+    switch (lt->type) {
+        case LXB_CSS_VALUE__LENGTH:
+        case LXB_CSS_VALUE__NUMBER:
+            return lxb_css_value_length_sr(&lt->length, cb, ctx);
+
+        case LXB_CSS_VALUE__UNDEF:
+            /* FIXME: ???? */
+            break;
+
+        default:
+            return lxb_css_value_serialize(lt->type, cb, ctx);
+    }
+
+    return LXB_STATUS_OK;
+}
+
+lxb_status_t
+lxb_css_value_percentage_type_sr(const lxb_css_value_percentage_type_t *pt,
+                                 lexbor_serialize_cb_f cb, void *ctx)
+{
+    switch (pt->type) {
+        case LXB_CSS_VALUE__PERCENTAGE:
+            return lxb_css_value_percentage_sr(&pt->percentage, cb, ctx);
+
+        case LXB_CSS_VALUE__UNDEF:
+            /* FIXME: ???? */
+            break;
+
+        default:
+            return lxb_css_value_serialize(pt->type, cb, ctx);
+    }
+
+    return LXB_STATUS_OK;
+}
+
+lxb_status_t
+lxb_css_value_number_type_sr(const lxb_css_value_number_type_t *num,
+                             lexbor_serialize_cb_f cb, void *ctx)
+{
+    switch (num->type) {
+        case LXB_CSS_VALUE__NUMBER:
+            return lxb_css_value_number_sr(&num->number, cb, ctx);
+
+        default:
+            return lxb_css_value_serialize(num->type, cb, ctx);
+    }
+
+    return LXB_STATUS_OK;
+}
+
+lxb_status_t
+lxb_css_value_integer_type_sr(const lxb_css_value_integer_type_t *num,
+                              lexbor_serialize_cb_f cb, void *ctx)
+{
+    switch (num->type) {
+        case LXB_CSS_VALUE__INTEGER:
+            return lxb_css_value_integer_sr(&num->integer, cb, ctx);
+
+        default:
+            return lxb_css_value_serialize(num->type, cb, ctx);
+    }
+
+    return LXB_STATUS_OK;
+}
+
+lxb_status_t
+lxb_css_value_length_percentage_type_sr(const lxb_css_value_length_percentage_type_t *lpt,
+                                        lexbor_serialize_cb_f cb, void *ctx)
+{
+    switch (lpt->type) {
+        case LXB_CSS_VALUE__LENGTH:
+            return lxb_css_value_length_percentage_sr(&lpt->length, cb, ctx);
+
+        default:
+            return lxb_css_value_serialize(lpt->type, cb, ctx);
+    }
+
+    return LXB_STATUS_OK;
+}
+
+lxb_status_t
+lxb_css_value_number_length_percentage_type_sr(const lxb_css_value_number_length_percentage_t *nlp,
+                                               lexbor_serialize_cb_f cb, void *ctx)
+{
+    switch (nlp->type) {
+        case LXB_CSS_VALUE__NUMBER:
+            return lxb_css_value_number_sr(&nlp->u.number, cb, ctx);
+
+        case LXB_CSS_VALUE__LENGTH:
+            return lxb_css_value_length_sr(&nlp->u.length, cb, ctx);
+
+        case LXB_CSS_VALUE__PERCENTAGE:
+            return lxb_css_value_percentage_sr(&nlp->u.percentage, cb, ctx);
+
+        default:
+            return lxb_css_value_serialize(nlp->type, cb, ctx);
+    }
+
+    return LXB_STATUS_OK;
+}
+
+lxb_status_t
+lxb_css_value_angle_sr(const lxb_css_value_angle_t *angle,
+                       lexbor_serialize_cb_f cb, void *ctx)
+{
+    size_t length;
+    lxb_char_t buf[128];
+    lxb_status_t status;
+    const lxb_css_data_t *data;
+
+    /* FIXME: If length != sizeof(buf)? */
+    length = lexbor_conv_float_to_data(angle->num, buf, sizeof(buf));
+
+    lexbor_serialize_write(cb, buf, length, ctx, status);
+
+    data = lxb_css_unit_by_id(angle->unit);
+
+    return cb(data->name, data->length, ctx);
+}
+
+lxb_status_t
+lxb_css_value_hue_sr(const lxb_css_value_hue_t *hue,
+                     lexbor_serialize_cb_f cb, void *ctx)
+{
+    switch (hue->type) {
+        case LXB_CSS_VALUE__NUMBER:
+            return lxb_css_value_number_sr(&hue->u.number, cb, ctx);
+
+        case LXB_CSS_VALUE__ANGLE:
+            return lxb_css_value_angle_sr(&hue->u.angle, cb, ctx);
+
+        case LXB_CSS_VALUE__UNDEF:
+            /* FIXME: ???? */
+            break;
+
+        default:
+            return lxb_css_value_serialize(hue->type, cb, ctx);
+    }
+
+    return LXB_STATUS_OK;
+}
+
+static lxb_status_t
+lxb_css_value_color_hex_sr(const lxb_css_value_color_hex_t *hex,
+                           lexbor_serialize_cb_f cb, void *ctx)
+{
+    lxb_status_t status;
+    static const lexbor_str_t str_hash = lexbor_str("#");
+    const lxb_css_value_color_hex_rgba_t *rgba = &hex->rgba;
+
+    const lxb_char_t *hmo = lexbor_str_res_map_hex_to_char_lowercase;
+    const char **hmt = lexbor_str_res_char_to_two_hex_value_lowercase;
+
+    lexbor_serialize_write(cb, str_hash.data, str_hash.length, ctx, status);
+
+    switch (hex->type) {
+        case LXB_CSS_PROPERTY_COLOR_HEX_TYPE_3:
+        case LXB_CSS_PROPERTY_COLOR_HEX_TYPE_4:
+            lexbor_serialize_write(cb, &hmo[rgba->r], 1, ctx, status);
+            lexbor_serialize_write(cb, &hmo[rgba->g], 1, ctx, status);
+            lexbor_serialize_write(cb, &hmo[rgba->b], 1, ctx, status);
+
+            if (hex->type == LXB_CSS_PROPERTY_COLOR_HEX_TYPE_4) {
+                lexbor_serialize_write(cb, &hmo[rgba->a], 1, ctx, status);
+            }
+
+            break;
+
+        case LXB_CSS_PROPERTY_COLOR_HEX_TYPE_6:
+        case LXB_CSS_PROPERTY_COLOR_HEX_TYPE_8:
+            lexbor_serialize_write(cb, hmt[rgba->r], 2, ctx, status);
+            lexbor_serialize_write(cb, hmt[rgba->g], 2, ctx, status);
+            lexbor_serialize_write(cb, hmt[rgba->b], 2, ctx, status);
+
+            if (hex->type == LXB_CSS_PROPERTY_COLOR_HEX_TYPE_8) {
+                lexbor_serialize_write(cb, hmt[rgba->a], 2, ctx, status);
+            }
+
+            break;
+
+        default:
+            break;
+    }
+
+    return LXB_STATUS_OK;
+}
+
+static lxb_status_t
+lxb_css_value_color_rgb_sr(const lxb_css_value_color_rgba_t *rgb,
+                           lexbor_serialize_cb_f cb, void *ctx,
+                           lxb_css_value_type_t type)
+{
+    lxb_status_t status;
+    const lexbor_str_t *sep;
+    static const lexbor_str_t str_rgb = lexbor_str("rgb(");
+    static const lexbor_str_t str_rgba = lexbor_str("rgba(");
+
+    if (type == LXB_CSS_COLOR_RGB) {
+        lexbor_serialize_write(cb, str_rgb.data, str_rgb.length, ctx, status);
+    }
+    else {
+        lexbor_serialize_write(cb, str_rgba.data, str_rgba.length, ctx, status);
+    }
+
+    sep = (rgb->old) ? &lxb_str_comma : &lxb_css_value_str_ws;
+
+    status = lxb_css_value_number_percentage_sr(&rgb->r, cb, ctx);
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    lexbor_serialize_write(cb, sep->data, sep->length, ctx, status);
+
+    status = lxb_css_value_number_percentage_sr(&rgb->g, cb, ctx);
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    lexbor_serialize_write(cb, sep->data, sep->length, ctx, status);
+
+    status = lxb_css_value_number_percentage_sr(&rgb->b, cb, ctx);
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    if (rgb->a.type == LXB_CSS_VALUE__UNDEF) {
+        return cb(lxb_str_rp.data, lxb_str_rp.length, ctx);
+    }
+
+    sep = (rgb->old) ? &lxb_str_comma : &lxb_str_alpha;
+
+    lexbor_serialize_write(cb, sep->data, sep->length, ctx, status);
+
+    status = lxb_css_value_number_percentage_sr(&rgb->a, cb, ctx);
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    return cb(lxb_str_rp.data, lxb_str_rp.length, ctx);
+}
+
+static lxb_status_t
+lxb_css_value_color_hsl_sr(const lxb_css_value_color_hsla_t *hsl,
+                           lexbor_serialize_cb_f cb, void *ctx,
+                           lxb_css_value_type_t type)
+{
+    lxb_status_t status;
+    const lexbor_str_t *sep;
+    static const lexbor_str_t str_hsl = lexbor_str("hsl(");
+    static const lexbor_str_t str_hsla = lexbor_str("hsla(");
+    static const lexbor_str_t str_hwb = lexbor_str("hwb(");
+
+    switch (type) {
+        case LXB_CSS_COLOR_HSL:
+            status = cb(str_hsl.data, str_hsl.length, ctx);
+            break;
+
+        case LXB_CSS_COLOR_HSLA:
+            status = cb(str_hsla.data, str_hsla.length, ctx);
+            break;
+
+        case LXB_CSS_COLOR_HWB:
+            status = cb(str_hwb.data, str_hwb.length, ctx);
+            break;
+
+        default:
+            return LXB_STATUS_ERROR_WRONG_ARGS;
+    }
+
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    sep = (hsl->old) ? &lxb_str_comma : &lxb_css_value_str_ws;
+
+    status = lxb_css_value_hue_sr(&hsl->h, cb, ctx);
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    lexbor_serialize_write(cb, sep->data, sep->length, ctx, status);
+
+    status = lxb_css_value_percentage_type_sr(&hsl->s, cb, ctx);
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    lexbor_serialize_write(cb, sep->data, sep->length, ctx, status);
+
+    status = lxb_css_value_percentage_type_sr(&hsl->l, cb, ctx);
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    if (hsl->a.type == LXB_CSS_VALUE__UNDEF) {
+        return cb(lxb_str_rp.data, lxb_str_rp.length, ctx);
+    }
+
+    sep = (hsl->old) ? &lxb_str_comma : &lxb_str_alpha;
+
+    lexbor_serialize_write(cb, sep->data, sep->length, ctx, status);
+
+    status = lxb_css_value_number_percentage_sr(&hsl->a, cb, ctx);
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    return cb(lxb_str_rp.data, lxb_str_rp.length, ctx);
+}
+
+static lxb_status_t
+lxb_css_value_color_lab_sr(const lxb_css_value_color_lab_t *lab,
+                           lexbor_serialize_cb_f cb, void *ctx,
+                           lxb_css_value_type_t type)
+{
+    lxb_status_t status;
+    static const lexbor_str_t str_lab = lexbor_str("lab(");
+    static const lexbor_str_t str_oklab = lexbor_str("oklab(");
+
+    switch (type) {
+        case LXB_CSS_COLOR_LAB:
+            status = cb(str_lab.data, str_lab.length, ctx);
+            break;
+
+        case LXB_CSS_COLOR_OKLAB:
+            status = cb(str_oklab.data, str_oklab.length, ctx);
+            break;
+
+        default:
+            return LXB_STATUS_ERROR_WRONG_ARGS;
+    }
+
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    status = lxb_css_value_number_percentage_sr(&lab->l, cb, ctx);
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    lexbor_serialize_write(cb, lxb_css_value_str_ws.data,
+                           lxb_css_value_str_ws.length, ctx, status);
+
+    status = lxb_css_value_number_percentage_sr(&lab->a, cb, ctx);
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    lexbor_serialize_write(cb, lxb_css_value_str_ws.data,
+                           lxb_css_value_str_ws.length, ctx, status);
+
+    status = lxb_css_value_number_percentage_sr(&lab->b, cb, ctx);
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    if (lab->alpha.type == LXB_CSS_VALUE__UNDEF) {
+        return cb(lxb_str_rp.data, lxb_str_rp.length, ctx);
+    }
+
+    lexbor_serialize_write(cb, lxb_str_alpha.data, lxb_str_alpha.length,
+                           ctx, status);
+
+    status = lxb_css_value_number_percentage_sr(&lab->alpha, cb, ctx);
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    return cb(lxb_str_rp.data, lxb_str_rp.length, ctx);
+}
+
+static lxb_status_t
+lxb_css_value_color_lch_sr(const lxb_css_value_color_lch_t *lch,
+                           lexbor_serialize_cb_f cb, void *ctx,
+                           lxb_css_value_type_t type)
+{
+    lxb_status_t status;
+    static const lexbor_str_t str_lch = lexbor_str("lch(");
+    static const lexbor_str_t str_oklch = lexbor_str("oklch(");
+
+    switch (type) {
+        case LXB_CSS_COLOR_LCH:
+            status = cb(str_lch.data, str_lch.length, ctx);
+            break;
+
+        case LXB_CSS_COLOR_OKLCH:
+            status = cb(str_oklch.data, str_oklch.length, ctx);
+            break;
+
+        default:
+            return LXB_STATUS_ERROR_WRONG_ARGS;
+    }
+
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    status = lxb_css_value_number_percentage_sr(&lch->l, cb, ctx);
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    lexbor_serialize_write(cb, lxb_css_value_str_ws.data,
+                           lxb_css_value_str_ws.length, ctx, status);
+
+    status = lxb_css_value_number_percentage_sr(&lch->c, cb, ctx);
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    lexbor_serialize_write(cb, lxb_css_value_str_ws.data,
+                           lxb_css_value_str_ws.length, ctx, status);
+
+    status = lxb_css_value_hue_sr(&lch->h, cb, ctx);
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    if (lch->a.type == LXB_CSS_VALUE__UNDEF) {
+        return cb(lxb_str_rp.data, lxb_str_rp.length, ctx);
+    }
+
+    lexbor_serialize_write(cb, lxb_str_alpha.data, lxb_str_alpha.length,
+                           ctx, status);
+
+    status = lxb_css_value_number_percentage_sr(&lch->a, cb, ctx);
+    if (status != LXB_STATUS_OK) {
+        return status;
+    }
+
+    return cb(lxb_str_rp.data, lxb_str_rp.length, ctx);
+}
+
+lxb_status_t
+lxb_css_value_color_serialize(const lxb_css_value_color_t *color,
+                              lexbor_serialize_cb_f cb, void *ctx)
+{
+    switch (color->type) {
+        case LXB_CSS_COLOR_HEX:
+            return lxb_css_value_color_hex_sr(&color->u.hex, cb, ctx);
+
+        case LXB_CSS_COLOR_RGB:
+        case LXB_CSS_COLOR_RGBA:
+            return lxb_css_value_color_rgb_sr(&color->u.rgb, cb, ctx,
+                                              color->type);
+
+        case LXB_CSS_COLOR_HSL:
+        case LXB_CSS_COLOR_HSLA:
+        case LXB_CSS_COLOR_HWB:
+            return lxb_css_value_color_hsl_sr(&color->u.hsl, cb, ctx,
+                                              color->type);
+
+        case LXB_CSS_COLOR_LAB:
+        case LXB_CSS_COLOR_OKLAB:
+            return lxb_css_value_color_lab_sr(&color->u.lab, cb, ctx,
+                                              color->type);
+
+        case LXB_CSS_COLOR_LCH:
+        case LXB_CSS_COLOR_OKLCH:
+            return lxb_css_value_color_lch_sr(&color->u.lch, cb, ctx,
+                                              color->type);
+
+        case LXB_CSS_VALUE__UNDEF:
+            break;
+
+        default:
+            return lxb_css_value_serialize(color->type, cb, ctx);
+    }
+
+    return LXB_STATUS_OK;
+}
diff --git a/ext/dom/lexbor/lexbor/css/value/const.h b/ext/dom/lexbor/lexbor/css/value/const.h
index c9b5241e1d7..a7bd64c6034 100644
--- a/ext/dom/lexbor/lexbor/css/value/const.h
+++ b/ext/dom/lexbor/lexbor/css/value/const.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2023 Alexander Borisov
+ * Copyright (C) 2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
diff --git a/ext/dom/lexbor/lexbor/css/value/res.h b/ext/dom/lexbor/lexbor/css/value/res.h
index 79b3c6b0322..180dc95f10e 100644
--- a/ext/dom/lexbor/lexbor/css/value/res.h
+++ b/ext/dom/lexbor/lexbor/css/value/res.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2023 Alexander Borisov
+ * Copyright (C) 2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
diff --git a/ext/dom/lexbor/lexbor/dom/base.h b/ext/dom/lexbor/lexbor/dom/base.h
index 167e43d7691..3894aa13ca6 100644
--- a/ext/dom/lexbor/lexbor/dom/base.h
+++ b/ext/dom/lexbor/lexbor/dom/base.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019-2024 Alexander Borisov
+ * Copyright (C) 2019-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -15,8 +15,8 @@ extern "C" {
 #include "lexbor/core/base.h"


-#define LXB_DOM_VERSION_MAJOR 1
-#define LXB_DOM_VERSION_MINOR 8
+#define LXB_DOM_VERSION_MAJOR 2
+#define LXB_DOM_VERSION_MINOR 0
 #define LXB_DOM_VERSION_PATCH 0

 #define LXB_DOM_VERSION_STRING                                                 \
diff --git a/ext/dom/lexbor/lexbor/dom/exception.c b/ext/dom/lexbor/lexbor/dom/exception.c
index 44fcf65d6b4..5433ce42aac 100644
--- a/ext/dom/lexbor/lexbor/dom/exception.c
+++ b/ext/dom/lexbor/lexbor/dom/exception.c
@@ -1,18 +1,372 @@
 /*
- * Copyright (C) 2018 Alexander Borisov
+ * Copyright (C) 2018-2025 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */

 #include "lexbor/dom/exception.h"
+#include "lexbor/dom/interfaces/document.h"


-/*
- * No inline functions for ABI.
- */
-void *
-lxb_dom_exception_code_ref_set_noi(lxb_dom_exception_code_t *var,
-                                   lxb_dom_exception_code_t code)
+typedef struct {
+    lexbor_str_t name;
+    lexbor_str_t message;
+}
+lxb_dom_exception_data_t;
+
+
+static const lxb_dom_exception_data_t lxb_dom_exception_data[LXB_DOM_EXCEPTION__LAST_ENTRY] =
+{
+    {
+        lexbor_str("Error"),
+        lexbor_str("")
+    },
+    {
+        lexbor_str("IndexSizeError"),
+        lexbor_str("Deprecated. Use RangeError instead.")
+    },
+    {
+        lexbor_str("DOMStringSizeError"),
+        lexbor_str("")
+    },
+    {
+        lexbor_str("HierarchyRequestError"),
+        lexbor_str("The operation would yield an incorrect node tree.")
+    },
+    {
+        lexbor_str("WrongDocumentError"),
+        lexbor_str("The object is in the wrong document.")
+    },
+    {
+        lexbor_str("InvalidCharacterError"),
+        lexbor_str("The string contains invalid characters.")
+    },
+    {
+        lexbor_str("NoDataAllowedError"),
+        lexbor_str("")
+    },
+    {
+        lexbor_str("NoModificationAllowedError"),
+        lexbor_str("The object can not be modified.")
+    },
+    {
+        lexbor_str("NotFoundError"),
+        lexbor_str("The object can not be found here.")
+    },
+    {
+        lexbor_str("NotSupportedError"),
+        lexbor_str("The operation is not supported.")
+    },
+    {
+        lexbor_str("InUseAttributeError"),
+        lexbor_str("The attribute is in use by another element.")
+    },
+    {
+        lexbor_str("InvalidStateError"),
+        lexbor_str("The object is in an invalid state.")
+    },
+    {
+        lexbor_str("SyntaxError"),
+        lexbor_str("The string did not match the expected pattern.")
+    },
+    {
+        lexbor_str("InvalidModificationError"),
+        lexbor_str("The object can not be modified in this way.")
+    },
+    {
+        lexbor_str("NamespaceError"),
+        lexbor_str("The operation is not allowed by Namespaces in XML.")
+    },
+    {
+        lexbor_str("InvalidAccessError"),
+        lexbor_str("Deprecated. Use TypeError for invalid arguments, "
+                   "\"NotSupportedError\" DOMException for unsupported operations, "
+                   "and \"NotAllowedError\" DOMException for denied requests instead.")
+    },
+    {
+        lexbor_str("ValidationError"),
+        lexbor_str("")
+    },
+    {
+        lexbor_str("TypeMismatchError"),
+        lexbor_str("Deprecated. Use TypeError instead.")
+    },
+    {
+        lexbor_str("SecurityError"),
+        lexbor_str("The operation is insecure.")
+    },
+    {
+        lexbor_str("NetworkError"),
+        lexbor_str("A network error occurred.")
+    },
+    {
+        lexbor_str("AbortError"),
+        lexbor_str("The operation was aborted.")
+    },
+    {
+        lexbor_str("URLMismatchError"),
+        lexbor_str("Deprecated.")
+    },
+    {
+        lexbor_str("QuotaExceededError"),
+        lexbor_str("Deprecated. Use the QuotaExceededError DOMException-derived "
+                   "interface instead.")
+    },
+    {
+        lexbor_str("TimeoutError"),
+        lexbor_str("The operation timed out.")
+    },
+    {
+        lexbor_str("InvalidNodeTypeError"),
+        lexbor_str("The supplied node is incorrect or has an incorrect ancestor "
+                   "for this operation.")
+    },
+    {
+        lexbor_str("DataCloneError"),
+        lexbor_str("The object can not be cloned.")
+    },
+    {
+        lexbor_str("EncodingError"),
+        lexbor_str("The encoding operation (either encoded or decoding) failed.")
+    },
+    {
+        lexbor_str("NotReadableError"),
+        lexbor_str("The I/O read operation failed.")
+    },
+    {
+        lexbor_str("UnknownError"),
+        lexbor_str("The operation failed for an unknown transient reason "
+                   "(e.g. out of memory).")
+    },
+    {
+        lexbor_str("ConstraintError"),
+        lexbor_str("A mutation operation in a transaction failed because a "
+                   "constraint was not satisfied.")
+    },
+    {
+        lexbor_str("DataError"),
+        lexbor_str("Provided data is inadequate.")
+    },
+    {
+        lexbor_str("TransactionInactiveError"),
+        lexbor_str("A request was placed against a transaction which is currently"
+                   " not active, or which is finished.")
+    },
+    {
+        lexbor_str("ReadOnlyError"),
+        lexbor_str("The mutating operation was attempted in a \"readonly\" transaction.")
+    },
+    {
+        lexbor_str("VersionError"),
+        lexbor_str("An attempt was made to open a database using a lower version"
+                   " than the existing version.")
+    },
+    {
+        lexbor_str("OperationError"),
+        lexbor_str("The operation failed for an operation-specific reason.")
+    },
+    {
+        lexbor_str("NotAllowedError"),
+        lexbor_str("The request is not allowed by the user agent or the platform"
+                   " in the current context, possibly because the user denied permission.")
+    },
+    {
+        lexbor_str("OptOutError"),
+        lexbor_str("The user opted out of the process.")
+    }
+};
+
+
+lxb_dom_exception_t *
+lxb_dom_exception_create(lxb_dom_document_t *document,
+                         const lxb_char_t *message, size_t message_length,
+                         const lxb_char_t *name, size_t name_length)
+{
+    lexbor_str_t *str;
+    const lxb_dom_exception_data_t *data;
+    lxb_dom_exception_t *exception;
+
+    exception = lexbor_mraw_alloc(document->mraw, sizeof(lxb_dom_exception_t));
+    if (exception == NULL) {
+        return NULL;
+    }
+
+    exception->document = document;
+
+    if (name != NULL && name_length > 0) {
+        exception->code = lxb_dom_exception_code_by_name(name, name_length);
+    }
+    else {
+        exception->code = LXB_DOM_EXCEPTION_ERR;
+    }
+
+    /* Message. */
+
+    if (message == NULL || message_length == 0) {
+        data = &lxb_dom_exception_data[exception->code];
+        exception->message = *((lexbor_str_t *) &data->message);
+    }
+    else {
+        str = &exception->message;
+        str->data = lexbor_mraw_alloc(document->mraw, message_length + 1);
+        if (str->data == NULL) {
+            goto failed;
+        }
+
+        memcpy(str->data, message, message_length);
+
+        str->data[message_length] = '\0';
+        str->length = message_length;
+    }
+
+    /* Name. */
+
+    if (exception->code != LXB_DOM_EXCEPTION_ERR
+        || name == NULL || name_length == 0)
+    {
+        data = &lxb_dom_exception_data[exception->code];
+        exception->name = *((lexbor_str_t *) &data->name);
+    }
+    else {
+        str = &exception->name;
+        str->data = lexbor_mraw_alloc(document->mraw, name_length + 1);
+        if (str->data == NULL) {
+            if (exception->message.length != 0) {
+                lexbor_mraw_free(document->mraw, exception->message.data);
+            }
+
+            goto failed;
+        }
+
+        memcpy(str->data, name, name_length);
+
+        str->data[name_length] = '\0';
+        str->length = name_length;
+    }
+
+    return exception;
+
+failed:
+
+    lexbor_mraw_free(document->mraw, exception);
+
+    return NULL;
+}
+
+lxb_dom_exception_t *
+lxb_dom_exception_create_by_code(lxb_dom_document_t *document,
+                                 const lxb_char_t *message, size_t length,
+                                 lxb_dom_exception_code_t code)
 {
-    return lxb_dom_exception_code_ref_set(var, code);
+    lexbor_str_t *str;
+    const lxb_dom_exception_data_t *data;
+    lxb_dom_exception_t *exception;
+
+    if (code <= LXB_DOM_EXCEPTION_OK || code >= LXB_DOM_EXCEPTION__LAST_ENTRY) {
+        return NULL;
+    }
+
+    exception = lexbor_mraw_alloc(document->mraw, sizeof(lxb_dom_exception_t));
+    if (exception == NULL) {
+        return NULL;
+    }
+
+    exception->document = document;
+    exception->code = code;
+
+    data = &lxb_dom_exception_data[code];
+
+    /* Message. */
+
+    if (message == NULL || length == 0) {
+        exception->message = *((lexbor_str_t *) &data->message);
+    }
+    else {
+        str = &exception->message;
+        str->data = lexbor_mraw_alloc(document->mraw, length + 1);
+        if (str->data == NULL) {
+            goto failed;
+        }
+
+        memcpy(str->data, message, length);
+
+        str->data[length] = '\0';
+        str->length = length;
+    }
+
+    /* Name. */
+
+    exception->name = *((lexbor_str_t *) &data->name);
+
+    return exception;
+
+failed:
+
+    lexbor_mraw_free(document->mraw, exception);
+
+    return NULL;
+}
+
+lxb_dom_exception_t *
+lxb_dom_exception_destroy(lxb_dom_exception_t *exception)
+{
+    const lxb_dom_exception_data_t *data;
+    lxb_dom_document_t *document = exception->document;
+
+    data = &lxb_dom_exception_data[exception->code];
+
+    if (exception->message.data != NULL
+        && exception->message.data != data->message.data)
+    {
+        lexbor_mraw_free(document->mraw, exception->message.data);
+    }
+
+    if (exception->name.data != NULL
+        && exception->name.data != data->name.data)
+    {
+        lexbor_mraw_free(document->mraw, exception->name.data);
+    }
+
+    lexbor_mraw_free(document->mraw, exception);
+
+    return NULL;
+}
+
+const lexbor_str_t *
+lxb_dom_exception_message_by_code(lxb_dom_exception_code_t code)
+{
+    if (code <= LXB_DOM_EXCEPTION_OK || code >= LXB_DOM_EXCEPTION__LAST_ENTRY) {
+        return NULL;
+    }
+
+    return &lxb_dom_exception_data[code].message;
+}
+
+const lexbor_str_t *
+lxb_dom_exception_name_by_code(lxb_dom_exception_code_t code)
+{
+    if (code <= LXB_DOM_EXCEPTION_OK || code >= LXB_DOM_EXCEPTION__LAST_ENTRY) {
+        return NULL;
+    }
+
+    return &lxb_dom_exception_data[code].name;
+}
+
+lxb_dom_exception_code_t
+lxb_dom_exception_code_by_name(const lxb_char_t *name, size_t length)
+{
+    const lexbor_str_t *str;
+    lxb_dom_exception_code_t code;
+
+    for (code = 0; code < LXB_DOM_EXCEPTION__LAST_ENTRY; code++) {
+        str = &lxb_dom_exception_data[code].name;
+
+        if (length == str->length
+            && lexbor_str_data_ncasecmp(str->data, name, length))
+        {
+            return code;
+        }
+    }
+
+    return LXB_DOM_EXCEPTION_ERR;
 }
diff --git a/ext/dom/lexbor/lexbor/dom/exception.h b/ext/dom/lexbor/lexbor/dom/exception.h
index 47a7cfee040..b306ed1443a 100644
--- a/ext/dom/lexbor/lexbor/dom/exception.h
+++ b/ext/dom/lexbor/lexbor/dom/exception.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 Alexander Borisov
+ * Copyright (C) 2018-2025 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -12,58 +12,84 @@ extern "C" {
 #endif

 #include "lexbor/core/base.h"
+#include "lexbor/core/str.h"
+#include "lexbor/dom/interface.h"


 typedef enum {
-    LXB_DOM_INDEX_SIZE_ERR = 0x00,
-    LXB_DOM_DOMSTRING_SIZE_ERR,
-    LXB_DOM_HIERARCHY_REQUEST_ERR,
-    LXB_DOM_WRONG_DOCUMENT_ERR,
-    LXB_DOM_INVALID_CHARACTER_ERR,
-    LXB_DOM_NO_DATA_ALLOWED_ERR,
-    LXB_DOM_NO_MODIFICATION_ALLOWED_ERR,
-    LXB_DOM_NOT_FOUND_ERR,
-    LXB_DOM_NOT_SUPPORTED_ERR,
-    LXB_DOM_INUSE_ATTRIBUTE_ERR,
-    LXB_DOM_INVALID_STATE_ERR,
-    LXB_DOM_SYNTAX_ERR,
-    LXB_DOM_INVALID_MODIFICATION_ERR,
-    LXB_DOM_NAMESPACE_ERR,
-    LXB_DOM_INVALID_ACCESS_ERR,
-    LXB_DOM_VALIDATION_ERR,
-    LXB_DOM_TYPE_MISMATCH_ERR,
-    LXB_DOM_SECURITY_ERR,
-    LXB_DOM_NETWORK_ERR,
-    LXB_DOM_ABORT_ERR,
-    LXB_DOM_URL_MISMATCH_ERR,
-    LXB_DOM_QUOTA_EXCEEDED_ERR,
-    LXB_DOM_TIMEOUT_ERR,
-    LXB_DOM_INVALID_NODE_TYPE_ERR,
-    LXB_DOM_DATA_CLONE_ERR
+    LXB_DOM_EXCEPTION_OK = -1,
+    LXB_DOM_EXCEPTION_ERR = 0,
+    LXB_DOM_EXCEPTION_INDEX_SIZE_ERR = 1, /* Deprecated. */
+    LXB_DOM_EXCEPTION_DOMSTRING_SIZE_ERR,
+    LXB_DOM_EXCEPTION_HIERARCHY_REQUEST_ERR,
+    LXB_DOM_EXCEPTION_WRONG_DOCUMENT_ERR,
+    LXB_DOM_EXCEPTION_INVALID_CHARACTER_ERR,
+    LXB_DOM_EXCEPTION_NO_DATA_ALLOWED_ERR,
+    LXB_DOM_EXCEPTION_NO_MODIFICATION_ALLOWED_ERR,
+    LXB_DOM_EXCEPTION_NOT_FOUND_ERR,
+    LXB_DOM_EXCEPTION_NOT_SUPPORTED_ERR,
+    LXB_DOM_EXCEPTION_INUSE_ATTRIBUTE_ERR,
+    LXB_DOM_EXCEPTION_INVALID_STATE_ERR,
+    LXB_DOM_EXCEPTION_SYNTAX_ERR,
+    LXB_DOM_EXCEPTION_INVALID_MODIFICATION_ERR,
+    LXB_DOM_EXCEPTION_NAMESPACE_ERR,
+    LXB_DOM_EXCEPTION_INVALID_ACCESS_ERR, /* Deprecated. */
+    LXB_DOM_EXCEPTION_VALIDATION_ERR,
+    LXB_DOM_EXCEPTION_TYPE_MISMATCH_ERR, /* Deprecated. */
+    LXB_DOM_EXCEPTION_SECURITY_ERR,
+    LXB_DOM_EXCEPTION_NETWORK_ERR,
+    LXB_DOM_EXCEPTION_ABORT_ERR,
+    LXB_DOM_EXCEPTION_URL_MISMATCH_ERR, /* Deprecated. */
+    LXB_DOM_EXCEPTION_QUOTA_EXCEEDED_ERR, /* Deprecated. */
+    LXB_DOM_EXCEPTION_TIMEOUT_ERR,
+    LXB_DOM_EXCEPTION_INVALID_NODE_TYPE_ERR,
+    LXB_DOM_EXCEPTION_DATA_CLONE_ERR,
+    LXB_DOM_EXCEPTION_ENCODING_ERR,
+    LXB_DOM_EXCEPTION_NOT_READABLE_ERR,
+    LXB_DOM_EXCEPTION_UNKNOWN_ERR,
+    LXB_DOM_EXCEPTION_CONSTRAINT_ERR,
+    LXB_DOM_EXCEPTION_DATA_ERR,
+    LXB_DOM_EXCEPTION_TRANSACTION_INACTIVE_ERR,
+    LXB_DOM_EXCEPTION_READ_ONLY_ERR,
+    LXB_DOM_EXCEPTION_VERSION_ERR,
+    LXB_DOM_EXCEPTION_OPERATION_ERR,
+    LXB_DOM_EXCEPTION_NOT_ALLOWED_ERR,
+    LXB_DOM_EXCEPTION_OPT_OUT_ERR,
+    LXB_DOM_EXCEPTION__LAST_ENTRY
 }
 lxb_dom_exception_code_t;

-
-/*
- * Inline functions
- */
-lxb_inline void *
-lxb_dom_exception_code_ref_set(lxb_dom_exception_code_t *var,
-                               lxb_dom_exception_code_t code)
-{
-    if (var != NULL) {
-        *var = code;
-    }
-
-    return NULL;
+typedef struct {
+    lexbor_str_t             name;
+    lexbor_str_t             message;
+    lxb_dom_exception_code_t code;
+    lxb_dom_document_t       *document;
 }
+lxb_dom_exception_t;

-/*
- * No inline functions for ABI.
- */
-LXB_API void *
-lxb_dom_exception_code_ref_set_noi(lxb_dom_exception_code_t *var,
-                                   lxb_dom_exception_code_t code);
+
+LXB_API lxb_dom_exception_t *
+lxb_dom_exception_create(lxb_dom_document_t *document,
+                         const lxb_char_t *message, size_t message_length,
+                         const lxb_char_t *name, size_t name_length);
+
+LXB_API lxb_dom_exception_t *
+lxb_dom_exception_create_by_code(lxb_dom_document_t *document,
+                                 const lxb_char_t *message, size_t length,
+                                 lxb_dom_exception_code_t code);
+
+LXB_API lxb_dom_exception_t *
+lxb_dom_exception_destroy(lxb_dom_exception_t *exception);
+
+
+LXB_API const lexbor_str_t *
+lxb_dom_exception_message_by_code(lxb_dom_exception_code_t code);
+
+LXB_API const lexbor_str_t *
+lxb_dom_exception_name_by_code(lxb_dom_exception_code_t code);
+
+LXB_API lxb_dom_exception_code_t
+lxb_dom_exception_code_by_name(const lxb_char_t *name, size_t length);


 #ifdef __cplusplus
diff --git a/ext/dom/lexbor/lexbor/dom/interface.h b/ext/dom/lexbor/lexbor/dom/interface.h
index 3eb4b133e9c..30753e0b43a 100644
--- a/ext/dom/lexbor/lexbor/dom/interface.h
+++ b/ext/dom/lexbor/lexbor/dom/interface.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018-2021 Alexander Borisov
+ * Copyright (C) 2018-2025 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -16,8 +16,6 @@ extern "C" {
 #include "lexbor/tag/const.h"
 #include "lexbor/ns/const.h"

-#include "lexbor/dom/exception.h"
-

 #define lxb_dom_interface_cdata_section(obj) ((lxb_dom_cdata_section_t *) (obj))
 #define lxb_dom_interface_character_data(obj) ((lxb_dom_character_data_t *) (obj))
diff --git a/ext/dom/lexbor/lexbor/dom/interfaces/attr_const.h b/ext/dom/lexbor/lexbor/dom/interfaces/attr_const.h
index 756ad5548e4..28afac5e0bd 100644
--- a/ext/dom/lexbor/lexbor/dom/interfaces/attr_const.h
+++ b/ext/dom/lexbor/lexbor/dom/interfaces/attr_const.h
@@ -39,22 +39,23 @@ typedef enum {
     LXB_DOM_ATTR_ID          = 0x0012,
     LXB_DOM_ATTR_IS          = 0x0013,
     LXB_DOM_ATTR_MAXLENGTH   = 0x0014,
-    LXB_DOM_ATTR_PLACEHOLDER = 0x0015,
-    LXB_DOM_ATTR_POOL        = 0x0016,
-    LXB_DOM_ATTR_PUBLIC      = 0x0017,
-    LXB_DOM_ATTR_READONLY    = 0x0018,
-    LXB_DOM_ATTR_REQUIRED    = 0x0019,
-    LXB_DOM_ATTR_SCHEME      = 0x001a,
-    LXB_DOM_ATTR_SELECTED    = 0x001b,
-    LXB_DOM_ATTR_SIZE        = 0x001c,
-    LXB_DOM_ATTR_SLOT        = 0x001d,
-    LXB_DOM_ATTR_SRC         = 0x001e,
-    LXB_DOM_ATTR_STYLE       = 0x001f,
-    LXB_DOM_ATTR_SYSTEM      = 0x0020,
-    LXB_DOM_ATTR_TITLE       = 0x0021,
-    LXB_DOM_ATTR_TYPE        = 0x0022,
-    LXB_DOM_ATTR_WIDTH       = 0x0023,
-    LXB_DOM_ATTR__LAST_ENTRY = 0x0024
+    LXB_DOM_ATTR_MULTIPLE    = 0x0015,
+    LXB_DOM_ATTR_PLACEHOLDER = 0x0016,
+    LXB_DOM_ATTR_POOL        = 0x0017,
+    LXB_DOM_ATTR_PUBLIC      = 0x0018,
+    LXB_DOM_ATTR_READONLY    = 0x0019,
+    LXB_DOM_ATTR_REQUIRED    = 0x001a,
+    LXB_DOM_ATTR_SCHEME      = 0x001b,
+    LXB_DOM_ATTR_SELECTED    = 0x001c,
+    LXB_DOM_ATTR_SIZE        = 0x001d,
+    LXB_DOM_ATTR_SLOT        = 0x001e,
+    LXB_DOM_ATTR_SRC         = 0x001f,
+    LXB_DOM_ATTR_STYLE       = 0x0020,
+    LXB_DOM_ATTR_SYSTEM      = 0x0021,
+    LXB_DOM_ATTR_TITLE       = 0x0022,
+    LXB_DOM_ATTR_TYPE        = 0x0023,
+    LXB_DOM_ATTR_WIDTH       = 0x0024,
+    LXB_DOM_ATTR__LAST_ENTRY = 0x0025
 }
 lxb_dom_attr_id_enum_t;

diff --git a/ext/dom/lexbor/lexbor/dom/interfaces/attr_res.h b/ext/dom/lexbor/lexbor/dom/interfaces/attr_res.h
index 85aa2c5061f..0796043cafd 100644
--- a/ext/dom/lexbor/lexbor/dom/interfaces/attr_res.h
+++ b/ext/dom/lexbor/lexbor/dom/interfaces/attr_res.h
@@ -63,6 +63,8 @@ static const lxb_dom_attr_data_t lxb_dom_attr_res_data_default[LXB_DOM_ATTR__LAS
      LXB_DOM_ATTR_IS, 1, true},
     {{.u.short_str = "maxlength", .length = 9, .next = NULL},
      LXB_DOM_ATTR_MAXLENGTH, 1, true},
+    {{.u.short_str = "multiple", .length = 8, .next = NULL},
+     LXB_DOM_ATTR_MULTIPLE, 1, true},
     {{.u.short_str = "placeholder", .length = 11, .next = NULL},
      LXB_DOM_ATTR_PLACEHOLDER, 1, true},
     {{.u.short_str = "pool", .length = 4, .next = NULL},
@@ -127,7 +129,7 @@ static const lexbor_shs_entry_t lxb_dom_attr_res_shs_data[40] =
     {"is", (void *) &lxb_dom_attr_res_data_default[LXB_DOM_ATTR_IS], 2, 0},
     {"type", (void *) &lxb_dom_attr_res_data_default[LXB_DOM_ATTR_TYPE], 4, 0},
     {"title", (void *) &lxb_dom_attr_res_data_default[LXB_DOM_ATTR_TITLE], 5, 0},
-    {NULL, NULL, 0, 0},
+    {"multiple", (void *) &lxb_dom_attr_res_data_default[LXB_DOM_ATTR_MULTIPLE], 8, 0},
     {"for", (void *) &lxb_dom_attr_res_data_default[LXB_DOM_ATTR_FOR], 3, 0},
     {"face", (void *) &lxb_dom_attr_res_data_default[LXB_DOM_ATTR_FACE], 4, 22},
     {"alt", (void *) &lxb_dom_attr_res_data_default[LXB_DOM_ATTR_ALT], 3, 23},
@@ -135,7 +137,7 @@ static const lexbor_shs_entry_t lxb_dom_attr_res_shs_data[40] =
     {"charset", (void *) &lxb_dom_attr_res_data_default[LXB_DOM_ATTR_CHARSET], 7, 26},
     {"maxlength", (void *) &lxb_dom_attr_res_data_default[LXB_DOM_ATTR_MAXLENGTH], 9, 0},
     {NULL, NULL, 0, 0},
-    {"checked", (void *) &lxb_dom_attr_res_data_default[LXB_DOM_ATTR_CHECKED], 7, 0},
+    {"checked", (void *) &lxb_dom_attr_res_data_default[LXB_DOM_ATTR_CHECKED], 7, 30},
     {NULL, NULL, 0, 0}
 };

diff --git a/ext/dom/lexbor/lexbor/dom/interfaces/character_data.c b/ext/dom/lexbor/lexbor/dom/interfaces/character_data.c
index bbca1865b39..12c7dfdd0d6 100644
--- a/ext/dom/lexbor/lexbor/dom/interfaces/character_data.c
+++ b/ext/dom/lexbor/lexbor/dom/interfaces/character_data.c
@@ -22,7 +22,7 @@ lxb_dom_character_data_interface_create(lxb_dom_document_t *document)
     lxb_dom_node_t *node = lxb_dom_interface_node(element);

     node->owner_document = lxb_dom_document_owner(document);
-    node->type = LXB_DOM_NODE_TYPE_UNDEF;
+    node->type = LXB_DOM_NODE_TYPE_CHARACTER_DATA;

     return element;
 }
diff --git a/ext/dom/lexbor/lexbor/dom/interfaces/document_type.c b/ext/dom/lexbor/lexbor/dom/interfaces/document_type.c
index 8c7465f4d62..46889162717 100644
--- a/ext/dom/lexbor/lexbor/dom/interfaces/document_type.c
+++ b/ext/dom/lexbor/lexbor/dom/interfaces/document_type.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018-2021 Alexander Borisov
+ * Copyright (C) 2018-2025 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -12,6 +12,10 @@ LXB_API lxb_dom_attr_data_t *
 lxb_dom_attr_qualified_name_append(lexbor_hash_t *hash, const lxb_char_t *name,
                                    size_t length);

+LXB_API lxb_dom_attr_data_t *
+lxb_dom_attr_local_name_append(lexbor_hash_t *hash,
+                               const lxb_char_t *name, size_t length);
+

 lxb_dom_document_type_t *
 lxb_dom_document_type_interface_create(lxb_dom_document_t *document)
@@ -29,6 +33,8 @@ lxb_dom_document_type_interface_create(lxb_dom_document_t *document)
     node->owner_document = lxb_dom_document_owner(document);
     node->type = LXB_DOM_NODE_TYPE_DOCUMENT_TYPE;

+    element->name = LXB_DOM_ATTR_HTML;
+
     return element;
 }

@@ -105,6 +111,103 @@ lxb_dom_document_type_interface_destroy(lxb_dom_document_type_t *document_type)
     return NULL;
 }

+lxb_dom_document_type_t *
+lxb_dom_document_type_create(lxb_dom_document_t *document,
+                             const lxb_char_t *name, size_t name_len,
+                             const lxb_char_t *pub, size_t pub_len,
+                             const lxb_char_t *sys, size_t sys_len,
+                             lxb_dom_exception_code_t *code)
+{
+    lxb_dom_attr_data_t *data;
+    lxb_dom_document_type_t *doctype;
+
+    if (!lxb_dom_document_type_valid_name(name, name_len)) {
+        if (code != NULL) {
+            *code = LXB_DOM_EXCEPTION_INVALID_CHARACTER_ERR;
+        }
+
+        return NULL;
+    }
+
+    doctype = lxb_dom_document_type_interface_create(document);
+    if (doctype == NULL) {
+        goto failed;
+    }
+
+    data = lxb_dom_attr_local_name_append(document->attrs, name, name_len);
+    if (data == NULL) {
+        goto failed;
+    }
+
+    doctype->name = data->attr_id;
+
+    if (pub != NULL && pub_len != 0) {
+        doctype->public_id.data = lxb_dom_document_create_text(document,
+                                                               pub_len + 1);
+        if (doctype->public_id.data == NULL) {
+            goto failed;
+        }
+
+        (void) lexbor_str_copy_to_with_null(&doctype->public_id, pub, pub_len);
+    }
+
+    if (sys != NULL && sys_len != 0) {
+        doctype->system_id.data = lxb_dom_document_create_text(document,
+                                                               sys_len + 1);
+        if (doctype->system_id.data == NULL) {
+            goto failed;
+        }
+
+        (void) lexbor_str_copy_to_with_null(&doctype->system_id, sys, sys_len);
+    }
+
+    if (code != NULL) {
+        *code = LXB_DOM_EXCEPTION_OK;
+    }
+
+    return doctype;
+
+failed:
+
+    if (doctype != NULL && doctype->public_id.data != NULL) {
+        lxb_dom_document_destroy_text(document, doctype->public_id.data);
+    }
+
+    if (code != NULL) {
+        *code = LXB_DOM_EXCEPTION_ERR;
+    }
+
+    return NULL;
+}
+
+bool
+lxb_dom_document_type_valid_name(const lxb_char_t *name, size_t length)
+{
+    lxb_char_t c;
+    const lxb_char_t *end;
+
+    if (name == NULL || length == 0) {
+        return false;
+    }
+
+    end = name + length;
+
+    while (name < end) {
+        c = *name++;
+        /*
+         * U+0009 TAB, U+000A LF, U+000C FF, U+000D CR, or U+0020 SPACE,
+         * or U+0000 NULL, or U+003E (>)
+         */
+        if (c == 0x09 || c == 0x0A || c == 0x0C || c == 0x0D || c == 0x20
+            || c == 0x00 || c == 0x3E)
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
 /*
  * No inline functions for ABI.
  */
diff --git a/ext/dom/lexbor/lexbor/dom/interfaces/document_type.h b/ext/dom/lexbor/lexbor/dom/interfaces/document_type.h
index 366aaba409a..c7a1960af66 100644
--- a/ext/dom/lexbor/lexbor/dom/interfaces/document_type.h
+++ b/ext/dom/lexbor/lexbor/dom/interfaces/document_type.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018-2021 Alexander Borisov
+ * Copyright (C) 2018-2025 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -37,6 +37,34 @@ lxb_dom_document_type_interface_clone(lxb_dom_document_t *document,
 LXB_API lxb_dom_document_type_t *
 lxb_dom_document_type_interface_destroy(lxb_dom_document_type_t *document_type);

+/*
+ * Create DocumentType by specification.
+ *
+ * https://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype
+ *
+ * @param[in] lxb_dom_document_t *. Not NULL.
+ * @param[in] const lxb_char_t *. Name. May be NULL, but then the return value
+ *            will be NULL and an exception code will be recorded.
+ * @param[in] size_t. Length of name. May be 0, but then the return value
+ *            will be NULL and an exception code will be recorded.
+ * @param[in] const lxb_char_t *. PublicID. Can be NULL.
+ * @param[in] size_t. Length of PublicID. Can be 0.
+ * @param[in] const lxb_char_t *. SystemID. Can be NULL.
+ * @param[in] size_t. Length of SystemID. Can be 0.
+ * @param[out] lxb_dom_exception_code_t. Can be NULL. If the variable is passed,
+ *             the code will definitely be assigned. LXB_DOM_EXCEPTION_OK
+ *             if successful.
+ *
+ * @return lxb_dom_document_type_t * if successful, otherwise NULL.
+ */
+LXB_API lxb_dom_document_type_t *
+lxb_dom_document_type_create(lxb_dom_document_t *document,
+                             const lxb_char_t *name, size_t name_len,
+                             const lxb_char_t *pub, size_t pub_len,
+                             const lxb_char_t *sys, size_t sys_len,
+                             lxb_dom_exception_code_t *code);
+LXB_API bool
+lxb_dom_document_type_valid_name(const lxb_char_t *ame, size_t name_len);

 /*
  * Inline functions
diff --git a/ext/dom/lexbor/lexbor/dom/interfaces/element.c b/ext/dom/lexbor/lexbor/dom/interfaces/element.c
index 09d9736e5d8..90d707d078b 100644
--- a/ext/dom/lexbor/lexbor/dom/interfaces/element.c
+++ b/ext/dom/lexbor/lexbor/dom/interfaces/element.c
@@ -581,6 +581,18 @@ lxb_dom_element_is_set(lxb_dom_element_t *element,
     return LXB_STATUS_OK;
 }

+lxb_dom_element_t *
+lxb_dom_element_by_id(lxb_dom_element_t *root,
+                      const lxb_char_t *qualified_name, size_t len)
+{
+    lxb_dom_node_t *node;
+
+    node = lxb_dom_node_by_id(lxb_dom_interface_node(root),
+                              qualified_name, len);
+
+    return lxb_dom_interface_element(node);
+}
+
 lxb_status_t
 lxb_dom_elements_by_tag_name(lxb_dom_element_t *root,
                              lxb_dom_collection_t *collection,
diff --git a/ext/dom/lexbor/lexbor/dom/interfaces/element.h b/ext/dom/lexbor/lexbor/dom/interfaces/element.h
index dd661d439cc..50d814fd376 100644
--- a/ext/dom/lexbor/lexbor/dom/interfaces/element.h
+++ b/ext/dom/lexbor/lexbor/dom/interfaces/element.h
@@ -135,6 +135,10 @@ LXB_API lxb_status_t
 lxb_dom_element_is_set(lxb_dom_element_t *element,
                        const lxb_char_t *is, size_t is_len);

+LXB_API lxb_dom_element_t *
+lxb_dom_element_by_id(lxb_dom_element_t *root,
+                      const lxb_char_t *qualified_name, size_t len);
+
 LXB_API lxb_status_t
 lxb_dom_elements_by_tag_name(lxb_dom_element_t *root,
                              lxb_dom_collection_t *collection,
diff --git a/ext/dom/lexbor/lexbor/dom/interfaces/node.c b/ext/dom/lexbor/lexbor/dom/interfaces/node.c
index a588ed388e4..f2bbaa391e3 100644
--- a/ext/dom/lexbor/lexbor/dom/interfaces/node.c
+++ b/ext/dom/lexbor/lexbor/dom/interfaces/node.c
@@ -10,6 +10,7 @@
 #include "lexbor/dom/interfaces/document_type.h"
 #include "lexbor/dom/interfaces/element.h"
 #include "lexbor/dom/interfaces/processing_instruction.h"
+#include "lexbor/dom/interfaces/shadow_root.h"


 typedef struct lxb_dom_node_cb_ctx lxb_dom_node_cb_ctx_t;
@@ -29,6 +30,13 @@ struct lxb_dom_node_cb_ctx {
     size_t                     value_length;
 };

+typedef struct {
+    lxb_dom_node_t   *node;
+    const lxb_char_t *value;
+    size_t           length;
+}
+lxb_dom_node_id_cb_ctx_t;
+

 LXB_API lxb_dom_attr_data_t *
 lxb_dom_attr_local_name_append(lexbor_hash_t *hash,
@@ -44,6 +52,9 @@ lxb_ns_append(lexbor_hash_t *hash, const lxb_char_t *link, size_t length);
 static lexbor_action_t
 lxb_dom_node_by_tag_name_cb(lxb_dom_node_t *node, void *ctx);

+static lexbor_action_t
+lxb_dom_node_by_id_cb(lxb_dom_node_t *node, void *ctx);
+
 static lexbor_action_t
 lxb_dom_node_by_tag_name_cb_all(lxb_dom_node_t *node, void *ctx);

@@ -443,6 +454,373 @@ lxb_dom_node_insert_after(lxb_dom_node_t *to, lxb_dom_node_t *node)
     }
 }

+lxb_dom_exception_code_t
+lxb_dom_node_pre_insert_validity(lxb_dom_node_t *parent, lxb_dom_node_t *node,
+                                 lxb_dom_node_t *child)
+{
+    size_t count;
+    lxb_dom_node_t *tmp;
+
+    /*
+     * If parent is not a Document, DocumentFragment, or Element node, then
+     * throw a "HierarchyRequestError" DOMException.
+     */
+    if (parent == NULL) {
+        return LXB_DOM_EXCEPTION_HIERARCHY_REQUEST_ERR;
+    }
+
+    switch (parent->type) {
+        case LXB_DOM_NODE_TYPE_ELEMENT:
+        case LXB_DOM_NODE_TYPE_DOCUMENT:
+        case LXB_DOM_NODE_TYPE_DOCUMENT_FRAGMENT:
+            break;
+
+        default:
+            return LXB_DOM_EXCEPTION_HIERARCHY_REQUEST_ERR;
+    }
+
+    if (lxb_dom_node_host_including_inclusive_ancestor(node, parent)) {
+        return LXB_DOM_EXCEPTION_HIERARCHY_REQUEST_ERR;
+    }
+
+    /*
+     * If child is non-null and its parent is not parent,
+     * then throw a "NotFoundError" DOMException.
+     */
+    if (child != NULL && parent != child->parent) {
+        return LXB_DOM_EXCEPTION_NOT_FOUND_ERR;
+    }
+
+    /*
+     * If node is not a DocumentFragment, DocumentType, Element,
+     * or CharacterData node, then throw a "HierarchyRequestError" DOMException.
+     */
+    if (node == NULL) {
+        return LXB_DOM_EXCEPTION_HIERARCHY_REQUEST_ERR;
+    }
+
+    switch (parent->type) {
+        case LXB_DOM_NODE_TYPE_ELEMENT:
+        case LXB_DOM_NODE_TYPE_DOCUMENT:
+        case LXB_DOM_NODE_TYPE_DOCUMENT_TYPE:
+        case LXB_DOM_NODE_TYPE_DOCUMENT_FRAGMENT:
+        case LXB_DOM_NODE_TYPE_CHARACTER_DATA:
+        case LXB_DOM_NODE_TYPE_TEXT:
+            break;
+
+        default:
+            return LXB_DOM_EXCEPTION_HIERARCHY_REQUEST_ERR;
+    }
+
+    /*
+     * If either node is a Text node and parent is a document, or node is
+     * a doctype and parent is not a document, then throw
+     * a "HierarchyRequestError" DOMException.
+     */
+    if ((node->type == LXB_DOM_NODE_TYPE_TEXT
+        && parent->type == LXB_DOM_NODE_TYPE_DOCUMENT)
+        || (node->type == LXB_DOM_NODE_TYPE_DOCUMENT_TYPE
+            && parent->type != LXB_DOM_NODE_TYPE_DOCUMENT))
+    {
+        return LXB_DOM_EXCEPTION_HIERARCHY_REQUEST_ERR;
+    }
+
+    if (parent->type != LXB_DOM_NODE_TYPE_DOCUMENT) {
+        return LXB_DOM_EXCEPTION_OK;
+    }
+
+    switch (node->type) {
+        case LXB_DOM_NODE_TYPE_DOCUMENT_FRAGMENT:
+            tmp = node->first_child;
+
+            if (tmp == NULL) {
+                return LXB_DOM_EXCEPTION_OK;
+            }
+
+            count = 0;
+
+            do {
+                if (tmp->type == LXB_DOM_NODE_TYPE_TEXT) {
+                    return LXB_DOM_EXCEPTION_HIERARCHY_REQUEST_ERR;
+                }
+                else if (tmp->type == LXB_DOM_NODE_TYPE_ELEMENT) {
+                    count += 1;
+
+                    if (count > 1) {
+                        return LXB_DOM_EXCEPTION_HIERARCHY_REQUEST_ERR;
+                    }
+                }
+
+                tmp = tmp->next;
+            }
+            while (tmp != NULL);
+
+            if (count != 1) {
+                return LXB_DOM_EXCEPTION_OK;
+            }
+
+            /* Fall Through. */
+
+        case LXB_DOM_NODE_TYPE_ELEMENT:
+            tmp = parent->first_child;
+
+            while (tmp != NULL) {
+                if (tmp->type == LXB_DOM_NODE_TYPE_ELEMENT) {
+                    return LXB_DOM_EXCEPTION_HIERARCHY_REQUEST_ERR;
+                }
+
+                tmp = tmp->next;
+            }
+
+            if (child == NULL) {
+                return LXB_DOM_EXCEPTION_OK;
+            }
+
+            if (child->type == LXB_DOM_NODE_TYPE_DOCUMENT_TYPE) {
+                return LXB_DOM_EXCEPTION_HIERARCHY_REQUEST_ERR;
+            }
+
+            tmp = child->next;
+
+            while (tmp != NULL) {
+                if (tmp->type == LXB_DOM_NODE_TYPE_DOCUMENT_TYPE) {
+                    return LXB_DOM_EXCEPTION_HIERARCHY_REQUEST_ERR;
+                }
+
+                tmp = tmp->next;
+            }
+
+            break;
+
+        case LXB_DOM_NODE_TYPE_DOCUMENT_TYPE:
+            tmp = parent->first_child;
+
+            while (tmp != NULL) {
+                if (tmp->type == LXB_DOM_NODE_TYPE_DOCUMENT_TYPE) {
+                    return LXB_DOM_EXCEPTION_HIERARCHY_REQUEST_ERR;
+                }
+                else if (tmp->type == LXB_DOM_NODE_TYPE_ELEMENT
+                         && child == NULL)
+                {
+                    return LXB_DOM_EXCEPTION_HIERARCHY_REQUEST_ERR;
+                }
+
+                tmp = tmp->next;
+            }
+
+            if (child == NULL) {
+                return LXB_DOM_EXCEPTION_OK;
+            }
+
+            tmp = child->prev;
+
+            while (tmp != NULL) {
+                if (tmp->type == LXB_DOM_NODE_TYPE_ELEMENT) {
+                    return LXB_DOM_EXCEPTION_HIERARCHY_REQUEST_ERR;
+                }
+
+                tmp = tmp->prev;
+            }
+
+            break;
+
+        default:
+            break;
+    }
+
+    return LXB_DOM_EXCEPTION_OK;
+}
+
+lxb_dom_exception_code_t
+lxb_dom_node_pre_insert(lxb_dom_node_t *parent, lxb_dom_node_t *node,
+                        lxb_dom_node_t *child)
+{
+    lxb_dom_exception_code_t ex_code;
+
+    ex_code = lxb_dom_node_pre_insert_validity(parent, node, child);
+    if (ex_code != LXB_DOM_EXCEPTION_OK) {
+        return ex_code;
+    }
+
+    if (child == node) {
+        child = node->next;
+    }
+
+    return lxb_dom_node_insert(parent, node, child, false);
+}
+
+lxb_inline lxb_dom_exception_code_t
+lxb_dom_node_insert_node(lxb_dom_node_t *parent, lxb_dom_node_t *node,
+                         lxb_dom_node_t *child, bool suppress_observers)
+{
+    lxb_dom_exception_code_t code;
+
+    code = lxb_dom_node_adopt(node);
+    if (code != LXB_DOM_EXCEPTION_OK) {
+        return code;
+    }
+
+    if (child == NULL) {
+        lxb_dom_node_insert_child(parent, node);
+    }
+    else {
+        lxb_dom_node_insert_before(child, node);
+    }
+
+    return LXB_DOM_EXCEPTION_OK;
+}
+
+lxb_dom_exception_code_t
+lxb_dom_node_insert(lxb_dom_node_t *parent, lxb_dom_node_t *node,
+                    lxb_dom_node_t *child, bool suppress_observers)
+{
+    lxb_dom_node_t *tmp, *next;
+    lxb_dom_exception_code_t code;
+
+    if (node->type == LXB_DOM_NODE_TYPE_DOCUMENT_FRAGMENT) {
+        if (node->first_child == NULL) {
+            return LXB_DOM_EXCEPTION_OK;
+        }
+    }
+
+    /* TODO: live range. */
+
+    if (node->type != LXB_DOM_NODE_TYPE_DOCUMENT_FRAGMENT) {
+        return lxb_dom_node_insert_node(parent, node, child,
+                                        suppress_observers);
+    }
+
+    tmp = node->first_child;
+
+    while (tmp != NULL) {
+        next = tmp->next;
+
+        code = lxb_dom_node_insert_node(parent, tmp, child,
+                                        suppress_observers);
+        if (code != LXB_DOM_EXCEPTION_OK) {
+            return code;
+        }
+
+        tmp = next;
+    }
+
+    /* TODO: Shadow and queue a tree mutation record. */
+
+    return LXB_DOM_EXCEPTION_OK;
+}
+
+lxb_dom_exception_code_t
+lxb_dom_node_insert_before_spec(lxb_dom_node_t *dst, lxb_dom_node_t *node,
+                                lxb_dom_node_t *child)
+{
+    return lxb_dom_node_pre_insert(dst, node, child);
+}
+
+lxb_dom_exception_code_t
+lxb_dom_node_append_child(lxb_dom_node_t *parent, lxb_dom_node_t *node)
+{
+    return lxb_dom_node_pre_insert(parent, node, NULL);
+}
+
+lxb_dom_exception_code_t
+lxb_dom_node_remove_child(lxb_dom_node_t *parent, lxb_dom_node_t *child)
+{
+    if (parent != child->parent) {
+        return LXB_DOM_EXCEPTION_NOT_FOUND_ERR;
+    }
+
+    return lxb_dom_node_remove_spec(child, false);
+}
+
+lxb_dom_exception_code_t
+lxb_dom_node_replace_child(lxb_dom_node_t *parent, lxb_dom_node_t *node,
+                           lxb_dom_node_t *child)
+{
+    lxb_dom_node_t *tmp, *next;
+    lxb_dom_node_t *before;
+    lxb_dom_exception_code_t code;
+
+    code = lxb_dom_node_pre_insert_validity(parent, node, child);
+    if (code != LXB_DOM_EXCEPTION_OK) {
+        return code;
+    }
+
+    before = child->prev;
+    if (before == NULL) {
+        before = child->next;
+    }
+
+    if (child->parent != NULL) {
+        code = lxb_dom_node_remove_spec(child, true);
+        if (code != LXB_DOM_EXCEPTION_OK) {
+            return code;
+        }
+    }
+
+    if (node->type != LXB_DOM_NODE_TYPE_DOCUMENT_FRAGMENT) {
+        return lxb_dom_node_insert_node(parent, node, before, true);
+    }
+
+    tmp = node->first_child;
+
+    while (tmp != NULL) {
+        next = tmp->next;
+
+        code = lxb_dom_node_insert_node(parent, tmp, before, true);
+        if (code != LXB_DOM_EXCEPTION_OK) {
+            return code;
+        }
+
+        tmp = next;
+    }
+
+    return LXB_DOM_EXCEPTION_OK;
+}
+
+lxb_dom_exception_code_t
+lxb_dom_node_replace_all_spec(lxb_dom_node_t *parent, lxb_dom_node_t *node)
+{
+    lxb_dom_node_t *child, *next;
+    lxb_dom_exception_code_t code;
+
+    child = parent->first_child;
+
+    while (child != NULL) {
+        next = child->next;
+
+        code = lxb_dom_node_remove_spec(child, true);
+        if (code != LXB_DOM_EXCEPTION_OK) {
+            return code;
+        }
+
+        child = next;
+    }
+
+    return lxb_dom_node_append_child(parent, node);
+}
+
+lxb_dom_exception_code_t
+lxb_dom_node_remove_spec(lxb_dom_node_t *node, bool suppress_observers)
+{
+    if (node->parent == NULL) {
+        return LXB_DOM_EXCEPTION_OK;
+    }
+
+    /* TODO: 3. Run the live range pre-remove steps, given node. */
+
+    /*
+     * TODO: For each NodeIterator object iterator whose root’s node document
+     * is node’s node document, run the NodeIterator pre-remove steps given
+     * node and iterator.
+     */
+
+    lxb_dom_node_remove(node);
+
+    /* TODO: finish everything else. */
+
+    return LXB_DOM_EXCEPTION_OK;
+}
+
 void
 lxb_dom_node_remove_wo_events(lxb_dom_node_t *node)
 {
@@ -617,6 +995,52 @@ lxb_dom_node_prepare_by(lxb_dom_document_t *document,
     return LXB_STATUS_OK;
 }

+lxb_dom_node_t *
+lxb_dom_node_by_id(lxb_dom_node_t *root,
+                   const lxb_char_t *qualified_name, size_t len)
+{
+    lxb_dom_node_id_cb_ctx_t ctx;
+
+    ctx.node = NULL;
+    ctx.value = qualified_name;
+    ctx.length = len;
+
+    lxb_dom_node_simple_walk(root, lxb_dom_node_by_id_cb, &ctx);
+
+    return ctx.node;
+}
+
+static lexbor_action_t
+lxb_dom_node_by_id_cb(lxb_dom_node_t *node, void *ctx)
+{
+    lxb_dom_node_id_cb_ctx_t *context;
+    const lxb_dom_attr_t *attr_id;
+
+    if (node->type != LXB_DOM_NODE_TYPE_ELEMENT) {
+        return LEXBOR_ACTION_OK;
+    }
+
+    context = ctx;
+    attr_id = lxb_dom_interface_element(node)->attr_id;
+
+    if (attr_id == NULL
+        || attr_id->value == NULL
+        || attr_id->value->length != context->length)
+    {
+        return LEXBOR_ACTION_OK;
+    }
+
+    const lxb_char_t *data = attr_id->value->data;
+    size_t length = attr_id->value->length;
+
+    if (lexbor_str_data_ncmp(context->value, data, length)) {
+        context->node = node;
+        return LEXBOR_ACTION_STOP;
+    }
+
+    return LEXBOR_ACTION_OK;
+}
+
 lxb_status_t
 lxb_dom_node_by_tag_name(lxb_dom_node_t *root,
                          lxb_dom_collection_t *collection,
@@ -1278,6 +1702,47 @@ lxb_dom_node_is_empty(const lxb_dom_node_t *root)
     return true;
 }

+bool
+lxb_dom_node_host_including_inclusive_ancestor(const lxb_dom_node_t *node,
+                                               const lxb_dom_node_t *parent)
+{
+    const lxb_dom_shadow_root_t *root;
+
+    while (parent != NULL) {
+        if (parent == node) {
+            return true;
+        }
+
+        if (parent->type == LXB_DOM_NODE_TYPE_SHADOW_ROOT) {
+            root = lxb_dom_interface_shadow_root(parent);
+            parent = &root->host->node;
+
+            continue;
+        }
+
+        parent = parent->parent;
+    }
+
+    return false;
+}
+
+lxb_dom_exception_code_t
+lxb_dom_node_adopt(lxb_dom_node_t *node)
+{
+    lxb_dom_exception_code_t code;
+
+    if (node->parent != NULL) {
+        code = lxb_dom_node_remove_spec(node, false);
+        if (code != LXB_DOM_EXCEPTION_OK) {
+            return code;
+        }
+    }
+
+    /* TODO: If document is not oldDocument steps. */
+
+    return LXB_DOM_EXCEPTION_OK;
+}
+
 lxb_tag_id_t
 lxb_dom_node_tag_id_noi(lxb_dom_node_t *node)
 {
@@ -1313,3 +1778,9 @@ lxb_dom_node_last_child_noi(lxb_dom_node_t *node)
 {
     return lxb_dom_node_last_child(node);
 }
+
+lxb_dom_node_type_t
+lxb_dom_node_type_noi(lxb_dom_node_t *node)
+{
+    return lxb_dom_node_type(node);
+}
diff --git a/ext/dom/lexbor/lexbor/dom/interfaces/node.h b/ext/dom/lexbor/lexbor/dom/interfaces/node.h
index b5d2c5069f0..b95373c5195 100644
--- a/ext/dom/lexbor/lexbor/dom/interfaces/node.h
+++ b/ext/dom/lexbor/lexbor/dom/interfaces/node.h
@@ -13,6 +13,7 @@ extern "C" {

 #include "lexbor/dom/interface.h"
 #include "lexbor/dom/collection.h"
+#include "lexbor/dom/exception.h"
 #include "lexbor/dom/interfaces/event_target.h"


@@ -59,7 +60,9 @@ typedef enum {
     LXB_DOM_NODE_TYPE_DOCUMENT_TYPE          = 0x0A,
     LXB_DOM_NODE_TYPE_DOCUMENT_FRAGMENT      = 0x0B,
     LXB_DOM_NODE_TYPE_NOTATION               = 0x0C, // historical
-    LXB_DOM_NODE_TYPE_LAST_ENTRY             = 0x0D
+    LXB_DOM_NODE_TYPE_CHARACTER_DATA,
+    LXB_DOM_NODE_TYPE_SHADOW_ROOT,
+    LXB_DOM_NODE_TYPE_LAST_ENTRY
 }
 lxb_dom_node_type_t;

@@ -135,12 +138,106 @@ lxb_dom_node_insert_after_wo_events(lxb_dom_node_t *to, lxb_dom_node_t *node);
 LXB_API void
 lxb_dom_node_insert_after(lxb_dom_node_t *to, lxb_dom_node_t *node);

+LXB_API lxb_dom_exception_code_t
+lxb_dom_node_pre_insert_validity(lxb_dom_node_t *parent, lxb_dom_node_t *node,
+                                 lxb_dom_node_t *child);
+
+LXB_API lxb_dom_exception_code_t
+lxb_dom_node_pre_insert(lxb_dom_node_t *parent, lxb_dom_node_t *node,
+                        lxb_dom_node_t *child);
+
+LXB_API lxb_dom_exception_code_t
+lxb_dom_node_insert(lxb_dom_node_t *parent, lxb_dom_node_t *node,
+                    lxb_dom_node_t *child, bool suppress_observers);
+
+/*
+ * Add a node as a child.
+ *
+ * Function according to specification. Node.appendChild(node).
+ *
+ * The function not only adds a node as a child, but also validates
+ * the possibility of adding it.
+ * For example, the lxb_dom_node_insert_child() function does not perform
+ * any validation.
+ *
+ * @param[in] lxb_dom_node_t *. Where to add. Not NULL.
+ * @param[in] lxb_dom_node_t *. Who to add. Not NULL.
+ *
+ * @return LXB_DOM_EXCEPTION_OK if successful, otherwise an error exception code.
+ */
+LXB_API lxb_dom_exception_code_t
+lxb_dom_node_append_child(lxb_dom_node_t *parent, lxb_dom_node_t *node);
+
+/*
+ * Insert before child.
+ *
+ * Function according to specification. Node.insertBefore(node, child).
+ *
+ * The function not only insert a node as a child, but also validates
+ * the possibility of adding it.
+ * For example, the lxb_dom_node_insert_before() function does not perform
+ * any validation.
+ *
+ * @param[in] lxb_dom_node_t *. Where to add. Not NULL.
+ * @param[in] lxb_dom_node_t *. Who to add. Not NULL.
+ * @param[in] lxb_dom_node_t *. The child before need to insert. Not NULL.
+ *
+ * @return LXB_DOM_EXCEPTION_OK if successful, otherwise an error exception code.
+ */
+LXB_API lxb_dom_exception_code_t
+lxb_dom_node_insert_before_spec(lxb_dom_node_t *dst, lxb_dom_node_t *node,
+                                lxb_dom_node_t *child);
+
+LXB_API lxb_dom_exception_code_t
+lxb_dom_node_remove_spec(lxb_dom_node_t *node, bool suppress_observers);
+
 LXB_API void
 lxb_dom_node_remove_wo_events(lxb_dom_node_t *node);

 LXB_API void
 lxb_dom_node_remove(lxb_dom_node_t *node);

+/*
+ * Removing a node.
+ *
+ * Function according to specification. Node.removeChild(node).
+ *
+ * The function not only removing a node, but also validates the possibility
+ * of adding it.
+ * For example, the lxb_dom_node_remove() function does not perform
+ * any validation.
+ *
+ * @param[in] lxb_dom_node_t *. Where remove. Not NULL.
+ * @param[in] lxb_dom_node_t *. Who remove. Not NULL.
+ *
+ * @return LXB_DOM_EXCEPTION_OK if successful, otherwise an error exception code.
+ */
+LXB_API lxb_dom_exception_code_t
+lxb_dom_node_remove_child(lxb_dom_node_t *parent, lxb_dom_node_t *child);
+
+/*
+ * The function replaces the child with a node.
+ *
+ * Function according to specification. Node.replaceChild(node, child).
+ *
+ * The function not only replace a node, but also validates the possibility
+ * of adding it.
+ * For example, the lxb_dom_node_replace_all() function does not perform
+ * any validation.
+ *
+ * @param[in] lxb_dom_node_t *. Where replace. Not NULL.
+ * @param[in] lxb_dom_node_t *. Who replace. Not NULL.
+ * @param[in] lxb_dom_node_t *. Replaceable child. Not NULL.
+ *
+ * @return LXB_DOM_EXCEPTION_OK if successful, otherwise an error exception code.
+ */
+LXB_API lxb_dom_exception_code_t
+lxb_dom_node_replace_child(lxb_dom_node_t *parent, lxb_dom_node_t *node,
+                           lxb_dom_node_t *child);
+
+LXB_API lxb_dom_exception_code_t
+lxb_dom_node_replace_all_spec(lxb_dom_node_t *parent, lxb_dom_node_t *node);
+
 LXB_API lxb_status_t
 lxb_dom_node_replace_all(lxb_dom_node_t *parent, lxb_dom_node_t *node);

@@ -148,6 +245,10 @@ LXB_API void
 lxb_dom_node_simple_walk(lxb_dom_node_t *root,
                          lxb_dom_node_simple_walker_f walker_cb, void *ctx);

+LXB_API lxb_dom_node_t *
+lxb_dom_node_by_id(lxb_dom_node_t *root,
+                   const lxb_char_t *qualified_name, size_t len);
+
 LXB_API lxb_status_t
 lxb_dom_node_by_tag_name(lxb_dom_node_t *root, lxb_dom_collection_t *collection,
                          const lxb_char_t *qualified_name, size_t len);
@@ -193,6 +294,12 @@ lxb_dom_node_text_content_set(lxb_dom_node_t *node,
 LXB_API bool
 lxb_dom_node_is_empty(const lxb_dom_node_t *root);

+LXB_API bool
+lxb_dom_node_host_including_inclusive_ancestor(const lxb_dom_node_t *node,
+                                               const lxb_dom_node_t *parent);
+
+LXB_API lxb_dom_exception_code_t
+lxb_dom_node_adopt(lxb_dom_node_t *node);

 /*
  * Inline functions
@@ -233,6 +340,12 @@ lxb_dom_node_last_child(lxb_dom_node_t *node)
     return node->last_child;
 }

+lxb_inline lxb_dom_node_type_t
+lxb_dom_node_type(lxb_dom_node_t *node)
+{
+    return node->type;
+}
+
 /*
  * No inline functions for ABI.
  */
@@ -254,6 +367,9 @@ lxb_dom_node_first_child_noi(lxb_dom_node_t *node);
 LXB_API lxb_dom_node_t *
 lxb_dom_node_last_child_noi(lxb_dom_node_t *node);

+LXB_API lxb_dom_node_type_t
+lxb_dom_node_type_noi(lxb_dom_node_t *node);
+

 #ifdef __cplusplus
 } /* extern "C" */
diff --git a/ext/dom/lexbor/lexbor/dom/interfaces/shadow_root.c b/ext/dom/lexbor/lexbor/dom/interfaces/shadow_root.c
index a7145bcec0d..e2c332d58b2 100644
--- a/ext/dom/lexbor/lexbor/dom/interfaces/shadow_root.c
+++ b/ext/dom/lexbor/lexbor/dom/interfaces/shadow_root.c
@@ -22,7 +22,7 @@ lxb_dom_shadow_root_interface_create(lxb_dom_document_t *document)
     lxb_dom_node_t *node = lxb_dom_interface_node(element);

     node->owner_document = lxb_dom_document_owner(document);
-    node->type = LXB_DOM_NODE_TYPE_UNDEF;
+    node->type = LXB_DOM_NODE_TYPE_SHADOW_ROOT;

     return element;
 }
diff --git a/ext/dom/lexbor/lexbor/encoding/base.h b/ext/dom/lexbor/lexbor/encoding/base.h
index 88d74cc9bf8..459287df383 100644
--- a/ext/dom/lexbor/lexbor/encoding/base.h
+++ b/ext/dom/lexbor/lexbor/encoding/base.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019-2024 Alexander Borisov
+ * Copyright (C) 2019-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -16,7 +16,7 @@ extern "C" {


 #define LXB_ENCODING_VERSION_MAJOR 2
-#define LXB_ENCODING_VERSION_MINOR 2
+#define LXB_ENCODING_VERSION_MINOR 3
 #define LXB_ENCODING_VERSION_PATCH 0

 #define LXB_ENCODING_VERSION_STRING                                            \
diff --git a/ext/dom/lexbor/lexbor/encoding/encode.c b/ext/dom/lexbor/lexbor/encoding/encode.c
index 4377fb31f58..f9a4f9f8eff 100644
--- a/ext/dom/lexbor/lexbor/encoding/encode.c
+++ b/ext/dom/lexbor/lexbor/encoding/encode.c
@@ -111,6 +111,122 @@
     return 1


+lxb_inline uint16_t
+lxb_encoding_multi_big5_index(lxb_codepoint_t cp)
+{
+    if (cp > 0x2F8A7) {
+        return UINT16_MAX;
+    }
+
+    if (cp < 65518) {
+        if (cp >= 167 && cp < 1106) {
+            return lxb_encoding_multi_big5_167_1106_map[cp - 167];
+        }
+        else if (cp >= 8211) {
+            if (cp < 40882) {
+                return lxb_encoding_multi_big5_8211_40882_map[cp - 8211];
+            }
+            else if (cp >= 64012) {
+                return lxb_encoding_multi_big5_64012_65518_map[cp - 64012];
+            }
+        }
+    }
+    else if (cp >= 131210) {
+        if (cp < 172369) {
+            return lxb_encoding_multi_big5_131210_172369_map[cp - 131210];
+        }
+        else if (cp >= 194708) {
+            if (cp < 194727) {
+                return lxb_encoding_multi_big5_194708_194727_map[cp - 194708];
+            }
+        }
+    }
+
+    return UINT16_MAX;
+}
+
+lxb_inline uint16_t
+lxb_encoding_multi_euc_kr_index(lxb_codepoint_t cp)
+{
+    if (cp > 0xFFE7) {
+        return UINT16_MAX;
+    }
+
+    if (cp < 13278) {
+        if (cp >= 161 && cp < 1106) {
+            return lxb_encoding_multi_euc_kr_161_1106_map[cp - 161];
+        }
+        else if (cp >= 8213) {
+            return lxb_encoding_multi_euc_kr_8213_13278_map[cp - 8213];
+        }
+    }
+    else if (cp >= 19968) {
+        if (cp < 55204) {
+            return lxb_encoding_multi_euc_kr_19968_55204_map[cp - 19968];
+        }
+        else if (cp >= 63744) {
+            if (cp < 65511) {
+                return lxb_encoding_multi_euc_kr_63744_65511_map[cp - 63744];
+            }
+        }
+    }
+
+    return UINT16_MAX;
+}
+
+lxb_inline uint16_t
+lxb_encoding_multi_gb18030_index(lxb_codepoint_t cp)
+{
+    if (cp > 0xFFE6) {
+        return UINT16_MAX;
+    }
+
+    if (cp < 40892) {
+        if (cp >= 164 && cp < 1106) {
+            return lxb_encoding_multi_gb18030_164_1106_map[cp - 164];
+        }
+        else if (cp >= 7743) {
+            return lxb_encoding_multi_gb18030_7743_40892_map[cp - 7743];
+        }
+    }
+    else if (cp >= 57344) {
+        if (cp < 65510) {
+            return lxb_encoding_multi_gb18030_57344_65510_map[cp - 57344];
+        }
+    }
+
+    return UINT16_MAX;
+}
+
+lxb_inline uint16_t
+lxb_encoding_multi_jis0208_index(lxb_codepoint_t cp)
+{
+    if (cp > 0xFFE6) {
+        return UINT16_MAX;
+    }
+
+    if (cp < 13262) {
+        if (cp >= 167 && cp < 1106) {
+            return lxb_encoding_multi_jis0208_167_1106_map[cp - 167];
+        }
+        else if (cp >= 8208) {
+            return lxb_encoding_multi_jis0208_8208_13262_map[cp - 8208];
+        }
+    }
+    else if (cp >= 19968) {
+        if (cp < 40865) {
+            return lxb_encoding_multi_jis0208_19968_40865_map[cp - 19968];
+        }
+        else if (cp >= 63785) {
+            if (cp < 65510) {
+                return lxb_encoding_multi_jis0208_63785_65510_map[cp - 63785];
+            }
+        }
+    }
+
+    return UINT16_MAX;
+}
+
 lxb_status_t
 lxb_encoding_encode_default(lxb_encoding_encode_t *ctx, const lxb_codepoint_t **cps,
                             const lxb_codepoint_t *end)
@@ -327,10 +443,10 @@ lxb_encoding_encode_iso_2022_jp(lxb_encoding_encode_t *ctx, const lxb_codepoint_
     unsigned state;
     lxb_codepoint_t cp;

-    size = 0;
     state = ctx->state;

     for (; *cps < end; (*cps)++) {
+        size = 0;
         cp = **cps;

     begin:
diff --git a/ext/dom/lexbor/lexbor/encoding/encoding.c b/ext/dom/lexbor/lexbor/encoding/encoding.c
index 19d3a147468..2a43f0fd70a 100644
--- a/ext/dom/lexbor/lexbor/encoding/encoding.c
+++ b/ext/dom/lexbor/lexbor/encoding/encoding.c
@@ -55,6 +55,74 @@ lxb_encoding_data_by_pre_name(const lxb_char_t *name, size_t length)
     return entry->value;
 }

+lxb_encoding_t
+lxb_encoding_prescan_validate(const lxb_char_t *name, size_t length)
+{
+    const lxb_encoding_data_t *data;
+
+    data = lxb_encoding_data_by_pre_name(name, length);
+    if (data == NULL) {
+        return LXB_ENCODING_DEFAULT;
+    }
+
+    if (data->encoding == LXB_ENCODING_UTF_16BE
+        || data->encoding == LXB_ENCODING_UTF_16LE)
+    {
+        return LXB_ENCODING_UTF_8;
+    }
+
+    if (data->encoding == LXB_ENCODING_X_USER_DEFINED) {
+        return LXB_ENCODING_WINDOWS_1252;
+    }
+
+    return data->encoding;
+}
+
+const lxb_encoding_data_t *
+lxb_encoding_data_prescan_validate(const lxb_char_t *name, size_t length)
+{
+    const lxb_encoding_data_t *data;
+
+    data = lxb_encoding_data_by_pre_name(name, length);
+    if (data == NULL) {
+        return NULL;
+    }
+
+    if (data->encoding == LXB_ENCODING_UTF_16BE
+        || data->encoding == LXB_ENCODING_UTF_16LE)
+    {
+        return lxb_encoding_data(LXB_ENCODING_UTF_8);
+    }
+
+    if (data->encoding == LXB_ENCODING_X_USER_DEFINED) {
+        return lxb_encoding_data(LXB_ENCODING_WINDOWS_1252);
+    }
+
+    return data;
+}
+
+lxb_encoding_t
+lxb_encoding_bom_sniff(const lxb_char_t *begin, size_t length)
+{
+    if (length >= 3) {
+        if (begin[0] == 0xEF && begin[1] == 0xBB && begin[2] == 0xBF) {
+            return LXB_ENCODING_UTF_8;
+        }
+    }
+
+    if (length >= 2) {
+        if (begin[0] == 0xFE && begin[1] == 0xFF) {
+            return LXB_ENCODING_UTF_16BE;
+        }
+
+        if (begin[0] == 0xFF && begin[1] == 0xFE) {
+            return LXB_ENCODING_UTF_16LE;
+        }
+    }
+
+    return LXB_ENCODING_DEFAULT;
+}
+
 void
 lxb_encoding_utf_8_skip_bom(const lxb_char_t **begin, size_t *length)
 {
@@ -100,6 +168,54 @@ lxb_encoding_utf_16le_skip_bom(const lxb_char_t **begin, size_t *length)
     }
 }

+const lxb_encoding_data_t *
+lxb_encoding_data_by_name(const lxb_char_t *name, size_t length)
+{
+    const lexbor_shs_entry_t *entry;
+
+    if (length == 0) {
+        return NULL;
+    }
+
+    entry = lexbor_shs_entry_get_lower_static(lxb_encoding_res_shs_entities,
+                                              name, length);
+    if (entry == NULL) {
+        return NULL;
+    }
+
+    return (const lxb_encoding_data_t *) entry->value;
+}
+
+const lxb_encoding_data_t *
+lxb_encoding_data(lxb_encoding_t encoding)
+{
+    if (encoding >= LXB_ENCODING_LAST_ENTRY) {
+        return NULL;
+    }
+
+    return &lxb_encoding_res_map[encoding];
+}
+
+lxb_encoding_encode_f
+lxb_encoding_encode_function(lxb_encoding_t encoding)
+{
+    if (encoding >= LXB_ENCODING_LAST_ENTRY) {
+        return NULL;
+    }
+
+    return lxb_encoding_res_map[encoding].encode;
+}
+
+lxb_encoding_decode_f
+lxb_encoding_decode_function(lxb_encoding_t encoding)
+{
+    if (encoding >= LXB_ENCODING_LAST_ENTRY) {
+        return NULL;
+    }
+
+    return lxb_encoding_res_map[encoding].decode;
+}
+
 /*
  * No inline functions for ABI.
  */
diff --git a/ext/dom/lexbor/lexbor/encoding/encoding.h b/ext/dom/lexbor/lexbor/encoding/encoding.h
index 7bda3ba5f56..7e08a368799 100644
--- a/ext/dom/lexbor/lexbor/encoding/encoding.h
+++ b/ext/dom/lexbor/lexbor/encoding/encoding.h
@@ -27,9 +27,18 @@ extern "C" {
 LXB_API const lxb_encoding_data_t *
 lxb_encoding_data_by_pre_name(const lxb_char_t *name, size_t length);

+LXB_API lxb_encoding_t
+lxb_encoding_prescan_validate(const lxb_char_t *name, size_t length);
+
+LXB_API const lxb_encoding_data_t *
+lxb_encoding_data_prescan_validate(const lxb_char_t *name, size_t length);
+
 /*
  * To skip BOM.
  */
+LXB_API lxb_encoding_t
+lxb_encoding_bom_sniff(const lxb_char_t *begin, size_t length);
+
 LXB_API void
 lxb_encoding_utf_8_skip_bom(const lxb_char_t **begin, size_t *length);

@@ -39,6 +48,20 @@ lxb_encoding_utf_16be_skip_bom(const lxb_char_t **begin, size_t *length);
 LXB_API void
 lxb_encoding_utf_16le_skip_bom(const lxb_char_t **begin, size_t *length);

+/*
+ * Encoding data.
+ */
+LXB_API const lxb_encoding_data_t *
+lxb_encoding_data_by_name(const lxb_char_t *name, size_t length);
+
+LXB_API const lxb_encoding_data_t *
+lxb_encoding_data(lxb_encoding_t encoding);
+
+LXB_API lxb_encoding_encode_f
+lxb_encoding_encode_function(lxb_encoding_t encoding);
+
+LXB_API lxb_encoding_decode_f
+lxb_encoding_decode_function(lxb_encoding_t encoding);

 /*
  * Inline functions
@@ -305,54 +328,6 @@ lxb_encoding_decode_finish_single(lxb_encoding_decode_t *decode)
 /*
  * Encoding data.
  */
-lxb_inline const lxb_encoding_data_t *
-lxb_encoding_data_by_name(const lxb_char_t *name, size_t length)
-{
-    const lexbor_shs_entry_t *entry;
-
-    if (length == 0) {
-        return NULL;
-    }
-
-    entry = lexbor_shs_entry_get_lower_static(lxb_encoding_res_shs_entities,
-                                              name, length);
-    if (entry == NULL) {
-        return NULL;
-    }
-
-    return (const lxb_encoding_data_t *) entry->value;
-}
-
-lxb_inline const lxb_encoding_data_t *
-lxb_encoding_data(lxb_encoding_t encoding)
-{
-    if (encoding >= LXB_ENCODING_LAST_ENTRY) {
-        return NULL;
-    }
-
-    return &lxb_encoding_res_map[encoding];
-}
-
-lxb_inline lxb_encoding_encode_f
-lxb_encoding_encode_function(lxb_encoding_t encoding)
-{
-    if (encoding >= LXB_ENCODING_LAST_ENTRY) {
-        return NULL;
-    }
-
-    return lxb_encoding_res_map[encoding].encode;
-}
-
-lxb_inline lxb_encoding_decode_f
-lxb_encoding_decode_function(lxb_encoding_t encoding)
-{
-    if (encoding >= LXB_ENCODING_LAST_ENTRY) {
-        return NULL;
-    }
-
-    return lxb_encoding_res_map[encoding].decode;
-}
-
 lxb_inline lxb_status_t
 lxb_encoding_data_call_encode(lxb_encoding_data_t *encoding_data, lxb_encoding_encode_t *ctx,
                               const lxb_codepoint_t **cp, const lxb_codepoint_t *end)
diff --git a/ext/dom/lexbor/lexbor/encoding/multi.c b/ext/dom/lexbor/lexbor/encoding/multi.c
index 78cd93ea82b..2651648c5c9 100644
--- a/ext/dom/lexbor/lexbor/encoding/multi.c
+++ b/ext/dom/lexbor/lexbor/encoding/multi.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2024 Alexander Borisov
+ * Copyright (C) 2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
diff --git a/ext/dom/lexbor/lexbor/encoding/multi.h b/ext/dom/lexbor/lexbor/encoding/multi.h
index 4e6da7b4728..a4c5def5ba6 100644
--- a/ext/dom/lexbor/lexbor/encoding/multi.h
+++ b/ext/dom/lexbor/lexbor/encoding/multi.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2024 Alexander Borisov
+ * Copyright (C) 2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -19,7 +19,7 @@ extern "C" {

 #include "lexbor/encoding/base.h"

-
+#ifndef LEXBOR_DISABLE_INTERNAL_EXTERN
 LXB_EXTERN lxb_codepoint_t lxb_encoding_multi_big5_map[19782];
 LXB_EXTERN lxb_codepoint_t lxb_encoding_multi_euc_kr_map[23750];
 LXB_EXTERN lxb_codepoint_t lxb_encoding_multi_gb18030_map[23940];
@@ -53,161 +53,7 @@ LXB_EXTERN uint16_t lxb_encoding_multi_jis0208_167_1106_map[939];
 LXB_EXTERN uint16_t lxb_encoding_multi_jis0208_8208_13262_map[5054];
 LXB_EXTERN uint16_t lxb_encoding_multi_jis0208_19968_40865_map[20897];
 LXB_EXTERN uint16_t lxb_encoding_multi_jis0208_63785_65510_map[1725];
-
-lxb_inline uint16_t
-lxb_encoding_multi_big5_index(lxb_codepoint_t cp)
-{
-    if (cp > 0x2F8A7) {
-        return UINT16_MAX;
-    }
-
-    if (cp < 65518) {
-        if (cp >= 167 && cp < 1106) {
-            return lxb_encoding_multi_big5_167_1106_map[cp - 167];
-        }
-        else if (cp >= 8211) {
-            if (cp < 40882) {
-                return lxb_encoding_multi_big5_8211_40882_map[cp - 8211];
-            }
-            else if (cp >= 64012) {
-                return lxb_encoding_multi_big5_64012_65518_map[cp - 64012];
-            }
-        }
-    }
-    else if (cp >= 131210) {
-        if (cp < 172369) {
-            return lxb_encoding_multi_big5_131210_172369_map[cp - 131210];
-        }
-        else if (cp >= 194708) {
-            if (cp < 194727) {
-                return lxb_encoding_multi_big5_194708_194727_map[cp - 194708];
-            }
-        }
-    }
-
-    return UINT16_MAX;
-}
-
-lxb_inline uint16_t
-lxb_encoding_multi_euc_kr_index(lxb_codepoint_t cp)
-{
-    if (cp > 0xFFE7) {
-        return UINT16_MAX;
-    }
-
-    if (cp < 13278) {
-        if (cp >= 161 && cp < 1106) {
-            return lxb_encoding_multi_euc_kr_161_1106_map[cp - 161];
-        }
-        else if (cp >= 8213) {
-            return lxb_encoding_multi_euc_kr_8213_13278_map[cp - 8213];
-        }
-    }
-    else if (cp >= 19968) {
-        if (cp < 55204) {
-            return lxb_encoding_multi_euc_kr_19968_55204_map[cp - 19968];
-        }
-        else if (cp >= 63744) {
-            if (cp < 65511) {
-                return lxb_encoding_multi_euc_kr_63744_65511_map[cp - 63744];
-            }
-        }
-    }
-
-    return UINT16_MAX;
-}
-
-lxb_inline uint16_t
-lxb_encoding_multi_gb18030_index(lxb_codepoint_t cp)
-{
-    if (cp > 0xFFE6) {
-        return UINT16_MAX;
-    }
-
-    if (cp < 40892) {
-        if (cp >= 164 && cp < 1106) {
-            return lxb_encoding_multi_gb18030_164_1106_map[cp - 164];
-        }
-        else if (cp >= 7743) {
-            return lxb_encoding_multi_gb18030_7743_40892_map[cp - 7743];
-        }
-    }
-    else if (cp >= 57344) {
-        if (cp < 65510) {
-            return lxb_encoding_multi_gb18030_57344_65510_map[cp - 57344];
-        }
-    }
-
-    return UINT16_MAX;
-}
-
-lxb_inline uint16_t
-lxb_encoding_multi_iso_2022_jp_katakana_index(lxb_codepoint_t cp)
-{
-    if (cp >= 12289 && cp < 12541) {
-        return lxb_encoding_multi_iso_2022_jp_katakana_12289_12541_map[cp - 12289];
-    }
-
-    return UINT16_MAX;
-}
-
-lxb_inline uint16_t
-lxb_encoding_multi_jis0212_index(lxb_codepoint_t cp)
-{
-    if (cp > 0xFF5F) {
-        return UINT16_MAX;
-    }
-
-    if (cp < 8483) {
-        if (cp >= 161 && cp < 1120) {
-            return lxb_encoding_multi_jis0212_161_1120_map[cp - 161];
-        }
-        else if (cp >= 8470) {
-            return lxb_encoding_multi_jis0212_8470_8483_map[cp - 8470];
-        }
-    }
-    else if (cp >= 19970) {
-        if (cp < 40870) {
-            return lxb_encoding_multi_jis0212_19970_40870_map[cp - 19970];
-        }
-        else if (cp >= 65374) {
-            if (cp < 65375) {
-                return lxb_encoding_multi_jis0212_65374_65375_map[cp - 65374];
-            }
-        }
-    }
-
-    return UINT16_MAX;
-}
-
-lxb_inline uint16_t
-lxb_encoding_multi_jis0208_index(lxb_codepoint_t cp)
-{
-    if (cp > 0xFFE6) {
-        return UINT16_MAX;
-    }
-
-    if (cp < 13262) {
-        if (cp >= 167 && cp < 1106) {
-            return lxb_encoding_multi_jis0208_167_1106_map[cp - 167];
-        }
-        else if (cp >= 8208) {
-            return lxb_encoding_multi_jis0208_8208_13262_map[cp - 8208];
-        }
-    }
-    else if (cp >= 19968) {
-        if (cp < 40865) {
-            return lxb_encoding_multi_jis0208_19968_40865_map[cp - 19968];
-        }
-        else if (cp >= 63785) {
-            if (cp < 65510) {
-                return lxb_encoding_multi_jis0208_63785_65510_map[cp - 63785];
-            }
-        }
-    }
-
-    return UINT16_MAX;
-}
+#endif /* !LEXBOR_DISABLE_INTERNAL_EXTERN */


 #ifdef __cplusplus
diff --git a/ext/dom/lexbor/lexbor/encoding/range.h b/ext/dom/lexbor/lexbor/encoding/range.h
index 18b33103442..ed9833d1cce 100644
--- a/ext/dom/lexbor/lexbor/encoding/range.h
+++ b/ext/dom/lexbor/lexbor/encoding/range.h
@@ -23,8 +23,9 @@ extern "C" {

 #define LXB_ENCODING_RANGE_INDEX_GB18030_SIZE 207

-
+#ifndef LEXBOR_DISABLE_INTERNAL_EXTERN
 LXB_EXTERN const lxb_encoding_range_index_t lxb_encoding_range_index_gb18030[207];
+#endif /* !LEXBOR_DISABLE_INTERNAL_EXTERN */


 #ifdef __cplusplus
diff --git a/ext/dom/lexbor/lexbor/encoding/res.h b/ext/dom/lexbor/lexbor/encoding/res.h
index 46a9f91ae9a..25334ebd27c 100644
--- a/ext/dom/lexbor/lexbor/encoding/res.h
+++ b/ext/dom/lexbor/lexbor/encoding/res.h
@@ -22,10 +22,10 @@ extern "C" {
 #include "lexbor/encoding/base.h"
 #include "lexbor/core/shs.h"

-
+#ifndef LEXBOR_DISABLE_INTERNAL_EXTERN
 LXB_EXTERN const lxb_encoding_data_t lxb_encoding_res_map[LXB_ENCODING_LAST_ENTRY];
 LXB_EXTERN const lexbor_shs_entry_t lxb_encoding_res_shs_entities[220];
-
+#endif /* !LEXBOR_DISABLE_INTERNAL_EXTERN */

 #ifdef __cplusplus
 } /* extern "C" */
diff --git a/ext/dom/lexbor/lexbor/encoding/single.h b/ext/dom/lexbor/lexbor/encoding/single.h
index 906279bf33e..c2a4271ac90 100644
--- a/ext/dom/lexbor/lexbor/encoding/single.h
+++ b/ext/dom/lexbor/lexbor/encoding/single.h
@@ -51,7 +51,7 @@ extern "C" {
 #define LXB_ENCODING_SINGLE_HASH_WINDOWS_874_SIZE 359
 #define LXB_ENCODING_SINGLE_HASH_X_MAC_CYRILLIC_SIZE 373

-
+#ifndef LEXBOR_DISABLE_INTERNAL_EXTERN
 LXB_EXTERN const lxb_encoding_single_index_t lxb_encoding_single_index_ibm866[128];
 LXB_EXTERN const lxb_encoding_single_index_t lxb_encoding_single_index_iso_8859_10[128];
 LXB_EXTERN const lxb_encoding_single_index_t lxb_encoding_single_index_iso_8859_13[128];
@@ -107,6 +107,7 @@ LXB_EXTERN const lexbor_shs_hash_t lxb_encoding_single_hash_windows_1257[356];
 LXB_EXTERN const lexbor_shs_hash_t lxb_encoding_single_hash_windows_1258[406];
 LXB_EXTERN const lexbor_shs_hash_t lxb_encoding_single_hash_windows_874[360];
 LXB_EXTERN const lexbor_shs_hash_t lxb_encoding_single_hash_x_mac_cyrillic[374];
+#endif /* !LEXBOR_DISABLE_INTERNAL_EXTERN */


 #ifdef __cplusplus
diff --git a/ext/dom/lexbor/lexbor/html/base.h b/ext/dom/lexbor/lexbor/html/base.h
index a701dc35c68..570222c6de5 100644
--- a/ext/dom/lexbor/lexbor/html/base.h
+++ b/ext/dom/lexbor/lexbor/html/base.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018-2024 Alexander Borisov
+ * Copyright (C) 2018-2025 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -15,7 +15,7 @@ extern "C" {


 #define LXB_HTML_VERSION_MAJOR 2
-#define LXB_HTML_VERSION_MINOR 6
+#define LXB_HTML_VERSION_MINOR 8
 #define LXB_HTML_VERSION_PATCH 0

 #define LXB_HTML_VERSION_STRING LEXBOR_STRINGIZE(LXB_HTML_VERSION_MAJOR) "."   \
diff --git a/ext/dom/lexbor/lexbor/html/encoding.c b/ext/dom/lexbor/lexbor/html/encoding.c
index 5368400dab8..857661246b5 100644
--- a/ext/dom/lexbor/lexbor/html/encoding.c
+++ b/ext/dom/lexbor/lexbor/html/encoding.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 Alexander Borisov
+ * Copyright (C) 2019-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -9,6 +9,31 @@
 #include "lexbor/core/str.h"


+typedef struct {
+    lexbor_str_t alias;
+    lexbor_str_t name;
+}
+lxb_html_encoding_name_t;
+
+static const lxb_html_encoding_name_t lxb_html_encoding_names[] = {
+    /* UTF-16BE */
+    { lexbor_str("unicodefffe"),     lexbor_str("UTF-8") },
+    { lexbor_str("utf-16be"),        lexbor_str("UTF-8") },
+
+    /* UTF-16LE */
+    { lexbor_str("csunicode"),       lexbor_str("UTF-8") },
+    { lexbor_str("iso-10646-ucs-2"), lexbor_str("UTF-8") },
+    { lexbor_str("ucs-2"),           lexbor_str("UTF-8") },
+    { lexbor_str("unicode"),         lexbor_str("UTF-8") },
+    { lexbor_str("unicodefeff"),     lexbor_str("UTF-8") },
+    { lexbor_str("utf-16"),          lexbor_str("UTF-8") },
+    { lexbor_str("utf-16le"),        lexbor_str("UTF-8") },
+
+    /* x-user-defined */
+    { lexbor_str("x-user-defined"),  lexbor_str("windows-1252") }
+};
+
+
 static const lxb_char_t *
 lxb_html_encoding_meta(lxb_html_encoding_t *em,
                        const lxb_char_t *data, const lxb_char_t *end);
@@ -99,6 +124,73 @@ lxb_html_encoding_destroy(lxb_html_encoding_t *em, bool self_destroy)
     return em;
 }

+const lxb_char_t *
+lxb_html_encoding_prescan(lxb_html_encoding_t *em, const lxb_char_t *data,
+                          const lxb_char_t *end, size_t *out_length)
+{
+    size_t len, length;
+    lxb_status_t status;
+    lxb_html_encoding_entry_t *entry;
+    const lxb_html_encoding_name_t *name;
+
+    static const lexbor_str_t lxb_html_encoding_utf_16le = lexbor_str("UTF-16LE");
+    static const lexbor_str_t lxb_html_encoding_utf_16be = lexbor_str("UTF-16BE");
+
+    len = end - data;
+
+    /* Prescan for UTF-16 XML declarations: If position points to. */
+    if (len >= 6) {
+        if (data[0] == 0x3C && data[1] == 0x00 && data[2] == 0x3F
+            && data[3] == 0x00 && data[4] == 0x78 && data[5] == 0x00)
+        {
+            *out_length = lxb_html_encoding_utf_16le.length;
+            return lxb_html_encoding_utf_16le.data;
+        }
+
+        if (data[0] == 0x00 && data[1] == 0x3C && data[2] == 0x00
+            && data[3] == 0x3F && data[4] == 0x00 && data[5] == 0x78)
+        {
+            *out_length = lxb_html_encoding_utf_16be.length;
+            return lxb_html_encoding_utf_16be.data;
+        }
+    }
+
+    status = lxb_html_encoding_determine(em, data, end);
+    if (status != LXB_STATUS_OK) {
+        goto EMPTY;
+    }
+
+    if (lxb_html_encoding_meta_length(em) == 0) {
+        goto EMPTY;
+    }
+
+    entry = lxb_html_encoding_meta_entry(em, 0);
+    len = entry->end - entry->name;
+    length = sizeof(lxb_html_encoding_names) / sizeof(lxb_html_encoding_name_t);
+
+    for (size_t i = 0; i < length; i++) {
+        name = &lxb_html_encoding_names[i];
+
+        if (len == name->alias.length
+            && lexbor_str_data_ncasecmp(entry->name, name->alias.data,
+                                        name->alias.length))
+        {
+            *out_length = lxb_html_encoding_names[i].name.length;
+            return lxb_html_encoding_names[i].name.data;
+        }
+    }
+
+    *out_length = entry->end - entry->name;
+
+    return entry->name;
+
+EMPTY:
+
+    *out_length = 0;
+
+    return NULL;
+}
+
 lxb_status_t
 lxb_html_encoding_determine(lxb_html_encoding_t *em,
                             const lxb_char_t *data, const lxb_char_t *end)
@@ -381,12 +473,12 @@ lxb_html_encoding_content(const lxb_char_t *data, const lxb_char_t *end,

         for (; data < end; data++) {
             if (*data == **name_end) {
-                break;
+                *name_end = data;
+                goto done;
             }
         }

-        *name_end = data;
-        goto done;
+        return NULL;
     }

     name = data;
diff --git a/ext/dom/lexbor/lexbor/html/encoding.h b/ext/dom/lexbor/lexbor/html/encoding.h
index ec65778f715..ad5a6198f94 100644
--- a/ext/dom/lexbor/lexbor/html/encoding.h
+++ b/ext/dom/lexbor/lexbor/html/encoding.h
@@ -1,5 +1,14 @@
 /*
- * Copyright (C) 2019 Alexander Borisov
+ * Copyright (C) 2019-2026 Alexander Borisov
+ *
+ * Functions for detecting encoding in an HTML byte stream.
+ *
+ * The HTML parser accepts only UTF-8 input. The detected encoding can be used
+ * with the Encoding module to convert the original byte stream from its
+ * encoding to UTF-8 before passing it to the parser.
+ *
+ * By specification:
+ *     https://html.spec.whatwg.org/#determining-the-character-encoding
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -12,12 +21,13 @@ extern "C" {
 #endif

 #include "lexbor/html/base.h"
-
 #include "lexbor/core/array_obj.h"


 typedef struct {
+    /* Pointer to the beginning of the encoding name in the original data. */
     const lxb_char_t *name;
+    /* Pointer to the end of the encoding name in the original data. */
     const lxb_char_t *end;
 }
 lxb_html_encoding_entry_t;
@@ -29,17 +39,101 @@ typedef struct {
 lxb_html_encoding_t;


+/*
+ * Initialization of the lxb_html_encoding_t object.
+ *
+ * The object can be allocated on the stack or created using
+ * lxb_html_encoding_create() function.
+ *
+ * @param[in] lxb_html_encoding_t *
+ *
+ * @return LXB_STATUS_OK if successful, otherwise an error status value.
+ */
 LXB_API lxb_status_t
 lxb_html_encoding_init(lxb_html_encoding_t *em);

+/*
+ * Destruction of the lxb_html_encoding_t object.
+ *
+ * Releases internal resources of the object.
+ * If the object was created using lxb_html_encoding_create(), set self_destroy
+ * to true.
+ *
+ * @param[in] lxb_html_encoding_t *
+ * @param[in] If true, the object itself will be freed.
+ *
+ * @return NULL if self_destroy is true. Pointer to the object if false.
+ */
 LXB_API lxb_html_encoding_t *
 lxb_html_encoding_destroy(lxb_html_encoding_t *em, bool self_destroy);

+/*
+ * Prescan a byte stream to determine its encoding.
+ *
+ * By specification:
+ *     https://html.spec.whatwg.org/#prescan-a-byte-stream-to-determine-its-encoding
+ *
+ * Returns the validated encoding name if found, or NULL otherwise.
+ *
+ * Important:
+ * The returned pointer is not guaranteed to point into the input data stream.
+ * It may reference an internal static string (e.g. when the found encoding name
+ * is matched against a known alias). Do not assume the returned pointer lies
+ * within the [data, end) range.
+ *
+ * @param[in] lxb_html_encoding_t *. Not NULL.
+ * @param[in] Pointer to the beginning of the data. Not NULL.
+ * @param[in] Pointer to the end of the data. Not NULL.
+ * @param[out] Length of the returned encoding name. Not NULL.
+ *
+ * @return Pointer to the encoding name, or NULL if no encoding was found.
+ */
+LXB_API const lxb_char_t *
+lxb_html_encoding_prescan(lxb_html_encoding_t *em, const lxb_char_t *data,
+                          const lxb_char_t *end, size_t *out_length);

+/*
+ * Prescan a byte stream to determine its encoding.
+ *
+ * Implementation of the HTML specification algorithm for extracting encoding
+ * from <meta> tags. Scans raw HTML bytes looking for <meta charset="..."> and
+ * <meta http-equiv="content-type" content="...;charset=..."> declarations.
+ *
+ * Results can be retrieved using lxb_html_encoding_meta_entry() and
+ * lxb_html_encoding_meta_length() functions.
+ *
+ * Important:
+ * The HTML specification requires that if the determined charset is
+ * UTF-16BE/LE, it must be replaced with UTF-8, and if it is x-user-defined,
+ * it must be replaced with windows-1252. This function does not perform these
+ * replacements because it returns pointers to the original data (start and end
+ * of the found encoding name), which can be useful for developers. To get the
+ * validated encoding according to the specification, use the
+ * lxb_encoding_data_prescan_validate()/lxb_encoding_prescan_validate()
+ * functions from the Encoding module, or handle these cases manually.
+ *
+ * @param[in] lxb_html_encoding_t *. Not NULL.
+ * @param[in] Pointer to the beginning of the data. Not NULL.
+ * @param[in] Pointer to the end of the data. Not NULL.
+ *
+ * @return LXB_STATUS_OK if successful, otherwise an error status value.
+ */
 LXB_API lxb_status_t
 lxb_html_encoding_determine(lxb_html_encoding_t *em,
                             const lxb_char_t *data, const lxb_char_t *end);

+/*
+ * Extract encoding name from a Content-Type string.
+ *
+ * Parses the value of a content attribute looking for "charset=<encoding>"
+ * pattern. For example, from "text/html; charset=utf-8" extracts "utf-8".
+ *
+ * @param[in] Pointer to the beginning of the content string. Not NULL.
+ * @param[in] Pointer to the end of the content string. Not NULL.
+ * @param[out] Pointer to the end of the encoding name. Not NULL.
+ *
+ * @return Pointer to the beginning of the encoding name, or NULL if not found.
+ */
 LXB_API const lxb_char_t *
 lxb_html_encoding_content(const lxb_char_t *data, const lxb_char_t *end,
                           const lxb_char_t **name_end);
@@ -48,6 +142,14 @@ lxb_html_encoding_content(const lxb_char_t *data, const lxb_char_t *end,
 /*
  * Inline functions
  */
+
+/*
+ * Create an lxb_html_encoding_t object on the heap.
+ *
+ * The object must be initialized using lxb_html_encoding_init() after creation.
+ *
+ * @return Pointer to a new object, or NULL if memory allocation failed.
+ */
 lxb_inline lxb_html_encoding_t *
 lxb_html_encoding_create(void)
 {
@@ -55,6 +157,14 @@ lxb_html_encoding_create(void)
                                                  sizeof(lxb_html_encoding_t));
 }

+/*
+ * Clean the lxb_html_encoding_t object for reuse.
+ *
+ * Resets internal state so the object can be used for a new prescan without
+ * reallocation. Does not free memory.
+ *
+ * @param[in] lxb_html_encoding_t *. Not NULL.
+ */
 lxb_inline void
 lxb_html_encoding_clean(lxb_html_encoding_t *em)
 {
@@ -62,18 +172,45 @@ lxb_html_encoding_clean(lxb_html_encoding_t *em)
     lexbor_array_obj_clean(&em->result);
 }

+/*
+ * Get an encoding entry from the results by index.
+ *
+ * Returns a pointer to the lxb_html_encoding_entry_t which contains pointers
+ * to the beginning and end of the encoding name in the original data.
+ *
+ * @param[in] lxb_html_encoding_t *. Not NULL.
+ * @param[in] Index of the entry.
+ *
+ * @return Pointer to the entry, or NULL if the index is out of bounds.
+ */
 lxb_inline lxb_html_encoding_entry_t *
 lxb_html_encoding_meta_entry(lxb_html_encoding_t *em, size_t idx)
 {
     return (lxb_html_encoding_entry_t *) lexbor_array_obj_get(&em->result, idx);
 }

+/*
+ * Get the number of encoding entries found.
+ *
+ * @param[in] lxb_html_encoding_t *. Not NULL.
+ *
+ * @return Number of entries in the result.
+ */
 lxb_inline size_t
 lxb_html_encoding_meta_length(lxb_html_encoding_t *em)
 {
     return lexbor_array_obj_length(&em->result);
 }

+/*
+ * Get the result array object directly.
+ *
+ * Returns the internal array of lxb_html_encoding_entry_t entries.
+ *
+ * @param[in] lxb_html_encoding_t *. Not NULL.
+ *
+ * @return Pointer to the lexbor_array_obj_t with results.
+ */
 lxb_inline lexbor_array_obj_t *
 lxb_html_encoding_meta_result(lxb_html_encoding_t *em)
 {
diff --git a/ext/dom/lexbor/lexbor/html/interface.c b/ext/dom/lexbor/lexbor/html/interface.c
index 1e7156d92a4..1b2a57c813e 100644
--- a/ext/dom/lexbor/lexbor/html/interface.c
+++ b/ext/dom/lexbor/lexbor/html/interface.c
@@ -26,30 +26,33 @@ lxb_html_interface_create(lxb_html_document_t *document, lxb_tag_id_t tag_id,
                           lxb_ns_id_t ns)
 {
     lxb_dom_node_t *node;
+    lxb_dom_element_t *domel;
+    lxb_html_unknown_element_t *unel;

     if (tag_id >= LXB_TAG__LAST_ENTRY) {
         if (ns == LXB_NS_HTML) {
-            lxb_html_unknown_element_t *unel;
-
             unel = lxb_html_unknown_element_interface_create(document);
             node = lxb_dom_interface_node(unel);
         }
         else if (ns == LXB_NS_SVG) {
             /* TODO: For this need implement SVGElement */
-            lxb_dom_element_t *domel;

             domel = lxb_dom_element_interface_create(&document->dom_document);
             node = lxb_dom_interface_node(domel);
         }
         else {
-            lxb_dom_element_t *domel;
-
             domel = lxb_dom_element_interface_create(&document->dom_document);
             node = lxb_dom_interface_node(domel);
         }
     }
     else {
-        node = lxb_html_interface_res_constructors[tag_id][ns](document);
+        if (ns < LXB_NS__LAST_ENTRY) {
+            node = lxb_html_interface_res_constructors[tag_id][ns](document);
+        }
+        else {
+            domel = lxb_dom_element_interface_create(&document->dom_document);
+            node = lxb_dom_interface_node(domel);
+        }
     }

     if (node == NULL) {
diff --git a/ext/dom/lexbor/lexbor/html/interface.h b/ext/dom/lexbor/lexbor/html/interface.h
index a58a9e7474d..503bef6345a 100644
--- a/ext/dom/lexbor/lexbor/html/interface.h
+++ b/ext/dom/lexbor/lexbor/html/interface.h
@@ -71,6 +71,7 @@ extern "C" {
 #define lxb_html_interface_quote(obj) ((lxb_html_quote_element_t *) (obj))
 #define lxb_html_interface_script(obj) ((lxb_html_script_element_t *) (obj))
 #define lxb_html_interface_select(obj) ((lxb_html_select_element_t *) (obj))
+#define lxb_html_interface_selectedcontent(obj) ((lxb_html_selectedcontent_element_t *) obj)
 #define lxb_html_interface_slot(obj) ((lxb_html_slot_element_t *) (obj))
 #define lxb_html_interface_source(obj) ((lxb_html_source_element_t *) (obj))
 #define lxb_html_interface_span(obj) ((lxb_html_span_element_t *) (obj))
@@ -146,6 +147,8 @@ typedef struct lxb_html_progress_element lxb_html_progress_element_t;
 typedef struct lxb_html_quote_element lxb_html_quote_element_t;
 typedef struct lxb_html_script_element lxb_html_script_element_t;
 typedef struct lxb_html_select_element lxb_html_select_element_t;
+typedef struct lxb_html_selectedcontent_element lxb_html_selectedcontent_element_t;
+typedef struct lxb_html_search_element lxb_html_search_element_t;
 typedef struct lxb_html_slot_element lxb_html_slot_element_t;
 typedef struct lxb_html_source_element lxb_html_source_element_t;
 typedef struct lxb_html_span_element lxb_html_span_element_t;
diff --git a/ext/dom/lexbor/lexbor/html/interface_res.h b/ext/dom/lexbor/lexbor/html/interface_res.h
index 980be3c7de0..8a2f765c30f 100644
--- a/ext/dom/lexbor/lexbor/html/interface_res.h
+++ b/ext/dom/lexbor/lexbor/html/interface_res.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018-2025 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -14,12 +14,10 @@
 #ifndef LXB_HTML_INTERFACE_RES_H
 #define LXB_HTML_INTERFACE_RES_H

-#endif /* LXB_HTML_INTERFACE_RES_H */
-
 #ifdef LXB_TAG_CONST_VERSION
-#ifndef LXB_TAG_CONST_VERSION_A161EC911182C3254E7A972D5C51DF86
+#ifndef LXB_TAG_CONST_VERSION_5AB3094FB370521074947DC082575715
 #error Mismatched tags version! See "lexbor/tag/const.h".
-#endif /* LXB_TAG_CONST_VERSION_A161EC911182C3254E7A972D5C51DF86 */
+#endif /* LXB_TAG_CONST_VERSION_5AB3094FB370521074947DC082575715 */
 #else
 #error You need to include "lexbor/tag/const.h".
 #endif /* LXB_TAG_CONST_VERSION */
@@ -97,7 +95,9 @@
 #include "lexbor/html/interfaces/progress_element.h"
 #include "lexbor/html/interfaces/quote_element.h"
 #include "lexbor/html/interfaces/script_element.h"
+#include "lexbor/html/interfaces/search_element.h"
 #include "lexbor/html/interfaces/select_element.h"
+#include "lexbor/html/interfaces/selectedcontent_element.h"
 #include "lexbor/html/interfaces/slot_element.h"
 #include "lexbor/html/interfaces/source_element.h"
 #include "lexbor/html/interfaces/span_element.h"
@@ -130,18 +130,6 @@ lxb_dom_element_interface_destroy_wrapper(void *interface)
     return lxb_dom_element_interface_destroy(interface);
 }

-lxb_inline void *
-lxb_html_unknown_element_interface_create_wrapper(void *interface)
-{
-    return lxb_html_unknown_element_interface_create(interface);
-}
-
-lxb_inline void *
-lxb_html_unknown_element_interface_destroy_wrapper(void *interface)
-{
-    return lxb_html_unknown_element_interface_destroy(interface);
-}
-
 lxb_inline void *
 lxb_html_element_interface_create_wrapper(void *interface)
 {
@@ -166,6 +154,18 @@ lxb_dom_text_interface_destroy_wrapper(void *interface)
     return lxb_dom_text_interface_destroy(interface);
 }

+lxb_inline void *
+lxb_dom_document_interface_create_wrapper(void *interface)
+{
+    return lxb_dom_document_interface_create(interface);
+}
+
+lxb_inline void *
+lxb_dom_document_interface_destroy_wrapper(void *interface)
+{
+    return lxb_dom_document_interface_destroy(interface);
+}
+
 lxb_inline void *
 lxb_html_document_interface_create_wrapper(void *interface)
 {
@@ -214,6 +214,18 @@ lxb_html_anchor_element_interface_destroy_wrapper(void *interface)
     return lxb_html_anchor_element_interface_destroy(interface);
 }

+lxb_inline void *
+lxb_html_unknown_element_interface_create_wrapper(void *interface)
+{
+    return lxb_html_unknown_element_interface_create(interface);
+}
+
+lxb_inline void *
+lxb_html_unknown_element_interface_destroy_wrapper(void *interface)
+{
+    return lxb_html_unknown_element_interface_destroy(interface);
+}
+
 lxb_inline void *
 lxb_html_area_element_interface_create_wrapper(void *interface)
 {
@@ -826,6 +838,18 @@ lxb_html_script_element_interface_destroy_wrapper(void *interface)
     return lxb_html_script_element_interface_destroy(interface);
 }

+lxb_inline void *
+lxb_html_search_element_interface_create_wrapper(void *interface)
+{
+    return lxb_html_search_element_interface_create(interface);
+}
+
+lxb_inline void *
+lxb_html_search_element_interface_destroy_wrapper(void *interface)
+{
+    return lxb_html_search_element_interface_destroy(interface);
+}
+
 lxb_inline void *
 lxb_html_select_element_interface_create_wrapper(void *interface)
 {
@@ -838,6 +862,18 @@ lxb_html_select_element_interface_destroy_wrapper(void *interface)
     return lxb_html_select_element_interface_destroy(interface);
 }

+lxb_inline void *
+lxb_html_selectedcontent_element_interface_create_wrapper(void *interface)
+{
+    return lxb_html_selectedcontent_element_interface_create(interface);
+}
+
+lxb_inline void *
+lxb_html_selectedcontent_element_interface_destroy_wrapper(void *interface)
+{
+    return lxb_html_selectedcontent_element_interface_destroy(interface);
+}
+
 lxb_inline void *
 lxb_html_slot_element_interface_create_wrapper(void *interface)
 {
@@ -1019,15 +1055,12 @@ lxb_html_video_element_interface_destroy_wrapper(void *interface)
 }


-#ifdef LXB_HTML_INTERFACE_RES_CONSTRUCTORS
-#ifndef LXB_HTML_INTERFACE_RES_CONSTRUCTORS_ENABLED
-#define LXB_HTML_INTERFACE_RES_CONSTRUCTORS_ENABLED
 static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_TAG__LAST_ENTRY][LXB_NS__LAST_ENTRY] =
 {
     /* LXB_TAG__UNDEF */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1037,8 +1070,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG__END_OF_FILE */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1048,52 +1081,52 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG__TEXT */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_text_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_text_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_text_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper
+        (lxb_dom_interface_constructor_f) lxb_dom_text_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_text_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_text_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_text_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_text_interface_create_wrapper
     },
     /* LXB_TAG__DOCUMENT */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_document_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_document_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_document_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper
+        (lxb_dom_interface_constructor_f) lxb_dom_document_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_document_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_document_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_document_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_document_interface_create_wrapper
     },
     /* LXB_TAG__EM_COMMENT */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_comment_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_comment_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_comment_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper
+        (lxb_dom_interface_constructor_f) lxb_dom_comment_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_comment_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_comment_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_comment_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_comment_interface_create_wrapper
     },
     /* LXB_TAG__EM_DOCTYPE */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_document_type_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper
+        (lxb_dom_interface_constructor_f) lxb_dom_document_type_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_document_type_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_document_type_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_document_type_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_document_type_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_document_type_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_document_type_interface_create_wrapper
     },
     /* LXB_TAG_A */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_anchor_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1103,8 +1136,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_ABBR */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1114,8 +1147,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_ACRONYM */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1125,8 +1158,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_ADDRESS */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1136,8 +1169,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_ALTGLYPH */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1147,8 +1180,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_ALTGLYPHDEF */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1158,8 +1191,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_ALTGLYPHITEM */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1169,8 +1202,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_ANIMATECOLOR */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1180,8 +1213,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_ANIMATEMOTION */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1191,8 +1224,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_ANIMATETRANSFORM */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1202,8 +1235,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_ANNOTATION_XML */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1213,8 +1246,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_APPLET */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1224,8 +1257,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_AREA */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_area_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1235,8 +1268,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_ARTICLE */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1246,8 +1279,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_ASIDE */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1257,8 +1290,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_AUDIO */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_audio_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1268,8 +1301,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_B */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1279,8 +1312,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_BASE */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_base_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1290,8 +1323,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_BASEFONT */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1301,8 +1334,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_BDI */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1312,8 +1345,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_BDO */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1323,8 +1356,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_BGSOUND */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1334,8 +1367,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_BIG */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1345,8 +1378,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_BLINK */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1356,8 +1389,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_BLOCKQUOTE */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_quote_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1367,8 +1400,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_BODY */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_body_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1378,8 +1411,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_BR */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_br_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1389,8 +1422,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_BUTTON */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_button_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1400,8 +1433,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_CANVAS */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_canvas_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1411,8 +1444,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_CAPTION */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_table_caption_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1422,8 +1455,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_CENTER */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1433,8 +1466,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_CITE */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1444,8 +1477,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_CLIPPATH */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1455,8 +1488,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_CODE */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1466,8 +1499,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_COL */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_table_col_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1477,8 +1510,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_COLGROUP */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_table_col_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1488,8 +1521,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_DATA */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_data_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1499,8 +1532,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_DATALIST */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_data_list_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1510,8 +1543,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_DD */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1521,8 +1554,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_DEL */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_mod_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1532,8 +1565,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_DESC */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1543,8 +1576,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_DETAILS */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_details_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1554,8 +1587,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_DFN */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1565,8 +1598,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_DIALOG */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_dialog_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1576,8 +1609,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_DIR */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_directory_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1587,8 +1620,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_DIV */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_div_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1598,8 +1631,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_DL */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_d_list_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1609,8 +1642,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_DT */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1620,8 +1653,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_EM */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1631,8 +1664,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_EMBED */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_embed_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1642,8 +1675,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FEBLEND */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1653,8 +1686,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FECOLORMATRIX */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1664,8 +1697,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FECOMPONENTTRANSFER */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1675,8 +1708,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FECOMPOSITE */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1686,8 +1719,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FECONVOLVEMATRIX */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1697,8 +1730,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FEDIFFUSELIGHTING */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1708,8 +1741,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FEDISPLACEMENTMAP */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1719,8 +1752,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FEDISTANTLIGHT */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1730,8 +1763,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FEDROPSHADOW */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1741,8 +1774,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FEFLOOD */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1752,8 +1785,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FEFUNCA */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1763,8 +1796,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FEFUNCB */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1774,8 +1807,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FEFUNCG */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1785,8 +1818,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FEFUNCR */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1796,8 +1829,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FEGAUSSIANBLUR */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1807,8 +1840,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FEIMAGE */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1818,8 +1851,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FEMERGE */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1829,8 +1862,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FEMERGENODE */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1840,8 +1873,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FEMORPHOLOGY */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1851,8 +1884,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FEOFFSET */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1862,8 +1895,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FEPOINTLIGHT */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1873,8 +1906,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FESPECULARLIGHTING */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1884,8 +1917,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FESPOTLIGHT */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1895,8 +1928,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FETILE */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1906,8 +1939,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FETURBULENCE */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1917,8 +1950,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FIELDSET */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_field_set_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1928,8 +1961,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FIGCAPTION */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1939,8 +1972,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FIGURE */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1950,8 +1983,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FONT */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_font_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1961,8 +1994,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FOOTER */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1972,8 +2005,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FOREIGNOBJECT */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1983,8 +2016,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FORM */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_form_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -1994,8 +2027,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FRAME */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_frame_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2005,8 +2038,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_FRAMESET */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_frame_set_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2016,8 +2049,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_GLYPHREF */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2027,8 +2060,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_H1 */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_heading_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2038,8 +2071,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_H2 */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_heading_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2049,8 +2082,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_H3 */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_heading_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2060,8 +2093,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_H4 */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_heading_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2071,8 +2104,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_H5 */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_heading_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2082,8 +2115,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_H6 */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_heading_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2093,8 +2126,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_HEAD */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_head_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2104,8 +2137,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_HEADER */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2115,8 +2148,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_HGROUP */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2126,8 +2159,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_HR */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_hr_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2137,8 +2170,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_HTML */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2148,8 +2181,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_I */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2159,8 +2192,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_IFRAME */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_iframe_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2170,8 +2203,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_IMAGE */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_image_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2181,8 +2214,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_IMG */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_image_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2192,8 +2225,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_INPUT */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_input_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2203,8 +2236,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_INS */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_mod_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2214,8 +2247,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_ISINDEX */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2225,8 +2258,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_KBD */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2236,8 +2269,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_KEYGEN */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2247,8 +2280,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_LABEL */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_label_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2258,8 +2291,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_LEGEND */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_legend_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2269,8 +2302,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_LI */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_li_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2280,8 +2313,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_LINEARGRADIENT */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2291,8 +2324,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_LINK */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_link_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2302,8 +2335,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_LISTING */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_pre_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2313,8 +2346,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_MAIN */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2324,8 +2357,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_MALIGNMARK */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2335,8 +2368,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_MAP */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_map_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2346,8 +2379,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_MARK */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2357,8 +2390,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_MARQUEE */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_marquee_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2368,8 +2401,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_MATH */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2379,8 +2412,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_MENU */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_menu_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2390,8 +2423,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_META */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_meta_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2401,8 +2434,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_METER */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_meter_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2412,8 +2445,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_MFENCED */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2423,8 +2456,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_MGLYPH */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2434,8 +2467,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_MI */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2445,8 +2478,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_MN */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2456,8 +2489,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_MO */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2467,8 +2500,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_MS */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2478,8 +2511,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_MTEXT */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2489,8 +2522,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_MULTICOL */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2500,8 +2533,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_NAV */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2511,8 +2544,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_NEXTID */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2522,8 +2555,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_NOBR */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2533,8 +2566,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_NOEMBED */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2544,8 +2577,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_NOFRAMES */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2555,8 +2588,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_NOSCRIPT */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2566,8 +2599,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_OBJECT */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_object_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2577,8 +2610,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_OL */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_o_list_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2588,8 +2621,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_OPTGROUP */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_opt_group_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2599,8 +2632,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_OPTION */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_option_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2610,8 +2643,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_OUTPUT */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_output_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2621,8 +2654,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_P */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_paragraph_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2632,8 +2665,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_PARAM */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_param_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2643,8 +2676,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_PATH */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2654,8 +2687,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_PICTURE */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_picture_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2665,8 +2698,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_PLAINTEXT */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2676,8 +2709,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_PRE */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_pre_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2687,8 +2720,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_PROGRESS */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_progress_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2698,8 +2731,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_Q */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_quote_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2709,8 +2742,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_RADIALGRADIENT */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2720,8 +2753,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_RB */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2731,8 +2764,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_RP */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2742,8 +2775,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_RT */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2753,8 +2786,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_RTC */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2764,8 +2797,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_RUBY */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2775,8 +2808,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_S */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2786,8 +2819,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_SAMP */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2797,8 +2830,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_SCRIPT */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_script_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2806,10 +2839,21 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper
     },
+    /* LXB_TAG_SEARCH */
+    {
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_html_search_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper
+    },
     /* LXB_TAG_SECTION */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2819,8 +2863,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_SELECT */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_select_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2828,10 +2872,21 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper
     },
+    /* LXB_TAG_SELECTEDCONTENT */
+    {
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_html_selectedcontent_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper
+    },
     /* LXB_TAG_SLOT */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_slot_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2841,8 +2896,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_SMALL */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2852,8 +2907,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_SOURCE */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_source_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2863,8 +2918,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_SPACER */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2874,8 +2929,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_SPAN */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_span_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2885,8 +2940,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_STRIKE */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2896,8 +2951,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_STRONG */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2907,8 +2962,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_STYLE */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_style_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2918,8 +2973,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_SUB */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2929,8 +2984,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_SUMMARY */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2940,8 +2995,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_SUP */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2951,8 +3006,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_SVG */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2962,8 +3017,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_TABLE */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_table_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2973,8 +3028,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_TBODY */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_table_section_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2984,8 +3039,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_TD */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_table_cell_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -2995,8 +3050,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_TEMPLATE */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_template_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -3006,8 +3061,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_TEXTAREA */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_text_area_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -3017,8 +3072,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_TEXTPATH */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -3028,8 +3083,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_TFOOT */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_table_section_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -3039,8 +3094,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_TH */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_table_cell_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -3050,8 +3105,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_THEAD */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_table_section_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -3061,8 +3116,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_TIME */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_time_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -3072,8 +3127,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_TITLE */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_title_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -3083,8 +3138,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_TR */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_table_row_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -3094,8 +3149,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_TRACK */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_track_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -3105,8 +3160,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_TT */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -3116,8 +3171,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_U */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -3127,8 +3182,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_UL */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_u_list_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -3138,8 +3193,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_VAR */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -3149,8 +3204,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_VIDEO */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_video_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -3160,8 +3215,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_WBR */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -3171,8 +3226,8 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
     },
     /* LXB_TAG_XMP */
     {
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
-        (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
+        (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_html_pre_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper,
@@ -3181,18 +3236,13 @@ static  lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_
         (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper
     }
 };
-#endif /* LXB_HTML_INTERFACE_RES_CONSTRUCTORS_ENABLED */
-#endif /* LXB_HTML_INTERFACE_RES_CONSTRUCTORS */

-#ifdef LXB_HTML_INTERFACE_RES_DESTRUCTOR
-#ifndef LXB_HTML_INTERFACE_RES_DESTRUCTOR_ENABLED
-#define LXB_HTML_INTERFACE_RES_DESTRUCTOR_ENABLED
 static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG__LAST_ENTRY][LXB_NS__LAST_ENTRY] =
 {
     /* LXB_TAG__UNDEF */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3202,8 +3252,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG__END_OF_FILE */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3213,52 +3263,52 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG__TEXT */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_text_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_text_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_text_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper
+        (lxb_dom_interface_destructor_f) lxb_dom_text_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_text_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_text_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_text_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_text_interface_destroy_wrapper
     },
     /* LXB_TAG__DOCUMENT */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_document_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_document_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_document_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper
+        (lxb_dom_interface_destructor_f) lxb_dom_document_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_document_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_document_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_document_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_document_interface_destroy_wrapper
     },
     /* LXB_TAG__EM_COMMENT */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_comment_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_comment_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_comment_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper
+        (lxb_dom_interface_destructor_f) lxb_dom_comment_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_comment_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_comment_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_comment_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_comment_interface_destroy_wrapper
     },
     /* LXB_TAG__EM_DOCTYPE */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_document_type_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper
+        (lxb_dom_interface_destructor_f) lxb_dom_document_type_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_document_type_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_document_type_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_document_type_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_document_type_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_document_type_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_document_type_interface_destroy_wrapper
     },
     /* LXB_TAG_A */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_anchor_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3268,8 +3318,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_ABBR */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3279,8 +3329,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_ACRONYM */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3290,8 +3340,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_ADDRESS */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3301,8 +3351,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_ALTGLYPH */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3312,8 +3362,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_ALTGLYPHDEF */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3323,8 +3373,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_ALTGLYPHITEM */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3334,8 +3384,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_ANIMATECOLOR */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3345,8 +3395,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_ANIMATEMOTION */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3356,8 +3406,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_ANIMATETRANSFORM */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3367,8 +3417,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_ANNOTATION_XML */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3378,8 +3428,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_APPLET */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3389,8 +3439,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_AREA */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_area_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3400,8 +3450,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_ARTICLE */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3411,8 +3461,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_ASIDE */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3422,8 +3472,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_AUDIO */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_audio_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3433,8 +3483,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_B */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3444,8 +3494,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_BASE */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_base_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3455,8 +3505,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_BASEFONT */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3466,8 +3516,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_BDI */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3477,8 +3527,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_BDO */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3488,8 +3538,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_BGSOUND */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3499,8 +3549,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_BIG */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3510,8 +3560,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_BLINK */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3521,8 +3571,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_BLOCKQUOTE */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_quote_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3532,8 +3582,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_BODY */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_body_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3543,8 +3593,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_BR */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_br_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3554,8 +3604,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_BUTTON */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_button_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3565,8 +3615,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_CANVAS */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_canvas_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3576,8 +3626,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_CAPTION */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_table_caption_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3587,8 +3637,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_CENTER */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3598,8 +3648,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_CITE */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3609,8 +3659,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_CLIPPATH */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3620,8 +3670,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_CODE */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3631,8 +3681,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_COL */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_table_col_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3642,8 +3692,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_COLGROUP */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_table_col_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3653,8 +3703,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_DATA */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_data_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3664,8 +3714,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_DATALIST */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_data_list_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3675,8 +3725,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_DD */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3686,8 +3736,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_DEL */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_mod_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3697,8 +3747,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_DESC */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3708,8 +3758,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_DETAILS */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_details_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3719,8 +3769,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_DFN */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3730,8 +3780,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_DIALOG */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_dialog_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3741,8 +3791,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_DIR */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_directory_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3752,8 +3802,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_DIV */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_div_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3763,8 +3813,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_DL */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_d_list_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3774,8 +3824,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_DT */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3785,8 +3835,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_EM */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3796,8 +3846,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_EMBED */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_embed_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3807,8 +3857,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FEBLEND */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3818,8 +3868,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FECOLORMATRIX */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3829,8 +3879,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FECOMPONENTTRANSFER */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3840,8 +3890,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FECOMPOSITE */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3851,8 +3901,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FECONVOLVEMATRIX */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3862,8 +3912,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FEDIFFUSELIGHTING */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3873,8 +3923,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FEDISPLACEMENTMAP */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3884,8 +3934,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FEDISTANTLIGHT */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3895,8 +3945,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FEDROPSHADOW */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3906,8 +3956,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FEFLOOD */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3917,8 +3967,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FEFUNCA */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3928,8 +3978,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FEFUNCB */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3939,8 +3989,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FEFUNCG */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3950,8 +4000,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FEFUNCR */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3961,8 +4011,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FEGAUSSIANBLUR */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3972,8 +4022,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FEIMAGE */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3983,8 +4033,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FEMERGE */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -3994,8 +4044,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FEMERGENODE */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4005,8 +4055,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FEMORPHOLOGY */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4016,8 +4066,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FEOFFSET */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4027,8 +4077,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FEPOINTLIGHT */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4038,8 +4088,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FESPECULARLIGHTING */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4049,8 +4099,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FESPOTLIGHT */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4060,8 +4110,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FETILE */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4071,8 +4121,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FETURBULENCE */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4082,8 +4132,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FIELDSET */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_field_set_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4093,8 +4143,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FIGCAPTION */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4104,8 +4154,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FIGURE */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4115,8 +4165,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FONT */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_font_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4126,8 +4176,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FOOTER */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4137,8 +4187,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FOREIGNOBJECT */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4148,8 +4198,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FORM */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_form_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4159,8 +4209,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FRAME */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_frame_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4170,8 +4220,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_FRAMESET */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_frame_set_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4181,8 +4231,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_GLYPHREF */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4192,8 +4242,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_H1 */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_heading_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4203,8 +4253,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_H2 */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_heading_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4214,8 +4264,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_H3 */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_heading_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4225,8 +4275,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_H4 */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_heading_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4236,8 +4286,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_H5 */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_heading_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4247,8 +4297,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_H6 */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_heading_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4258,8 +4308,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_HEAD */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_head_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4269,8 +4319,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_HEADER */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4280,8 +4330,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_HGROUP */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4291,8 +4341,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_HR */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_hr_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4302,8 +4352,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_HTML */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4313,8 +4363,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_I */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4324,8 +4374,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_IFRAME */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_iframe_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4335,8 +4385,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_IMAGE */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_image_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4346,8 +4396,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_IMG */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_image_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4357,8 +4407,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_INPUT */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_input_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4368,8 +4418,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_INS */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_mod_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4379,8 +4429,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_ISINDEX */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4390,8 +4440,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_KBD */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4401,8 +4451,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_KEYGEN */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4412,8 +4462,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_LABEL */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_label_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4423,8 +4473,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_LEGEND */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_legend_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4434,8 +4484,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_LI */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_li_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4445,8 +4495,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_LINEARGRADIENT */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4456,8 +4506,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_LINK */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_link_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4467,8 +4517,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_LISTING */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_pre_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4478,8 +4528,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_MAIN */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4489,8 +4539,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_MALIGNMARK */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4500,8 +4550,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_MAP */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_map_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4511,8 +4561,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_MARK */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4522,8 +4572,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_MARQUEE */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_marquee_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4533,8 +4583,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_MATH */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4544,8 +4594,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_MENU */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_menu_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4555,8 +4605,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_META */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_meta_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4566,8 +4616,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_METER */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_meter_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4577,8 +4627,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_MFENCED */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4588,8 +4638,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_MGLYPH */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4599,8 +4649,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_MI */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4610,8 +4660,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_MN */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4621,8 +4671,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_MO */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4632,8 +4682,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_MS */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4643,8 +4693,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_MTEXT */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4654,8 +4704,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_MULTICOL */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4665,8 +4715,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_NAV */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4676,8 +4726,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_NEXTID */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4687,8 +4737,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_NOBR */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4698,8 +4748,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_NOEMBED */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4709,8 +4759,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_NOFRAMES */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4720,8 +4770,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_NOSCRIPT */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4731,8 +4781,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_OBJECT */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_object_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4742,8 +4792,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_OL */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_o_list_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4753,8 +4803,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_OPTGROUP */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_opt_group_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4764,8 +4814,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_OPTION */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_option_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4775,8 +4825,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_OUTPUT */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_output_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4786,8 +4836,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_P */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_paragraph_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4797,8 +4847,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_PARAM */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_param_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4808,8 +4858,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_PATH */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4819,8 +4869,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_PICTURE */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_picture_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4830,8 +4880,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_PLAINTEXT */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4841,8 +4891,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_PRE */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_pre_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4852,8 +4902,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_PROGRESS */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_progress_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4863,8 +4913,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_Q */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_quote_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4874,8 +4924,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_RADIALGRADIENT */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4885,8 +4935,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_RB */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4896,8 +4946,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_RP */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4907,8 +4957,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_RT */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4918,8 +4968,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_RTC */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4929,8 +4979,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_RUBY */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4940,8 +4990,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_S */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4951,8 +5001,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_SAMP */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4962,8 +5012,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_SCRIPT */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_script_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4971,10 +5021,21 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper
     },
+    /* LXB_TAG_SEARCH */
+    {
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_html_search_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper
+    },
     /* LXB_TAG_SECTION */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4984,8 +5045,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_SELECT */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_select_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -4993,10 +5054,21 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper
     },
+    /* LXB_TAG_SELECTEDCONTENT */
+    {
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_html_selectedcontent_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper
+    },
     /* LXB_TAG_SLOT */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_slot_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5006,8 +5078,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_SMALL */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5017,8 +5089,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_SOURCE */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_source_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5028,8 +5100,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_SPACER */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5039,8 +5111,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_SPAN */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_span_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5050,8 +5122,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_STRIKE */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5061,8 +5133,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_STRONG */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5072,8 +5144,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_STYLE */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_style_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5083,8 +5155,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_SUB */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5094,8 +5166,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_SUMMARY */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5105,8 +5177,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_SUP */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5116,8 +5188,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_SVG */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5127,8 +5199,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_TABLE */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_table_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5138,8 +5210,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_TBODY */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_table_section_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5149,8 +5221,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_TD */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_table_cell_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5160,8 +5232,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_TEMPLATE */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_template_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5171,8 +5243,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_TEXTAREA */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_text_area_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5182,8 +5254,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_TEXTPATH */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5193,8 +5265,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_TFOOT */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_table_section_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5204,8 +5276,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_TH */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_table_cell_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5215,8 +5287,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_THEAD */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_table_section_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5226,8 +5298,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_TIME */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_time_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5237,8 +5309,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_TITLE */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_title_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5248,8 +5320,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_TR */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_table_row_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5259,8 +5331,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_TRACK */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_track_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5270,8 +5342,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_TT */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5281,8 +5353,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_U */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5292,8 +5364,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_UL */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_u_list_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5303,8 +5375,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_VAR */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5314,8 +5386,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_VIDEO */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_video_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5325,8 +5397,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_WBR */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5336,8 +5408,8 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
     },
     /* LXB_TAG_XMP */
     {
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
-        (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
+        (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_html_pre_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper,
@@ -5346,5 +5418,5 @@ static  lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG
         (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper
     }
 };
-#endif /* LXB_HTML_INTERFACE_RES_DESTRUCTOR_ENABLED */
-#endif /* LXB_HTML_INTERFACE_RES_DESTRUCTOR */
+
+#endif /* LXB_HTML_INTERFACE_RES_H */
diff --git a/ext/dom/lexbor/lexbor/html/interfaces/document.c b/ext/dom/lexbor/lexbor/html/interfaces/document.c
index 34a2c6db0e5..b40c6c8692f 100644
--- a/ext/dom/lexbor/lexbor/html/interfaces/document.c
+++ b/ext/dom/lexbor/lexbor/html/interfaces/document.c
@@ -11,16 +11,18 @@
 #include "lexbor/html/interfaces/style_element.h"
 #include "lexbor/html/node.h"
 #include "lexbor/html/parser.h"
+#include "lexbor/html/tokenizer.h"

 #include "lexbor/tag/tag.h"

 #include "lexbor/dom/interfaces/text.h"
 #include "lexbor/dom/interfaces/element.h"

-#define LXB_HTML_TAG_RES_DATA
-#define LXB_HTML_TAG_RES_SHS_DATA
-#include "lexbor/html/tag_res.h"

+#ifndef LEXBOR_DISABLE_INTERNAL_EXTERN
+    LXB_EXTERN lxb_html_tag_category_t lxb_html_tag_res_cats[LXB_TAG__LAST_ENTRY][LXB_NS__LAST_ENTRY];
+    LXB_EXTERN lxb_html_tag_fixname_t lxb_html_tag_res_fixname_svg[LXB_TAG__LAST_ENTRY];
+#endif

 lxb_status_t
 lxb_html_parse_chunk_prepare(lxb_html_parser_t *parser,
@@ -34,7 +36,7 @@ lxb_html_document_title_walker(lxb_dom_node_t *node, void *ctx);


 lxb_inline lxb_dom_interface_t *
-lxb_html_document_interface_create_wrapper(lxb_dom_document_t *document,
+lxb_html_document_interface_create_handler(lxb_dom_document_t *document,
                                            lxb_tag_id_t tag_id, lxb_ns_id_t ns)
 {
     return lxb_html_interface_create(lxb_html_interface_document(document),
@@ -60,7 +62,7 @@ lxb_html_document_interface_create(lxb_html_document_t *document)
     }

     status = lxb_dom_document_init(doc, lxb_dom_interface_document(document),
-                                   lxb_html_document_interface_create_wrapper,
+                                   lxb_html_document_interface_create_handler,
                                    lxb_html_interface_clone,
                                    lxb_html_interface_destroy,
                                    LXB_DOM_DOCUMENT_DTYPE_HTML, LXB_NS_HTML);
@@ -267,6 +269,7 @@ lxb_html_document_parser_prepare(lxb_html_document_t *document)
 {
     lxb_status_t status;
     lxb_dom_document_t *doc;
+    lxb_html_parser_t *parser;

     doc = lxb_dom_interface_document(document);

@@ -278,6 +281,10 @@ lxb_html_document_parser_prepare(lxb_html_document_t *document)
             lxb_html_parser_destroy(doc->parser);
             return status;
         }
+
+        parser = doc->parser;
+
+        lxb_html_tokenizer_keep_duplicate_set(parser->tkz, true);
     }
     else if (lxb_html_parser_state(doc->parser) != LXB_HTML_PARSER_STATE_BEGIN) {
         lxb_html_parser_clean(doc->parser);
diff --git a/ext/dom/lexbor/lexbor/html/interfaces/option_element.c b/ext/dom/lexbor/lexbor/html/interfaces/option_element.c
index 77e1e23d387..19f085da042 100644
--- a/ext/dom/lexbor/lexbor/html/interfaces/option_element.c
+++ b/ext/dom/lexbor/lexbor/html/interfaces/option_element.c
@@ -5,6 +5,8 @@
  */

 #include "lexbor/html/interfaces/option_element.h"
+#include "lexbor/html/interfaces/select_element.h"
+#include "lexbor/html/interfaces/selectedcontent_element.h"
 #include "lexbor/html/interfaces/document.h"


@@ -33,3 +35,48 @@ lxb_html_option_element_interface_destroy(lxb_html_option_element_t *option_elem
     (void) lxb_dom_node_interface_destroy(lxb_dom_interface_node(option_element));
     return NULL;
 }
+
+lxb_dom_exception_code_t
+lxb_html_option_maybe_clone_to_selectedcontent(lxb_html_option_element_t *option)
+{
+    bool is;
+    lxb_dom_node_t *select;
+    lxb_html_select_element_t *select_el;
+    lxb_html_selectedcontent_element_t *sel_content;
+
+    is = lxb_html_option_element_selectedness(lxb_html_interface_option(option));
+    if (!is) {
+        return LXB_DOM_EXCEPTION_OK;
+    }
+
+    select = lxb_dom_interface_node(option);
+
+    do {
+        select = select->parent;
+
+        if (select == NULL) {
+            return LXB_DOM_EXCEPTION_OK;
+        }
+    }
+    while (select->local_name != LXB_TAG_SELECT || select->ns != LXB_NS_HTML);
+
+    select_el = lxb_html_interface_select(select);
+
+    sel_content = lxb_html_select_get_enabled_selectedcontent(select_el);
+    if (sel_content == NULL) {
+        return LXB_DOM_EXCEPTION_OK;
+    }
+
+    return lxb_html_selectedcontent_clone_option(sel_content, option);
+}
+
+bool
+lxb_html_option_element_selectedness(lxb_html_option_element_t *option)
+{
+    lxb_dom_attr_t *selected;
+
+    selected = lxb_dom_element_attr_by_id(lxb_dom_interface_element(option),
+                                          LXB_DOM_ATTR_SELECTED);
+
+    return selected != NULL;
+}
diff --git a/ext/dom/lexbor/lexbor/html/interfaces/option_element.h b/ext/dom/lexbor/lexbor/html/interfaces/option_element.h
index a59763898de..99d4977aa03 100644
--- a/ext/dom/lexbor/lexbor/html/interfaces/option_element.h
+++ b/ext/dom/lexbor/lexbor/html/interfaces/option_element.h
@@ -27,6 +27,13 @@ LXB_API lxb_html_option_element_t *
 lxb_html_option_element_interface_destroy(lxb_html_option_element_t *option_element);


+LXB_API lxb_dom_exception_code_t
+lxb_html_option_maybe_clone_to_selectedcontent(lxb_html_option_element_t *option);
+
+LXB_API bool
+lxb_html_option_element_selectedness(lxb_html_option_element_t *option);
+
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
diff --git a/ext/dom/lexbor/lexbor/html/interfaces/search_element.c b/ext/dom/lexbor/lexbor/html/interfaces/search_element.c
new file mode 100644
index 00000000000..00ca2a6ba3f
--- /dev/null
+++ b/ext/dom/lexbor/lexbor/html/interfaces/search_element.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 Alexander Borisov
+ *
+ * Author: Alexander Borisov <borisov@lexbor.com>
+ */
+
+#include "lexbor/html/interfaces/search_element.h"
+#include "lexbor/html/interfaces/document.h"
+
+
+lxb_html_search_element_t *
+lxb_html_search_element_interface_create(lxb_html_document_t *document)
+{
+    lxb_html_search_element_t *element;
+
+    element = lexbor_mraw_calloc(document->dom_document.mraw,
+                                 sizeof(lxb_html_search_element_t));
+    if (element == NULL) {
+        return NULL;
+    }
+
+    lxb_dom_node_t *node = lxb_dom_interface_node(element);
+
+    node->owner_document = lxb_html_document_original_ref(document);
+    node->type = LXB_DOM_NODE_TYPE_ELEMENT;
+
+    return element;
+}
+
+lxb_html_search_element_t *
+lxb_html_search_element_interface_destroy(lxb_html_search_element_t *search_element)
+{
+    (void) lxb_dom_node_interface_destroy(lxb_dom_interface_node(search_element));
+    return NULL;
+}
diff --git a/ext/dom/lexbor/lexbor/html/interfaces/search_element.h b/ext/dom/lexbor/lexbor/html/interfaces/search_element.h
new file mode 100644
index 00000000000..a4286217640
--- /dev/null
+++ b/ext/dom/lexbor/lexbor/html/interfaces/search_element.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2018 Alexander Borisov
+ *
+ * Author: Alexander Borisov <borisov@lexbor.com>
+ */
+
+#ifndef LEXBOR_HTML_SEARCH_ELEMENT_H
+#define LEXBOR_HTML_SEARCH_ELEMENT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "lexbor/html/interface.h"
+#include "lexbor/html/interfaces/element.h"
+
+
+struct lxb_html_search_element {
+    lxb_html_element_t element;
+};
+
+
+LXB_API lxb_html_search_element_t *
+lxb_html_search_element_interface_create(lxb_html_document_t *document);
+
+LXB_API lxb_html_search_element_t *
+lxb_html_search_element_interface_destroy(lxb_html_search_element_t *search_element);
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* LEXBOR_HTML_SEARCH_ELEMENT_H */
diff --git a/ext/dom/lexbor/lexbor/html/interfaces/select_element.c b/ext/dom/lexbor/lexbor/html/interfaces/select_element.c
index 69f8abe8dd5..8b338dc76da 100644
--- a/ext/dom/lexbor/lexbor/html/interfaces/select_element.c
+++ b/ext/dom/lexbor/lexbor/html/interfaces/select_element.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 Alexander Borisov
+ * Copyright (C) 2018-2025 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -8,6 +8,10 @@
 #include "lexbor/html/interfaces/document.h"


+static lexbor_action_t
+lxb_html_select_find_selectedcontent_cb(lxb_dom_node_t *node, void *ctx);
+
+
 lxb_html_select_element_t *
 lxb_html_select_element_interface_create(lxb_html_document_t *document)
 {
@@ -33,3 +37,44 @@ lxb_html_select_element_interface_destroy(lxb_html_select_element_t *select_elem
     (void) lxb_dom_node_interface_destroy(lxb_dom_interface_node(select_element));
     return NULL;
 }
+
+lxb_html_selectedcontent_element_t *
+lxb_html_select_get_enabled_selectedcontent(lxb_html_select_element_t *el)
+{
+    lxb_dom_attr_t *multiple;
+    lxb_dom_node_t *selectedcontent, *node;
+
+    multiple = lxb_dom_element_attr_by_id(lxb_dom_interface_element(el),
+                                          LXB_DOM_ATTR_MULTIPLE);
+    if (multiple != NULL) {
+        return NULL;
+    }
+
+    selectedcontent = NULL;
+    node = lxb_dom_interface_node(el);
+
+    lxb_dom_node_simple_walk(node, lxb_html_select_find_selectedcontent_cb,
+                             &selectedcontent);
+    if (selectedcontent == NULL) {
+        return NULL;
+    }
+
+    return lxb_html_interface_selectedcontent(selectedcontent);
+}
+
+static lexbor_action_t
+lxb_html_select_find_selectedcontent_cb(lxb_dom_node_t *node, void *ctx)
+{
+    lxb_dom_node_t **selectedcontent;
+
+    if (node->local_name == LXB_TAG_SELECTEDCONTENT
+        && node->ns == LXB_NS_HTML)
+    {
+        selectedcontent = ctx;
+        *selectedcontent = node;
+
+        return LEXBOR_ACTION_STOP;
+    }
+
+    return LEXBOR_ACTION_OK;
+}
diff --git a/ext/dom/lexbor/lexbor/html/interfaces/select_element.h b/ext/dom/lexbor/lexbor/html/interfaces/select_element.h
index 8676db5da90..03e20d197cd 100644
--- a/ext/dom/lexbor/lexbor/html/interfaces/select_element.h
+++ b/ext/dom/lexbor/lexbor/html/interfaces/select_element.h
@@ -26,6 +26,8 @@ lxb_html_select_element_interface_create(lxb_html_document_t *document);
 LXB_API lxb_html_select_element_t *
 lxb_html_select_element_interface_destroy(lxb_html_select_element_t *select_element);

+LXB_API lxb_html_selectedcontent_element_t *
+lxb_html_select_get_enabled_selectedcontent(lxb_html_select_element_t *el);

 #ifdef __cplusplus
 } /* extern "C" */
diff --git a/ext/dom/lexbor/lexbor/html/interfaces/selectedcontent_element.c b/ext/dom/lexbor/lexbor/html/interfaces/selectedcontent_element.c
new file mode 100644
index 00000000000..41b1c0d58b8
--- /dev/null
+++ b/ext/dom/lexbor/lexbor/html/interfaces/selectedcontent_element.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2025 Alexander Borisov
+ *
+ * Author: Alexander Borisov <borisov@lexbor.com>
+ */
+
+#include "lexbor/dom/interfaces/document_fragment.h"
+#include "lexbor/html/interfaces/selectedcontent_element.h"
+#include "lexbor/html/interfaces/document.h"
+
+
+lxb_html_selectedcontent_element_t *
+lxb_html_selectedcontent_element_interface_create(lxb_html_document_t *document)
+{
+    lxb_html_selectedcontent_element_t *element;
+
+    element = lexbor_mraw_calloc(document->dom_document.mraw,
+                                 sizeof(lxb_html_selectedcontent_element_t));
+    if (element == NULL) {
+        return NULL;
+    }
+
+    lxb_dom_node_t *node = lxb_dom_interface_node(element);
+
+    node->owner_document = lxb_html_document_original_ref(document);
+    node->type = LXB_DOM_NODE_TYPE_ELEMENT;
+
+    return element;
+}
+
+lxb_html_selectedcontent_element_t *
+lxb_html_selectedcontent_element_interface_destroy(lxb_html_selectedcontent_element_t *selectedcontent_element)
+{
+    (void) lxb_dom_node_interface_destroy(lxb_dom_interface_node(selectedcontent_element));
+    return NULL;
+}
+
+lxb_dom_exception_code_t
+lxb_html_selectedcontent_clone_option(lxb_html_selectedcontent_element_t *sc,
+                                      lxb_html_option_element_t *option)
+{
+    lxb_dom_node_t *node, *child, *opt_node;
+    lxb_dom_document_fragment_t fragment;
+
+    memset(&fragment, 0x00, sizeof(lxb_dom_document_fragment_t));
+
+    opt_node = lxb_dom_interface_node(option);
+
+    fragment.node.type = LXB_DOM_NODE_TYPE_DOCUMENT_FRAGMENT;
+    fragment.node.owner_document = opt_node->owner_document;
+
+    node = opt_node->first_child;
+
+    while (node != NULL) {
+        child = lxb_dom_node_clone(node, true);
+        if (child == NULL) {
+            return LXB_DOM_EXCEPTION_ERR;
+        }
+
+        lxb_dom_node_insert_child_wo_events(lxb_dom_interface_node(&fragment),
+                                            child);
+        node = node->next;
+    }
+
+    return lxb_dom_node_replace_all_spec(lxb_dom_interface_node(sc),
+                                         lxb_dom_interface_node(&fragment));
+}
diff --git a/ext/dom/lexbor/lexbor/html/interfaces/selectedcontent_element.h b/ext/dom/lexbor/lexbor/html/interfaces/selectedcontent_element.h
new file mode 100644
index 00000000000..5d38b59f501
--- /dev/null
+++ b/ext/dom/lexbor/lexbor/html/interfaces/selectedcontent_element.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2025 Alexander Borisov
+ *
+ * Author: Alexander Borisov <borisov@lexbor.com>
+ */
+
+#ifndef LEXBOR_HTML_SELECTEDCONTENT_ELEMENT_H
+#define LEXBOR_HTML_SELECTEDCONTENT_ELEMENT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "lexbor/html/interface.h"
+#include "lexbor/html/interfaces/element.h"
+
+
+struct lxb_html_selectedcontent_element {
+    lxb_html_element_t element;
+};
+
+
+LXB_API lxb_html_selectedcontent_element_t *
+lxb_html_selectedcontent_element_interface_create(lxb_html_document_t *document);
+
+LXB_API lxb_html_selectedcontent_element_t *
+lxb_html_selectedcontent_element_interface_destroy(lxb_html_selectedcontent_element_t *selectedcontent_element);
+
+LXB_API lxb_dom_exception_code_t
+lxb_html_selectedcontent_clone_option(lxb_html_selectedcontent_element_t *sc,
+                                      lxb_html_option_element_t *option);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* LEXBOR_HTML_SELECTEDCONTENT_ELEMENT_H */
diff --git a/ext/dom/lexbor/lexbor/html/parser.c b/ext/dom/lexbor/lexbor/html/parser.c
index caca15e4be2..7d051045101 100644
--- a/ext/dom/lexbor/lexbor/html/parser.c
+++ b/ext/dom/lexbor/lexbor/html/parser.c
@@ -13,9 +13,10 @@
 #include "lexbor/html/tree/template_insertion.h"
 #include "lexbor/html/tree/insertion_mode.h"

-#define LXB_HTML_TAG_RES_DATA
-#define LXB_HTML_TAG_RES_SHS_DATA
-#include "lexbor/html/tag_res.h"
+#ifndef LEXBOR_DISABLE_INTERNAL_EXTERN
+    LXB_EXTERN lxb_html_tag_category_t lxb_html_tag_res_cats[LXB_TAG__LAST_ENTRY][LXB_NS__LAST_ENTRY];
+    LXB_EXTERN lxb_html_tag_fixname_t lxb_html_tag_res_fixname_svg[LXB_TAG__LAST_ENTRY];
+#endif


 static void
@@ -43,6 +44,8 @@ lxb_html_parser_init(lxb_html_parser_t *parser)
         return status;
     }

+    lxb_html_tokenizer_keep_duplicate_set(parser->tkz, true);
+
     /* Tree */
     parser->tree = lxb_html_tree_create();
     status = lxb_html_tree_init(parser->tree, parser->tkz);
@@ -339,7 +342,9 @@ lxb_html_parse_fragment_chunk_destroy(lxb_html_parser_t *parser)
         parser->tree->fragment = NULL;
     }

-    if (lxb_html_document_is_original(parser->tree->document) == false) {
+    if (parser->tree->document != NULL
+        && lxb_html_document_is_original(parser->tree->document) == false)
+    {
         if (parser->root != NULL) {
             doc = lxb_dom_interface_node(parser->tree->document)->owner_document;
             parser->root->parent = &doc->node;
diff --git a/ext/dom/lexbor/lexbor/html/style.c b/ext/dom/lexbor/lexbor/html/style.c
deleted file mode 100644
index b07dbf12cae..00000000000
--- a/ext/dom/lexbor/lexbor/html/style.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2022-2023 Alexander Borisov
- *
- * Author: Alexander Borisov <borisov@lexbor.com>
- */
-
-#include "lexbor/html/style.h"
-
-
-uintptr_t
-lxb_html_style_id_by_name(lxb_html_document_t *doc,
-                          const lxb_char_t *name, size_t size)
-{
-    const lxb_css_entry_data_t *data;
-
-    data = lxb_css_property_by_name(name, size);
-
-    if (data == NULL) {
-        return lxb_html_document_css_customs_find_id(doc, name, size);
-    }
-
-    return data->unique;
-}
diff --git a/ext/dom/lexbor/lexbor/html/style.h b/ext/dom/lexbor/lexbor/html/style.h
deleted file mode 100644
index 10800bcd659..00000000000
--- a/ext/dom/lexbor/lexbor/html/style.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2022-2023 Alexander Borisov
- *
- * Author: Alexander Borisov <borisov@lexbor.com>
- */
-
-#ifndef LEXBOR_HTML_STYLE_H
-#define LEXBOR_HTML_STYLE_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "lexbor/core/avl.h"
-#include "lexbor/css/selectors/selector.h"
-#include "lexbor/html/interfaces/document.h"
-
-
-typedef struct lxb_html_style_weak lxb_html_style_weak_t;
-
-struct lxb_html_style_weak {
-    void                           *value;
-    lxb_css_selector_specificity_t sp;
-
-    lxb_html_style_weak_t          *next;
-};
-
-typedef struct {
-    lexbor_avl_node_t              entry;
-    lxb_html_style_weak_t          *weak;
-
-    lxb_css_selector_specificity_t sp;
-}
-lxb_html_style_node_t;
-
-
-LXB_API uintptr_t
-lxb_html_style_id_by_name(lxb_html_document_t *doc,
-                          const lxb_char_t *name, size_t size);
-
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* LEXBOR_HTML_STYLE_H */
diff --git a/ext/dom/lexbor/lexbor/html/tag.c b/ext/dom/lexbor/lexbor/html/tag.c
new file mode 100644
index 00000000000..48f894963c5
--- /dev/null
+++ b/ext/dom/lexbor/lexbor/html/tag.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2026 Alexander Borisov
+ *
+ * Author: Alexander Borisov <borisov@lexbor.com>
+ */
+
+#include "lexbor/html/tag.h"
+#include "lexbor/html/tag_res.h"
+
+
+bool
+lxb_html_tag_is_category(lxb_tag_id_t tag_id, lxb_ns_id_t ns,
+                         lxb_html_tag_category_t cat)
+{
+    if (tag_id < LXB_TAG__LAST_ENTRY && ns < LXB_NS__LAST_ENTRY) {
+        return lxb_html_tag_res_cats[tag_id][ns] & cat;
+    }
+
+    return (LXB_HTML_TAG_CATEGORY_ORDINARY) & cat;
+}
+
+const lxb_html_tag_fixname_t *
+lxb_html_tag_fixname_svg(lxb_tag_id_t tag_id)
+{
+    if (tag_id >= LXB_TAG__LAST_ENTRY) {
+        return NULL;
+    }
+
+    return &lxb_html_tag_res_fixname_svg[tag_id];
+}
diff --git a/ext/dom/lexbor/lexbor/html/tag.h b/ext/dom/lexbor/lexbor/html/tag.h
index 6570d7d40b7..b559d31f688 100644
--- a/ext/dom/lexbor/lexbor/html/tag.h
+++ b/ext/dom/lexbor/lexbor/html/tag.h
@@ -28,8 +28,7 @@ enum lxb_html_tag_category {
     LXB_HTML_TAG_CATEGORY_SCOPE           = 0x0008,
     LXB_HTML_TAG_CATEGORY_SCOPE_LIST_ITEM = 0x0010,
     LXB_HTML_TAG_CATEGORY_SCOPE_BUTTON    = 0x0020,
-    LXB_HTML_TAG_CATEGORY_SCOPE_TABLE     = 0x0040,
-    LXB_HTML_TAG_CATEGORY_SCOPE_SELECT    = 0x0080,
+    LXB_HTML_TAG_CATEGORY_SCOPE_TABLE     = 0x0040
 };

 typedef struct {
@@ -39,35 +38,17 @@ typedef struct {
 lxb_html_tag_fixname_t;


-#define LXB_HTML_TAG_RES_CATS
-#define LXB_HTML_TAG_RES_FIXNAME_SVG
-#include "lexbor/html/tag_res.h"
+LXB_API bool
+lxb_html_tag_is_category(lxb_tag_id_t tag_id, lxb_ns_id_t ns,
+                         lxb_html_tag_category_t cat);
+
+LXB_API const lxb_html_tag_fixname_t *
+lxb_html_tag_fixname_svg(lxb_tag_id_t tag_id);


 /*
  * Inline functions
  */
-lxb_inline bool
-lxb_html_tag_is_category(lxb_tag_id_t tag_id, lxb_ns_id_t ns,
-                         lxb_html_tag_category_t cat)
-{
-    if (tag_id < LXB_TAG__LAST_ENTRY && ns < LXB_NS__LAST_ENTRY) {
-        return lxb_html_tag_res_cats[tag_id][ns] & cat;
-    }
-
-    return (LXB_HTML_TAG_CATEGORY_ORDINARY|LXB_HTML_TAG_CATEGORY_SCOPE_SELECT) & cat;
-}
-
-lxb_inline const lxb_html_tag_fixname_t *
-lxb_html_tag_fixname_svg(lxb_tag_id_t tag_id)
-{
-    if (tag_id >= LXB_TAG__LAST_ENTRY) {
-        return NULL;
-    }
-
-    return &lxb_html_tag_res_fixname_svg[tag_id];
-}
-
 lxb_inline bool
 lxb_html_tag_is_void(lxb_tag_id_t tag_id)
 {
diff --git a/ext/dom/lexbor/lexbor/html/tag_res.h b/ext/dom/lexbor/lexbor/html/tag_res.h
index 97c28640ccd..5e2453a59f2 100644
--- a/ext/dom/lexbor/lexbor/html/tag_res.h
+++ b/ext/dom/lexbor/lexbor/html/tag_res.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -14,14 +14,10 @@
 #ifndef LXB_HTML_TAG_RES_H
 #define LXB_HTML_TAG_RES_H

-#include "lexbor/html/tag.h"
-
-#endif /* LXB_HTML_TAG_RES_H */
-
 #ifdef LXB_TAG_CONST_VERSION
-#ifndef LXB_TAG_CONST_VERSION_A161EC911182C3254E7A972D5C51DF86
+#ifndef LXB_TAG_CONST_VERSION_5AB3094FB370521074947DC082575715
 #error Mismatched tags version! See "lexbor/tag/const.h".
-#endif /* LXB_TAG_CONST_VERSION_A161EC911182C3254E7A972D5C51DF86 */
+#endif /* LXB_TAG_CONST_VERSION_5AB3094FB370521074947DC082575715 */
 #else
 #error You need to include "lexbor/tag/const.h".
 #endif /* LXB_TAG_CONST_VERSION */
@@ -34,1835 +30,1476 @@
 #error You need to include "lexbor/ns/const.h".
 #endif /* LXB_NS_CONST_VERSION */

-#ifdef LXB_HTML_TAG_RES_CATS
-#ifndef LXB_HTML_TAG_RES_CATS_ENABLED
-#define LXB_HTML_TAG_RES_CATS_ENABLED
-static  lxb_html_tag_category_t lxb_html_tag_res_cats[LXB_TAG__LAST_ENTRY][LXB_NS__LAST_ENTRY] =
+LXB_API  lxb_html_tag_category_t lxb_html_tag_res_cats[LXB_TAG__LAST_ENTRY][LXB_NS__LAST_ENTRY] =
 {
     /* LXB_TAG__UNDEF */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG__END_OF_FILE */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG__TEXT */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY_ORDINARY,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY_ORDINARY,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY_ORDINARY,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY_ORDINARY
     },
     /* LXB_TAG__DOCUMENT */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY_ORDINARY,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY_ORDINARY,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY_ORDINARY,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY_ORDINARY
     },
     /* LXB_TAG__EM_COMMENT */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY_ORDINARY,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY_ORDINARY,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY_ORDINARY,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY_ORDINARY
     },
     /* LXB_TAG__EM_DOCTYPE */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY_ORDINARY,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY_ORDINARY,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY_ORDINARY,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY_ORDINARY
     },
     /* LXB_TAG_A */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_FORMATTING
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_FORMATTING,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_ABBR */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_ACRONYM */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_ADDRESS */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_ALTGLYPH */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_ALTGLYPHDEF */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_ALTGLYPHITEM */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_ANIMATECOLOR */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_ANIMATEMOTION */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_ANIMATETRANSFORM */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_ANNOTATION_XML */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY_SCOPE
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY_SCOPE
             |LXB_HTML_TAG_CATEGORY_SCOPE_BUTTON
             |LXB_HTML_TAG_CATEGORY_SCOPE_LIST_ITEM
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
             |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_APPLET */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
         LXB_HTML_TAG_CATEGORY_SCOPE
             |LXB_HTML_TAG_CATEGORY_SCOPE_BUTTON
             |LXB_HTML_TAG_CATEGORY_SCOPE_LIST_ITEM
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
             |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_AREA */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_ARTICLE */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_ASIDE */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_AUDIO */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_B */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_FORMATTING
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_FORMATTING,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_BASE */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_BASEFONT */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_BDI */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_BDO */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_BGSOUND */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_BIG */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_FORMATTING
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_FORMATTING,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_BLINK */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_BLOCKQUOTE */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_BODY */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_BR */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_BUTTON */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
         LXB_HTML_TAG_CATEGORY_SCOPE_BUTTON
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
             |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_CANVAS */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_CAPTION */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
         LXB_HTML_TAG_CATEGORY_SCOPE
             |LXB_HTML_TAG_CATEGORY_SCOPE_BUTTON
             |LXB_HTML_TAG_CATEGORY_SCOPE_LIST_ITEM
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
             |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_CENTER */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_CITE */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_CLIPPATH */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_CODE */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_FORMATTING
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_FORMATTING,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_COL */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_COLGROUP */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_DATA */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_DATALIST */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_DD */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_DEL */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_DESC */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
         LXB_HTML_TAG_CATEGORY_SCOPE
             |LXB_HTML_TAG_CATEGORY_SCOPE_BUTTON
             |LXB_HTML_TAG_CATEGORY_SCOPE_LIST_ITEM
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
             |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_DETAILS */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_DFN */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_DIALOG */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_DIR */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_DIV */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_DL */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_DT */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_EM */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_FORMATTING
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_FORMATTING,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_EMBED */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FEBLEND */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FECOLORMATRIX */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FECOMPONENTTRANSFER */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FECOMPOSITE */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FECONVOLVEMATRIX */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FEDIFFUSELIGHTING */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FEDISPLACEMENTMAP */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FEDISTANTLIGHT */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FEDROPSHADOW */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FEFLOOD */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FEFUNCA */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FEFUNCB */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FEFUNCG */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FEFUNCR */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FEGAUSSIANBLUR */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FEIMAGE */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FEMERGE */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FEMERGENODE */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FEMORPHOLOGY */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FEOFFSET */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FEPOINTLIGHT */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FESPECULARLIGHTING */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FESPOTLIGHT */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FETILE */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FETURBULENCE */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FIELDSET */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FIGCAPTION */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FIGURE */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FONT */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_FORMATTING
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_FORMATTING,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FOOTER */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FOREIGNOBJECT */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
         LXB_HTML_TAG_CATEGORY_SCOPE
             |LXB_HTML_TAG_CATEGORY_SCOPE_BUTTON
             |LXB_HTML_TAG_CATEGORY_SCOPE_LIST_ITEM
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
             |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FORM */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FRAME */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_FRAMESET */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_GLYPHREF */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_H1 */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_H2 */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_H3 */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_H4 */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_H5 */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_H6 */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_HEAD */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_HEADER */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_HGROUP */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_HR */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_HTML */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
         LXB_HTML_TAG_CATEGORY_SCOPE
             |LXB_HTML_TAG_CATEGORY_SCOPE_BUTTON
             |LXB_HTML_TAG_CATEGORY_SCOPE_LIST_ITEM
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
             |LXB_HTML_TAG_CATEGORY_SCOPE_TABLE
             |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_I */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_FORMATTING
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_FORMATTING,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_IFRAME */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_IMAGE */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_IMG */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_INPUT */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_INS */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_ISINDEX */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_KBD */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_KEYGEN */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_LABEL */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_LEGEND */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_LI */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_LINEARGRADIENT */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_LINK */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_LISTING */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_MAIN */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_MALIGNMARK */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY_ORDINARY,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY_ORDINARY,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_MAP */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_MARK */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_MARQUEE */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
         LXB_HTML_TAG_CATEGORY_SCOPE
             |LXB_HTML_TAG_CATEGORY_SCOPE_BUTTON
             |LXB_HTML_TAG_CATEGORY_SCOPE_LIST_ITEM
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
             |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_MATH */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY_ORDINARY,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_MENU */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_META */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_METER */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_MFENCED */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY_ORDINARY,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_MGLYPH */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY_ORDINARY,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY_ORDINARY,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_MI */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY_SCOPE
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY_SCOPE
             |LXB_HTML_TAG_CATEGORY_SCOPE_BUTTON
             |LXB_HTML_TAG_CATEGORY_SCOPE_LIST_ITEM
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
             |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_MN */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY_SCOPE
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY_SCOPE
             |LXB_HTML_TAG_CATEGORY_SCOPE_BUTTON
             |LXB_HTML_TAG_CATEGORY_SCOPE_LIST_ITEM
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
             |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_MO */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY_SCOPE
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY_SCOPE
             |LXB_HTML_TAG_CATEGORY_SCOPE_BUTTON
             |LXB_HTML_TAG_CATEGORY_SCOPE_LIST_ITEM
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
             |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_MS */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY_SCOPE
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY_SCOPE
             |LXB_HTML_TAG_CATEGORY_SCOPE_BUTTON
             |LXB_HTML_TAG_CATEGORY_SCOPE_LIST_ITEM
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
             |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_MTEXT */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY_SCOPE
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY_SCOPE
             |LXB_HTML_TAG_CATEGORY_SCOPE_BUTTON
             |LXB_HTML_TAG_CATEGORY_SCOPE_LIST_ITEM
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
             |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_MULTICOL */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_NAV */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_NEXTID */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_NOBR */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_FORMATTING
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_FORMATTING,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_NOEMBED */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_NOFRAMES */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_NOSCRIPT */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_OBJECT */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
         LXB_HTML_TAG_CATEGORY_SCOPE
             |LXB_HTML_TAG_CATEGORY_SCOPE_BUTTON
             |LXB_HTML_TAG_CATEGORY_SCOPE_LIST_ITEM
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
             |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_OL */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
         LXB_HTML_TAG_CATEGORY_SCOPE_LIST_ITEM
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
             |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_OPTGROUP */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_OPTION */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_OUTPUT */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_P */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_PARAM */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_PATH */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_PICTURE */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_PLAINTEXT */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_PRE */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_PROGRESS */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_Q */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_RADIALGRADIENT */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_RB */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_RP */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_RT */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_RTC */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_RUBY */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_S */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_FORMATTING
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_FORMATTING,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_SAMP */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_SCRIPT */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
+    },
+    /* LXB_TAG_SEARCH */
+    {
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_SECTION */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_SELECT */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SCOPE
+            |LXB_HTML_TAG_CATEGORY_SCOPE_BUTTON
+            |LXB_HTML_TAG_CATEGORY_SCOPE_LIST_ITEM
             |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
+    },
+    /* LXB_TAG_SELECTEDCONTENT */
+    {
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_SLOT */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_SMALL */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_FORMATTING
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_FORMATTING,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_SOURCE */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_SPACER */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_SPAN */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_STRIKE */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_FORMATTING
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_FORMATTING,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_STRONG */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_FORMATTING
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_FORMATTING,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_STYLE */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_SUB */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_SUMMARY */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_SUP */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_SVG */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_TABLE */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
         LXB_HTML_TAG_CATEGORY_SCOPE
             |LXB_HTML_TAG_CATEGORY_SCOPE_BUTTON
             |LXB_HTML_TAG_CATEGORY_SCOPE_LIST_ITEM
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
             |LXB_HTML_TAG_CATEGORY_SCOPE_TABLE
             |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_TBODY */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_TD */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
         LXB_HTML_TAG_CATEGORY_SCOPE
             |LXB_HTML_TAG_CATEGORY_SCOPE_BUTTON
             |LXB_HTML_TAG_CATEGORY_SCOPE_LIST_ITEM
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
             |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_TEMPLATE */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
         LXB_HTML_TAG_CATEGORY_SCOPE
             |LXB_HTML_TAG_CATEGORY_SCOPE_BUTTON
             |LXB_HTML_TAG_CATEGORY_SCOPE_LIST_ITEM
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
             |LXB_HTML_TAG_CATEGORY_SCOPE_TABLE
             |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_TEXTAREA */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_TEXTPATH */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_TFOOT */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_TH */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
         LXB_HTML_TAG_CATEGORY_SCOPE
             |LXB_HTML_TAG_CATEGORY_SCOPE_BUTTON
             |LXB_HTML_TAG_CATEGORY_SCOPE_LIST_ITEM
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
             |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_THEAD */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_TIME */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_TITLE */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
         LXB_HTML_TAG_CATEGORY_SCOPE
             |LXB_HTML_TAG_CATEGORY_SCOPE_BUTTON
             |LXB_HTML_TAG_CATEGORY_SCOPE_LIST_ITEM
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
             |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_TR */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_TRACK */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_TT */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_FORMATTING
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_FORMATTING,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_U */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_FORMATTING
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_FORMATTING,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_UL */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
         LXB_HTML_TAG_CATEGORY_SCOPE_LIST_ITEM
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
             |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_VAR */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_VIDEO */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_ORDINARY
-            |LXB_HTML_TAG_CATEGORY_SCOPE_SELECT,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_ORDINARY,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_WBR */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     },
     /* LXB_TAG_XMP */
     {
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY_SCOPE_SELECT
-            |LXB_HTML_TAG_CATEGORY_SPECIAL,
-        LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF,
-        LXB_HTML_TAG_CATEGORY__UNDEF, LXB_HTML_TAG_CATEGORY__UNDEF
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY_SPECIAL,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF,
+        LXB_HTML_TAG_CATEGORY__UNDEF,LXB_HTML_TAG_CATEGORY__UNDEF
     }
 };
-#endif /* LXB_HTML_TAG_RES_CATS_ENABLED */
-#endif /* LXB_HTML_TAG_RES_CATS */

-#ifdef LXB_HTML_TAG_RES_FIXNAME_SVG
-#ifndef LXB_HTML_TAG_RES_FIXNAME_SVG_ENABLED
-#define LXB_HTML_TAG_RES_FIXNAME_SVG_ENABLED
-static  lxb_html_tag_fixname_t lxb_html_tag_res_fixname_svg[LXB_TAG__LAST_ENTRY] =
+LXB_API  lxb_html_tag_fixname_t lxb_html_tag_res_fixname_svg[LXB_TAG__LAST_ENTRY] =
 {
     /* LXB_TAG__UNDEF */
     {NULL, 0},
@@ -2188,10 +1825,14 @@ static  lxb_html_tag_fixname_t lxb_html_tag_res_fixname_svg[LXB_TAG__LAST_ENTRY]
     {NULL, 0},
     /* LXB_TAG_SCRIPT */
     {NULL, 0},
+    /* LXB_TAG_SEARCH */
+    {NULL, 0},
     /* LXB_TAG_SECTION */
     {NULL, 0},
     /* LXB_TAG_SELECT */
     {NULL, 0},
+    /* LXB_TAG_SELECTEDCONTENT */
+    {NULL, 0},
     /* LXB_TAG_SLOT */
     {NULL, 0},
     /* LXB_TAG_SMALL */
@@ -2256,7 +1897,7 @@ static  lxb_html_tag_fixname_t lxb_html_tag_res_fixname_svg[LXB_TAG__LAST_ENTRY]
     {NULL, 0},
     /* LXB_TAG_XMP */
     {NULL, 0},
-
+
 };
-#endif /* LXB_HTML_TAG_RES_FIXNAME_SVG_ENABLED */
-#endif /* LXB_HTML_TAG_RES_FIXNAME_SVG */
+
+#endif /* LXB_HTML_TAG_RES_H */
diff --git a/ext/dom/lexbor/lexbor/html/token.c b/ext/dom/lexbor/lexbor/html/token.c
index 0f5d076adf5..d4ab1bbb767 100644
--- a/ext/dom/lexbor/lexbor/html/token.c
+++ b/ext/dom/lexbor/lexbor/html/token.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018-2020 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -7,11 +7,12 @@
 #include "lexbor/html/token.h"
 #include "lexbor/html/tokenizer.h"

-#define LEXBOR_STR_RES_MAP_LOWERCASE
-#define LEXBOR_STR_RES_ANSI_REPLACEMENT_CHARACTER
-#define LEXBOR_STR_RES_MAP_HEX
-#define LEXBOR_STR_RES_MAP_NUM
-#include "lexbor/core/str_res.h"
+#ifndef LEXBOR_DISABLE_INTERNAL_EXTERN
+    LXB_EXTERN const lxb_char_t lexbor_str_res_map_lowercase[256];
+    LXB_EXTERN const lxb_char_t lexbor_str_res_ansi_replacement_character[4];
+    LXB_EXTERN const lxb_char_t lexbor_str_res_map_num[256];
+    LXB_EXTERN const lxb_char_t lexbor_str_res_map_hex[256];
+#endif

 #include "lexbor/dom/interfaces/document_type.h"

diff --git a/ext/dom/lexbor/lexbor/html/tokenizer.c b/ext/dom/lexbor/lexbor/html/tokenizer.c
index 0bd9aec504f..1d9f3781255 100644
--- a/ext/dom/lexbor/lexbor/html/tokenizer.c
+++ b/ext/dom/lexbor/lexbor/html/tokenizer.c
@@ -11,19 +11,20 @@
 #include "lexbor/html/tokenizer/state_script.h"
 #include "lexbor/html/tree.h"

-#define LXB_HTML_TAG_RES_DATA
-#define LXB_HTML_TAG_RES_SHS_DATA
-#include "lexbor/html/tag_res.h"
+
+#ifndef LEXBOR_DISABLE_INTERNAL_EXTERN
+    LXB_EXTERN lxb_html_tag_category_t lxb_html_tag_res_cats[LXB_TAG__LAST_ENTRY][LXB_NS__LAST_ENTRY];
+    LXB_EXTERN lxb_html_tag_fixname_t lxb_html_tag_res_fixname_svg[LXB_TAG__LAST_ENTRY];
+#endif


 #define LXB_HTML_TKZ_TEMP_SIZE (4096 * 4)


 enum {
-    LXB_HTML_TOKENIZER_OPT_UNDEF           = 0x00,
-    LXB_HTML_TOKENIZER_OPT_TAGS_SELF       = 0x01,
-    LXB_HTML_TOKENIZER_OPT_ATTRS_SELF      = 0x02,
-    LXB_HTML_TOKENIZER_OPT_ATTRS_MRAW_SELF = 0x04
+    LXB_HTML_TOKENIZER_OPT_TAGS_SELF       = 1 << 0,
+    LXB_HTML_TOKENIZER_OPT_ATTRS_SELF      = 1 << 1,
+    LXB_HTML_TOKENIZER_OPT_ATTRS_MRAW_SELF = 1 << 2
 };


@@ -206,6 +207,8 @@ lxb_html_tokenizer_clean(lxb_html_tokenizer_t *tkz)
     tkz->is_eof = false;
     tkz->status = LXB_STATUS_OK;

+    tkz->utf8_buf_len = 0;
+
     tkz->pos = tkz->start;

     lexbor_mraw_clean(tkz->mraw);
@@ -304,12 +307,268 @@ lxb_html_tokenizer_begin(lxb_html_tokenizer_t *tkz)
     return LXB_STATUS_OK;
 }

+/*
+ * Input stream validation.
+ *
+ * Per the HTML spec §13.2.3.5: surrogates, noncharacters, and controls
+ * (other than ASCII whitespace and NULL) in the input stream are parse errors.
+ *
+ * This is a fast linear scan that only fires when
+ * LXB_HTML_TOKENIZER_OPT_VALIDATE_INPUT is set.
+ */
+
+/*
+ * Lookup: 1 if the byte is a single-byte control that needs reporting.
+ * Covers 0x01–0x08, 0x0B, 0x0E–0x1F, 0x7F.
+ * Excludes 0x00 (handled by tokenizer as UNNUCH), 0x09 (TAB), 0x0A (LF),
+ * 0x0C (FF), 0x0D (CR), 0x20 (SPACE).
+ */
+static const lxb_char_t
+lxb_html_tkz_validate_ctl[256] =
+{
+/*       0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F */
+/* 0 */  0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1,
+/* 1 */  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* 2 */  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* 3 */  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* 4 */  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* 5 */  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* 6 */  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* 7 */  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+/* 8+ */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static void
+lxb_html_tokenizer_validate_codepoint(lxb_html_tokenizer_t *tkz,
+                                      uint32_t cp, const lxb_char_t *pos)
+{
+    /* C1 controls: U+0080–U+009F */
+    if (cp >= 0x0080 && cp <= 0x009F) {
+        lxb_html_tokenizer_error_add(tkz->parse_errors, pos,
+                                     LXB_HTML_TOKENIZER_ERROR_COCHININST);
+        return;
+    }
+
+    /* Surrogates: U+D800–U+DFFF */
+    if (cp >= 0xD800 && cp <= 0xDFFF) {
+        lxb_html_tokenizer_error_add(tkz->parse_errors, pos,
+                                     LXB_HTML_TOKENIZER_ERROR_SUININST);
+        return;
+    }
+
+    /* Noncharacters: U+FDD0–U+FDEF */
+    if (cp >= 0xFDD0 && cp <= 0xFDEF) {
+        lxb_html_tokenizer_error_add(tkz->parse_errors, pos,
+                                     LXB_HTML_TOKENIZER_ERROR_NOININST);
+        return;
+    }
+
+    /* Noncharacters: U+xFFFE and U+xFFFF on every plane */
+    if ((cp & 0xFFFE) == 0xFFFE && cp <= 0x10FFFF) {
+        lxb_html_tokenizer_error_add(tkz->parse_errors, pos,
+                                     LXB_HTML_TOKENIZER_ERROR_NOININST);
+    }
+}
+
+static void
+lxb_html_tokenizer_validate_flush_utf8(lxb_html_tokenizer_t *tkz,
+                                       const lxb_char_t *pos)
+{
+    uint32_t cp;
+    unsigned len = tkz->utf8_buf_len;
+    const lxb_char_t *b = tkz->utf8_buf;
+
+    if (len < 2) {
+        goto done;
+    }
+
+    if ((b[0] & 0xE0) == 0xC0) {
+        cp = ((uint32_t)(b[0] & 0x1F) << 6) | (b[1] & 0x3F);
+        lxb_html_tokenizer_validate_codepoint(tkz, cp, pos);
+        goto done;
+    }
+
+    if (len < 3) {
+        goto done;
+    }
+
+    if ((b[0] & 0xF0) == 0xE0) {
+        cp = ((uint32_t)(b[0] & 0x0F) << 12)
+           | ((uint32_t)(b[1] & 0x3F) << 6)
+           | (b[2] & 0x3F);
+        lxb_html_tokenizer_validate_codepoint(tkz, cp, pos);
+        goto done;
+    }
+
+    if (len < 4) {
+        goto done;
+    }
+
+    if ((b[0] & 0xF8) == 0xF0) {
+        cp = ((uint32_t)(b[0] & 0x07) << 18)
+           | ((uint32_t)(b[1] & 0x3F) << 12)
+           | ((uint32_t)(b[2] & 0x3F) << 6)
+           | (b[3] & 0x3F);
+        lxb_html_tokenizer_validate_codepoint(tkz, cp, pos);
+    }
+
+done:
+
+    tkz->utf8_buf_len = 0;
+}
+
+static void
+lxb_html_tokenizer_validate_input(lxb_html_tokenizer_t *tkz,
+                                  const lxb_char_t *data, size_t size)
+{
+    uint32_t cp;
+    unsigned need, len;
+    const lxb_char_t *p, *end;
+
+    p = data;
+    end = data + size;
+
+    /* Continue incomplete UTF-8 sequence from previous chunk. */
+    if (tkz->utf8_buf_len > 0) {
+        lxb_char_t lead = tkz->utf8_buf[0];
+
+        if ((lead & 0xE0) == 0xC0) {
+            need = 2;
+        }
+        else if ((lead & 0xF0) == 0xE0) {
+            need = 3;
+        }
+        else {
+            need = 4;
+        }
+
+        while (tkz->utf8_buf_len < need && p < end) {
+            if ((*p & 0xC0) != 0x80) {
+                /* Broken sequence, skip. */
+                tkz->utf8_buf_len = 0;
+                break;
+            }
+
+            tkz->utf8_buf[tkz->utf8_buf_len++] = *p++;
+        }
+
+        if (tkz->utf8_buf_len == need) {
+            lxb_html_tokenizer_validate_flush_utf8(tkz, data);
+        }
+        else if (p >= end) {
+            /* Still incomplete, wait for more data. */
+            return;
+        }
+        else {
+            /* Broken sequence was reset above. */
+        }
+    }
+
+    while (p < end) {
+        lxb_char_t b = *p;
+
+        /* Fast path: printable ASCII (0x20–0x7E), TAB, LF, FF, CR, NULL. */
+        if (b < 0x80) {
+            if (lxb_html_tkz_validate_ctl[b]) {
+                lxb_html_tokenizer_error_add(tkz->parse_errors, p,
+                                             LXB_HTML_TOKENIZER_ERROR_COCHININST);
+            }
+
+            p++;
+            continue;
+        }
+
+        /* Multi-byte UTF-8. Determine expected length. */
+        if ((b & 0xE0) == 0xC0) {
+            need = 2;
+        }
+        else if ((b & 0xF0) == 0xE0) {
+            need = 3;
+        }
+        else if ((b & 0xF8) == 0xF0) {
+            need = 4;
+        }
+        else {
+            /* Invalid lead byte or continuation byte, skip. */
+            p++;
+            continue;
+        }
+
+        /* Check if the full sequence is available in this chunk. */
+        if ((unsigned)(end - p) < need) {
+            /* Save partial sequence for next chunk. */
+            len = (unsigned)(end - p);
+            memcpy(tkz->utf8_buf, p, len);
+            tkz->utf8_buf_len = len;
+            return;
+        }
+
+        /* Quick filter: only decode if lead byte can start a bad codepoint.
+         *
+         * 0xC2       -> C1 controls (U+0080–U+009F): second byte 0x80–0x9F
+         * 0xED       -> surrogates (U+D800–U+DFFF): second byte 0xA0–0xBF
+         * 0xEF       -> nonchars U+FDD0–U+FDEF (0xEF 0xB7 0x90–0xAF)
+         *               and U+FFFE/U+FFFF (0xEF 0xBF 0xBE/0xBF)
+         * 0xF0–0xF4  -> nonchars U+xFFFE/U+xFFFF on planes 1–16
+         */
+        if (b == 0xC2) {
+            if (p[1] <= 0x9F) {
+                cp = ((uint32_t)(b & 0x1F) << 6) | (p[1] & 0x3F);
+                lxb_html_tokenizer_validate_codepoint(tkz, cp, p);
+            }
+        }
+        else if (b == 0xED) {
+            if (p[1] >= 0xA0) {
+                cp = ((uint32_t)(b & 0x0F) << 12)
+                   | ((uint32_t)(p[1] & 0x3F) << 6)
+                   | (p[2] & 0x3F);
+                lxb_html_tokenizer_validate_codepoint(tkz, cp, p);
+            }
+        }
+        else if (b == 0xEF) {
+            if (p[1] == 0xB7 && p[2] >= 0x90 && p[2] <= 0xAF) {
+                /* U+FDD0–U+FDEF */
+                lxb_html_tokenizer_error_add(tkz->parse_errors, p,
+                                             LXB_HTML_TOKENIZER_ERROR_NOININST);
+            }
+            else if (p[1] == 0xBF && (p[2] == 0xBE || p[2] == 0xBF)) {
+                /* U+FFFE, U+FFFF */
+                lxb_html_tokenizer_error_add(tkz->parse_errors, p,
+                                             LXB_HTML_TOKENIZER_ERROR_NOININST);
+            }
+        }
+        else if (b >= 0xF0 && b <= 0xF4) {
+            /* 4-byte: check for xFFFE/xFFFF. */
+            if (p[2] == 0xBF && (p[3] == 0xBE || p[3] == 0xBF)) {
+                cp = ((uint32_t)(b & 0x07) << 18)
+                   | ((uint32_t)(p[1] & 0x3F) << 12)
+                   | ((uint32_t)(p[2] & 0x3F) << 6)
+                   | (p[3] & 0x3F);
+                lxb_html_tokenizer_validate_codepoint(tkz, cp, p);
+            }
+        }
+
+        p += need;
+    }
+}
+
 lxb_status_t
 lxb_html_tokenizer_chunk(lxb_html_tokenizer_t *tkz, const lxb_char_t *data,
                          size_t size)
 {
     const lxb_char_t *end = data + size;

+    if (tkz->opt & LXB_HTML_TOKENIZER_OPT_VALIDATE_INPUT) {
+        lxb_html_tokenizer_validate_input(tkz, data, size);
+    }
+
     tkz->is_eof = false;
     tkz->status = LXB_STATUS_OK;
     tkz->last = end;
@@ -457,6 +716,46 @@ lxb_html_tokenizer_set_state_by_tag(lxb_html_tokenizer_t *tkz, bool scripting,
     }
 }

+void
+lxb_html_tokenizer_attr_last_duplicate(lxb_html_tokenizer_t *tkz)
+{
+    lxb_html_token_t *token;
+    lxb_html_token_attr_t *attr, *last;
+
+    token = tkz->token;
+    attr = token->attr_first;
+    last = token->attr_last;
+
+    while (attr != last) {
+        if (attr->name == last->name) {
+            lxb_html_tokenizer_error_add(tkz->parse_errors, last->name_begin,
+                                         LXB_HTML_TOKENIZER_ERROR_DUAT);
+
+            lxb_html_token_attr_remove(token, last);
+            lxb_html_token_attr_destroy(last, tkz->dobj_token_attr);
+            return;
+        }
+
+        attr = attr->next;
+    }
+}
+
+void
+lxb_html_tokenizer_validate_close_tag(lxb_html_tokenizer_t *tkz)
+{
+    if (tkz->token->attr_last != NULL) {
+        lxb_html_tokenizer_error_add(tkz->parse_errors,
+                                     tkz->token->attr_last->name_begin,
+                                     LXB_HTML_TOKENIZER_ERROR_ENTAWIAT);
+    }
+
+    if (tkz->token->type & LXB_HTML_TOKEN_TYPE_CLOSE_SELF) {
+        lxb_html_tokenizer_error_add(tkz->parse_errors, tkz->token->end,
+                                     LXB_HTML_TOKENIZER_ERROR_ENTAWITRSO);
+    }
+}
+
+
 /*
  * No inline functions for ABI.
  */
@@ -508,6 +807,13 @@ lxb_html_tokenizer_tree_set_noi(lxb_html_tokenizer_t *tkz,
     lxb_html_tokenizer_tree_set(tkz, tree);
 }

+void
+lxb_html_tokenizer_input_validation_set_noi(lxb_html_tokenizer_t *tkz,
+                                            bool enabled)
+{
+    lxb_html_tokenizer_input_validation_set(tkz, enabled);
+}
+
 lexbor_mraw_t *
 lxb_html_tokenizer_mraw_noi(lxb_html_tokenizer_t *tkz)
 {
@@ -519,3 +825,10 @@ lxb_html_tokenizer_tags_noi(lxb_html_tokenizer_t *tkz)
 {
     return lxb_html_tokenizer_tags(tkz);
 }
+
+void
+lxb_html_tokenizer_keep_duplicate_set_noi(lxb_html_tokenizer_t *tkz,
+                                          bool keep)
+{
+    lxb_html_tokenizer_keep_duplicate_set(tkz, keep);
+}
diff --git a/ext/dom/lexbor/lexbor/html/tokenizer.h b/ext/dom/lexbor/lexbor/html/tokenizer.h
index 74bb55ef0fd..aa1ac37d996 100644
--- a/ext/dom/lexbor/lexbor/html/tokenizer.h
+++ b/ext/dom/lexbor/lexbor/html/tokenizer.h
@@ -21,6 +21,12 @@ extern "C" {
 #include "lexbor/ns/ns.h"


+enum {
+    LXB_HTML_TOKENIZER_OPT_UNDEF               = 0x00,
+    LXB_HTML_TOKENIZER_OPT_VALIDATE_INPUT      = 1 << 3,
+    LXB_HTML_TOKENIZER_OPT_ATTR_KEEP_DUPLICATE = 1 << 4
+};
+
 /* State */
 typedef const lxb_char_t *
 (*lxb_html_tokenizer_state_f)(lxb_html_tokenizer_t *tkz,
@@ -90,6 +96,10 @@ struct lxb_html_tokenizer {
     lxb_status_t                     status;
     bool                             is_eof;

+    /* Input stream validation (for cross-chunk UTF-8). */
+    lxb_char_t                       utf8_buf[4];
+    unsigned                         utf8_buf_len;
+
     lxb_html_tokenizer_t             *base;
     size_t                           ref_count;
 };
@@ -97,8 +107,9 @@ struct lxb_html_tokenizer {

 #include "lexbor/html/tokenizer/error.h"

-
-extern const lxb_char_t *lxb_html_tokenizer_eof;
+#ifndef LEXBOR_DISABLE_INTERNAL_EXTERN
+    LXB_EXTERN const lxb_char_t *lxb_html_tokenizer_eof;
+#endif

 LXB_API lxb_html_tokenizer_t *
 lxb_html_tokenizer_create(void);
@@ -156,6 +167,11 @@ LXB_API void
 lxb_html_tokenizer_set_state_by_tag(lxb_html_tokenizer_t *tkz, bool scripting,
                                     lxb_tag_id_t tag_id, lxb_ns_id_t ns);

+LXB_API void
+lxb_html_tokenizer_attr_last_duplicate(lxb_html_tokenizer_t *tkz);
+
+LXB_API void
+lxb_html_tokenizer_validate_close_tag(lxb_html_tokenizer_t *tkz);

 /*
  * Inline functions
@@ -250,6 +266,28 @@ lxb_html_tokenizer_mraw(lxb_html_tokenizer_t *tkz)
     return tkz->mraw;
 }

+lxb_inline void
+lxb_html_tokenizer_input_validation_set(lxb_html_tokenizer_t *tkz, bool enabled)
+{
+    if (enabled) {
+        tkz->opt |= LXB_HTML_TOKENIZER_OPT_VALIDATE_INPUT;
+    }
+    else {
+        tkz->opt &= ~LXB_HTML_TOKENIZER_OPT_VALIDATE_INPUT;
+    }
+}
+
+lxb_inline void
+lxb_html_tokenizer_keep_duplicate_set(lxb_html_tokenizer_t *tkz, bool keep)
+{
+    if (keep) {
+        tkz->opt |= LXB_HTML_TOKENIZER_OPT_ATTR_KEEP_DUPLICATE;
+    }
+    else {
+        tkz->opt &= ~LXB_HTML_TOKENIZER_OPT_ATTR_KEEP_DUPLICATE;
+    }
+}
+
 lxb_inline lxb_status_t
 lxb_html_tokenizer_temp_realloc(lxb_html_tokenizer_t *tkz, size_t size)
 {
@@ -331,12 +369,20 @@ LXB_API void
 lxb_html_tokenizer_tree_set_noi(lxb_html_tokenizer_t *tkz,
                                 lxb_html_tree_t *tree);

+LXB_API void
+lxb_html_tokenizer_input_validation_set_noi(lxb_html_tokenizer_t *tkz,
+                                            bool enabled);
+
 LXB_API lexbor_mraw_t *
 lxb_html_tokenizer_mraw_noi(lxb_html_tokenizer_t *tkz);

 LXB_API lexbor_hash_t *
 lxb_html_tokenizer_tags_noi(lxb_html_tokenizer_t *tkz);

+LXB_API void
+lxb_html_tokenizer_keep_duplicate_set_noi(lxb_html_tokenizer_t *tkz,
+                                          bool keep);
+

 #ifdef __cplusplus
 } /* extern "C" */
diff --git a/ext/dom/lexbor/lexbor/html/tokenizer/error.c b/ext/dom/lexbor/lexbor/html/tokenizer/error.c
index c2381ad97c8..241fac50976 100644
--- a/ext/dom/lexbor/lexbor/html/tokenizer/error.c
+++ b/ext/dom/lexbor/lexbor/html/tokenizer/error.c
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2018 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */

+#include "lexbor/core/str.h"
 #include "lexbor/html/tokenizer/error.h"


@@ -26,3 +27,76 @@ lxb_html_tokenizer_error_add(lexbor_array_obj_t *parse_errors,

     return entry;
 }
+
+const lxb_char_t *
+lxb_html_tokenizer_error_to_string(lxb_html_tokenizer_error_id_t id,
+                                   size_t *len)
+{
+    static const lexbor_str_t unknown = lexbor_str("unknown error");
+
+    static const lexbor_str_t errors[LXB_HTML_TOKENIZER_ERROR_LAST_ENTRY] = {
+        lexbor_str("abrupt closing of empty comment"),
+        lexbor_str("abrupt doctype public identifier"),
+        lexbor_str("abrupt doctype system identifier"),
+        lexbor_str("absence of digits in numeric character reference"),
+        lexbor_str("cdata in html content"),
+        lexbor_str("character reference outside unicode range"),
+        lexbor_str("control character in input stream"),
+        lexbor_str("control character reference"),
+        lexbor_str("end tag with attributes"),
+        lexbor_str("duplicate attribute"),
+        lexbor_str("end tag with trailing solidus"),
+        lexbor_str("eof before tag name"),
+        lexbor_str("eof in cdata"),
+        lexbor_str("eof in comment"),
+        lexbor_str("eof in doctype"),
+        lexbor_str("eof in script html comment like text"),
+        lexbor_str("eof in tag"),
+        lexbor_str("incorrectly closed comment"),
+        lexbor_str("incorrectly opened comment"),
+        lexbor_str("invalid character sequence after doctype name"),
+        lexbor_str("invalid first character of tag name"),
+        lexbor_str("missing attribute value"),
+        lexbor_str("missing doctype name"),
+        lexbor_str("missing doctype public identifier"),
+        lexbor_str("missing doctype system identifier"),
+        lexbor_str("missing end tag name"),
+        lexbor_str("missing quote before doctype public identifier"),
+        lexbor_str("missing quote before doctype system identifier"),
+        lexbor_str("missing semicolon after character reference"),
+        lexbor_str("missing whitespace after doctype public keyword"),
+        lexbor_str("missing whitespace after doctype system keyword"),
+        lexbor_str("missing whitespace before doctype name"),
+        lexbor_str("missing whitespace between attributes"),
+        lexbor_str("missing whitespace between doctype public and system identifiers"),
+        lexbor_str("nested comment"),
+        lexbor_str("noncharacter character reference"),
+        lexbor_str("noncharacter in input stream"),
+        lexbor_str("non void html element start tag with trailing solidus"),
+        lexbor_str("null character reference"),
+        lexbor_str("surrogate character reference"),
+        lexbor_str("surrogate in input stream"),
+        lexbor_str("unexpected character after doctype system identifier"),
+        lexbor_str("unexpected character in attribute name"),
+        lexbor_str("unexpected character in unquoted attribute value"),
+        lexbor_str("unexpected equals sign before attribute name"),
+        lexbor_str("unexpected null character"),
+        lexbor_str("unexpected question mark instead of tag name"),
+        lexbor_str("unexpected solidus in tag"),
+        lexbor_str("unknown named character reference")
+    };
+
+    if (id >= (sizeof(errors) / sizeof(lexbor_str_t))) {
+        if (len != NULL) {
+            *len = unknown.length;
+        }
+
+        return unknown.data;
+    }
+
+    if (len != NULL) {
+        *len = errors[id].length;
+    }
+
+    return errors[id].data;
+}
diff --git a/ext/dom/lexbor/lexbor/html/tokenizer/error.h b/ext/dom/lexbor/lexbor/html/tokenizer/error.h
index 2685f039d51..617ff636935 100644
--- a/ext/dom/lexbor/lexbor/html/tokenizer/error.h
+++ b/ext/dom/lexbor/lexbor/html/tokenizer/error.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -21,102 +21,103 @@ typedef enum {
     /* abrupt-closing-of-empty-comment */
     LXB_HTML_TOKENIZER_ERROR_ABCLOFEMCO         = 0x0000,
     /* abrupt-doctype-public-identifier */
-    LXB_HTML_TOKENIZER_ERROR_ABDOPUID           = 0x0001,
+    LXB_HTML_TOKENIZER_ERROR_ABDOPUID,
     /* abrupt-doctype-system-identifier */
-    LXB_HTML_TOKENIZER_ERROR_ABDOSYID           = 0x0002,
+    LXB_HTML_TOKENIZER_ERROR_ABDOSYID,
     /* absence-of-digits-in-numeric-character-reference */
-    LXB_HTML_TOKENIZER_ERROR_ABOFDIINNUCHRE     = 0x0003,
+    LXB_HTML_TOKENIZER_ERROR_ABOFDIINNUCHRE,
     /* cdata-in-html-content */
-    LXB_HTML_TOKENIZER_ERROR_CDINHTCO           = 0x0004,
+    LXB_HTML_TOKENIZER_ERROR_CDINHTCO,
     /* character-reference-outside-unicode-range */
-    LXB_HTML_TOKENIZER_ERROR_CHREOUUNRA         = 0x0005,
+    LXB_HTML_TOKENIZER_ERROR_CHREOUUNRA,
     /* control-character-in-input-stream */
-    LXB_HTML_TOKENIZER_ERROR_COCHININST         = 0x0006,
+    LXB_HTML_TOKENIZER_ERROR_COCHININST,
     /* control-character-reference */
-    LXB_HTML_TOKENIZER_ERROR_COCHRE             = 0x0007,
+    LXB_HTML_TOKENIZER_ERROR_COCHRE,
     /* end-tag-with-attributes */
-    LXB_HTML_TOKENIZER_ERROR_ENTAWIAT           = 0x0008,
+    LXB_HTML_TOKENIZER_ERROR_ENTAWIAT,
     /* duplicate-attribute */
-    LXB_HTML_TOKENIZER_ERROR_DUAT               = 0x0009,
+    LXB_HTML_TOKENIZER_ERROR_DUAT,
     /* end-tag-with-trailing-solidus */
-    LXB_HTML_TOKENIZER_ERROR_ENTAWITRSO         = 0x000A,
+    LXB_HTML_TOKENIZER_ERROR_ENTAWITRSO,
     /* eof-before-tag-name */
-    LXB_HTML_TOKENIZER_ERROR_EOBETANA           = 0x000B,
+    LXB_HTML_TOKENIZER_ERROR_EOBETANA,
     /* eof-in-cdata */
-    LXB_HTML_TOKENIZER_ERROR_EOINCD             = 0x000C,
+    LXB_HTML_TOKENIZER_ERROR_EOINCD,
     /* eof-in-comment */
-    LXB_HTML_TOKENIZER_ERROR_EOINCO             = 0x000D,
+    LXB_HTML_TOKENIZER_ERROR_EOINCO,
     /* eof-in-doctype */
-    LXB_HTML_TOKENIZER_ERROR_EOINDO             = 0x000E,
+    LXB_HTML_TOKENIZER_ERROR_EOINDO,
     /* eof-in-script-html-comment-like-text */
-    LXB_HTML_TOKENIZER_ERROR_EOINSCHTCOLITE     = 0x000F,
+    LXB_HTML_TOKENIZER_ERROR_EOINSCHTCOLITE,
     /* eof-in-tag */
-    LXB_HTML_TOKENIZER_ERROR_EOINTA             = 0x0010,
+    LXB_HTML_TOKENIZER_ERROR_EOINTA,
     /* incorrectly-closed-comment */
-    LXB_HTML_TOKENIZER_ERROR_INCLCO             = 0x0011,
+    LXB_HTML_TOKENIZER_ERROR_INCLCO,
     /* incorrectly-opened-comment */
-    LXB_HTML_TOKENIZER_ERROR_INOPCO             = 0x0012,
+    LXB_HTML_TOKENIZER_ERROR_INOPCO,
     /* invalid-character-sequence-after-doctype-name */
-    LXB_HTML_TOKENIZER_ERROR_INCHSEAFDONA       = 0x0013,
+    LXB_HTML_TOKENIZER_ERROR_INCHSEAFDONA,
     /* invalid-first-character-of-tag-name */
-    LXB_HTML_TOKENIZER_ERROR_INFICHOFTANA       = 0x0014,
+    LXB_HTML_TOKENIZER_ERROR_INFICHOFTANA,
     /* missing-attribute-value */
-    LXB_HTML_TOKENIZER_ERROR_MIATVA             = 0x0015,
+    LXB_HTML_TOKENIZER_ERROR_MIATVA,
     /* missing-doctype-name */
-    LXB_HTML_TOKENIZER_ERROR_MIDONA             = 0x0016,
+    LXB_HTML_TOKENIZER_ERROR_MIDONA,
     /* missing-doctype-public-identifier */
-    LXB_HTML_TOKENIZER_ERROR_MIDOPUID           = 0x0017,
+    LXB_HTML_TOKENIZER_ERROR_MIDOPUID,
     /* missing-doctype-system-identifier */
-    LXB_HTML_TOKENIZER_ERROR_MIDOSYID           = 0x0018,
+    LXB_HTML_TOKENIZER_ERROR_MIDOSYID,
     /* missing-end-tag-name */
-    LXB_HTML_TOKENIZER_ERROR_MIENTANA           = 0x0019,
+    LXB_HTML_TOKENIZER_ERROR_MIENTANA,
     /* missing-quote-before-doctype-public-identifier */
-    LXB_HTML_TOKENIZER_ERROR_MIQUBEDOPUID       = 0x001A,
+    LXB_HTML_TOKENIZER_ERROR_MIQUBEDOPUID,
     /* missing-quote-before-doctype-system-identifier */
-    LXB_HTML_TOKENIZER_ERROR_MIQUBEDOSYID       = 0x001B,
+    LXB_HTML_TOKENIZER_ERROR_MIQUBEDOSYID,
     /* missing-semicolon-after-character-reference */
-    LXB_HTML_TOKENIZER_ERROR_MISEAFCHRE         = 0x001C,
+    LXB_HTML_TOKENIZER_ERROR_MISEAFCHRE,
     /* missing-whitespace-after-doctype-public-keyword */
-    LXB_HTML_TOKENIZER_ERROR_MIWHAFDOPUKE       = 0x001D,
+    LXB_HTML_TOKENIZER_ERROR_MIWHAFDOPUKE,
     /* missing-whitespace-after-doctype-system-keyword */
-    LXB_HTML_TOKENIZER_ERROR_MIWHAFDOSYKE       = 0x001E,
+    LXB_HTML_TOKENIZER_ERROR_MIWHAFDOSYKE,
     /* missing-whitespace-before-doctype-name */
-    LXB_HTML_TOKENIZER_ERROR_MIWHBEDONA         = 0x001F,
+    LXB_HTML_TOKENIZER_ERROR_MIWHBEDONA,
     /* missing-whitespace-between-attributes */
-    LXB_HTML_TOKENIZER_ERROR_MIWHBEAT           = 0x0020,
+    LXB_HTML_TOKENIZER_ERROR_MIWHBEAT,
     /* missing-whitespace-between-doctype-public-and-system-identifiers */
-    LXB_HTML_TOKENIZER_ERROR_MIWHBEDOPUANSYID   = 0x0021,
+    LXB_HTML_TOKENIZER_ERROR_MIWHBEDOPUANSYID,
     /* nested-comment */
-    LXB_HTML_TOKENIZER_ERROR_NECO               = 0x0022,
+    LXB_HTML_TOKENIZER_ERROR_NECO,
     /* noncharacter-character-reference */
-    LXB_HTML_TOKENIZER_ERROR_NOCHRE             = 0x0023,
+    LXB_HTML_TOKENIZER_ERROR_NOCHRE,
     /* noncharacter-in-input-stream */
-    LXB_HTML_TOKENIZER_ERROR_NOININST           = 0x0024,
+    LXB_HTML_TOKENIZER_ERROR_NOININST,
     /* non-void-html-element-start-tag-with-trailing-solidus */
-    LXB_HTML_TOKENIZER_ERROR_NOVOHTELSTTAWITRSO = 0x0025,
+    LXB_HTML_TOKENIZER_ERROR_NOVOHTELSTTAWITRSO,
     /* null-character-reference */
-    LXB_HTML_TOKENIZER_ERROR_NUCHRE             = 0x0026,
+    LXB_HTML_TOKENIZER_ERROR_NUCHRE,
     /* surrogate-character-reference */
-    LXB_HTML_TOKENIZER_ERROR_SUCHRE             = 0x0027,
+    LXB_HTML_TOKENIZER_ERROR_SUCHRE,
     /* surrogate-in-input-stream */
-    LXB_HTML_TOKENIZER_ERROR_SUININST           = 0x0028,
+    LXB_HTML_TOKENIZER_ERROR_SUININST,
     /* unexpected-character-after-doctype-system-identifier */
-    LXB_HTML_TOKENIZER_ERROR_UNCHAFDOSYID       = 0x0029,
+    LXB_HTML_TOKENIZER_ERROR_UNCHAFDOSYID,
     /* unexpected-character-in-attribute-name */
-    LXB_HTML_TOKENIZER_ERROR_UNCHINATNA         = 0x002A,
+    LXB_HTML_TOKENIZER_ERROR_UNCHINATNA,
     /* unexpected-character-in-unquoted-attribute-value */
-    LXB_HTML_TOKENIZER_ERROR_UNCHINUNATVA       = 0x002B,
+    LXB_HTML_TOKENIZER_ERROR_UNCHINUNATVA,
     /* unexpected-equals-sign-before-attribute-name */
-    LXB_HTML_TOKENIZER_ERROR_UNEQSIBEATNA       = 0x002C,
+    LXB_HTML_TOKENIZER_ERROR_UNEQSIBEATNA,
     /* unexpected-null-character */
-    LXB_HTML_TOKENIZER_ERROR_UNNUCH             = 0x002D,
+    LXB_HTML_TOKENIZER_ERROR_UNNUCH,
     /* unexpected-question-mark-instead-of-tag-name */
-    LXB_HTML_TOKENIZER_ERROR_UNQUMAINOFTANA     = 0x002E,
+    LXB_HTML_TOKENIZER_ERROR_UNQUMAINOFTANA,
     /* unexpected-solidus-in-tag */
-    LXB_HTML_TOKENIZER_ERROR_UNSOINTA           = 0x002F,
+    LXB_HTML_TOKENIZER_ERROR_UNSOINTA,
     /* unknown-named-character-reference */
-    LXB_HTML_TOKENIZER_ERROR_UNNACHRE           = 0x0030,
-    LXB_HTML_TOKENIZER_ERROR_LAST_ENTRY         = 0x0031,
+    LXB_HTML_TOKENIZER_ERROR_UNNACHRE,
+
+    LXB_HTML_TOKENIZER_ERROR_LAST_ENTRY
 }
 lxb_html_tokenizer_error_id_t;

@@ -132,10 +133,13 @@ lxb_html_tokenizer_error_add(lexbor_array_obj_t *parse_errors,
                              const lxb_char_t *pos,
                              lxb_html_tokenizer_error_id_t id);

+LXB_API const lxb_char_t *
+lxb_html_tokenizer_error_to_string(lxb_html_tokenizer_error_id_t id,
+                                   size_t *len);
+

 #ifdef __cplusplus
 } /* extern "C" */
 #endif

 #endif /* LEXBOR_HTML_TOKENIZER_ERROR_H */
-
diff --git a/ext/dom/lexbor/lexbor/html/tokenizer/res.h b/ext/dom/lexbor/lexbor/html/tokenizer/res.h
index 5ec5c68bf65..55c77f9e6c3 100644
--- a/ext/dom/lexbor/lexbor/html/tokenizer/res.h
+++ b/ext/dom/lexbor/lexbor/html/tokenizer/res.h
@@ -1,12 +1,12 @@
 /*
- * Copyright (C) 2018 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */

 /*
- * Caution!!! Important!!!
- * This file is generated by the script
+ * Important!
+ * This file generated by the script
  * "utils/lexbor/html/tokenizer_entities_bst.py"!
  * Do not change this file!
  */
@@ -15,12 +15,6 @@
 #ifndef LXB_HTML_TOKENIZER_RES_H
 #define LXB_HTML_TOKENIZER_RES_H

-#endif /* LXB_HTML_TOKENIZER_RES */
-
-
-#ifdef LXB_HTML_TOKENIZER_RES_ENTITIES_SBST
-#ifndef LXB_HTML_TOKENIZER_RES_ENTITIES_SBST_ENABLED
-#define LXB_HTML_TOKENIZER_RES_ENTITIES_SBST_ENABLED
 static const lexbor_sbst_entry_static_t lxb_html_tokenizer_res_entities_sbst[] =
 {
 	{0x00, {0}, 0, 0, 0, 0}, {0x61, {0}, 0, 3, 2, 53},
@@ -4951,6 +4945,6 @@ static const lexbor_sbst_entry_static_t lxb_html_tokenizer_res_entities_sbst[] =
 	{0x3b, "\xd1\x8e", 2, 0, 0, 0}, {0x70, {0}, 0, 0, 0, 9852},
 	{0x66, {0}, 0, 0, 0, 9853}, {0x3b, "\xf0\x9d\x95\xaa", 4, 0, 0, 0}
 };
-#endif /* LXB_HTML_TOKENIZER_RES_ENTITIES_SBST_ENABLED */
-#endif /* LXB_HTML_TOKENIZER_RES_ENTITIES_SBST */

+
+#endif /* LXB_HTML_TOKENIZER_RES */
diff --git a/ext/dom/lexbor/lexbor/html/tokenizer/state.c b/ext/dom/lexbor/lexbor/html/tokenizer/state.c
index 207b909a189..6c3cbebe92a 100644
--- a/ext/dom/lexbor/lexbor/html/tokenizer/state.c
+++ b/ext/dom/lexbor/lexbor/html/tokenizer/state.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018-2020 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -8,16 +8,16 @@
 #include "lexbor/html/tokenizer/state_comment.h"
 #include "lexbor/html/tokenizer/state_doctype.h"

-#define LEXBOR_STR_RES_ANSI_REPLACEMENT_CHARACTER
-#define LEXBOR_STR_RES_ALPHANUMERIC_CHARACTER
-#define LEXBOR_STR_RES_REPLACEMENT_CHARACTER
-#define LEXBOR_STR_RES_ALPHA_CHARACTER
-#define LEXBOR_STR_RES_MAP_HEX
-#define LEXBOR_STR_RES_MAP_NUM
-#include "lexbor/core/str_res.h"
-#include "lexbor/core/swar.h"
+#ifndef LEXBOR_DISABLE_INTERNAL_EXTERN
+    LXB_EXTERN const lxb_char_t lexbor_str_res_map_num[256];
+    LXB_EXTERN const lxb_char_t lexbor_str_res_map_hex[256];
+    LXB_EXTERN const lxb_char_t lexbor_str_res_ansi_replacement_character[4];
+    LXB_EXTERN const size_t     lexbor_str_res_alphanumeric_character[256];
+    LXB_EXTERN const size_t     lexbor_str_res_alpha_character[256];
+    LXB_EXTERN const size_t     lexbor_str_res_replacement_character[160];
+#endif

-#define LXB_HTML_TOKENIZER_RES_ENTITIES_SBST
+#include "lexbor/core/swar.h"
 #include "lexbor/html/tokenizer/res.h"


@@ -123,11 +123,6 @@ lxb_html_tokenizer_state_markup_declaration_cdata(lxb_html_tokenizer_t *tkz,
                                                   const lxb_char_t *end);

 /* CDATA Section */
-static const lxb_char_t *
-lxb_html_tokenizer_state_cdata_section_before(lxb_html_tokenizer_t *tkz,
-                                              const lxb_char_t *data,
-                                              const lxb_char_t *end);
-
 static const lxb_char_t *
 lxb_html_tokenizer_state_cdata_section(lxb_html_tokenizer_t *tkz,
                                        const lxb_char_t *data,
@@ -282,7 +277,7 @@ lxb_html_tokenizer_state_data(lxb_html_tokenizer_t *tkz,
                         lxb_html_tokenizer_state_token_set_end_eof(tkz);
                     }

-                    if (tkz->token->begin != tkz->token->end) {
+                    if (tkz->pos != tkz->start) {
                         tkz->token->tag_id = LXB_TAG__TEXT;

                         lxb_html_tokenizer_state_append_data_m(tkz, data);
@@ -381,7 +376,7 @@ lxb_html_tokenizer_state_plaintext(lxb_html_tokenizer_t *tkz,
                     }

                     lxb_html_tokenizer_state_set_text(tkz);
-                    lxb_html_tokenizer_state_token_done_m(tkz, end);
+                    lxb_html_tokenizer_state_token_text_done_m(tkz, end);

                     return end;
                 }
@@ -1451,8 +1446,8 @@ lxb_html_tokenizer_state_markup_declaration_open(lxb_html_tokenizer_t *tkz,
     else if (*data == 0x5B) {
         if ((end - data) < 7) {
             tkz->markup = (lxb_char_t *) "[CDATA[";
-
             tkz->state = lxb_html_tokenizer_state_markup_declaration_cdata;
+
             return data;
         }

@@ -1469,6 +1464,9 @@ lxb_html_tokenizer_state_markup_declaration_open(lxb_html_tokenizer_t *tkz,
                 return data;
             }

+            lxb_html_tokenizer_error_add(tkz->parse_errors, data,
+                                         LXB_HTML_TOKENIZER_ERROR_CDINHTCO);
+
             tkz->state = lxb_html_tokenizer_state_bogus_comment_before;

             return data;
@@ -1504,6 +1502,8 @@ lxb_html_tokenizer_state_markup_declaration_comment(lxb_html_tokenizer_t *tkz,
         return (data + 1);
     }

+    lxb_html_tokenizer_state_append_m(tkz, "-", 1);
+
     lxb_html_tokenizer_error_add(tkz->parse_errors, data,
                                  LXB_HTML_TOKENIZER_ERROR_INOPCO);

@@ -1538,6 +1538,8 @@ lxb_html_tokenizer_state_markup_declaration_doctype(lxb_html_tokenizer_t *tkz,
         return data;
     }

+    lxb_html_tokenizer_state_append_m(tkz, data, (end - data));
+
     tkz->markup = pos;

     return end;
@@ -1575,6 +1577,9 @@ lxb_html_tokenizer_state_markup_declaration_cdata(lxb_html_tokenizer_t *tkz,

         lxb_html_tokenizer_state_append_m(tkz, "[CDATA", 6);

+        lxb_html_tokenizer_error_add(tkz->parse_errors, data,
+                                     LXB_HTML_TOKENIZER_ERROR_CDINHTCO);
+
         tkz->state = lxb_html_tokenizer_state_bogus_comment_before;
         return data;
     }
@@ -1587,7 +1592,7 @@ lxb_html_tokenizer_state_markup_declaration_cdata(lxb_html_tokenizer_t *tkz,
 /*
  * Helper function. No in the specification. For 12.2.5.69
  */
-static const lxb_char_t *
+const lxb_char_t *
 lxb_html_tokenizer_state_cdata_section_before(lxb_html_tokenizer_t *tkz,
                                               const lxb_char_t *data,
                                               const lxb_char_t *end)
@@ -1661,7 +1666,7 @@ lxb_html_tokenizer_state_cdata_section(lxb_html_tokenizer_t *tkz,
                     }

                     lxb_html_tokenizer_state_set_text(tkz);
-                    lxb_html_tokenizer_state_token_done_m(tkz, end);
+                    lxb_html_tokenizer_state_token_text_done_m(tkz, end);

                     return end;
                 }
@@ -1726,7 +1731,7 @@ lxb_html_tokenizer_state_cdata_section_end(lxb_html_tokenizer_t *tkz,
         tkz->state = lxb_html_tokenizer_state_data_before;

         lxb_html_tokenizer_state_set_text(tkz);
-        lxb_html_tokenizer_state_token_done_m(tkz, end);
+        lxb_html_tokenizer_state_token_text_done_m(tkz, end);

         return (data + 1);
     }
@@ -1857,9 +1862,28 @@ lxb_html_tokenizer_state_char_ref_named(lxb_html_tokenizer_t *tkz,
      */
     /* U+003B SEMICOLON character (;) */
     if (tkz->is_attribute && tkz->entity_match->key != 0x3B) {
+        lxb_char_t ch;
+
+        /*
+         * The "next input character" per the spec is the character immediately
+         * after the matched entity, not the character that broke the SBST
+         * lookup.  For example, for "&noti;" the match is "&not"
+         * and the next input character is 'i', not ';'.
+         *
+         * If there are trailing characters in the buffer after the match,
+         * the next input character is the first one after entity_end.
+         * Otherwise it is *data (the character that terminated the SBST).
+         */
+        if (&tkz->start[tkz->entity_end + 1] < tkz->pos) {
+            ch = tkz->start[tkz->entity_end + 1];
+        }
+        else {
+            ch = *data;
+        }
+
         /* U+003D EQUALS SIGN character (=) or ASCII alphanumeric */
-        if (*data == 0x3D
-            || lexbor_str_res_alphanumeric_character[*data] != LEXBOR_STR_RES_SLIP)
+        if (ch == 0x3D
+            || lexbor_str_res_alphanumeric_character[ch] != LEXBOR_STR_RES_SLIP)
         {
             return data;
         }
@@ -1902,16 +1926,30 @@ lxb_html_tokenizer_state_char_ref_ambiguous_ampersand(lxb_html_tokenizer_t *tkz,
                                                       const lxb_char_t *data,
                                                       const lxb_char_t *end)
 {
-    /* ASCII alphanumeric */
-    /* Skipped, not need */
+    const lxb_char_t *begin = data;

-    /* U+003B SEMICOLON (;) */
-    if (*data == 0x3B) {
-        lxb_html_tokenizer_error_add(tkz->parse_errors, data,
-                                     LXB_HTML_TOKENIZER_ERROR_UNNACHRE);
+    while (data < end) {
+        /* Not ASCII alphanumeric */
+        if (lexbor_str_res_alphanumeric_character[ *data ] == LEXBOR_STR_RES_SLIP) {
+            lxb_html_tokenizer_state_append_m(tkz, begin, (data - begin));
+
+            /* U+003B SEMICOLON (;) */
+            if (*data == 0x3B) {
+                lxb_html_tokenizer_error_add(tkz->parse_errors, data,
+                                             LXB_HTML_TOKENIZER_ERROR_UNNACHRE);
+            }
+
+            tkz->state = tkz->state_return;
+
+            return data;
+        }
+
+        data += 1;
     }

-    tkz->state = tkz->state_return;
+    if (begin < data) {
+        lxb_html_tokenizer_state_append_m(tkz, begin, (data - begin));
+    }

     return data;
 }
@@ -2002,6 +2040,10 @@ lxb_html_tokenizer_state_char_ref_hexademical(lxb_html_tokenizer_t *tkz,
             if (*data == ';') {
                 data++;
             }
+            else {
+                lxb_html_tokenizer_error_add(tkz->parse_errors, data,
+                                             LXB_HTML_TOKENIZER_ERROR_MISEAFCHRE);
+            }

             return lxb_html_tokenizer_state_char_ref_numeric_end(tkz, data, end);
         }
@@ -2032,6 +2074,10 @@ lxb_html_tokenizer_state_char_ref_decimal(lxb_html_tokenizer_t *tkz,
             if (*data == ';') {
                 data++;
             }
+            else {
+                lxb_html_tokenizer_error_add(tkz->parse_errors, data,
+                                             LXB_HTML_TOKENIZER_ERROR_MISEAFCHRE);
+            }

             return lxb_html_tokenizer_state_char_ref_numeric_end(tkz, data, end);
         }
diff --git a/ext/dom/lexbor/lexbor/html/tokenizer/state.h b/ext/dom/lexbor/lexbor/html/tokenizer/state.h
index 5b095b4249d..52eaa9a2c07 100644
--- a/ext/dom/lexbor/lexbor/html/tokenizer/state.h
+++ b/ext/dom/lexbor/lexbor/html/tokenizer/state.h
@@ -110,6 +110,10 @@ extern "C" {

 #define lxb_html_tokenizer_state_token_attr_add_m(tkz, attr, v_return)         \
     do {                                                                       \
+        if (!(tkz->opt & LXB_HTML_TOKENIZER_OPT_ATTR_KEEP_DUPLICATE)) {        \
+            lxb_html_tokenizer_attr_last_duplicate(tkz);                       \
+        }                                                                      \
+                                                                               \
         attr = lxb_html_token_attr_append(tkz->token, tkz->dobj_token_attr);   \
         if (attr == NULL) {                                                    \
             tkz->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;                  \
@@ -145,6 +149,14 @@ extern "C" {
     (tkz->token->attr_last->value_end = tkz->last)

 #define _lxb_html_tokenizer_state_token_done_m(tkz, v_end)                     \
+    if (!(tkz->opt & LXB_HTML_TOKENIZER_OPT_ATTR_KEEP_DUPLICATE)) {            \
+        lxb_html_tokenizer_attr_last_duplicate(tkz);                           \
+    }                                                                          \
+                                                                               \
+    if (tkz->token->type & LXB_HTML_TOKEN_TYPE_CLOSE) {                        \
+        lxb_html_tokenizer_validate_close_tag(tkz);                            \
+    }                                                                          \
+                                                                               \
     tkz->token = tkz->callback_token_done(tkz, tkz->token,                     \
                                           tkz->callback_token_ctx);            \
     if (tkz->token == NULL) {                                                  \
@@ -154,23 +166,32 @@ extern "C" {
         return v_end;                                                          \
     }

-#define lxb_html_tokenizer_state_token_done_m(tkz, v_end)                      \
+#define lxb_html_tokenizer_state_token_text_done_m(tkz, v_end)                 \
     do {                                                                       \
-        if (tkz->token->begin != tkz->token->end) {                            \
-            _lxb_html_tokenizer_state_token_done_m(tkz, v_end)                 \
+        if (tkz->token->text_start != tkz->token->text_end) {                  \
+            _lxb_html_tokenizer_state_token_done_m(tkz, v_end);                \
         }                                                                      \
         lxb_html_token_clean(tkz->token);                                      \
         tkz->pos = tkz->start;                                                 \
     }                                                                          \
     while (0)

-#define lxb_html_tokenizer_state_token_done_wo_check_m(tkz, v_end)             \
+#define lxb_html_tokenizer_state_token_done_m(tkz, v_end)                      \
     do {                                                                       \
         _lxb_html_tokenizer_state_token_done_m(tkz, v_end)                     \
         lxb_html_token_clean(tkz->token);                                      \
+        tkz->pos = tkz->start;                                                 \
     }                                                                          \
     while (0)

+/*
+ * This macro is alias; it serves to ensure that when reading the code,
+ * we clearly understand where checks are not necessary, i.e., we are 100% sure
+ * that the token has been collected and is ready to be sent.
+ */
+#define lxb_html_tokenizer_state_token_done_wo_check_m(tkz, v_end)             \
+    lxb_html_tokenizer_state_token_done_m(tkz, v_end)
+
 #define lxb_html_tokenizer_state_set_text(tkz)                                 \
     do {                                                                       \
         tkz->token->text_start = tkz->start;                                   \
@@ -180,7 +201,7 @@ extern "C" {

 #define lxb_html_tokenizer_state_token_emit_text_not_empty_m(tkz, v_end)       \
     do {                                                                       \
-        if (tkz->token->begin != tkz->token->end) {                            \
+        if (tkz->start != tkz->pos) {                                          \
             tkz->token->tag_id = LXB_TAG__TEXT;                                \
                                                                                \
             lxb_html_tokenizer_state_set_text(tkz);                            \
@@ -211,6 +232,11 @@ lxb_html_tokenizer_state_self_closing_start_tag(lxb_html_tokenizer_t *tkz,
                                                 const lxb_char_t *data,
                                                 const lxb_char_t *end);

+LXB_API const lxb_char_t *
+lxb_html_tokenizer_state_cdata_section_before(lxb_html_tokenizer_t *tkz,
+                                              const lxb_char_t *data,
+                                              const lxb_char_t *end);
+
 LXB_API const lxb_char_t *
 lxb_html_tokenizer_state_cr(lxb_html_tokenizer_t *tkz, const lxb_char_t *data,
                             const lxb_char_t *end);
diff --git a/ext/dom/lexbor/lexbor/html/tokenizer/state_comment.c b/ext/dom/lexbor/lexbor/html/tokenizer/state_comment.c
index fd1c2ead980..870b54578c6 100644
--- a/ext/dom/lexbor/lexbor/html/tokenizer/state_comment.c
+++ b/ext/dom/lexbor/lexbor/html/tokenizer/state_comment.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018-2020 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -7,9 +7,9 @@
 #include "lexbor/html/tokenizer/state_comment.h"
 #include "lexbor/html/tokenizer/state.h"

-#define LEXBOR_STR_RES_ANSI_REPLACEMENT_CHARACTER
-#include "lexbor/core/str_res.h"
-
+#ifndef LEXBOR_DISABLE_INTERNAL_EXTERN
+LXB_EXTERN const lxb_char_t lexbor_str_res_ansi_replacement_character[4];
+#endif

 static const lxb_char_t *
 lxb_html_tokenizer_state_comment_start(lxb_html_tokenizer_t *tkz,
@@ -143,8 +143,6 @@ lxb_html_tokenizer_state_comment_start_dash(lxb_html_tokenizer_t *tkz,
     /* EOF */
     else if (*data == 0x00) {
         if (tkz->is_eof) {
-            lxb_html_tokenizer_state_append_m(tkz, "-", 1);
-
             lxb_html_tokenizer_error_add(tkz->parse_errors, tkz->last,
                                          LXB_HTML_TOKENIZER_ERROR_EOINCO);

@@ -452,8 +450,12 @@ lxb_html_tokenizer_state_comment_end_bang(lxb_html_tokenizer_t *tkz,
                                           const lxb_char_t *data,
                                           const lxb_char_t *end)
 {
+    static const lexbor_str_t two = lexbor_str("--!");
+
     /* U+002D HYPHEN-MINUS (-) */
     if (*data == 0x2D) {
+        lxb_html_tokenizer_state_append_m(tkz, two.data, two.length);
+
         tkz->state = lxb_html_tokenizer_state_comment_end_dash;

         return (data + 1);
@@ -481,6 +483,11 @@ lxb_html_tokenizer_state_comment_end_bang(lxb_html_tokenizer_t *tkz,

             return end;
         }
+
+        lxb_html_tokenizer_state_append_m(tkz, two.data, two.length);
+    }
+    else {
+        lxb_html_tokenizer_state_append_m(tkz, two.data, two.length);
     }

     tkz->state = lxb_html_tokenizer_state_comment;
diff --git a/ext/dom/lexbor/lexbor/html/tokenizer/state_doctype.c b/ext/dom/lexbor/lexbor/html/tokenizer/state_doctype.c
index 90466789cc0..7ccb02e08b2 100644
--- a/ext/dom/lexbor/lexbor/html/tokenizer/state_doctype.c
+++ b/ext/dom/lexbor/lexbor/html/tokenizer/state_doctype.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018-2020 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -7,10 +7,9 @@
 #include "lexbor/html/tokenizer/state_doctype.h"
 #include "lexbor/html/tokenizer/state.h"

-
-#define LEXBOR_STR_RES_ANSI_REPLACEMENT_CHARACTER
-#include "lexbor/core/str_res.h"
-
+#ifndef LEXBOR_DISABLE_INTERNAL_EXTERN
+    LXB_EXTERN const lxb_char_t lexbor_str_res_ansi_replacement_character[4];
+#endif

 lxb_dom_attr_data_t *
 lxb_dom_attr_local_name_append(lexbor_hash_t *hash,
@@ -527,6 +526,7 @@ lxb_html_tokenizer_state_doctype_after_name_public(lxb_html_tokenizer_t *tkz,
         lxb_html_tokenizer_error_add(tkz->parse_errors, data,
                                      LXB_HTML_TOKENIZER_ERROR_INCHSEAFDONA);

+        tkz->token->type |= LXB_HTML_TOKEN_TYPE_FORCE_QUIRKS;
         tkz->state = lxb_html_tokenizer_state_doctype_bogus;

         return data;
@@ -577,6 +577,7 @@ lxb_html_tokenizer_state_doctype_after_name_system(lxb_html_tokenizer_t *tkz,
         lxb_html_tokenizer_error_add(tkz->parse_errors, data,
                                      LXB_HTML_TOKENIZER_ERROR_INCHSEAFDONA);

+        tkz->token->type |= LXB_HTML_TOKEN_TYPE_FORCE_QUIRKS;
         tkz->state = lxb_html_tokenizer_state_doctype_bogus;

         return data;
@@ -797,6 +798,7 @@ lxb_html_tokenizer_state_doctype_public_identifier_double_quoted(lxb_html_tokeni
             /* U+003E GREATER-THAN SIGN (>) */
             case 0x3E:
                 tkz->state = lxb_html_tokenizer_state_data_before;
+                tkz->token->type |= LXB_HTML_TOKEN_TYPE_FORCE_QUIRKS;

                 lxb_html_tokenizer_error_add(tkz->parse_errors, data,
                                              LXB_HTML_TOKENIZER_ERROR_ABDOPUID);
@@ -912,6 +914,7 @@ lxb_html_tokenizer_state_doctype_public_identifier_single_quoted(lxb_html_tokeni
             /* U+003E GREATER-THAN SIGN (>) */
             case 0x3E:
                 tkz->state = lxb_html_tokenizer_state_data_before;
+                tkz->token->type |= LXB_HTML_TOKEN_TYPE_FORCE_QUIRKS;

                 lxb_html_tokenizer_error_add(tkz->parse_errors, data,
                                              LXB_HTML_TOKENIZER_ERROR_ABDOPUID);
@@ -1350,6 +1353,7 @@ lxb_html_tokenizer_state_doctype_system_identifier_double_quoted(lxb_html_tokeni
             /* U+003E GREATER-THAN SIGN (>) */
             case 0x3E:
                 tkz->state = lxb_html_tokenizer_state_data_before;
+                tkz->token->type |= LXB_HTML_TOKEN_TYPE_FORCE_QUIRKS;

                 lxb_html_tokenizer_error_add(tkz->parse_errors, data,
                                              LXB_HTML_TOKENIZER_ERROR_ABDOSYID);
@@ -1465,6 +1469,7 @@ lxb_html_tokenizer_state_doctype_system_identifier_single_quoted(lxb_html_tokeni
             /* U+003E GREATER-THAN SIGN (>) */
             case 0x3E:
                 tkz->state = lxb_html_tokenizer_state_data_before;
+                tkz->token->type |= LXB_HTML_TOKEN_TYPE_FORCE_QUIRKS;

                 lxb_html_tokenizer_error_add(tkz->parse_errors, data,
                                              LXB_HTML_TOKENIZER_ERROR_ABDOSYID);
diff --git a/ext/dom/lexbor/lexbor/html/tokenizer/state_rawtext.c b/ext/dom/lexbor/lexbor/html/tokenizer/state_rawtext.c
index 6629ca91034..456266b6e33 100644
--- a/ext/dom/lexbor/lexbor/html/tokenizer/state_rawtext.c
+++ b/ext/dom/lexbor/lexbor/html/tokenizer/state_rawtext.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018-2020 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -7,10 +7,10 @@
 #include "lexbor/html/tokenizer/state_rawtext.h"
 #include "lexbor/html/tokenizer/state.h"

-#define LEXBOR_STR_RES_ANSI_REPLACEMENT_CHARACTER
-#define LEXBOR_STR_RES_ALPHA_CHARACTER
-#include "lexbor/core/str_res.h"
-
+#ifndef LEXBOR_DISABLE_INTERNAL_EXTERN
+    LXB_EXTERN const lxb_char_t lexbor_str_res_ansi_replacement_character[4];
+    LXB_EXTERN const size_t     lexbor_str_res_alpha_character[256];
+#endif

 const lxb_tag_data_t *
 lxb_tag_append_lower(lexbor_hash_t *hash,
@@ -114,7 +114,7 @@ lxb_html_tokenizer_state_rawtext(lxb_html_tokenizer_t *tkz,
                     tkz->token->tag_id = LXB_TAG__TEXT;

                     lxb_html_tokenizer_state_set_text(tkz);
-                    lxb_html_tokenizer_state_token_done_m(tkz, end);
+                    lxb_html_tokenizer_state_token_text_done_m(tkz, end);

                     return end;
                 }
@@ -246,7 +246,7 @@ lxb_html_tokenizer_state_rawtext_end_tag_name(lxb_html_tokenizer_t *tkz,
                 tkz->pos = &tkz->start[tkz->entity_start];

                 lxb_html_tokenizer_state_set_text(tkz);
-                lxb_html_tokenizer_state_token_done_m(tkz, end);
+                lxb_html_tokenizer_state_token_text_done_m(tkz, end);

                 /* Init close token */
                 tkz->token->tag_id = tkz->tmp_tag_id;
@@ -291,7 +291,7 @@ lxb_html_tokenizer_state_rawtext_end_tag_name(lxb_html_tokenizer_t *tkz,
     tkz->pos = &tkz->start[tkz->entity_start];

     lxb_html_tokenizer_state_set_text(tkz);
-    lxb_html_tokenizer_state_token_done_m(tkz, end);
+    lxb_html_tokenizer_state_token_text_done_m(tkz, end);

     /* Init close token */
     tkz->token->tag_id = tkz->tmp_tag_id;
diff --git a/ext/dom/lexbor/lexbor/html/tokenizer/state_rcdata.c b/ext/dom/lexbor/lexbor/html/tokenizer/state_rcdata.c
index f47dc7e87a2..02e68b32454 100644
--- a/ext/dom/lexbor/lexbor/html/tokenizer/state_rcdata.c
+++ b/ext/dom/lexbor/lexbor/html/tokenizer/state_rcdata.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018-2020 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -7,10 +7,10 @@
 #include "lexbor/html/tokenizer/state_rcdata.h"
 #include "lexbor/html/tokenizer/state.h"

-#define LEXBOR_STR_RES_ANSI_REPLACEMENT_CHARACTER
-#define LEXBOR_STR_RES_ALPHA_CHARACTER
-#include "lexbor/core/str_res.h"
-
+#ifndef LEXBOR_DISABLE_INTERNAL_EXTERN
+    LXB_EXTERN const lxb_char_t lexbor_str_res_ansi_replacement_character[4];
+    LXB_EXTERN const size_t     lexbor_str_res_alpha_character[256];
+#endif

 const lxb_tag_data_t *
 lxb_tag_append_lower(lexbor_hash_t *hash,
@@ -123,7 +123,7 @@ lxb_html_tokenizer_state_rcdata(lxb_html_tokenizer_t *tkz,
                     tkz->token->tag_id = LXB_TAG__TEXT;

                     lxb_html_tokenizer_state_set_text(tkz);
-                    lxb_html_tokenizer_state_token_done_m(tkz, end);
+                    lxb_html_tokenizer_state_token_text_done_m(tkz, end);

                     return end;
                 }
@@ -255,7 +255,7 @@ lxb_html_tokenizer_state_rcdata_end_tag_name(lxb_html_tokenizer_t *tkz,
                 tkz->pos = &tkz->start[tkz->entity_start];

                 lxb_html_tokenizer_state_set_text(tkz);
-                lxb_html_tokenizer_state_token_done_m(tkz, end);
+                lxb_html_tokenizer_state_token_text_done_m(tkz, end);

                 /* Init close token */
                 tkz->token->tag_id = tkz->tmp_tag_id;
@@ -300,7 +300,7 @@ lxb_html_tokenizer_state_rcdata_end_tag_name(lxb_html_tokenizer_t *tkz,
     tkz->pos = &tkz->start[tkz->entity_start];

     lxb_html_tokenizer_state_set_text(tkz);
-    lxb_html_tokenizer_state_token_done_m(tkz, end);
+    lxb_html_tokenizer_state_token_text_done_m(tkz, end);

     /* Init close token */
     tkz->token->tag_id = tkz->tmp_tag_id;
diff --git a/ext/dom/lexbor/lexbor/html/tokenizer/state_script.c b/ext/dom/lexbor/lexbor/html/tokenizer/state_script.c
index 4d56d18f7f3..26e694f8f51 100644
--- a/ext/dom/lexbor/lexbor/html/tokenizer/state_script.c
+++ b/ext/dom/lexbor/lexbor/html/tokenizer/state_script.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018-2020 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -7,12 +7,11 @@
 #include "lexbor/html/tokenizer/state_script.h"
 #include "lexbor/html/tokenizer/state.h"

-#define LEXBOR_STR_RES_ALPHA_CHARACTER
-#define LEXBOR_STR_RES_ANSI_REPLACEMENT_CHARACTER
-#include "lexbor/core/str_res.h"
-
-#include "lexbor/core/str_res.h"
-
+#ifndef LEXBOR_DISABLE_INTERNAL_EXTERN
+    LXB_EXTERN const size_t lexbor_str_res_alpha_character[256];
+    LXB_EXTERN const size_t lexbor_str_res_replacement_character[160];
+    LXB_EXTERN const lxb_char_t lexbor_str_res_ansi_replacement_character[4];
+#endif

 const lxb_tag_data_t *
 lxb_tag_append_lower(lexbor_hash_t *hash,
@@ -203,7 +202,7 @@ lxb_html_tokenizer_state_script_data(lxb_html_tokenizer_t *tkz,
                     tkz->token->tag_id = LXB_TAG__TEXT;

                     lxb_html_tokenizer_state_set_text(tkz);
-                    lxb_html_tokenizer_state_token_done_m(tkz, end);
+                    lxb_html_tokenizer_state_token_text_done_m(tkz, end);

                     return end;
                 }
@@ -347,7 +346,7 @@ lxb_html_tokenizer_state_script_data_end_tag_name(lxb_html_tokenizer_t *tkz,
                 tkz->pos = &tkz->start[tkz->entity_start];

                 lxb_html_tokenizer_state_set_text(tkz);
-                lxb_html_tokenizer_state_token_done_m(tkz, end);
+                lxb_html_tokenizer_state_token_text_done_m(tkz, end);

                 /* Init close token */
                 tkz->token->tag_id = tkz->tmp_tag_id;
@@ -391,7 +390,7 @@ lxb_html_tokenizer_state_script_data_end_tag_name(lxb_html_tokenizer_t *tkz,
     tkz->pos = &tkz->start[tkz->entity_start];

     lxb_html_tokenizer_state_set_text(tkz);
-    lxb_html_tokenizer_state_token_done_m(tkz, end);
+    lxb_html_tokenizer_state_token_text_done_m(tkz, end);

     /* Init close token */
     tkz->token->tag_id = tkz->tmp_tag_id;
@@ -517,7 +516,7 @@ lxb_html_tokenizer_state_script_data_escaped(lxb_html_tokenizer_t *tkz,

                     lxb_html_tokenizer_state_set_text(tkz);
                     lxb_html_tokenizer_state_token_set_end_eof(tkz);
-                    lxb_html_tokenizer_state_token_done_m(tkz, end);
+                    lxb_html_tokenizer_state_token_text_done_m(tkz, end);

                     return end;
                 }
@@ -581,7 +580,7 @@ lxb_html_tokenizer_state_script_data_escaped_dash(lxb_html_tokenizer_t *tkz,

                 lxb_html_tokenizer_state_set_text(tkz);
                 lxb_html_tokenizer_state_token_set_end_eof(tkz);
-                lxb_html_tokenizer_state_token_done_m(tkz, end);
+                lxb_html_tokenizer_state_token_text_done_m(tkz, end);

                 return end;
             }
@@ -758,7 +757,7 @@ lxb_html_tokenizer_state_script_data_escaped_end_tag_name(
                 tkz->pos = &tkz->start[tkz->entity_start];

                 lxb_html_tokenizer_state_set_text(tkz);
-                lxb_html_tokenizer_state_token_done_m(tkz, end);
+                lxb_html_tokenizer_state_token_text_done_m(tkz, end);

                 /* Init close token */
                 tkz->token->tag_id = tkz->tmp_tag_id;
@@ -802,7 +801,7 @@ lxb_html_tokenizer_state_script_data_escaped_end_tag_name(
     tkz->pos = &tkz->start[tkz->entity_start];

     lxb_html_tokenizer_state_set_text(tkz);
-    lxb_html_tokenizer_state_token_done_m(tkz, end);
+    lxb_html_tokenizer_state_token_text_done_m(tkz, end);

     /* Init close token */
     tkz->token->tag_id = tkz->tmp_tag_id;
@@ -947,7 +946,7 @@ lxb_html_tokenizer_state_script_data_double_escaped(lxb_html_tokenizer_t *tkz,

                     lxb_html_tokenizer_state_set_text(tkz);
                     lxb_html_tokenizer_state_token_set_end_eof(tkz);
-                    lxb_html_tokenizer_state_token_done_m(tkz, end);
+                    lxb_html_tokenizer_state_token_text_done_m(tkz, end);

                     return end;
                 }
@@ -1011,7 +1010,7 @@ lxb_html_tokenizer_state_script_data_double_escaped_dash(lxb_html_tokenizer_t *t

                 lxb_html_tokenizer_state_set_text(tkz);
                 lxb_html_tokenizer_state_token_set_end_eof(tkz);
-                lxb_html_tokenizer_state_token_done_m(tkz, end);
+                lxb_html_tokenizer_state_token_text_done_m(tkz, end);

                 return end;
             }
@@ -1077,7 +1076,7 @@ lxb_html_tokenizer_state_script_data_double_escaped_dash_dash(

                 lxb_html_tokenizer_state_set_text(tkz);
                 lxb_html_tokenizer_state_token_set_end_eof(tkz);
-                lxb_html_tokenizer_state_token_done_m(tkz, end);
+                lxb_html_tokenizer_state_token_text_done_m(tkz, end);

                 return end;
             }
diff --git a/ext/dom/lexbor/lexbor/html/tree.c b/ext/dom/lexbor/lexbor/html/tree.c
index 91bfd17ee1d..3f4c18d7fa4 100644
--- a/ext/dom/lexbor/lexbor/html/tree.c
+++ b/ext/dom/lexbor/lexbor/html/tree.c
@@ -19,6 +19,7 @@
 #include "lexbor/html/interface.h"
 #include "lexbor/html/interfaces/template_element.h"
 #include "lexbor/html/interfaces/unknown_element.h"
+#include "lexbor/html/interfaces/option_element.h"
 #include "lexbor/html/tokenizer/state_rawtext.h"
 #include "lexbor/html/tokenizer/state_rcdata.h"

@@ -390,7 +391,8 @@ lxb_html_tree_appropriate_place_inserting_node(lxb_html_tree_t *tree,

 lxb_html_element_t *
 lxb_html_tree_insert_foreign_element(lxb_html_tree_t *tree,
-                                     lxb_html_token_t *token, lxb_ns_id_t ns)
+                                     lxb_html_token_t *token, lxb_ns_id_t ns,
+                                     bool only_add_stack)
 {
     lxb_status_t status;
     lxb_dom_node_t *pos;
@@ -407,7 +409,9 @@ lxb_html_tree_insert_foreign_element(lxb_html_tree_t *tree,
         return NULL;
     }

-    lxb_html_tree_insert_node(pos, lxb_dom_interface_node(element), ipos);
+    if (only_add_stack == false) {
+        lxb_html_tree_insert_node(pos, lxb_dom_interface_node(element), ipos);
+    }

     status = lxb_html_tree_open_elements_push(tree,
                                               lxb_dom_interface_node(element));
@@ -1033,44 +1037,7 @@ lxb_html_tree_reset_insertion_mode_appropriately(lxb_html_tree_t *tree)
             continue;
         }

-        /* Step 4 */
-        if (node->local_name == LXB_TAG_SELECT) {
-            /* Step 4.1 */
-            if (last) {
-                tree->mode = lxb_html_tree_insertion_mode_in_select;
-                return;
-            }
-
-            /* Step 4.2 */
-            size_t ancestor = idx;
-
-            for (;;) {
-                /* Step 4.3 */
-                if (ancestor == 0) {
-                    tree->mode = lxb_html_tree_insertion_mode_in_select;
-                    return;
-                }
-
-                /* Step 4.4 */
-                ancestor--;
-
-                /* Step 4.5 */
-                lxb_dom_node_t *ancestor_node = list[ancestor];
-
-                if(lxb_html_tree_node_is(ancestor_node, LXB_TAG_TEMPLATE)) {
-                    tree->mode = lxb_html_tree_insertion_mode_in_select;
-                    return;
-                }
-
-                /* Step 4.6 */
-                else if(lxb_html_tree_node_is(ancestor_node, LXB_TAG_TABLE)) {
-                    tree->mode = lxb_html_tree_insertion_mode_in_select_in_table;
-                    return;
-                }
-            }
-        }
-
-        /* Step 5-15 */
+        /* Step 4-15 */
         switch (node->local_name) {
             case LXB_TAG_TD:
             case LXB_TAG_TH:
@@ -1309,6 +1276,41 @@ lxb_html_tree_element_in_scope_td_th(lxb_html_tree_t *tree)
     return NULL;
 }

+lxb_dom_node_t *
+lxb_html_tree_element_in_scope_option_optgroup(lxb_html_tree_t *tree)
+{
+    lxb_dom_node_t *node;
+
+    size_t idx = tree->open_elements->length;
+    void **list = tree->open_elements->list;
+
+    while (idx != 0) {
+        idx--;
+        node = list[idx];
+
+        switch (node->local_name) {
+            case LXB_TAG_OPTION:
+            case LXB_TAG_OPTGROUP:
+                if (node->ns == LXB_NS_HTML) {
+                    return node;
+                }
+
+                break;
+
+            default:
+                break;
+        }
+
+        if (lxb_html_tag_is_category(node->local_name, LXB_NS_HTML,
+                                     LXB_HTML_TAG_CATEGORY_SCOPE))
+        {
+            return NULL;
+        }
+    }
+
+    return NULL;
+}
+
 bool
 lxb_html_tree_check_scope_element(lxb_html_tree_t *tree)
 {
@@ -1362,8 +1364,6 @@ lxb_html_tree_close_p_element(lxb_html_tree_t *tree, lxb_html_token_t *token)
                                                  true);
 }

-#include "lexbor/html/serialize.h"
-
 bool
 lxb_html_tree_adoption_agency_algorithm(lxb_html_tree_t *tree,
                                         lxb_html_token_t *token,
diff --git a/ext/dom/lexbor/lexbor/html/tree.h b/ext/dom/lexbor/lexbor/html/tree.h
index 8ad32a4c1be..7b2c6203049 100644
--- a/ext/dom/lexbor/lexbor/html/tree.h
+++ b/ext/dom/lexbor/lexbor/html/tree.h
@@ -114,7 +114,8 @@ lxb_html_tree_appropriate_place_inserting_node(lxb_html_tree_t *tree,

 LXB_API lxb_html_element_t *
 lxb_html_tree_insert_foreign_element(lxb_html_tree_t *tree,
-                                     lxb_html_token_t *token, lxb_ns_id_t ns);
+                                     lxb_html_token_t *token, lxb_ns_id_t ns,
+                                     bool only_add_stack);

 LXB_API lxb_html_element_t *
 lxb_html_tree_create_element_for_token(lxb_html_tree_t *tree,
@@ -201,6 +202,9 @@ lxb_html_tree_element_in_scope_tbody_thead_tfoot(lxb_html_tree_t *tree);
 LXB_API lxb_dom_node_t *
 lxb_html_tree_element_in_scope_td_th(lxb_html_tree_t *tree);

+LXB_API lxb_dom_node_t *
+lxb_html_tree_element_in_scope_option_optgroup(lxb_html_tree_t *tree);
+
 LXB_API bool
 lxb_html_tree_check_scope_element(lxb_html_tree_t *tree);

@@ -307,7 +311,8 @@ lxb_inline lxb_html_element_t *
 lxb_html_tree_insert_html_element(lxb_html_tree_t *tree,
                                   lxb_html_token_t *token)
 {
-    return lxb_html_tree_insert_foreign_element(tree, token, LXB_NS_HTML);
+    return lxb_html_tree_insert_foreign_element(tree, token, LXB_NS_HTML,
+                                                false);
 }

 lxb_inline void
@@ -374,6 +379,21 @@ lxb_html_tree_attach_document(lxb_html_tree_t *tree, lxb_html_document_t *doc)
     tree->document = doc;
 }

+lxb_inline bool
+lxb_html_tree_is_fragment(lxb_html_tree_t *tree)
+{
+    return tree->fragment != NULL;
+}
+
+lxb_inline bool
+lxb_html_tree_is_fragment_element(lxb_html_tree_t *tree,
+                                  lxb_tag_id_t tag_id, lxb_ns_id_t ns)
+{
+    lxb_dom_node_t *fragment = tree->fragment;
+
+    return lxb_html_tree_is_fragment(tree)
+            && fragment->local_name == tag_id && fragment->ns == ns;
+}

 #ifdef __cplusplus
 } /* extern "C" */
diff --git a/ext/dom/lexbor/lexbor/html/tree/error.c b/ext/dom/lexbor/lexbor/html/tree/error.c
index 88ad8c44795..ef36eab8d22 100644
--- a/ext/dom/lexbor/lexbor/html/tree/error.c
+++ b/ext/dom/lexbor/lexbor/html/tree/error.c
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2018 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */

+#include "lexbor/core/str.h"
 #include "lexbor/html/tree/error.h"


@@ -27,3 +28,68 @@ lxb_html_tree_error_add(lexbor_array_obj_t *parse_errors,

     return entry;
 }
+
+const lxb_char_t *
+lxb_html_tree_error_to_string(lxb_html_tree_error_id_t id, size_t *len)
+{
+    static const lexbor_str_t unknown = lexbor_str("unknown error");
+
+    static const lexbor_str_t errors[LXB_HTML_RULES_ERROR_LAST_ENTRY] = {
+        lexbor_str("unexpected token"),
+        lexbor_str("unexpected closed token"),
+        lexbor_str("null character"),
+        lexbor_str("unexpected character token"),
+        lexbor_str("unexpected token in initial mode"),
+        lexbor_str("bad doctype token in initial mode"),
+        lexbor_str("doctype token in before html mode"),
+        lexbor_str("unexpected closed token in before html mode"),
+        lexbor_str("doctype token in before head mode"),
+        lexbor_str("unexpected closed token in before head mode"),
+        lexbor_str("doctype token in head mode"),
+        lexbor_str("non void html element start tag with trailing solidus"),
+        lexbor_str("head token in head mode"),
+        lexbor_str("unexpected closed token in head mode"),
+        lexbor_str("template closed token without opening in head mode"),
+        lexbor_str("template element is not current in head mode"),
+        lexbor_str("doctype token in head noscript mode"),
+        lexbor_str("doctype token after head mode"),
+        lexbor_str("head token after head mode"),
+        lexbor_str("doctype token in body mode"),
+        lexbor_str("bad ending open elements is wrong"),
+        lexbor_str("open elements is wrong"),
+        lexbor_str("unexpected element in open elements stack"),
+        lexbor_str("missing element in open elements stack"),
+        lexbor_str("no body element in scope"),
+        lexbor_str("missing element in scope"),
+        lexbor_str("unexpected element in scope"),
+        lexbor_str("unexpected element in active formatting stack"),
+        lexbor_str("unexpected end of file"),
+        lexbor_str("characters in table text"),
+        lexbor_str("doctype token in table mode"),
+        lexbor_str("doctype token in select mode"),
+        lexbor_str("doctype token after body mode"),
+        lexbor_str("doctype token in frameset mode"),
+        lexbor_str("doctype token after frameset mode"),
+        lexbor_str("doctype token foreign content mode"),
+        lexbor_str("select in scope"),
+        lexbor_str("fragment parsing select in context parse input"),
+        lexbor_str("fragment parsing select in context parse select"),
+        lexbor_str("hr parsing select option optgroup in scope"),
+        lexbor_str("option parsing option in scope"),
+        lexbor_str("optgroup parsing option optgroup in scope")
+    };
+
+    if (id >= (sizeof(errors) / sizeof(lexbor_str_t))) {
+        if (len != NULL) {
+            *len = unknown.length;
+        }
+
+        return unknown.data;
+    }
+
+    if (len != NULL) {
+        *len = errors[id].length;
+    }
+
+    return errors[id].data;
+}
diff --git a/ext/dom/lexbor/lexbor/html/tree/error.h b/ext/dom/lexbor/lexbor/html/tree/error.h
index ed1859f355a..b1867725ef9 100644
--- a/ext/dom/lexbor/lexbor/html/tree/error.h
+++ b/ext/dom/lexbor/lexbor/html/tree/error.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -90,6 +90,18 @@ typedef enum {
     LXB_HTML_RULES_ERROR_DOTOAFFRMO,
     /* doctype-token-foreign-content-mode */
     LXB_HTML_RULES_ERROR_DOTOFOCOMO,
+    /* select-in-scope */
+    LXB_HTML_RULES_ERROR_SEINSC,
+    /* fragment-parsing-select-in-context-parse-input */
+    LXB_HTML_RULES_ERROR_FRPASEINCOPAIN,
+    /* fragment-parsing-select-in-context-parse-select */
+    LXB_HTML_RULES_ERROR_FRPASEINCOPASE,
+    /* hr-parsing-select-option-optgroup-in-scope */
+    LXB_HTML_RULES_ERROR_HRPASEOPOPINSC,
+    /* option-parsing-option-in-scope */
+    LXB_HTML_RULES_ERROR_OPPAOPINSC,
+    /* optgroup-parsing-option-optgroup-in-scope */
+    LXB_HTML_RULES_ERROR_OPPAOPOPINSC,

     LXB_HTML_RULES_ERROR_LAST_ENTRY
 }
@@ -108,10 +120,12 @@ LXB_API lxb_html_tree_error_t *
 lxb_html_tree_error_add(lexbor_array_obj_t *parse_errors,
                         lxb_html_token_t *token, lxb_html_tree_error_id_t id);

+LXB_API const lxb_char_t *
+lxb_html_tree_error_to_string(lxb_html_tree_error_id_t id, size_t *len);
+

 #ifdef __cplusplus
 } /* extern "C" */
 #endif

 #endif /* LEXBOR_HTML_TREE_ERROR_H */
-
diff --git a/ext/dom/lexbor/lexbor/html/tree/insertion_mode.h b/ext/dom/lexbor/lexbor/html/tree/insertion_mode.h
index 97cc29fa6aa..5817f3c015f 100644
--- a/ext/dom/lexbor/lexbor/html/tree/insertion_mode.h
+++ b/ext/dom/lexbor/lexbor/html/tree/insertion_mode.h
@@ -91,14 +91,6 @@ LXB_API bool
 lxb_html_tree_insertion_mode_in_cell(lxb_html_tree_t *tree,
                                      lxb_html_token_t *token);

-LXB_API bool
-lxb_html_tree_insertion_mode_in_select(lxb_html_tree_t *tree,
-                                       lxb_html_token_t *token);
-
-LXB_API bool
-lxb_html_tree_insertion_mode_in_select_in_table(lxb_html_tree_t *tree,
-                                                lxb_html_token_t *token);
-
 LXB_API bool
 lxb_html_tree_insertion_mode_in_template(lxb_html_tree_t *tree,
                                          lxb_html_token_t *token);
diff --git a/ext/dom/lexbor/lexbor/html/tree/insertion_mode/foreign_content.c b/ext/dom/lexbor/lexbor/html/tree/insertion_mode/foreign_content.c
index 900557a59c3..7e546e34fd9 100644
--- a/ext/dom/lexbor/lexbor/html/tree/insertion_mode/foreign_content.c
+++ b/ext/dom/lexbor/lexbor/html/tree/insertion_mode/foreign_content.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018-2020 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -8,10 +8,10 @@
 #include "lexbor/html/tree/open_elements.h"
 #include "lexbor/html/interfaces/element.h"

-#define LEXBOR_TOKENIZER_CHARS_MAP
-#define LEXBOR_STR_RES_ANSI_REPLACEMENT_CHARACTER
-#include "lexbor/core/str_res.h"
-
+#ifndef LEXBOR_DISABLE_INTERNAL_EXTERN
+    LXB_EXTERN const lxb_char_t lexbor_str_res_ansi_replacement_character[4];
+    LXB_EXTERN const unsigned char lexbor_tokenizer_chars_map[256];
+#endif

 lxb_status_t
 lxb_dom_element_qualified_name_set(lxb_dom_element_t *element,
@@ -87,7 +87,8 @@ lxb_html_tree_insertion_mode_foreign_content_anything_else(lxb_html_tree_t *tree
         tree->before_append_attr = lxb_html_tree_adjust_attributes_svg;
     }

-    element = lxb_html_tree_insert_foreign_element(tree, token, node->ns);
+    element = lxb_html_tree_insert_foreign_element(tree, token, node->ns,
+                                                   false);
     if (element == NULL) {
         tree->before_append_attr = NULL;
         tree->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
@@ -259,22 +260,19 @@ lxb_html_tree_insertion_mode_foreign_content_all(lxb_html_tree_t *tree,

     lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_UNTO);

-    if (tree->fragment != NULL) {
-        return lxb_html_tree_insertion_mode_foreign_content_anything_else(tree,
-                                                                          token);
-    }
+    node = lxb_html_tree_current_node(tree);

-    do {
+    while (node != NULL &&
+           !(lxb_html_tree_mathml_text_integration_point(node)
+             || lxb_html_tree_html_integration_point(node)
+             || node->ns == LXB_NS_HTML))
+    {
         lxb_html_tree_open_elements_pop(tree);

         node = lxb_html_tree_current_node(tree);
     }
-    while (node &&
-           !(lxb_html_tree_mathml_text_integration_point(node)
-            || lxb_html_tree_html_integration_point(node)
-            || node->ns == LXB_NS_HTML));

-    return false;
+    return tree->mode(tree, token);
 }

 bool
@@ -286,6 +284,10 @@ lxb_html_tree_insertion_mode_foreign_content(lxb_html_tree_t *tree,
             case LXB_TAG_SCRIPT:
                 return lxb_html_tree_insertion_mode_foreign_content_script_closed(tree,
                                                                                   token);
+            case LXB_TAG_P:
+            case LXB_TAG_BR:
+                return lxb_html_tree_insertion_mode_foreign_content_all(tree,
+                                                                        token);
             default:
                 return lxb_html_tree_insertion_mode_foreign_content_anything_else_closed(tree,
                                                                                          token);
diff --git a/ext/dom/lexbor/lexbor/html/tree/insertion_mode/in_body.c b/ext/dom/lexbor/lexbor/html/tree/insertion_mode/in_body.c
index 32cc4047694..38610c7cdd2 100644
--- a/ext/dom/lexbor/lexbor/html/tree/insertion_mode/in_body.c
+++ b/ext/dom/lexbor/lexbor/html/tree/insertion_mode/in_body.c
@@ -1,19 +1,25 @@
 /*
- * Copyright (C) 2018-2020 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */

-#define LEXBOR_TOKENIZER_CHARS_MAP
-#include "lexbor/core/str_res.h"
-
 #include "lexbor/html/tree/insertion_mode.h"
 #include "lexbor/html/tree/open_elements.h"
 #include "lexbor/html/tree/active_formatting.h"
 #include "lexbor/html/interfaces/head_element.h"
+#include "lexbor/html/interfaces/option_element.h"
 #include "lexbor/html/tokenizer/state.h"
+#include "lexbor/html/parser.h"
 #include "lexbor/html/tokenizer/state_rcdata.h"

+#ifndef LEXBOR_DISABLE_INTERNAL_EXTERN
+    LXB_EXTERN const unsigned char lexbor_tokenizer_chars_map[256];
+#endif
+
+static bool
+lxb_html_tree_insertion_mode_in_body_anything_else_closed(lxb_html_tree_t *tree,
+                                                          lxb_html_token_t *token);

 /*
  * User case insertion mode.
@@ -691,7 +697,7 @@ lxb_html_tree_insertion_mode_in_body_button(lxb_html_tree_t *tree,
  * "address", "article", "aside", "blockquote", "button",  "center", "details",
  * "dialog", "dir", "div", "dl", "fieldset", "figcaption", "figure", "footer",
  * "header", "hgroup", "listing", "main", "menu", "nav", "ol", "pre", "section",
- * "summary", "ul"
+ * "select", "summary", "ul"
  */
 lxb_inline bool
 lxb_html_tree_insertion_mode_in_body_abcdfhlmnopsu_closed(lxb_html_tree_t *tree,
@@ -1204,13 +1210,63 @@ lxb_html_tree_insertion_mode_in_body_br_closed(lxb_html_tree_t *tree,
     return lxb_html_tree_insertion_mode_in_body_abeikw(tree, token);
 }

+lxb_inline bool
+lxb_html_tree_insertion_mode_in_body_option_closed(lxb_html_tree_t *tree,
+                                                   lxb_html_token_t *token)
+{
+    bool is;
+    size_t index;
+    lxb_dom_node_t *node;
+    lxb_html_option_element_t *option;
+    lxb_dom_exception_code_t code;
+
+    node = lxb_html_tree_open_elements_find_reverse(tree, LXB_TAG_OPTION,
+                                                    LXB_NS_HTML, &index);
+
+    lxb_html_tree_insertion_mode_in_body_anything_else_closed(tree, token);
+
+    if (node != NULL) {
+        is = lxb_html_tree_open_elements_find_by_node(tree, node, &index);
+
+        if (!is) {
+            option = lxb_html_interface_option(node);
+
+            code = lxb_html_option_maybe_clone_to_selectedcontent(option);
+            if (code != LXB_DOM_EXCEPTION_OK) {
+                tree->status = LXB_STATUS_ERROR;
+
+                return lxb_html_tree_process_abort(tree);
+            }
+        }
+    }
+
+    return true;
+}
+
 lxb_inline bool
 lxb_html_tree_insertion_mode_in_body_input(lxb_html_tree_t *tree,
                                            lxb_html_token_t *token)
 {
+    bool is;
+    lxb_dom_node_t *node;
     lxb_dom_attr_t *attr;
     lxb_html_element_t *element;

+    is = lxb_html_tree_is_fragment_element(tree, LXB_TAG_SELECT, LXB_NS_HTML);
+    if (is) {
+        lxb_html_tree_parse_error(tree, token,
+                                  LXB_HTML_RULES_ERROR_FRPASEINCOPAIN);
+        return true;
+    }
+
+    node = lxb_html_tree_element_in_scope(tree, LXB_TAG_SELECT, LXB_NS_HTML,
+                                          LXB_HTML_TAG_CATEGORY_SCOPE);
+    if (node != NULL) {
+        lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_SEINSC);
+        lxb_html_tree_open_elements_pop_until_node(tree, node, true);
+    }
+
+
     tree->status = lxb_html_tree_active_formatting_reconstruct_elements(tree);
     if (tree->status != LXB_STATUS_OK) {
         return lxb_html_tree_process_abort(tree);
@@ -1277,6 +1333,19 @@ lxb_html_tree_insertion_mode_in_body_hr(lxb_html_tree_t *tree,
         lxb_html_tree_close_p_element(tree, token);
     }

+    node = lxb_html_tree_element_in_scope(tree, LXB_TAG_SELECT, LXB_NS_HTML,
+                                          LXB_HTML_TAG_CATEGORY_SCOPE);
+    if (node != NULL) {
+        lxb_html_tree_generate_implied_end_tags(tree, LXB_TAG__UNDEF,
+                                                LXB_NS__UNDEF);
+
+        node = lxb_html_tree_element_in_scope_option_optgroup(tree);
+        if (node != NULL) {
+            lxb_html_tree_parse_error(tree, token,
+                                      LXB_HTML_RULES_ERROR_HRPASEOPOPINSC);
+        }
+    }
+
     element = lxb_html_tree_insert_html_element(tree, token);
     if (element == NULL) {
         tree->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
@@ -1396,8 +1465,25 @@ lxb_inline bool
 lxb_html_tree_insertion_mode_in_body_select(lxb_html_tree_t *tree,
                                             lxb_html_token_t *token)
 {
+    bool is;
+    lxb_dom_node_t *node;
     lxb_html_element_t *element;

+    is = lxb_html_tree_is_fragment_element(tree, LXB_TAG_SELECT, LXB_NS_HTML);
+    if (is) {
+        lxb_html_tree_parse_error(tree, token,
+                                  LXB_HTML_RULES_ERROR_FRPASEINCOPASE);
+        return true;
+    }
+
+    node = lxb_html_tree_element_in_scope(tree, LXB_TAG_SELECT, LXB_NS_HTML,
+                                          LXB_HTML_TAG_CATEGORY_SCOPE);
+    if (node != NULL) {
+        lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_SEINSC);
+        lxb_html_tree_open_elements_pop_until_node(tree, node, true);
+        return true;
+    }
+
     tree->status = lxb_html_tree_active_formatting_reconstruct_elements(tree);
     if (tree->status != LXB_STATUS_OK) {
         return lxb_html_tree_process_abort(tree);
@@ -1412,34 +1498,81 @@ lxb_html_tree_insertion_mode_in_body_select(lxb_html_tree_t *tree,

     tree->frameset_ok = false;

-    if (tree->mode == lxb_html_tree_insertion_mode_in_table
-        || tree->mode == lxb_html_tree_insertion_mode_in_caption
-        || tree->mode == lxb_html_tree_insertion_mode_in_table_body
-        || tree->mode == lxb_html_tree_insertion_mode_in_row
-        || tree->mode == lxb_html_tree_insertion_mode_in_cell)
-    {
-        tree->mode = lxb_html_tree_insertion_mode_in_select_in_table;
+    return true;
+}
+
+/*
+ * "option"
+ */
+lxb_inline bool
+lxb_html_tree_insertion_mode_in_body_option(lxb_html_tree_t *tree,
+                                            lxb_html_token_t *token)
+{
+    lxb_dom_node_t *node;
+    lxb_html_element_t *element;
+
+    node = lxb_html_tree_element_in_scope(tree, LXB_TAG_SELECT, LXB_NS_HTML,
+                                          LXB_HTML_TAG_CATEGORY_SCOPE);
+    if (node != NULL) {
+        lxb_html_tree_generate_implied_end_tags(tree, LXB_TAG_OPTGROUP,
+                                                LXB_NS_HTML);
+
+        node = lxb_html_tree_element_in_scope(tree, LXB_TAG_OPTION, LXB_NS_HTML,
+                                              LXB_HTML_TAG_CATEGORY_SCOPE);
+        if (node != NULL) {
+            lxb_html_tree_parse_error(tree, token,
+                                      LXB_HTML_RULES_ERROR_OPPAOPINSC);
+        }
     }
     else {
-        tree->mode = lxb_html_tree_insertion_mode_in_select;
+        node = lxb_html_tree_current_node(tree);
+        if (lxb_html_tree_node_is(node, LXB_TAG_OPTION)) {
+            lxb_html_tree_open_elements_pop(tree);
+        }
+    }
+
+    tree->status = lxb_html_tree_active_formatting_reconstruct_elements(tree);
+    if (tree->status != LXB_STATUS_OK) {
+        return lxb_html_tree_process_abort(tree);
+    }
+
+    element = lxb_html_tree_insert_html_element(tree, token);
+    if (element == NULL) {
+        tree->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
+
+        return lxb_html_tree_process_abort(tree);
     }

     return true;
 }

 /*
- * "optgroup", "option"
+ * "optgroup"
  */
 lxb_inline bool
-lxb_html_tree_insertion_mode_in_body_optopt(lxb_html_tree_t *tree,
-                                            lxb_html_token_t *token)
+lxb_html_tree_insertion_mode_in_body_optgroup(lxb_html_tree_t *tree,
+                                              lxb_html_token_t *token)
 {
     lxb_dom_node_t *node;
     lxb_html_element_t *element;

-    node = lxb_html_tree_current_node(tree);
-    if (lxb_html_tree_node_is(node, LXB_TAG_OPTION)) {
-        lxb_html_tree_open_elements_pop(tree);
+    node = lxb_html_tree_element_in_scope(tree, LXB_TAG_SELECT, LXB_NS_HTML,
+                                          LXB_HTML_TAG_CATEGORY_SCOPE);
+    if (node != NULL) {
+        lxb_html_tree_generate_implied_end_tags(tree, LXB_TAG__UNDEF,
+                                                LXB_NS__UNDEF);
+
+        node = lxb_html_tree_element_in_scope_option_optgroup(tree);
+        if (node != NULL) {
+            lxb_html_tree_parse_error(tree, token,
+                                      LXB_HTML_RULES_ERROR_OPPAOPOPINSC);
+        }
+    }
+    else {
+        node = lxb_html_tree_current_node(tree);
+        if (lxb_html_tree_node_is(node, LXB_TAG_OPTION)) {
+            lxb_html_tree_open_elements_pop(tree);
+        }
     }

     tree->status = lxb_html_tree_active_formatting_reconstruct_elements(tree);
@@ -1539,7 +1672,8 @@ lxb_html_tree_insertion_mode_in_body_math(lxb_html_tree_t *tree,

     tree->before_append_attr = lxb_html_tree_adjust_attributes_mathml;

-    element = lxb_html_tree_insert_foreign_element(tree, token, LXB_NS_MATH);
+    element = lxb_html_tree_insert_foreign_element(tree, token, LXB_NS_MATH,
+                                                   false);
     if (element == NULL) {
         tree->before_append_attr = NULL;
         tree->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
@@ -1570,7 +1704,8 @@ lxb_html_tree_insertion_mode_in_body_svg(lxb_html_tree_t *tree,

     tree->before_append_attr = lxb_html_tree_adjust_attributes_svg;

-    element = lxb_html_tree_insert_foreign_element(tree, token, LXB_NS_SVG);
+    element = lxb_html_tree_insert_foreign_element(tree, token, LXB_NS_SVG,
+                                                   false);
     if (element == NULL) {
         tree->before_append_attr = NULL;
         tree->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
@@ -1643,7 +1778,7 @@ lxb_html_tree_insertion_mode_in_body_noscript(lxb_html_tree_t *tree,
     return true;
 }

-lxb_inline bool
+static bool
 lxb_html_tree_insertion_mode_in_body_anything_else_closed(lxb_html_tree_t *tree,
                                                           lxb_html_token_t *token)
 {
@@ -1719,7 +1854,9 @@ lxb_html_tree_insertion_mode_in_body(lxb_html_tree_t *tree,
             case LXB_TAG_NAV:
             case LXB_TAG_OL:
             case LXB_TAG_PRE:
+            case LXB_TAG_SEARCH:
             case LXB_TAG_SECTION:
+            case LXB_TAG_SELECT:
             case LXB_TAG_SUMMARY:
             case LXB_TAG_UL:
                 return lxb_html_tree_insertion_mode_in_body_abcdfhlmnopsu_closed(tree,
@@ -1770,6 +1907,10 @@ lxb_html_tree_insertion_mode_in_body(lxb_html_tree_t *tree,
                 return lxb_html_tree_insertion_mode_in_body_br_closed(tree,
                                                                       token);

+            case LXB_TAG_OPTION:
+                return lxb_html_tree_insertion_mode_in_body_option_closed(tree,
+                                                                          token);
+
             default:
                 return lxb_html_tree_insertion_mode_in_body_anything_else_closed(tree,
                                                                                  token);
@@ -1831,6 +1972,7 @@ lxb_html_tree_insertion_mode_in_body(lxb_html_tree_t *tree,
         case LXB_TAG_NAV:
         case LXB_TAG_OL:
         case LXB_TAG_P:
+        case LXB_TAG_SEARCH:
         case LXB_TAG_SECTION:
         case LXB_TAG_SUMMARY:
         case LXB_TAG_UL:
@@ -1934,9 +2076,11 @@ lxb_html_tree_insertion_mode_in_body(lxb_html_tree_t *tree,
         case LXB_TAG_SELECT:
             return lxb_html_tree_insertion_mode_in_body_select(tree, token);

-        case LXB_TAG_OPTGROUP:
         case LXB_TAG_OPTION:
-            return lxb_html_tree_insertion_mode_in_body_optopt(tree, token);
+            return lxb_html_tree_insertion_mode_in_body_option(tree, token);
+
+        case LXB_TAG_OPTGROUP:
+            return lxb_html_tree_insertion_mode_in_body_optgroup(tree, token);

         case LXB_TAG_RB:
         case LXB_TAG_RTC:
diff --git a/ext/dom/lexbor/lexbor/html/tree/insertion_mode/in_head_noscript.c b/ext/dom/lexbor/lexbor/html/tree/insertion_mode/in_head_noscript.c
index 78e4c5919fe..1b40ecf62d8 100644
--- a/ext/dom/lexbor/lexbor/html/tree/insertion_mode/in_head_noscript.c
+++ b/ext/dom/lexbor/lexbor/html/tree/insertion_mode/in_head_noscript.c
@@ -101,6 +101,13 @@ lxb_html_tree_insertion_mode_in_head_noscript_closed(lxb_html_tree_t *tree,
                                                                             token);
     }

+    if (token->tag_id == LXB_TAG_NOSCRIPT) {
+        lxb_html_tree_open_elements_pop(tree);
+        tree->mode = lxb_html_tree_insertion_mode_in_head;
+
+        return true;
+    }
+
     lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_UNTO);

     return true;
diff --git a/ext/dom/lexbor/lexbor/html/tree/insertion_mode/in_select.c b/ext/dom/lexbor/lexbor/html/tree/insertion_mode/in_select.c
deleted file mode 100644
index b4eed2c5d3a..00000000000
--- a/ext/dom/lexbor/lexbor/html/tree/insertion_mode/in_select.c
+++ /dev/null
@@ -1,375 +0,0 @@
-/*
- * Copyright (C) 2018-2020 Alexander Borisov
- *
- * Author: Alexander Borisov <borisov@lexbor.com>
- */
-
-#include "lexbor/html/tree/insertion_mode.h"
-#include "lexbor/html/tree/open_elements.h"
-
-
-lxb_inline bool
-lxb_html_tree_insertion_mode_in_select_text(lxb_html_tree_t *tree,
-                                            lxb_html_token_t *token)
-{
-    lexbor_str_t str;
-
-    if (token->null_count != 0) {
-        lxb_html_tree_parse_error(tree, token,
-                                  LXB_HTML_RULES_ERROR_NUCH);
-
-        tree->status = lxb_html_token_make_text_drop_null(token, &str,
-                                                          tree->document->dom_document.text);
-    }
-    else {
-        tree->status = lxb_html_token_make_text(token, &str,
-                                                tree->document->dom_document.text);
-    }
-
-    if (tree->status != LXB_STATUS_OK) {
-        return lxb_html_tree_process_abort(tree);
-    }
-
-    /* Can be zero only if all NULL are gone */
-    if (str.length == 0) {
-        lexbor_str_destroy(&str, tree->document->dom_document.text, false);
-
-        return true;
-    }
-
-    tree->status = lxb_html_tree_insert_character_for_data(tree, &str, NULL);
-    if (tree->status != LXB_STATUS_OK) {
-        return lxb_html_tree_process_abort(tree);
-    }
-
-    return true;
-}
-
-lxb_inline bool
-lxb_html_tree_insertion_mode_in_select_comment(lxb_html_tree_t *tree,
-                                               lxb_html_token_t *token)
-{
-    lxb_dom_comment_t *comment;
-
-    comment = lxb_html_tree_insert_comment(tree, token, NULL);
-    if (comment == NULL) {
-        tree->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
-
-        return lxb_html_tree_process_abort(tree);
-    }
-
-    return true;
-}
-
-lxb_inline bool
-lxb_html_tree_insertion_mode_in_select_doctype(lxb_html_tree_t *tree,
-                                               lxb_html_token_t *token)
-{
-    lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_DOTOINSEMO);
-
-    return true;
-}
-
-lxb_inline bool
-lxb_html_tree_insertion_mode_in_select_html(lxb_html_tree_t *tree,
-                                            lxb_html_token_t *token)
-{
-    return lxb_html_tree_insertion_mode_in_body(tree, token);
-}
-
-lxb_inline bool
-lxb_html_tree_insertion_mode_in_select_option(lxb_html_tree_t *tree,
-                                              lxb_html_token_t *token)
-{
-    lxb_html_element_t *element;
-    lxb_dom_node_t *node = lxb_html_tree_current_node(tree);
-
-    if (lxb_html_tree_node_is(node, LXB_TAG_OPTION)) {
-        lxb_html_tree_open_elements_pop(tree);
-    }
-
-    element = lxb_html_tree_insert_html_element(tree, token);
-    if (element == NULL) {
-        tree->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
-
-        return lxb_html_tree_process_abort(tree);
-    }
-
-    return true;
-}
-
-lxb_inline bool
-lxb_html_tree_insertion_mode_in_select_optgroup(lxb_html_tree_t *tree,
-                                                lxb_html_token_t *token)
-{
-    lxb_html_element_t *element;
-    lxb_dom_node_t *node = lxb_html_tree_current_node(tree);
-
-    if (lxb_html_tree_node_is(node, LXB_TAG_OPTION)) {
-        lxb_html_tree_open_elements_pop(tree);
-    }
-
-    node = lxb_html_tree_current_node(tree);
-
-    if (lxb_html_tree_node_is(node, LXB_TAG_OPTGROUP)) {
-        lxb_html_tree_open_elements_pop(tree);
-    }
-
-    element = lxb_html_tree_insert_html_element(tree, token);
-    if (element == NULL) {
-        tree->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
-
-        return lxb_html_tree_process_abort(tree);
-    }
-
-    return true;
-}
-
-lxb_inline bool
-lxb_html_tree_insertion_mode_in_select_hr(lxb_html_tree_t *tree,
-                                          lxb_html_token_t *token)
-{
-    lxb_html_element_t *element;
-    lxb_dom_node_t *node = lxb_html_tree_current_node(tree);
-
-    if (lxb_html_tree_node_is(node, LXB_TAG_OPTION)) {
-        lxb_html_tree_open_elements_pop(tree);
-    }
-
-    node = lxb_html_tree_current_node(tree);
-
-    if (lxb_html_tree_node_is(node, LXB_TAG_OPTGROUP)) {
-        lxb_html_tree_open_elements_pop(tree);
-    }
-
-    element = lxb_html_tree_insert_html_element(tree, token);
-    if (element == NULL) {
-        tree->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
-
-        return lxb_html_tree_process_abort(tree);
-    }
-
-    lxb_html_tree_open_elements_pop(tree);
-
-    lxb_html_tree_acknowledge_token_self_closing(tree, token);
-
-    return true;
-}
-
-lxb_inline bool
-lxb_html_tree_insertion_mode_in_select_optgroup_closed(lxb_html_tree_t *tree,
-                                                       lxb_html_token_t *token)
-{
-    lxb_dom_node_t *node = lxb_html_tree_current_node(tree);
-
-    if (lxb_html_tree_node_is(node, LXB_TAG_OPTION)
-        && tree->open_elements->length > 1)
-    {
-        node = lxb_html_tree_open_elements_get(tree,
-                                               tree->open_elements->length - 2);
-        if (node != NULL && lxb_html_tree_node_is(node, LXB_TAG_OPTGROUP)) {
-            lxb_html_tree_open_elements_pop(tree);
-        }
-    }
-
-    node = lxb_html_tree_current_node(tree);
-
-    if (lxb_html_tree_node_is(node, LXB_TAG_OPTGROUP) == false) {
-        lxb_html_tree_parse_error(tree, token,
-                                  LXB_HTML_RULES_ERROR_UNELINOPELST);
-        return true;
-    }
-
-    lxb_html_tree_open_elements_pop(tree);
-
-    return true;
-}
-
-lxb_inline bool
-lxb_html_tree_insertion_mode_in_select_option_closed(lxb_html_tree_t *tree,
-                                                     lxb_html_token_t *token)
-{
-    lxb_dom_node_t *node = lxb_html_tree_current_node(tree);
-
-    if (lxb_html_tree_node_is(node, LXB_TAG_OPTION) == false) {
-        lxb_html_tree_parse_error(tree, token,
-                                  LXB_HTML_RULES_ERROR_UNELINOPELST);
-        return true;
-    }
-
-    lxb_html_tree_open_elements_pop(tree);
-
-    return true;
-}
-
-lxb_inline bool
-lxb_html_tree_insertion_mode_in_select_select_closed(lxb_html_tree_t *tree,
-                                                     lxb_html_token_t *token)
-{
-    lxb_dom_node_t *node;
-
-    node = lxb_html_tree_element_in_scope(tree, LXB_TAG_SELECT, LXB_NS_HTML,
-                                          LXB_HTML_TAG_CATEGORY_SCOPE_SELECT);
-    if (node == NULL) {
-        lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_UNCLTO);
-
-        return true;
-    }
-
-    lxb_html_tree_open_elements_pop_until_tag_id(tree, LXB_TAG_SELECT,
-                                                 LXB_NS_HTML, true);
-
-    lxb_html_tree_reset_insertion_mode_appropriately(tree);
-
-    return true;
-}
-
-lxb_inline bool
-lxb_html_tree_insertion_mode_in_select_select(lxb_html_tree_t *tree,
-                                              lxb_html_token_t *token)
-{
-    lxb_dom_node_t *node;
-
-    lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_UNTO);
-
-    node = lxb_html_tree_element_in_scope(tree, LXB_TAG_SELECT, LXB_NS_HTML,
-                                          LXB_HTML_TAG_CATEGORY_SCOPE_SELECT);
-    if (node == NULL) {
-        return true;
-    }
-
-    lxb_html_tree_open_elements_pop_until_tag_id(tree, LXB_TAG_SELECT,
-                                                 LXB_NS_HTML, true);
-
-    lxb_html_tree_reset_insertion_mode_appropriately(tree);
-
-    return true;
-}
-
-/*
- * "input", "keygen", "textarea"
- */
-lxb_inline bool
-lxb_html_tree_insertion_mode_in_select_ikt(lxb_html_tree_t *tree,
-                                           lxb_html_token_t *token)
-{
-    lxb_dom_node_t *node;
-
-    lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_UNTO);
-
-    node = lxb_html_tree_element_in_scope(tree, LXB_TAG_SELECT, LXB_NS_HTML,
-                                          LXB_HTML_TAG_CATEGORY_SCOPE_SELECT);
-    if (node == NULL) {
-        return true;
-    }
-
-    lxb_html_tree_open_elements_pop_until_tag_id(tree, LXB_TAG_SELECT,
-                                                 LXB_NS_HTML, true);
-
-    lxb_html_tree_reset_insertion_mode_appropriately(tree);
-
-    return false;
-}
-
-/*
- * A start tag whose tag name is one of: "script", "template"
- * An end tag whose tag name is "template"
- */
-lxb_inline bool
-lxb_html_tree_insertion_mode_in_select_st_open_closed(lxb_html_tree_t *tree,
-                                                      lxb_html_token_t *token)
-{
-    return lxb_html_tree_insertion_mode_in_head(tree, token);
-}
-
-lxb_inline bool
-lxb_html_tree_insertion_mode_in_select_end_of_file(lxb_html_tree_t *tree,
-                                                   lxb_html_token_t *token)
-{
-    return lxb_html_tree_insertion_mode_in_body(tree, token);
-}
-
-lxb_inline bool
-lxb_html_tree_insertion_mode_in_select_anything_else(lxb_html_tree_t *tree,
-                                                     lxb_html_token_t *token)
-{
-    lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_UNTO);
-
-    return true;
-}
-
-lxb_inline bool
-lxb_html_tree_insertion_mode_in_select_anything_else_closed(lxb_html_tree_t *tree,
-                                                            lxb_html_token_t *token)
-{
-    lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_UNCLTO);
-
-    return true;
-}
-
-bool
-lxb_html_tree_insertion_mode_in_select(lxb_html_tree_t *tree,
-                                       lxb_html_token_t *token)
-{
-    if (token->type & LXB_HTML_TOKEN_TYPE_CLOSE) {
-        switch (token->tag_id) {
-            case LXB_TAG_OPTGROUP:
-                return lxb_html_tree_insertion_mode_in_select_optgroup_closed(tree,
-                                                                              token);
-            case LXB_TAG_OPTION:
-                return lxb_html_tree_insertion_mode_in_select_option_closed(tree,
-                                                                            token);
-            case LXB_TAG_SELECT:
-                return lxb_html_tree_insertion_mode_in_select_select_closed(tree,
-                                                                            token);
-            case LXB_TAG_TEMPLATE:
-                return lxb_html_tree_insertion_mode_in_select_st_open_closed(tree,
-                                                                             token);
-            default:
-                return lxb_html_tree_insertion_mode_in_select_anything_else_closed(tree,
-                                                                                   token);
-        }
-    }
-
-    switch (token->tag_id) {
-        case LXB_TAG__TEXT:
-            return lxb_html_tree_insertion_mode_in_select_text(tree, token);
-
-        case LXB_TAG__EM_COMMENT:
-            return lxb_html_tree_insertion_mode_in_select_comment(tree, token);
-
-        case LXB_TAG__EM_DOCTYPE:
-            return lxb_html_tree_insertion_mode_in_select_doctype(tree, token);
-
-        case LXB_TAG_HTML:
-            return lxb_html_tree_insertion_mode_in_select_html(tree, token);
-
-        case LXB_TAG_OPTION:
-            return lxb_html_tree_insertion_mode_in_select_option(tree, token);
-
-        case LXB_TAG_OPTGROUP:
-            return lxb_html_tree_insertion_mode_in_select_optgroup(tree, token);
-
-        case LXB_TAG_HR:
-            return lxb_html_tree_insertion_mode_in_select_hr(tree, token);
-
-        case LXB_TAG_SELECT:
-            return lxb_html_tree_insertion_mode_in_select_select(tree, token);
-
-        case LXB_TAG_INPUT:
-        case LXB_TAG_KEYGEN:
-        case LXB_TAG_TEXTAREA:
-            return lxb_html_tree_insertion_mode_in_select_ikt(tree, token);
-
-        case LXB_TAG_SCRIPT:
-        case LXB_TAG_TEMPLATE:
-            return lxb_html_tree_insertion_mode_in_select_st_open_closed(tree,
-                                                                         token);
-        case LXB_TAG__END_OF_FILE:
-            return lxb_html_tree_insertion_mode_in_select_end_of_file(tree,
-                                                                      token);
-        default:
-            return lxb_html_tree_insertion_mode_in_select_anything_else(tree,
-                                                                        token);
-    }
-}
diff --git a/ext/dom/lexbor/lexbor/html/tree/insertion_mode/in_select_in_table.c b/ext/dom/lexbor/lexbor/html/tree/insertion_mode/in_select_in_table.c
deleted file mode 100644
index 7db2e259191..00000000000
--- a/ext/dom/lexbor/lexbor/html/tree/insertion_mode/in_select_in_table.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2018-2019 Alexander Borisov
- *
- * Author: Alexander Borisov <borisov@lexbor.com>
- */
-
-#include "lexbor/html/tree/insertion_mode.h"
-#include "lexbor/html/tree/open_elements.h"
-
-
-/*
- * "caption", "table", "tbody", "tfoot", "thead", "tr", "td", "th"
- */
-lxb_inline bool
-lxb_html_tree_insertion_mode_in_select_in_table_ct(lxb_html_tree_t *tree,
-                                                   lxb_html_token_t *token)
-{
-    lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_UNTO);
-
-    lxb_html_tree_open_elements_pop_until_tag_id(tree, LXB_TAG_SELECT,
-                                                 LXB_NS_HTML, true);
-
-    lxb_html_tree_reset_insertion_mode_appropriately(tree);
-
-    return false;
-}
-
-/*
- * "caption", "table", "tbody", "tfoot", "thead", "tr", "td", "th"
- */
-lxb_inline bool
-lxb_html_tree_insertion_mode_in_select_in_table_ct_closed(lxb_html_tree_t *tree,
-                                                          lxb_html_token_t *token)
-{
-    lxb_dom_node_t *node;
-
-    lxb_html_tree_parse_error(tree, token, LXB_HTML_RULES_ERROR_UNCLTO);
-
-    node = lxb_html_tree_element_in_scope(tree, token->tag_id, LXB_NS_HTML,
-                                          LXB_HTML_TAG_CATEGORY_SCOPE_TABLE);
-    if (node == NULL) {
-        return true;
-    }
-
-    lxb_html_tree_open_elements_pop_until_tag_id(tree, LXB_TAG_SELECT,
-                                                 LXB_NS_HTML, true);
-
-    lxb_html_tree_reset_insertion_mode_appropriately(tree);
-
-    return false;
-}
-
-lxb_inline bool
-lxb_html_tree_insertion_mode_in_select_in_table_anything_else(lxb_html_tree_t *tree,
-                                                              lxb_html_token_t *token)
-{
-    return lxb_html_tree_insertion_mode_in_select(tree, token);
-}
-
-lxb_inline bool
-lxb_html_tree_insertion_mode_in_select_in_table_anything_else_closed(lxb_html_tree_t *tree,
-                                                                     lxb_html_token_t *token)
-{
-    return lxb_html_tree_insertion_mode_in_select_in_table_anything_else(tree,
-                                                                         token);
-}
-
-bool
-lxb_html_tree_insertion_mode_in_select_in_table(lxb_html_tree_t *tree,
-                                                lxb_html_token_t *token)
-{
-    if (token->tag_id >= LXB_TAG__LAST_ENTRY) {
-        if (token->type & LXB_HTML_TOKEN_TYPE_CLOSE) {
-            return lxb_html_tree_insertion_mode_in_select_in_table_anything_else_closed(tree,
-                                                                                        token);
-        }
-
-        return lxb_html_tree_insertion_mode_in_select_in_table_anything_else(tree,
-                                                                             token);
-    }
-
-    if (token->type & LXB_HTML_TOKEN_TYPE_CLOSE) {
-        switch (token->tag_id) {
-            case LXB_TAG_CAPTION:
-            case LXB_TAG_TABLE:
-            case LXB_TAG_TBODY:
-            case LXB_TAG_TFOOT:
-            case LXB_TAG_THEAD:
-            case LXB_TAG_TR:
-            case LXB_TAG_TH:
-            case LXB_TAG_TD:
-                return lxb_html_tree_insertion_mode_in_select_in_table_ct_closed(tree,
-                                                                                 token);
-            default:
-                return lxb_html_tree_insertion_mode_in_select_in_table_anything_else_closed(tree,
-                                                                                            token);
-        }
-    }
-
-    switch (token->tag_id) {
-        case LXB_TAG_CAPTION:
-        case LXB_TAG_TABLE:
-        case LXB_TAG_TBODY:
-        case LXB_TAG_TFOOT:
-        case LXB_TAG_THEAD:
-        case LXB_TAG_TR:
-        case LXB_TAG_TH:
-        case LXB_TAG_TD:
-            return lxb_html_tree_insertion_mode_in_select_in_table_ct(tree,
-                                                                      token);
-        default:
-            return lxb_html_tree_insertion_mode_in_select_in_table_anything_else(tree,
-                                                                                 token);
-    }
-}
diff --git a/ext/dom/lexbor/lexbor/ns/base.h b/ext/dom/lexbor/lexbor/ns/base.h
index a5b01baa0e6..94ee0b7f871 100644
--- a/ext/dom/lexbor/lexbor/ns/base.h
+++ b/ext/dom/lexbor/lexbor/ns/base.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 Alexander Borisov
+ * Copyright (C) 2019-2025 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -16,7 +16,7 @@ extern "C" {


 #define LXB_NS_VERSION_MAJOR 1
-#define LXB_NS_VERSION_MINOR 2
+#define LXB_NS_VERSION_MINOR 4
 #define LXB_NS_VERSION_PATCH 0

 #define LXB_NS_VERSION_STRING                                                  \
diff --git a/ext/dom/lexbor/lexbor/ns/const.h b/ext/dom/lexbor/lexbor/ns/const.h
index 463d8d4998b..2115629b9bd 100644
--- a/ext/dom/lexbor/lexbor/ns/const.h
+++ b/ext/dom/lexbor/lexbor/ns/const.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
diff --git a/ext/dom/lexbor/lexbor/ns/ns.c b/ext/dom/lexbor/lexbor/ns/ns.c
index 87e870cf627..4ffd02519c9 100644
--- a/ext/dom/lexbor/lexbor/ns/ns.c
+++ b/ext/dom/lexbor/lexbor/ns/ns.c
@@ -1,13 +1,14 @@
 /*
- * Copyright (C) 2018-2019 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */

 #include "lexbor/core/shs.h"

-#define LEXBOR_STR_RES_MAP_LOWERCASE
-#include "lexbor/core/str_res.h"
+#ifndef LEXBOR_DISABLE_INTERNAL_EXTERN
+    LXB_EXTERN const lxb_char_t lexbor_str_res_map_lowercase[256];
+#endif

 #include "lexbor/ns/ns.h"
 #include "lexbor/ns/res.h"
diff --git a/ext/dom/lexbor/lexbor/ns/res.h b/ext/dom/lexbor/lexbor/ns/res.h
index ca3ab04cb6e..c953ab07469 100644
--- a/ext/dom/lexbor/lexbor/ns/res.h
+++ b/ext/dom/lexbor/lexbor/ns/res.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018-2019 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -50,7 +50,7 @@ static const lxb_ns_prefix_data_t lxb_ns_prefix_res_data[LXB_NS__LAST_ENTRY] =
     {{.u.short_str = "xmlns", .length = 5, .next = NULL}, LXB_NS_XMLNS, 1, true}
 };

-static const lexbor_shs_entry_t lxb_ns_res_shs_data[] =
+static const lexbor_shs_entry_t lxb_ns_res_shs_data[29] =
 {
     {NULL, NULL, 28, 0}, {"html", (void *) &lxb_ns_prefix_res_data[2], 4, 0},
     {"xmlns", (void *) &lxb_ns_prefix_res_data[7], 5, 0}, {NULL, NULL, 0, 0},
@@ -69,7 +69,7 @@ static const lexbor_shs_entry_t lxb_ns_res_shs_data[] =
     {"xml", (void *) &lxb_ns_prefix_res_data[6], 3, 0}
 };

-static const lexbor_shs_entry_t lxb_ns_res_shs_link_data[] =
+static const lexbor_shs_entry_t lxb_ns_res_shs_link_data[23] =
 {
     {NULL, NULL, 22, 0},
     {"http://www.w3.org/1999/xhtml", (void *) &lxb_ns_res_data[2], 28, 0},
diff --git a/ext/dom/lexbor/lexbor/selectors-adapted/selectors.c b/ext/dom/lexbor/lexbor/selectors-adapted/selectors.c
index 7a494017a2d..26e6f333fa8 100644
--- a/ext/dom/lexbor/lexbor/selectors-adapted/selectors.c
+++ b/ext/dom/lexbor/lexbor/selectors-adapted/selectors.c
@@ -1,9 +1,9 @@
 /*
- * Copyright (C) 2021-2025 Alexander Borisov
+ * Copyright (C) 2021-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  * Adapted for PHP + libxml2 by: Niels Dossche <nielsdos@php.net>
- * Based on Lexbor (upstream commit 971faf11a5f45433b9193a143e2897d8c0fd5611)
+ * Based on Lexbor (upstream commit 5291cde0d40f77e7c4ea364b7cd726269e0bf1f9)
  */

 #include <libxml/xmlstring.h>
@@ -1356,8 +1356,8 @@ lxb_selectors_state_after_nth_child(lxb_selectors_t *selectors,
 	current = selectors->current;

 	if (current->index == 0) {
-		selectors->state = lxb_selectors_state_not_found;
 		selectors->current = selectors->current->parent;
+		lxb_selectors_switch_to_not_found(selectors, selectors->current);

 		return selectors->current->entry;
 	}
diff --git a/ext/dom/lexbor/lexbor/selectors/base.h b/ext/dom/lexbor/lexbor/selectors/base.h
index 64af0261a75..19bdda73849 100644
--- a/ext/dom/lexbor/lexbor/selectors/base.h
+++ b/ext/dom/lexbor/lexbor/selectors/base.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021-2023 Alexander Borisov
+ * Copyright (C) 2021-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -15,7 +15,7 @@ extern "C" {


 #define LXB_SELECTORS_VERSION_MAJOR 0
-#define LXB_SELECTORS_VERSION_MINOR 3
+#define LXB_SELECTORS_VERSION_MINOR 6
 #define LXB_SELECTORS_VERSION_PATCH 0

 #define LXB_SELECTORS_VERSION_STRING LEXBOR_STRINGIZE(LXB_SELECTORS_VERSION_MAJOR) "."   \
diff --git a/ext/dom/lexbor/lexbor/selectors/selectors.c b/ext/dom/lexbor/lexbor/selectors/selectors.c
index 45db265302a..20324323405 100644
--- a/ext/dom/lexbor/lexbor/selectors/selectors.c
+++ b/ext/dom/lexbor/lexbor/selectors/selectors.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021-2024 Alexander Borisov
+ * Copyright (C) 2021-2025 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -10,48 +10,74 @@


 static lxb_status_t
-lxb_selectors_state_tree(lxb_selectors_t *selectors, lxb_dom_node_t *root,
-                         const lxb_css_selector_list_t *list);
+lxb_selectors_tree(lxb_selectors_t *selectors, lxb_dom_node_t *root);

 static lxb_status_t
-lxb_selectors_state_run(lxb_selectors_t *selectors, lxb_dom_node_t *node,
-                        const lxb_css_selector_list_t *list);
+lxb_selectors_run(lxb_selectors_t *selectors, lxb_dom_node_t *node);

 static lxb_selectors_entry_t *
 lxb_selectors_state_find(lxb_selectors_t *selectors,
                          lxb_selectors_entry_t *entry);

 static lxb_selectors_entry_t *
-lxb_selectors_state_find_check(lxb_selectors_t *selectors, lxb_dom_node_t *node,
-                               const lxb_css_selector_t *selector,
-                               lxb_selectors_entry_t *entry);
+lxb_selectors_state_found_check(lxb_selectors_t *selectors,
+                                lxb_selectors_entry_t *entry);
+
+static lxb_selectors_entry_t *
+lxb_selectors_state_found_check_forward(lxb_selectors_t *selectors,
+                                        lxb_selectors_entry_t *entry);
+
+static lxb_selectors_entry_t *
+lxb_selectors_state_found(lxb_selectors_t *selectors,
+                          lxb_selectors_entry_t *entry);

 static lxb_selectors_entry_t *
-lxb_selectors_state_pseudo_class_function(lxb_selectors_t *selectors,
-                                          lxb_selectors_entry_t *entry);
+lxb_selectors_state_found_forward(lxb_selectors_t *selectors,
+                                  lxb_selectors_entry_t *entry);

-static lxb_dom_node_t *
-lxb_selectors_next_node(lxb_selectors_nested_t *main);
+static lxb_selectors_entry_t *
+lxb_selectors_state_not_found(lxb_selectors_t *selectors,
+                              lxb_selectors_entry_t *entry);

-static lxb_dom_node_t *
-lxb_selectors_state_has_relative(lxb_dom_node_t *node,
-                                 const lxb_css_selector_t *selector);
+static lxb_selectors_entry_t *
+lxb_selectors_state_not_found_forward(lxb_selectors_t *selectors,
+                                      lxb_selectors_entry_t *entry);

 static lxb_selectors_entry_t *
-lxb_selectors_state_after_find_has(lxb_selectors_t *selectors,
-                                   lxb_selectors_entry_t *entry);
+lxb_selectors_next_list(lxb_selectors_t *selectors,
+                        lxb_selectors_entry_t *entry);
+
+static lxb_selectors_entry_t *
+lxb_selectors_next_list_forward(lxb_selectors_t *selectors,
+                                lxb_selectors_entry_t *entry);
+
+static lxb_selectors_entry_t *
+lxb_selectors_make_following(lxb_selectors_t *selectors,
+                             lxb_selectors_entry_t *entry);
+
+static lxb_selectors_entry_t *
+lxb_selectors_make_following_forward(lxb_selectors_t *selectors,
+                                     lxb_selectors_entry_t *entry);

 static lxb_selectors_entry_t *
 lxb_selectors_state_after_find(lxb_selectors_t *selectors,
                                lxb_selectors_entry_t *entry);

+static lxb_selectors_entry_t *
+lxb_selectors_state_after_not(lxb_selectors_t *selectors,
+                              lxb_selectors_entry_t *entry);
+
 static lxb_selectors_entry_t *
 lxb_selectors_state_after_nth_child(lxb_selectors_t *selectors,
                                     lxb_selectors_entry_t *entry);

+static lxb_selectors_entry_t *
+lxb_selectors_state_nth_child_found(lxb_selectors_t *selectors,
+                                    lxb_selectors_entry_t *entry);
+
 static bool
 lxb_selectors_match(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry,
-                    const lxb_css_selector_t *selector, lxb_dom_node_t *node);
+                    lxb_dom_node_t *node);

 static bool
 lxb_selectors_match_element(const lxb_css_selector_t *selector,
@@ -73,7 +99,8 @@ lxb_selectors_pseudo_class(const lxb_css_selector_t *selector,
                            const lxb_dom_node_t *node);

 static bool
-lxb_selectors_pseudo_class_function(const lxb_css_selector_t *selector,
+lxb_selectors_pseudo_class_function(lxb_selectors_t *selectors,
+                                    const lxb_css_selector_t *selector,
                                     lxb_dom_node_t *node);

 static bool
@@ -109,6 +136,10 @@ static lxb_status_t
 lxb_selectors_cb_not(lxb_dom_node_t *node,
                      lxb_css_selector_specificity_t spec, void *ctx);

+static lxb_status_t
+lxb_selectors_cb_nth_ok(lxb_dom_node_t *node,
+                        lxb_css_selector_specificity_t spec, void *ctx);
+

 lxb_selectors_t *
 lxb_selectors_create(void)
@@ -168,17 +199,118 @@ lxb_selectors_destroy(lxb_selectors_t *selectors, bool self_destroy)
     return selectors;
 }

+static lxb_selectors_entry_t *
+lxb_selectors_state_entry_create(lxb_selectors_t *selectors,
+                                 const lxb_css_selector_t *selector,
+                                 lxb_selectors_entry_t *root,
+                                 lxb_dom_node_t *node)
+{
+    lxb_selectors_entry_t *entry;
+    lxb_css_selector_combinator_t combinator;
+
+    combinator = selector->combinator;
+
+    do {
+        selector = selector->prev;
+
+        entry = lexbor_dobject_calloc(selectors->objs);
+        if (entry == NULL) {
+            selectors->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
+            return NULL;
+        }
+
+        entry->combinator = selector->combinator;
+        entry->selector = selector;
+        entry->node = node;
+
+        if (root->prev != NULL) {
+            root->prev->next = entry;
+            entry->prev = root->prev;
+        }
+
+        entry->next = root;
+        root->prev = entry;
+    }
+    while (selector->combinator == LXB_CSS_SELECTOR_COMBINATOR_CLOSE
+           && selector->prev != NULL);
+
+    entry->combinator = combinator;
+
+    return entry;
+}
+
+static lxb_selectors_entry_t *
+lxb_selectors_state_entry_create_forward(lxb_selectors_t *selectors,
+                                         const lxb_css_selector_t *selector,
+                                         lxb_selectors_entry_t *root,
+                                         lxb_dom_node_t *node)
+{
+    lxb_selectors_entry_t *entry;
+
+    selector = selector->next;
+
+    entry = lexbor_dobject_calloc(selectors->objs);
+    if (entry == NULL) {
+        selectors->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
+        return NULL;
+    }
+
+    entry->combinator = selector->combinator;
+    entry->selector = selector;
+    entry->node = node;
+
+    entry->prev = root;
+    root->next = entry;
+
+    return entry;
+}
+
+static lxb_selectors_entry_t *
+lxb_selectors_entry_make_first(lxb_selectors_t *selectors,
+                               lxb_css_selector_t *selector)
+{
+    lxb_selectors_entry_t *entry, *prev;
+
+    prev = NULL;
+
+    do {
+        entry = lexbor_dobject_calloc(selectors->objs);
+        if (entry == NULL) {
+            return NULL;
+        }
+
+        entry->selector = selector;
+        entry->combinator = LXB_CSS_SELECTOR_COMBINATOR_CLOSE;
+
+        if (prev != NULL) {
+            prev->next = entry;
+            entry->prev = prev;
+        }
+
+        if (selector->combinator != LXB_CSS_SELECTOR_COMBINATOR_CLOSE
+            || selector->prev == NULL)
+        {
+            break;
+        }
+
+        prev = entry;
+        selector = selector->prev;
+    }
+    while (true);
+
+    return entry;
+}
+
 lxb_inline lxb_dom_node_t *
 lxb_selectors_descendant(lxb_selectors_t *selectors,
                          lxb_selectors_entry_t *entry,
-                         const lxb_css_selector_t *selector,
                          lxb_dom_node_t *node)
 {
     node = node->parent;

     while (node != NULL) {
         if (node->type == LXB_DOM_NODE_TYPE_ELEMENT
-            && lxb_selectors_match(selectors, entry, selector, node))
+            && lxb_selectors_match(selectors, entry, node))
         {
             return node;
         }
@@ -189,11 +321,69 @@ lxb_selectors_descendant(lxb_selectors_t *selectors,
     return NULL;
 }

+lxb_inline lxb_dom_node_t *
+lxb_selectors_descendant_forward(lxb_selectors_t *selectors,
+                                 lxb_selectors_entry_t *entry,
+                                 lxb_dom_node_t *node)
+{
+    lxb_dom_node_t *root;
+    lxb_selectors_nested_t *current = selectors->current;
+
+    if (entry->prev != NULL) {
+        root = entry->prev->node;
+    }
+    else {
+        root = current->root;
+    }
+
+    do {
+        if (node->first_child != NULL) {
+            node = node->first_child;
+        }
+        else {
+
+        next:
+
+            while (node != root && node->next == NULL) {
+                node = node->parent;
+            }
+
+            if (node == root) {
+                break;
+            }
+
+            node = node->next;
+        }
+
+        if (node->type != LXB_DOM_NODE_TYPE_ELEMENT) {
+            goto next;
+        }
+
+        if (lxb_selectors_match(selectors, entry, node)) {
+            return node;
+        }
+    }
+    while (node != NULL);
+
+    return NULL;
+}
+
 lxb_inline lxb_dom_node_t *
 lxb_selectors_close(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry,
-                    const lxb_css_selector_t *selector, lxb_dom_node_t *node)
+                    lxb_dom_node_t *node)
+{
+    if (lxb_selectors_match(selectors, entry, node)) {
+        return node;
+    }
+
+    return NULL;
+}
+
+lxb_inline lxb_dom_node_t *
+lxb_selectors_close_forward(lxb_selectors_t *selectors,
+                            lxb_selectors_entry_t *entry, lxb_dom_node_t *node)
 {
-    if (lxb_selectors_match(selectors, entry, selector, node)) {
+    if (lxb_selectors_match(selectors, entry, node)) {
         return node;
     }

@@ -202,12 +392,12 @@ lxb_selectors_close(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry,

 lxb_inline lxb_dom_node_t *
 lxb_selectors_child(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry,
-                    const lxb_css_selector_t *selector, lxb_dom_node_t *root)
+                    lxb_dom_node_t *root)
 {
     root = root->parent;

     if (root != NULL && root->type == LXB_DOM_NODE_TYPE_ELEMENT
-        && lxb_selectors_match(selectors, entry, selector, root))
+        && lxb_selectors_match(selectors, entry, root))
     {
         return root;
     }
@@ -215,15 +405,47 @@ lxb_selectors_child(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry,
     return NULL;
 }

+lxb_inline lxb_dom_node_t *
+lxb_selectors_child_forward(lxb_selectors_t *selectors,
+                            lxb_selectors_entry_t *entry, lxb_dom_node_t *root)
+{
+    if (entry->prev != NULL) {
+        if (entry->prev->node == root) {
+            root = root->first_child;
+        }
+        else {
+            root = root->next;
+        }
+    }
+    else if (selectors->current->root == root) {
+        root = root->first_child;
+    }
+    else {
+        root = root->next;
+    }
+
+    while (root != NULL) {
+        if (root->type == LXB_DOM_NODE_TYPE_ELEMENT
+            && lxb_selectors_match(selectors, entry, root))
+        {
+            return root;
+        }
+
+        root = root->next;
+    }
+
+    return NULL;
+}
+
 lxb_inline lxb_dom_node_t *
 lxb_selectors_sibling(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry,
-                      const lxb_css_selector_t *selector, lxb_dom_node_t *node)
+                      lxb_dom_node_t *node)
 {
     node = node->prev;

     while (node != NULL) {
         if (node->type == LXB_DOM_NODE_TYPE_ELEMENT) {
-            if (lxb_selectors_match(selectors, entry, selector, node)) {
+            if (lxb_selectors_match(selectors, entry, node)) {
                 return node;
             }

@@ -236,15 +458,36 @@ lxb_selectors_sibling(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry,
     return NULL;
 }

+lxb_inline lxb_dom_node_t *
+lxb_selectors_sibling_forward(lxb_selectors_t *selectors,
+                              lxb_selectors_entry_t *entry, lxb_dom_node_t *node)
+{
+    node = node->next;
+
+    while (node != NULL) {
+        if (node->type == LXB_DOM_NODE_TYPE_ELEMENT) {
+            if (lxb_selectors_match(selectors, entry, node)) {
+                return node;
+            }
+
+            return NULL;
+        }
+
+        node = node->next;
+    }
+
+    return NULL;
+}
+
 lxb_inline lxb_dom_node_t *
 lxb_selectors_following(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry,
-                        const lxb_css_selector_t *selector, lxb_dom_node_t *node)
+                        lxb_dom_node_t *node)
 {
     node = node->prev;

     while (node != NULL) {
         if (node->type == LXB_DOM_NODE_TYPE_ELEMENT &&
-            lxb_selectors_match(selectors, entry, selector, node))
+            lxb_selectors_match(selectors, entry, node))
         {
             return node;
         }
@@ -255,6 +498,57 @@ lxb_selectors_following(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry
     return NULL;
 }

+lxb_inline lxb_dom_node_t *
+lxb_selectors_following_forward(lxb_selectors_t *selectors,
+                                lxb_selectors_entry_t *entry,
+                                lxb_dom_node_t *node)
+{
+    node = node->next;
+
+    while (node != NULL) {
+        if (node->type == LXB_DOM_NODE_TYPE_ELEMENT &&
+            lxb_selectors_match(selectors, entry, node))
+        {
+            return node;
+        }
+
+        node = node->next;
+    }
+
+    return NULL;
+}
+
+lxb_inline void
+lxb_selectors_switch_to_found_check(lxb_selectors_t *selectors,
+                                    lxb_selectors_nested_t *current)
+{
+    if (current->forward) {
+        selectors->state = lxb_selectors_state_found_check_forward;
+    }
+    else {
+        selectors->state = lxb_selectors_state_found_check;
+    }
+}
+
+lxb_inline void
+lxb_selectors_switch_to_not_found(lxb_selectors_t *selectors,
+                                  lxb_selectors_nested_t *current)
+{
+    if (current->forward) {
+        selectors->state = lxb_selectors_state_not_found_forward;
+    }
+    else {
+        selectors->state = lxb_selectors_state_not_found;
+    }
+}
+
+static lxb_selectors_entry_t *
+lxb_selectors_state_failed(lxb_selectors_t *selectors,
+                           lxb_selectors_entry_t *entry)
+{
+    return NULL;
+}
+
 lxb_status_t
 lxb_selectors_find(lxb_selectors_t *selectors, lxb_dom_node_t *root,
                    const lxb_css_selector_list_t *list,
@@ -263,23 +557,23 @@ lxb_selectors_find(lxb_selectors_t *selectors, lxb_dom_node_t *root,
     lxb_selectors_entry_t *entry;
     lxb_selectors_nested_t nested;

-    entry = lexbor_dobject_calloc(selectors->objs);
+    entry = lxb_selectors_entry_make_first(selectors, list->last);
     if (entry == NULL) {
         return LXB_STATUS_ERROR_MEMORY_ALLOCATION;
     }

-    entry->combinator = LXB_CSS_SELECTOR_COMBINATOR_CLOSE;
-    entry->selector = list->last;
-
     nested.parent = NULL;
     nested.entry = entry;
+    nested.first = entry;
+    nested.top = entry;
     nested.cb = cb;
     nested.ctx = ctx;
+    nested.forward = false;

     selectors->current = &nested;
     selectors->status = LXB_STATUS_OK;

-    return lxb_selectors_state_tree(selectors, root, list);
+    return lxb_selectors_tree(selectors, root);
 }

 lxb_status_t
@@ -295,23 +589,23 @@ lxb_selectors_match_node(lxb_selectors_t *selectors, lxb_dom_node_t *node,
         return LXB_STATUS_OK;
     }

-    entry = lexbor_dobject_calloc(selectors->objs);
+    entry = lxb_selectors_entry_make_first(selectors, list->last);
     if (entry == NULL) {
         return LXB_STATUS_ERROR_MEMORY_ALLOCATION;
     }

-    entry->combinator = LXB_CSS_SELECTOR_COMBINATOR_CLOSE;
-    entry->selector = list->last;
-
     nested.parent = NULL;
     nested.entry = entry;
+    nested.first = entry;
+    nested.top = entry;
     nested.cb = cb;
     nested.ctx = ctx;
+    nested.forward = false;

     selectors->current = &nested;
     selectors->status = LXB_STATUS_OK;

-    status = lxb_selectors_state_run(selectors, node, list);
+    status = lxb_selectors_run(selectors, node);

     lxb_selectors_clean(selectors);

@@ -320,15 +614,14 @@ lxb_selectors_match_node(lxb_selectors_t *selectors, lxb_dom_node_t *node,

 lxb_status_t
 lxb_selectors_find_reverse(lxb_selectors_t *selectors, lxb_dom_node_t *root,
-                           lxb_css_selector_list_t *list,
+                           const lxb_css_selector_list_t *list,
                            lxb_selectors_cb_f cb, void *ctx)
 {
     return lxb_selectors_find(selectors, root, list, cb, ctx);
 }

 static lxb_status_t
-lxb_selectors_state_tree(lxb_selectors_t *selectors, lxb_dom_node_t *root,
-                         const lxb_css_selector_list_t *list)
+lxb_selectors_tree(lxb_selectors_t *selectors, lxb_dom_node_t *root)
 {
     lxb_status_t status;
     lxb_dom_node_t *node;
@@ -353,7 +646,7 @@ lxb_selectors_state_tree(lxb_selectors_t *selectors, lxb_dom_node_t *root,
             goto next;
         }

-        status = lxb_selectors_state_run(selectors, node, list);
+        status = lxb_selectors_run(selectors, node);
         if (status != LXB_STATUS_OK) {
             if (status == LXB_STATUS_STOP) {
                 break;
@@ -391,32 +684,24 @@ lxb_selectors_state_tree(lxb_selectors_t *selectors, lxb_dom_node_t *root,
 }

 static lxb_status_t
-lxb_selectors_state_run(lxb_selectors_t *selectors, lxb_dom_node_t *node,
-                        const lxb_css_selector_list_t *list)
+lxb_selectors_run(lxb_selectors_t *selectors, lxb_dom_node_t *node)
 {
     lxb_selectors_entry_t *entry;
+    lxb_selectors_nested_t *current = selectors->current;

-    entry = selectors->current->entry;
+    entry = current->entry;

     entry->node = node;
+    current->root = node;
     selectors->state = lxb_selectors_state_find;
-    selectors->first = entry;
-
-again:

     do {
         entry = selectors->state(selectors, entry);
     }
     while (entry != NULL);

-    if (selectors->current->parent != NULL
-        && selectors->status == LXB_STATUS_OK)
-    {
-        entry = selectors->current->entry;
-        selectors->state = selectors->current->return_state;
-
-        goto again;
-    }
+    current->first = current->top;
+    current->entry = current->top;

     return selectors->status;
 }
@@ -426,92 +711,28 @@ lxb_selectors_state_find(lxb_selectors_t *selectors,
                          lxb_selectors_entry_t *entry)
 {
     lxb_dom_node_t *node;
-    lxb_selectors_entry_t *next;
-    const lxb_css_selector_t *selector;
-    const lxb_css_selector_anb_of_t *anb;
-    const lxb_css_selector_pseudo_t *pseudo;
-
-    selector = entry->selector;
-
-    if (selector->type == LXB_CSS_SELECTOR_TYPE_PSEUDO_CLASS_FUNCTION) {
-        pseudo = &selector->u.pseudo;
-
-        /* Optimizing. */

-        switch (pseudo->type) {
-            case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_CHILD:
-            case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_CHILD:
-                anb = pseudo->data;
-
-                if (anb->of != NULL) {
-                    break;
-                }
-
-                goto godoit;
-
-            case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_OF_TYPE:
-            case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_OF_TYPE:
-                goto godoit;
-
-            default:
-                break;
-        }
-
-        if (entry->nested == NULL) {
-            next = lexbor_dobject_calloc(selectors->objs);
-            if (next == NULL) {
-                selectors->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
-                return NULL;
-            }
-
-            next->combinator = LXB_CSS_SELECTOR_COMBINATOR_CLOSE;
-
-            entry->nested = lexbor_dobject_calloc(selectors->nested);
-            if (entry->nested == NULL) {
-                selectors->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
-                return NULL;
-            }
-
-            entry->nested->entry = next;
-            entry->nested->parent = selectors->current;
-        }
-
-        selectors->state = lxb_selectors_state_pseudo_class_function;
-        selectors->current->last = entry;
-        selectors->current = entry->nested;
-
-        next = entry->nested->entry;
-        next->node = entry->node;
-
-        return next;
-    }
-
-godoit:
+    selectors->state = lxb_selectors_state_found_check;

     switch (entry->combinator) {
         case LXB_CSS_SELECTOR_COMBINATOR_DESCENDANT:
-            node = lxb_selectors_descendant(selectors, entry,
-                                            selector, entry->node);
+            node = lxb_selectors_descendant(selectors, entry, entry->node);
             break;

         case LXB_CSS_SELECTOR_COMBINATOR_CLOSE:
-            node = lxb_selectors_close(selectors, entry,
-                                       selector, entry->node);
+            node = lxb_selectors_close(selectors, entry, entry->node);
             break;

         case LXB_CSS_SELECTOR_COMBINATOR_CHILD:
-            node = lxb_selectors_child(selectors, entry,
-                                       selector, entry->node);
+            node = lxb_selectors_child(selectors, entry, entry->node);
             break;

         case LXB_CSS_SELECTOR_COMBINATOR_SIBLING:
-            node = lxb_selectors_sibling(selectors, entry,
-                                         selector, entry->node);
+            node = lxb_selectors_sibling(selectors, entry, entry->node);
             break;

         case LXB_CSS_SELECTOR_COMBINATOR_FOLLOWING:
-            node = lxb_selectors_following(selectors, entry,
-                                           selector, entry->node);
+            node = lxb_selectors_following(selectors, entry, entry->node);
             break;

         case LXB_CSS_SELECTOR_COMBINATOR_CELL:
@@ -520,534 +741,447 @@ lxb_selectors_state_find(lxb_selectors_t *selectors,
             return NULL;
     }

-    return lxb_selectors_state_find_check(selectors, node, selector, entry);
+    if (node == NULL) {
+        selectors->state = lxb_selectors_state_not_found;
+    }
+    else {
+        selectors->current->entry->node = node;
+    }
+
+    return selectors->current->entry;
 }

 static lxb_selectors_entry_t *
-lxb_selectors_state_find_check(lxb_selectors_t *selectors, lxb_dom_node_t *node,
-                               const lxb_css_selector_t *selector,
-                               lxb_selectors_entry_t *entry)
+lxb_selectors_state_find_forward(lxb_selectors_t *selectors,
+                                 lxb_selectors_entry_t *entry)
 {
-    lxb_selectors_entry_t *next;
-    lxb_selectors_nested_t *current;
-
-    if (node == NULL) {
-
-    try_next:
-
-        if (entry->next == NULL) {
-
-        try_next_list:
-
-            if (selector->list->next == NULL) {
-                return NULL;
-            }
-
-            /*
-             * Try the following selectors from the selector list.
-             */
+    lxb_dom_node_t *node;

-            if (entry->following != NULL) {
-                entry->following->node = entry->node;
+    selectors->state = lxb_selectors_state_found_check_forward;

-                if (selectors->current->parent == NULL) {
-                    selectors->first = entry->following;
-                }
+    switch (entry->combinator) {
+        case LXB_CSS_SELECTOR_COMBINATOR_DESCENDANT:
+            node = lxb_selectors_descendant_forward(selectors, entry,
+                                                    entry->node);
+            break;

-                return entry->following;
-            }
+        case LXB_CSS_SELECTOR_COMBINATOR_CLOSE:
+            node = lxb_selectors_close_forward(selectors, entry,
+                                               entry->node);
+            break;

-            next = lexbor_dobject_calloc(selectors->objs);
-            if (next == NULL) {
-                selectors->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
-                return NULL;
-            }
+        case LXB_CSS_SELECTOR_COMBINATOR_CHILD:
+            node = lxb_selectors_child_forward(selectors, entry, entry->node);
+            break;

-            next->combinator = LXB_CSS_SELECTOR_COMBINATOR_CLOSE;
-            next->selector = selector->list->next->last;
-            next->node = entry->node;
+        case LXB_CSS_SELECTOR_COMBINATOR_SIBLING:
+            node = lxb_selectors_sibling_forward(selectors, entry, entry->node);
+            break;

-            entry->following = next;
+        case LXB_CSS_SELECTOR_COMBINATOR_FOLLOWING:
+            node = lxb_selectors_following_forward(selectors, entry,
+                                                   entry->node);
+            break;

-            if (selectors->current->parent == NULL) {
-                selectors->first = next;
-            }
+        case LXB_CSS_SELECTOR_COMBINATOR_CELL:
+        default:
+            selectors->status = LXB_STATUS_ERROR;
+            return NULL;
+    }

-            return next;
-        }
+    if (node == NULL) {
+    try_next:

         do {
-            entry = entry->next;
-
-            while (entry->combinator == LXB_CSS_SELECTOR_COMBINATOR_CLOSE) {
-                if (entry->next == NULL) {
-                    selector = entry->selector;
-                    goto try_next;
-                }
-
-                entry = entry->next;
+            if (entry->prev == NULL) {
+                return lxb_selectors_next_list_forward(selectors, entry);
             }

-            switch (entry->combinator) {
-                case LXB_CSS_SELECTOR_COMBINATOR_DESCENDANT:
-                    node = entry->node->parent;
-
-                    if (node == NULL
-                        || node->type != LXB_DOM_NODE_TYPE_ELEMENT)
-                    {
-                        node = NULL;
-                    }
-
-                    break;
-
-                case LXB_CSS_SELECTOR_COMBINATOR_FOLLOWING:
-                    node = entry->node->prev;
-                    break;
-
-                case LXB_CSS_SELECTOR_COMBINATOR_SIBLING:
-                case LXB_CSS_SELECTOR_COMBINATOR_CHILD:
-                case LXB_CSS_SELECTOR_COMBINATOR_CLOSE:
-                    node = NULL;
-                    break;
-
-                case LXB_CSS_SELECTOR_COMBINATOR_CELL:
-                default:
-                    selectors->status = LXB_STATUS_ERROR;
-                    return NULL;
-            }
+            entry = entry->prev;
         }
-        while (node == NULL);
+        while (entry->combinator == LXB_CSS_SELECTOR_COMBINATOR_CLOSE);

-        entry->node = node;
+        if (entry->combinator == LXB_CSS_SELECTOR_COMBINATOR_SIBLING) {
+            goto try_next;
+        }

-        return entry;
+        selectors->current->entry = entry;
+        selectors->state = lxb_selectors_state_find_forward;
+    }
+    else {
+        selectors->current->entry->node = node;
     }

-    if (selector->prev == NULL) {
-        current = selectors->current;
-
-        selectors->status = current->cb(current->entry->node,
-                                        selector->list->specificity,
-                                        current->ctx);
+    return selectors->current->entry;
+}

-        if ((selectors->options & LXB_SELECTORS_OPT_MATCH_FIRST) == 0
-            && current->parent == NULL)
-        {
-            if (selectors->status == LXB_STATUS_OK) {
-                entry = selectors->first;
-                goto try_next_list;
-            }
-        }
+lxb_inline lxb_selectors_entry_t *
+lxb_selectors_done(lxb_selectors_t *selectors)
+{
+    lxb_selectors_nested_t *current = selectors->current;

+    if (current->parent == NULL) {
         return NULL;
     }

-    if (entry->prev == NULL) {
-        next = lexbor_dobject_calloc(selectors->objs);
-        if (next == NULL) {
-            selectors->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
-            return NULL;
-        }
+    selectors->current = current->parent;

-        next->combinator = selector->combinator;
-        next->selector = selector->prev;
-        next->node = node;
+    return selectors->current->entry;
+}

-        next->next = entry;
-        entry->prev = next;
+lxb_inline lxb_selectors_entry_t *
+lxb_selectors_exit(lxb_selectors_t *selectors)
+{
+    lxb_selectors_nested_t *current = selectors->current;

-        return next;
+    if (current->parent == NULL) {
+        return NULL;
     }

-    entry->prev->node = node;
+    selectors->state = current->return_state;

-    return entry->prev;
+    return current->entry;
 }

 static lxb_selectors_entry_t *
-lxb_selectors_state_pseudo_class_function(lxb_selectors_t *selectors,
-                                          lxb_selectors_entry_t *entry)
+lxb_selectors_state_found_check(lxb_selectors_t *selectors,
+                                lxb_selectors_entry_t *entry)
 {
-    lxb_dom_node_t *node, *base;
     lxb_selectors_nested_t *current;
-    const lxb_css_selector_list_t *list;
-    lxb_css_selector_anb_of_t *anb;
-    const lxb_css_selector_pseudo_t *pseudo;
+    lxb_dom_node_t *node;
+    lxb_selectors_entry_t *prev;
+    const lxb_css_selector_t *selector;

     current = selectors->current;
+    entry = current->entry;
+    node = entry->node;

-    base = lxb_selectors_next_node(current);
-    if (base == NULL) {
-        goto not_found;
-    }
-
-    pseudo = &current->parent->last->selector->u.pseudo;
-
-    switch (pseudo->type) {
-        case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_HAS:
-            list = (lxb_css_selector_list_t *) pseudo->data;
-            node = lxb_selectors_state_has_relative(base, list->first);
-
-            if (node == NULL) {
-                selectors->current = selectors->current->parent;
-                entry = selectors->current->last;
-
-                selectors->state = lxb_selectors_state_find;
-
-                return lxb_selectors_state_find_check(selectors, NULL,
-                                                      entry->selector, entry);
-            }
-
-            current->root = base;
-
-            current->entry->selector = list->last;
-            current->entry->node = node;
-            current->return_state = lxb_selectors_state_after_find_has;
-            current->cb = lxb_selectors_cb_ok;
-            current->ctx = &current->found;
-            current->found = false;
-
-            selectors->state = lxb_selectors_state_find;
+    if (entry->prev == NULL) {
+        selector = entry->selector;

-            return entry;
+        while (selector->combinator == LXB_CSS_SELECTOR_COMBINATOR_CLOSE
+               && selector->prev != NULL)
+        {
+            selector = selector->prev;
+        }

-        case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_CURRENT:
-        case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_IS:
-        case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_WHERE:
-            current->entry->selector = ((lxb_css_selector_list_t *) pseudo->data)->last;
-            current->entry->node = base;
-            current->return_state = lxb_selectors_state_after_find;
-            current->cb = lxb_selectors_cb_ok;
-            current->ctx = &current->found;
-            current->found = false;
+        if (selector->prev == NULL) {
+            return lxb_selectors_state_found(selectors, entry);
+        }

-            selectors->state = lxb_selectors_state_find;
+        prev = lxb_selectors_state_entry_create(selectors, selector,
+                                                entry, node);
+        current->entry = prev;
+        selectors->state = lxb_selectors_state_find;

-            return entry;
+        return prev;
+    }

-        case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NOT:
-            current->entry->selector = ((lxb_css_selector_list_t *) pseudo->data)->last;
-            current->entry->node = base;
-            current->return_state = lxb_selectors_state_after_find;
-            current->cb = lxb_selectors_cb_not;
-            current->ctx = &current->found;
-            current->found = true;
+    selectors->state = lxb_selectors_state_find;

-            selectors->state = lxb_selectors_state_find;
+    current->entry = entry->prev;
+    entry->prev->node = node;

-            return entry;
+    return entry->prev;
+}

-        case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_CHILD:
-        case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_CHILD:
-            anb = pseudo->data;
+static lxb_selectors_entry_t *
+lxb_selectors_state_found_check_forward(lxb_selectors_t *selectors,
+                                        lxb_selectors_entry_t *entry)
+{
+    lxb_selectors_nested_t *current;
+    lxb_dom_node_t *node;
+    lxb_selectors_entry_t *next;
+    const lxb_css_selector_t *selector;

-            current->entry->selector = anb->of->last;
-            current->entry->node = base;
-            current->return_state = lxb_selectors_state_after_nth_child;
-            current->cb = lxb_selectors_cb_ok;
-            current->ctx = &current->found;
-            current->root = base;
-            current->index = 0;
-            current->found = false;
+    current = selectors->current;
+    entry = current->entry;
+    node = entry->node;

-            selectors->state = lxb_selectors_state_find;
+    if (entry->next == NULL) {
+        selector = entry->selector;

-            return entry;
+        if (selector->next == NULL) {
+            return lxb_selectors_state_found_forward(selectors, entry);
+        }

-        /*
-         * This one can only happen if the user has somehow messed up the
-         * selector.
-         */
+        next = lxb_selectors_state_entry_create_forward(selectors, selector,
+                                                        entry, node);
+        current->entry = next;
+        selectors->state = lxb_selectors_state_find_forward;

-        case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_OF_TYPE:
-        case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_OF_TYPE:
-        case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_DIR:
-        case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_LANG:
-        case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_COL:
-        case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_COL:
-        default:
-            break;
+        return next;
     }

-not_found:
+    selectors->state = lxb_selectors_state_find_forward;

-    selectors->current = selectors->current->parent;
-    entry = selectors->current->last;
+    current->entry = entry->next;
+    entry->next->node = node;

-    selectors->state = lxb_selectors_state_find;
-
-    return lxb_selectors_state_find_check(selectors, NULL,
-                                          entry->selector, entry);
+    return entry->next;
 }

-static lxb_dom_node_t *
-lxb_selectors_next_node(lxb_selectors_nested_t *main)
+static lxb_selectors_entry_t *
+lxb_selectors_state_found(lxb_selectors_t *selectors,
+                          lxb_selectors_entry_t *entry)
 {
-    lxb_dom_node_t *node = main->entry->node;
-
-    switch (main->parent->last->combinator) {
-        case LXB_CSS_SELECTOR_COMBINATOR_DESCENDANT:
-        case LXB_CSS_SELECTOR_COMBINATOR_CHILD:
-            if (node->parent == NULL
-                || node->parent->type != LXB_DOM_NODE_TYPE_ELEMENT)
-            {
-                return NULL;
-            }
-
-            return node->parent;
+    lxb_selectors_nested_t *current;
+    const lxb_css_selector_t *selector;

-        case LXB_CSS_SELECTOR_COMBINATOR_CLOSE:
-            return node;
+    current = selectors->current;
+    selector = current->entry->selector;

-        case LXB_CSS_SELECTOR_COMBINATOR_SIBLING:
-        case LXB_CSS_SELECTOR_COMBINATOR_FOLLOWING:
-            node = node->prev;
-            break;
+    selectors->state = lxb_selectors_state_find;

-        default:
-            return NULL;
-    }
+    selectors->status = current->cb(current->root,
+                                    selector->list->specificity,
+                                    current->ctx);

-    while (node != NULL) {
-        if (node->type == LXB_DOM_NODE_TYPE_ELEMENT) {
-            break;
+    if ((selectors->options & LXB_SELECTORS_OPT_MATCH_FIRST) == 0
+        && current->parent == NULL)
+    {
+        if (selectors->status == LXB_STATUS_OK) {
+            entry = selectors->current->first;
+            return lxb_selectors_next_list(selectors, entry);
         }
-
-        node = node->prev;
     }

-    return node;
+    return lxb_selectors_done(selectors);
 }

-static lxb_dom_node_t *
-lxb_selectors_state_has_relative(lxb_dom_node_t *node,
-                                 const lxb_css_selector_t *selector)
+static lxb_selectors_entry_t *
+lxb_selectors_state_found_forward(lxb_selectors_t *selectors,
+                                  lxb_selectors_entry_t *entry)
 {
-    lxb_dom_node_t *root = node;
-
-    switch (selector->combinator) {
-        case LXB_CSS_SELECTOR_COMBINATOR_DESCENDANT:
-        case LXB_CSS_SELECTOR_COMBINATOR_CHILD:
-            node = node->first_child;
-            break;
-
-        case LXB_CSS_SELECTOR_COMBINATOR_SIBLING:
-        case LXB_CSS_SELECTOR_COMBINATOR_FOLLOWING:
-            node = node->next;
-            break;
+    lxb_selectors_nested_t *current;
+    const lxb_css_selector_t *selector;

-        default:
-            return NULL;
-    }
+    current = selectors->current;
+    selector = current->entry->selector;

-    while (node != NULL) {
-        if (node->type == LXB_DOM_NODE_TYPE_ELEMENT) {
-            break;
-        }
+    selectors->state = lxb_selectors_state_find_forward;

-        while (node !=root && node->next == NULL) {
-            node = node->parent;
-        }
+    selectors->status = current->cb(current->root,
+                                    selector->list->specificity,
+                                    current->ctx);

-        if (node == root) {
-            return NULL;
+    if ((selectors->options & LXB_SELECTORS_OPT_MATCH_FIRST) == 0
+        && current->parent == NULL)
+    {
+        if (selectors->status == LXB_STATUS_OK) {
+            entry = selectors->current->first;
+            return lxb_selectors_next_list_forward(selectors, entry);
         }
-
-        node = node->next;
     }

-    return node;
+    return lxb_selectors_done(selectors);
 }

+
 static lxb_selectors_entry_t *
-lxb_selectors_state_after_find_has(lxb_selectors_t *selectors,
-                                   lxb_selectors_entry_t *entry)
+lxb_selectors_state_not_found(lxb_selectors_t *selectors,
+                              lxb_selectors_entry_t *entry)
 {
-    lxb_dom_node_t *node;
-    lxb_selectors_entry_t *parent;
     lxb_selectors_nested_t *current;

-    if (selectors->current->found) {
-        node = selectors->current->root;
-
-        selectors->current = selectors->current->parent;
-        parent = selectors->current->last;
+    current = selectors->current;
+    entry = current->entry;

-        selectors->state = lxb_selectors_state_find;
+try_next:

-        return lxb_selectors_state_find_check(selectors, node,
-                                              parent->selector, parent);
+    if (entry->next == NULL) {
+        return lxb_selectors_next_list(selectors, entry);
     }

-    current = selectors->current;
-    node = entry->node;
+    entry = entry->next;

-    switch (entry->selector->list->first->combinator) {
-        case LXB_CSS_SELECTOR_COMBINATOR_DESCENDANT:
-            if (node->first_child != NULL) {
-                node = node->first_child;
-            }
-            else {
-
-            next:
+    while (entry->combinator == LXB_CSS_SELECTOR_COMBINATOR_CLOSE) {
+        if (entry->next == NULL) {
+            goto try_next;
+        }

-                while (node != current->root && node->next == NULL) {
-                    node = node->parent;
-                }
+        entry = entry->next;
+    }

-                if (node == current->root) {
-                    goto failed;
-                }
+    switch (entry->combinator) {
+        case LXB_CSS_SELECTOR_COMBINATOR_SIBLING:
+        case LXB_CSS_SELECTOR_COMBINATOR_CHILD:
+        case LXB_CSS_SELECTOR_COMBINATOR_CLOSE:
+            goto try_next;

-                node = node->next;
-            }
+        default:
+            break;
+    }

-            if (node->type != LXB_DOM_NODE_TYPE_ELEMENT) {
-                goto next;
-            }
+    current->entry = entry;
+    selectors->state = lxb_selectors_state_find;

-            break;
+    return entry;
+}

-        case LXB_CSS_SELECTOR_COMBINATOR_CHILD:
-        case LXB_CSS_SELECTOR_COMBINATOR_FOLLOWING:
-            node = node->next;
+static lxb_selectors_entry_t *
+lxb_selectors_state_not_found_forward(lxb_selectors_t *selectors,
+                                      lxb_selectors_entry_t *entry)
+{
+try_next:

-            while (node != NULL && node->type != LXB_DOM_NODE_TYPE_ELEMENT) {
-                node = node->next;
-            }
+    if (entry->prev == NULL) {
+        return lxb_selectors_next_list_forward(selectors, entry);
+    }

-            if (node == NULL) {
-                goto failed;
-            }
+    while (entry->combinator == LXB_CSS_SELECTOR_COMBINATOR_CLOSE) {
+        if (entry->prev == NULL) {
+            goto try_next;
+        }

-            break;
+        entry = entry->prev;
+    }

-        case LXB_CSS_SELECTOR_COMBINATOR_SIBLING:
-            goto failed;
+    if (entry->combinator == LXB_CSS_SELECTOR_COMBINATOR_SIBLING) {
+        if (entry->prev != NULL) {
+            entry = entry->prev;
+        }

-        case LXB_CSS_SELECTOR_COMBINATOR_CLOSE:
-        case LXB_CSS_SELECTOR_COMBINATOR_CELL:
-        default:
-            selectors->status = LXB_STATUS_ERROR;
-            return NULL;
+        goto try_next;
     }

-    entry->node = node;
-    selectors->state = lxb_selectors_state_find;
+    selectors->current->entry = entry;
+    selectors->state = lxb_selectors_state_find_forward;

     return entry;
+}

-failed:
-
-    selectors->current = selectors->current->parent;
-    parent = selectors->current->last;
+static lxb_selectors_entry_t *
+lxb_selectors_next_list(lxb_selectors_t *selectors,
+                        lxb_selectors_entry_t *entry)
+{
+    if (entry->selector->list->next == NULL) {
+        return lxb_selectors_exit(selectors);
+    }

     selectors->state = lxb_selectors_state_find;

-    return lxb_selectors_state_find_check(selectors, NULL,
-                                          parent->selector, parent);
+    /*
+     * Try the following selectors from the selector list.
+     */
+
+    return lxb_selectors_make_following(selectors, entry);
 }

+static lxb_selectors_entry_t *
+lxb_selectors_next_list_forward(lxb_selectors_t *selectors,
+                                lxb_selectors_entry_t *entry)
+{
+    if (entry->selector->list->next == NULL) {
+        return lxb_selectors_exit(selectors);
+    }
+
+    selectors->state = lxb_selectors_state_find_forward;
+
+    /*
+     * Try the following selectors from the selector list.
+     */
+
+    return lxb_selectors_make_following_forward(selectors, entry);
+}

 static lxb_selectors_entry_t *
-lxb_selectors_state_after_find(lxb_selectors_t *selectors,
-                               lxb_selectors_entry_t *entry)
+lxb_selectors_make_following(lxb_selectors_t *selectors,
+                             lxb_selectors_entry_t *entry)
 {
-    lxb_dom_node_t *node;
-    lxb_selectors_entry_t *parent;
+    lxb_selectors_entry_t *next;
     lxb_selectors_nested_t *current;
+    const lxb_css_selector_t *selector;

+    selector = entry->selector;
     current = selectors->current;

-    if (current->found) {
-        node = entry->node;
-
-        selectors->current = current->parent;
-        parent = selectors->current->last;
+    if (entry->following != NULL) {
+        entry->following->node = current->root;
+        current->first = entry->following;
+        current->entry = entry->following;

-        selectors->state = lxb_selectors_state_find;
+        return entry->following;
+    }

-        return lxb_selectors_state_find_check(selectors, node,
-                                              parent->selector, parent);
+    next = lxb_selectors_entry_make_first(selectors,
+                                          selector->list->next->last);
+    if (next == NULL) {
+        selectors->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
+        return NULL;
     }

-    node = entry->node;
+    next->node = current->root;

-    switch (current->parent->last->combinator) {
-        case LXB_CSS_SELECTOR_COMBINATOR_DESCENDANT:
-            if (node->parent != NULL
-                && node->parent->type == LXB_DOM_NODE_TYPE_ELEMENT)
-            {
-                node = node->parent;
-            }
-            else {
-                node = NULL;
-            }
+    entry->following = next;
+    current->first = next;
+    current->entry = next;

-            break;
+    return next;
+}

-        case LXB_CSS_SELECTOR_COMBINATOR_FOLLOWING:
-            node = node->prev;
+static lxb_selectors_entry_t *
+lxb_selectors_make_following_forward(lxb_selectors_t *selectors,
+                                     lxb_selectors_entry_t *entry)
+{
+    lxb_selectors_entry_t *next;
+    lxb_selectors_nested_t *current;
+    const lxb_css_selector_t *selector;

-            while (node != NULL && node->type != LXB_DOM_NODE_TYPE_ELEMENT) {
-                node = node->prev;
-            }
+    selector = entry->selector;
+    current = selectors->current;

-            break;
+    if (entry->following != NULL) {
+        entry->following->node = current->root;
+        current->first = entry->following;
+        current->entry = entry->following;

-        case LXB_CSS_SELECTOR_COMBINATOR_CHILD:
-        case LXB_CSS_SELECTOR_COMBINATOR_SIBLING:
-        case LXB_CSS_SELECTOR_COMBINATOR_CLOSE:
-            node = NULL;
-            break;
+        return entry->following;
+    }

-        case LXB_CSS_SELECTOR_COMBINATOR_CELL:
-        default:
-            selectors->status = LXB_STATUS_ERROR;
-            return NULL;
+    next = lexbor_dobject_calloc(selectors->objs);
+    if (next == NULL) {
+        selectors->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
+        return NULL;
     }

-    if (node == NULL) {
-        selectors->current = current->parent;
-        parent = selectors->current->last;
+    next->selector = selector->list->next->first;
+    next->node = current->root;
+    next->combinator = next->selector->combinator;

-        selectors->state = lxb_selectors_state_find;
+    entry->following = next;
+    current->first = next;
+    current->entry = next;

-        return lxb_selectors_state_find_check(selectors, node,
-                                              parent->selector, parent);
-    }
+    return next;
+}

-    entry->node = node;
-    selectors->state = lxb_selectors_state_find;
+static lxb_selectors_entry_t *
+lxb_selectors_state_after_find(lxb_selectors_t *selectors,
+                               lxb_selectors_entry_t *entry)
+{
+    selectors->current = selectors->current->parent;

-    return entry;
+    lxb_selectors_switch_to_not_found(selectors, selectors->current);
+
+    return selectors->current->entry;
 }

 static lxb_selectors_entry_t *
-lxb_selectors_state_after_nth_child(lxb_selectors_t *selectors,
-                                    lxb_selectors_entry_t *entry)
+lxb_selectors_state_after_not(lxb_selectors_t *selectors,
+                              lxb_selectors_entry_t *entry)
 {
-    bool found;
-    lxb_dom_node_t *node;
-    lxb_selectors_entry_t *parent;
-    lxb_selectors_nested_t *current;
-    const lxb_css_selector_t *selector;
-    const lxb_css_selector_pseudo_t *pseudo;
-
-    current = selectors->current;
-    selector = current->parent->last->selector;
-    pseudo = &selector->u.pseudo;
+    selectors->current = selectors->current->parent;

-    node = entry->node;
+    lxb_selectors_switch_to_found_check(selectors, selectors->current);

-    if (current->found) {
-        current->index += 1;
-    }
-    else if (current->root == node) {
-        node = NULL;
-        goto done;
-    }
+    return selectors->current->entry;
+}

+lxb_inline lxb_dom_node_t *
+lxb_selectors_state_nth_child_node(const lxb_css_selector_pseudo_t *pseudo,
+                                   lxb_dom_node_t *node)
+{
     if (pseudo->type == LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_CHILD) {
         node = node->prev;

@@ -1071,48 +1205,100 @@ lxb_selectors_state_after_nth_child(lxb_selectors_t *selectors,
         }
     }

+    return node;
+}
+
+lxb_inline lxb_selectors_entry_t *
+lxb_selectors_state_nth_child_done(lxb_selectors_t *selectors,
+                                   const lxb_css_selector_pseudo_t *pseudo,
+                                   size_t index)
+{
+    if (lxb_selectors_anb_calc(pseudo->data, index)) {
+        lxb_selectors_switch_to_found_check(selectors, selectors->current);
+    }
+    else {
+        lxb_selectors_switch_to_not_found(selectors, selectors->current);
+    }
+
+    return selectors->current->entry;
+}
+
+static lxb_selectors_entry_t *
+lxb_selectors_state_after_nth_child(lxb_selectors_t *selectors,
+                                    lxb_selectors_entry_t *entry)
+{
+    lxb_dom_node_t *node;
+    lxb_selectors_nested_t *current;
+    const lxb_css_selector_pseudo_t *pseudo;
+
+    current = selectors->current;
+
+    if (current->index == 0) {
+        selectors->current = selectors->current->parent;
+        lxb_selectors_switch_to_not_found(selectors, selectors->current);
+
+        return selectors->current->entry;
+    }
+
+    pseudo = &current->parent->entry->selector->u.pseudo;
+    node = lxb_selectors_state_nth_child_node(pseudo, current->root);
+
     if (node == NULL) {
-        goto done;
+        selectors->current = selectors->current->parent;
+
+        return lxb_selectors_state_nth_child_done(selectors, pseudo,
+                                                  current->index);
     }

-    entry->node = node;
-    current->found = false;
+    current->root = node;
+    current->entry->node = node;
+
     selectors->state = lxb_selectors_state_find;

     return entry;
+}

-done:
+static lxb_selectors_entry_t *
+lxb_selectors_state_nth_child_found(lxb_selectors_t *selectors,
+                                    lxb_selectors_entry_t *entry)
+{
+    lxb_dom_node_t *node;
+    lxb_selectors_nested_t *current;
+    const lxb_css_selector_pseudo_t *pseudo;

-    if (current->index > 0) {
-        found = lxb_selectors_anb_calc(pseudo->data, current->index);
+    current = entry->nested;
+    pseudo = &entry->selector->u.pseudo;
+    node = lxb_selectors_state_nth_child_node(pseudo, current->root);

-        node = (found) ? current->root : NULL;
+    if (node == NULL) {
+        return lxb_selectors_state_nth_child_done(selectors, pseudo,
+                                                  current->index);
     }

-    selectors->state = lxb_selectors_state_find;
-    selectors->current = selectors->current->parent;
+    current->root = node;
+    current->entry->node = node;

-    parent = selectors->current->last;
+    selectors->current = current;
+    selectors->state = lxb_selectors_state_find;

-    return lxb_selectors_state_find_check(selectors, node,
-                                          parent->selector, parent);
+    return current->entry;
 }

 static bool
 lxb_selectors_match(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry,
-                    const lxb_css_selector_t *selector, lxb_dom_node_t *node)
+                    lxb_dom_node_t *node)
 {
     lxb_dom_element_t *element;

-    switch (selector->type) {
+    switch (entry->selector->type) {
         case LXB_CSS_SELECTOR_TYPE_ANY:
             return true;

         case LXB_CSS_SELECTOR_TYPE_ELEMENT:
-            return lxb_selectors_match_element(selector, node, entry);
+            return lxb_selectors_match_element(entry->selector, node, entry);

         case LXB_CSS_SELECTOR_TYPE_ID:
-            return lxb_selectors_match_id(selector, node);
+            return lxb_selectors_match_id(entry->selector, node);

         case LXB_CSS_SELECTOR_TYPE_CLASS:
             element = lxb_dom_interface_element(node);
@@ -1124,19 +1310,19 @@ lxb_selectors_match(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry,
             }

             return lxb_selectors_match_class(element->attr_class->value,
-                                             &selector->name, true);
+                                             &entry->selector->name, true);

         case LXB_CSS_SELECTOR_TYPE_ATTRIBUTE:
-            return lxb_selectors_match_attribute(selector, node, entry);
+            return lxb_selectors_match_attribute(entry->selector, node, entry);

         case LXB_CSS_SELECTOR_TYPE_PSEUDO_CLASS:
-            return lxb_selectors_pseudo_class(selector, node);
+            return lxb_selectors_pseudo_class(entry->selector, node);

         case LXB_CSS_SELECTOR_TYPE_PSEUDO_CLASS_FUNCTION:
-            return lxb_selectors_pseudo_class_function(selector, node);
-
+            return lxb_selectors_pseudo_class_function(selectors,
+                                                       entry->selector, node);
         case LXB_CSS_SELECTOR_TYPE_PSEUDO_ELEMENT:
-            return lxb_selectors_pseudo_element(selector, node);
+            return lxb_selectors_pseudo_element(entry->selector, node);

         case LXB_CSS_SELECTOR_TYPE_PSEUDO_ELEMENT_FUNCTION:
             return false;
@@ -1641,19 +1827,141 @@ lxb_selectors_pseudo_class(const lxb_css_selector_t *selector,
     return false;
 }

+static lxb_selectors_nested_t *
+lxb_selectors_nested_make(lxb_selectors_t *selectors, lxb_dom_node_t *node,
+                          lxb_css_selector_t *selector, bool forward)
+{
+    lxb_selectors_entry_t *next;
+    lxb_selectors_entry_t *entry;
+
+    entry = selectors->current->entry;
+    entry->node = node;
+
+    if (entry->nested == NULL) {
+        if (!forward) {
+            next = lxb_selectors_entry_make_first(selectors, selector);
+            if (next == NULL) {
+                selectors->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
+                return NULL;
+            }
+        }
+        else {
+            next = lexbor_dobject_calloc(selectors->objs);
+            if (next == NULL) {
+                selectors->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
+                return NULL;
+            }
+
+            next->combinator = selector->combinator;
+            next->selector = selector;
+        }
+
+        entry->nested = lexbor_dobject_calloc(selectors->nested);
+        if (entry->nested == NULL) {
+            selectors->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
+            return NULL;
+        }
+
+        entry->nested->top = next;
+        entry->nested->parent = selectors->current;
+        entry->nested->forward = forward;
+    }
+
+    selectors->current = entry->nested;
+    entry->nested->entry = entry->nested->top;
+    entry->nested->first = entry->nested->top;
+
+    selectors->current->root = node;
+    selectors->current->ctx = selectors;
+
+    return selectors->current;
+}
+
 static bool
-lxb_selectors_pseudo_class_function(const lxb_css_selector_t *selector,
+lxb_selectors_pseudo_class_function(lxb_selectors_t *selectors,
+                                    const lxb_css_selector_t *selector,
                                     lxb_dom_node_t *node)
 {
+    bool is;
     size_t index;
     lxb_dom_node_t *base;
+    lxb_selectors_nested_t *current;
+    const lexbor_str_t *str;
+    const lxb_dom_text_t *text;
+    const lxb_css_selector_list_t *list;
+    const lxb_css_selector_anb_of_t *anb;
     const lxb_css_selector_pseudo_t *pseudo;
+    const lxb_css_selector_contains_t *contains;

     pseudo = &selector->u.pseudo;

     switch (pseudo->type) {
+        case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_HAS:
+            list = (lxb_css_selector_list_t *) pseudo->data;
+
+            current = lxb_selectors_nested_make(selectors, node,
+                                                list->first, true);
+            if (current == NULL) {
+                goto failed;
+            }
+
+            current->cb = lxb_selectors_cb_ok;
+            current->return_state = lxb_selectors_state_after_find;
+            selectors->state = lxb_selectors_state_find_forward;
+
+            break;
+
+        case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_CURRENT:
+        case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_IS:
+        case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_WHERE:
+            list = (lxb_css_selector_list_t *) pseudo->data;
+
+            current = lxb_selectors_nested_make(selectors, node, list->last,
+                                                false);
+            if (current == NULL) {
+                goto failed;
+            }
+
+            current->cb = lxb_selectors_cb_ok;
+            current->return_state = lxb_selectors_state_after_find;
+            selectors->state = lxb_selectors_state_find;
+
+            break;
+
+        case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NOT:
+            list = (lxb_css_selector_list_t *) pseudo->data;
+
+            current = lxb_selectors_nested_make(selectors, node, list->last,
+                                                false);
+            if (current == NULL) {
+                goto failed;
+            }
+
+            current->cb = lxb_selectors_cb_not;
+            current->return_state = lxb_selectors_state_after_not;
+            selectors->state = lxb_selectors_state_find;
+
+            break;
+
         case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_CHILD:
         case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_CHILD:
+            anb = pseudo->data;
+
+            if (anb->of != NULL) {
+                current = lxb_selectors_nested_make(selectors, node,
+                                                    anb->of->last, false);
+                if (current == NULL) {
+                    goto failed;
+                }
+
+                current->return_state = lxb_selectors_state_after_nth_child;
+                current->cb = lxb_selectors_cb_nth_ok;
+                current->index = 0;
+                selectors->state = lxb_selectors_state_find;
+
+                return true;
+            }
+
             index = 0;

             if (pseudo->type == LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_CHILD) {
@@ -1711,15 +2019,52 @@ lxb_selectors_pseudo_class_function(const lxb_css_selector_t *selector,

             return lxb_selectors_anb_calc(pseudo->data, index);

+        case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_LEXBOR_CONTAINS:
+            contains = pseudo->data;
+
+            node = node->first_child;
+            while (node != NULL) {
+                if (node->type == LXB_DOM_NODE_TYPE_TEXT) {
+                    text = lxb_dom_interface_text(node);
+                    str = &text->char_data.data;
+
+                    if (contains->insensitive) {
+                        is = lexbor_str_data_ncasecmp_contain(str->data, str->length,
+                                                              contains->str.data,
+                                                              contains->str.length);
+                    }
+                    else {
+                        is = lexbor_str_data_ncmp_contain(str->data, str->length,
+                                                          contains->str.data,
+                                                          contains->str.length);
+                    }
+
+                    if (is) {
+                        return true;
+                    }
+                }
+
+                node = node->next;
+            }
+
+            return false;
+
         case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_DIR:
         case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_LANG:
         case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_COL:
         case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_COL:
         default:
-            break;
+            return false;
     }

-    return false;
+    return true;
+
+failed:
+
+    selectors->state = lxb_selectors_state_failed;
+    selectors->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION;
+
+    return true;
 }

 static bool
@@ -1900,7 +2245,10 @@ static lxb_status_t
 lxb_selectors_cb_ok(lxb_dom_node_t *node,
                     lxb_css_selector_specificity_t spec, void *ctx)
 {
-    *((bool *) ctx) = true;
+    lxb_selectors_t *selectors = ctx;
+
+    lxb_selectors_switch_to_found_check(selectors, selectors->current->parent);
+
     return LXB_STATUS_OK;
 }

@@ -1908,7 +2256,22 @@ static lxb_status_t
 lxb_selectors_cb_not(lxb_dom_node_t *node,
                      lxb_css_selector_specificity_t spec, void *ctx)
 {
-    *((bool *) ctx) = false;
+    lxb_selectors_t *selectors = ctx;
+
+    lxb_selectors_switch_to_not_found(selectors, selectors->current->parent);
+
+    return LXB_STATUS_OK;
+}
+
+static lxb_status_t
+lxb_selectors_cb_nth_ok(lxb_dom_node_t *node,
+                        lxb_css_selector_specificity_t spec, void *ctx)
+{
+    lxb_selectors_t *selectors = ctx;
+
+    selectors->current->index += 1;
+    selectors->state = lxb_selectors_state_nth_child_found;
+
     return LXB_STATUS_OK;
 }

diff --git a/ext/dom/lexbor/lexbor/selectors/selectors.h b/ext/dom/lexbor/lexbor/selectors/selectors.h
index a9db864ff17..b6fe28a4eac 100644
--- a/ext/dom/lexbor/lexbor/selectors/selectors.h
+++ b/ext/dom/lexbor/lexbor/selectors/selectors.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021-2024 Alexander Borisov
+ * Copyright (C) 2021-2025 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -89,11 +89,13 @@ struct lxb_selectors_nested {
     void                     *ctx;

     lxb_dom_node_t           *root;
-    lxb_selectors_entry_t    *last;
     lxb_selectors_nested_t   *parent;
+    lxb_selectors_entry_t    *first;
+    lxb_selectors_entry_t    *top;

     size_t                   index;
-    bool                     found;
+
+    bool                     forward;
 };

 struct lxb_selectors {
@@ -102,7 +104,6 @@ struct lxb_selectors {
     lexbor_dobject_t         *nested;

     lxb_selectors_nested_t   *current;
-    lxb_selectors_entry_t    *first;

     lxb_selectors_opt_t      options;
     lxb_status_t             status;
@@ -220,7 +221,7 @@ lxb_selectors_match_node(lxb_selectors_t *selectors, lxb_dom_node_t *node,
  */
 LXB_API LXB_DEPRECATED(lxb_status_t
 lxb_selectors_find_reverse(lxb_selectors_t *selectors, lxb_dom_node_t *root,
-                           lxb_css_selector_list_t *list,
+                           const lxb_css_selector_list_t *list,
                            lxb_selectors_cb_f cb, void *ctx));

 /*
diff --git a/ext/dom/lexbor/lexbor/tag/base.h b/ext/dom/lexbor/lexbor/tag/base.h
index 94886ee4f47..27ba326cf40 100644
--- a/ext/dom/lexbor/lexbor/tag/base.h
+++ b/ext/dom/lexbor/lexbor/tag/base.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019-2024 Alexander Borisov
+ * Copyright (C) 2019-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -16,7 +16,7 @@ extern "C" {


 #define LXB_TAG_VERSION_MAJOR 1
-#define LXB_TAG_VERSION_MINOR 3
+#define LXB_TAG_VERSION_MINOR 5
 #define LXB_TAG_VERSION_PATCH 0

 #define LXB_TAG_VERSION_STRING                                                 \
diff --git a/ext/dom/lexbor/lexbor/tag/const.h b/ext/dom/lexbor/lexbor/tag/const.h
index 1a598d34747..b08e387da32 100644
--- a/ext/dom/lexbor/lexbor/tag/const.h
+++ b/ext/dom/lexbor/lexbor/tag/const.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -14,8 +14,8 @@
 #ifndef LXB_TAG_CONST_H
 #define LXB_TAG_CONST_H

-#define LXB_TAG_CONST_VERSION "A161EC911182C3254E7A972D5C51DF86"
-#define LXB_TAG_CONST_VERSION_A161EC911182C3254E7A972D5C51DF86
+#define LXB_TAG_CONST_VERSION "5AB3094FB370521074947DC082575715"
+#define LXB_TAG_CONST_VERSION_5AB3094FB370521074947DC082575715


 typedef uintptr_t lxb_tag_id_t;
@@ -183,41 +183,43 @@ typedef enum {
     LXB_TAG_S                   = 0x009f,
     LXB_TAG_SAMP                = 0x00a0,
     LXB_TAG_SCRIPT              = 0x00a1,
-    LXB_TAG_SECTION             = 0x00a2,
-    LXB_TAG_SELECT              = 0x00a3,
-    LXB_TAG_SLOT                = 0x00a4,
-    LXB_TAG_SMALL               = 0x00a5,
-    LXB_TAG_SOURCE              = 0x00a6,
-    LXB_TAG_SPACER              = 0x00a7,
-    LXB_TAG_SPAN                = 0x00a8,
-    LXB_TAG_STRIKE              = 0x00a9,
-    LXB_TAG_STRONG              = 0x00aa,
-    LXB_TAG_STYLE               = 0x00ab,
-    LXB_TAG_SUB                 = 0x00ac,
-    LXB_TAG_SUMMARY             = 0x00ad,
-    LXB_TAG_SUP                 = 0x00ae,
-    LXB_TAG_SVG                 = 0x00af,
-    LXB_TAG_TABLE               = 0x00b0,
-    LXB_TAG_TBODY               = 0x00b1,
-    LXB_TAG_TD                  = 0x00b2,
-    LXB_TAG_TEMPLATE            = 0x00b3,
-    LXB_TAG_TEXTAREA            = 0x00b4,
-    LXB_TAG_TEXTPATH            = 0x00b5,
-    LXB_TAG_TFOOT               = 0x00b6,
-    LXB_TAG_TH                  = 0x00b7,
-    LXB_TAG_THEAD               = 0x00b8,
-    LXB_TAG_TIME                = 0x00b9,
-    LXB_TAG_TITLE               = 0x00ba,
-    LXB_TAG_TR                  = 0x00bb,
-    LXB_TAG_TRACK               = 0x00bc,
-    LXB_TAG_TT                  = 0x00bd,
-    LXB_TAG_U                   = 0x00be,
-    LXB_TAG_UL                  = 0x00bf,
-    LXB_TAG_VAR                 = 0x00c0,
-    LXB_TAG_VIDEO               = 0x00c1,
-    LXB_TAG_WBR                 = 0x00c2,
-    LXB_TAG_XMP                 = 0x00c3,
-    LXB_TAG__LAST_ENTRY         = 0x00c4
+    LXB_TAG_SEARCH              = 0x00a2,
+    LXB_TAG_SECTION             = 0x00a3,
+    LXB_TAG_SELECT              = 0x00a4,
+    LXB_TAG_SELECTEDCONTENT     = 0x00a5,
+    LXB_TAG_SLOT                = 0x00a6,
+    LXB_TAG_SMALL               = 0x00a7,
+    LXB_TAG_SOURCE              = 0x00a8,
+    LXB_TAG_SPACER              = 0x00a9,
+    LXB_TAG_SPAN                = 0x00aa,
+    LXB_TAG_STRIKE              = 0x00ab,
+    LXB_TAG_STRONG              = 0x00ac,
+    LXB_TAG_STYLE               = 0x00ad,
+    LXB_TAG_SUB                 = 0x00ae,
+    LXB_TAG_SUMMARY             = 0x00af,
+    LXB_TAG_SUP                 = 0x00b0,
+    LXB_TAG_SVG                 = 0x00b1,
+    LXB_TAG_TABLE               = 0x00b2,
+    LXB_TAG_TBODY               = 0x00b3,
+    LXB_TAG_TD                  = 0x00b4,
+    LXB_TAG_TEMPLATE            = 0x00b5,
+    LXB_TAG_TEXTAREA            = 0x00b6,
+    LXB_TAG_TEXTPATH            = 0x00b7,
+    LXB_TAG_TFOOT               = 0x00b8,
+    LXB_TAG_TH                  = 0x00b9,
+    LXB_TAG_THEAD               = 0x00ba,
+    LXB_TAG_TIME                = 0x00bb,
+    LXB_TAG_TITLE               = 0x00bc,
+    LXB_TAG_TR                  = 0x00bd,
+    LXB_TAG_TRACK               = 0x00be,
+    LXB_TAG_TT                  = 0x00bf,
+    LXB_TAG_U                   = 0x00c0,
+    LXB_TAG_UL                  = 0x00c1,
+    LXB_TAG_VAR                 = 0x00c2,
+    LXB_TAG_VIDEO               = 0x00c3,
+    LXB_TAG_WBR                 = 0x00c4,
+    LXB_TAG_XMP                 = 0x00c5,
+    LXB_TAG__LAST_ENTRY         = 0x00c6
 }
 lxb_tag_id_enum_t;

diff --git a/ext/dom/lexbor/lexbor/tag/res.h b/ext/dom/lexbor/lexbor/tag/res.h
index 4ad1f37e034..5672d4a5a5f 100644
--- a/ext/dom/lexbor/lexbor/tag/res.h
+++ b/ext/dom/lexbor/lexbor/tag/res.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 Alexander Borisov
+ * Copyright (C) 2018-2026 Alexander Borisov
  *
  * Author: Alexander Borisov <borisov@lexbor.com>
  */
@@ -17,9 +17,9 @@
 #endif /* LXB_TAG_RES_H */

 #ifdef LXB_TAG_CONST_VERSION
-#ifndef LXB_TAG_CONST_VERSION_A161EC911182C3254E7A972D5C51DF86
+#ifndef LXB_TAG_CONST_VERSION_5AB3094FB370521074947DC082575715
 #error Mismatched tags version! See "lexbor/tag/const.h".
-#endif /* LXB_TAG_CONST_VERSION_A161EC911182C3254E7A972D5C51DF86 */
+#endif /* LXB_TAG_CONST_VERSION_5AB3094FB370521074947DC082575715 */
 #else
 #error You need to include "lexbor/tag/const.h".
 #endif /* LXB_TAG_CONST_VERSION */
@@ -188,8 +188,10 @@ static const lxb_tag_data_t lxb_tag_res_data_default[LXB_TAG__LAST_ENTRY] =
     {{.u.short_str = "s", .length = 1, .next = NULL}, LXB_TAG_S, 1, true},
     {{.u.short_str = "samp", .length = 4, .next = NULL}, LXB_TAG_SAMP, 1, true},
     {{.u.short_str = "script", .length = 6, .next = NULL}, LXB_TAG_SCRIPT, 1, true},
+    {{.u.short_str = "search", .length = 6, .next = NULL}, LXB_TAG_SEARCH, 1, true},
     {{.u.short_str = "section", .length = 7, .next = NULL}, LXB_TAG_SECTION, 1, true},
     {{.u.short_str = "select", .length = 6, .next = NULL}, LXB_TAG_SELECT, 1, true},
+    {{.u.short_str = "selectedcontent", .length = 15, .next = NULL}, LXB_TAG_SELECTEDCONTENT, 1, true},
     {{.u.short_str = "slot", .length = 4, .next = NULL}, LXB_TAG_SLOT, 1, true},
     {{.u.short_str = "small", .length = 5, .next = NULL}, LXB_TAG_SMALL, 1, true},
     {{.u.short_str = "source", .length = 6, .next = NULL}, LXB_TAG_SOURCE, 1, true},
@@ -389,8 +391,10 @@ static const lxb_tag_data_t lxb_tag_res_data_upper_default[LXB_TAG__LAST_ENTRY]
     {{.u.short_str = "S", .length = 1, .next = NULL}, LXB_TAG_S, 1, true},
     {{.u.short_str = "SAMP", .length = 4, .next = NULL}, LXB_TAG_SAMP, 1, true},
     {{.u.short_str = "SCRIPT", .length = 6, .next = NULL}, LXB_TAG_SCRIPT, 1, true},
+    {{.u.short_str = "SEARCH", .length = 6, .next = NULL}, LXB_TAG_SEARCH, 1, true},
     {{.u.short_str = "SECTION", .length = 7, .next = NULL}, LXB_TAG_SECTION, 1, true},
     {{.u.short_str = "SELECT", .length = 6, .next = NULL}, LXB_TAG_SELECT, 1, true},
+    {{.u.short_str = "SELECTEDCONTENT", .length = 15, .next = NULL}, LXB_TAG_SELECTEDCONTENT, 1, true},
     {{.u.short_str = "SLOT", .length = 4, .next = NULL}, LXB_TAG_SLOT, 1, true},
     {{.u.short_str = "SMALL", .length = 5, .next = NULL}, LXB_TAG_SMALL, 1, true},
     {{.u.short_str = "SOURCE", .length = 6, .next = NULL}, LXB_TAG_SOURCE, 1, true},
@@ -426,81 +430,81 @@ static const lxb_tag_data_t lxb_tag_res_data_upper_default[LXB_TAG__LAST_ENTRY]
 };
 #endif

-static const lexbor_shs_entry_t lxb_tag_res_shs_data_default[] =
+static const lexbor_shs_entry_t lxb_tag_res_shs_data_default[263] =
 {
     {NULL, NULL, 262, 0}, {"radialgradient", (void *) &lxb_tag_res_data_default[153], 14, 0},
     {"fecomponenttransfer", (void *) &lxb_tag_res_data_default[58], 19, 0}, {"abbr", (void *) &lxb_tag_res_data_default[7], 4, 1},
     {"feflood", (void *) &lxb_tag_res_data_default[65], 7, 0}, {"marquee", (void *) &lxb_tag_res_data_default[121], 7, 0},
     {"feblend", (void *) &lxb_tag_res_data_default[56], 7, 4}, {"optgroup", (void *) &lxb_tag_res_data_default[142], 8, 0},
-    {"video", (void *) &lxb_tag_res_data_default[193], 5, 10}, {"u", (void *) &lxb_tag_res_data_default[190], 1, 0},
+    {"video", (void *) &lxb_tag_res_data_default[195], 5, 10}, {"u", (void *) &lxb_tag_res_data_default[192], 1, 0},
     {"iframe", (void *) &lxb_tag_res_data_default[103], 6, 0}, {"animatecolor", (void *) &lxb_tag_res_data_default[13], 12, 0},
     {"output", (void *) &lxb_tag_res_data_default[144], 6, 0}, {"figcaption", (void *) &lxb_tag_res_data_default[82], 10, 0},
     {"mglyph", (void *) &lxb_tag_res_data_default[127], 6, 0}, {"!--", (void *) &lxb_tag_res_data_default[4], 3, 0},
     {"fefuncg", (void *) &lxb_tag_res_data_default[68], 7, 0}, {"aside", (void *) &lxb_tag_res_data_default[20], 5, 0},
-    {"style", (void *) &lxb_tag_res_data_default[171], 5, 0}, {"strike", (void *) &lxb_tag_res_data_default[169], 6, 0},
+    {"style", (void *) &lxb_tag_res_data_default[173], 5, 0}, {"strike", (void *) &lxb_tag_res_data_default[171], 6, 0},
     {"header", (void *) &lxb_tag_res_data_default[98], 6, 0}, {"glyphref", (void *) &lxb_tag_res_data_default[90], 8, 23},
     {"label", (void *) &lxb_tag_res_data_default[111], 5, 0}, {"feconvolvematrix", (void *) &lxb_tag_res_data_default[60], 16, 0},
-    {"altglyphdef", (void *) &lxb_tag_res_data_default[11], 11, 0}, {"title", (void *) &lxb_tag_res_data_default[186], 5, 0},
+    {"altglyphdef", (void *) &lxb_tag_res_data_default[11], 11, 0}, {"title", (void *) &lxb_tag_res_data_default[188], 5, 0},
     {"head", (void *) &lxb_tag_res_data_default[97], 4, 0}, {"noframes", (void *) &lxb_tag_res_data_default[138], 8, 0},
     {"code", (void *) &lxb_tag_res_data_default[39], 4, 30}, {"rb", (void *) &lxb_tag_res_data_default[154], 2, 5},
     {"blink", (void *) &lxb_tag_res_data_default[29], 5, 0}, {"image", (void *) &lxb_tag_res_data_default[104], 5, 0},
     {"col", (void *) &lxb_tag_res_data_default[40], 3, 8}, {"object", (void *) &lxb_tag_res_data_default[140], 6, 12},
-    {"template", (void *) &lxb_tag_res_data_default[179], 8, 36}, {"h2", (void *) &lxb_tag_res_data_default[92], 2, 13},
+    {"template", (void *) &lxb_tag_res_data_default[181], 8, 36}, {"h2", (void *) &lxb_tag_res_data_default[92], 2, 13},
     {"lineargradient", (void *) &lxb_tag_res_data_default[114], 14, 0}, {"math", (void *) &lxb_tag_res_data_default[122], 4, 0},
     {"base", (void *) &lxb_tag_res_data_default[23], 4, 45}, {"dl", (void *) &lxb_tag_res_data_default[52], 2, 14},
-    {"del", (void *) &lxb_tag_res_data_default[45], 3, 16}, {"svg", (void *) &lxb_tag_res_data_default[175], 3, 17},
+    {"del", (void *) &lxb_tag_res_data_default[45], 3, 16}, {"svg", (void *) &lxb_tag_res_data_default[177], 3, 17},
     {"dir", (void *) &lxb_tag_res_data_default[50], 3, 0}, {"article", (void *) &lxb_tag_res_data_default[19], 7, 0},
-    {"strong", (void *) &lxb_tag_res_data_default[170], 6, 0}, {"dialog", (void *) &lxb_tag_res_data_default[49], 6, 0},
-    {"details", (void *) &lxb_tag_res_data_default[47], 7, 0}, {"textpath", (void *) &lxb_tag_res_data_default[181], 8, 52},
+    {"strong", (void *) &lxb_tag_res_data_default[172], 6, 0}, {"dialog", (void *) &lxb_tag_res_data_default[49], 6, 0},
+    {"details", (void *) &lxb_tag_res_data_default[47], 7, 0}, {"textpath", (void *) &lxb_tag_res_data_default[183], 8, 52},
     {"mark", (void *) &lxb_tag_res_data_default[120], 4, 0}, {"basefont", (void *) &lxb_tag_res_data_default[24], 8, 0},
     {"fediffuselighting", (void *) &lxb_tag_res_data_default[61], 17, 0}, {"fespecularlighting", (void *) &lxb_tag_res_data_default[77], 18, 0},
     {"blockquote", (void *) &lxb_tag_res_data_default[30], 10, 0}, {"script", (void *) &lxb_tag_res_data_default[161], 6, 58},
     {"malignmark", (void *) &lxb_tag_res_data_default[118], 10, 0}, {"hr", (void *) &lxb_tag_res_data_default[100], 2, 18},
-    {"source", (void *) &lxb_tag_res_data_default[166], 6, 19}, {"mn", (void *) &lxb_tag_res_data_default[129], 2, 0},
-    {"select", (void *) &lxb_tag_res_data_default[163], 6, 0}, {"main", (void *) &lxb_tag_res_data_default[117], 4, 20},
+    {"source", (void *) &lxb_tag_res_data_default[168], 6, 19}, {"mn", (void *) &lxb_tag_res_data_default[129], 2, 0},
+    {"select", (void *) &lxb_tag_res_data_default[164], 6, 0}, {"main", (void *) &lxb_tag_res_data_default[117], 4, 20},
     {"fieldset", (void *) &lxb_tag_res_data_default[81], 8, 62}, {"ins", (void *) &lxb_tag_res_data_default[107], 3, 0},
     {"frameset", (void *) &lxb_tag_res_data_default[89], 8, 0}, {"button", (void *) &lxb_tag_res_data_default[33], 6, 0},
     {"fecolormatrix", (void *) &lxb_tag_res_data_default[57], 13, 0}, {"q", (void *) &lxb_tag_res_data_default[152], 1, 0},
-    {"animatemotion", (void *) &lxb_tag_res_data_default[14], 13, 0}, {"time", (void *) &lxb_tag_res_data_default[185], 4, 21},
-    {"table", (void *) &lxb_tag_res_data_default[176], 5, 25}, {"h6", (void *) &lxb_tag_res_data_default[96], 2, 26},
+    {"animatemotion", (void *) &lxb_tag_res_data_default[14], 13, 0}, {"time", (void *) &lxb_tag_res_data_default[187], 4, 21},
+    {"table", (void *) &lxb_tag_res_data_default[178], 5, 25}, {"h6", (void *) &lxb_tag_res_data_default[96], 2, 26},
     {"cite", (void *) &lxb_tag_res_data_default[37], 4, 28}, {"img", (void *) &lxb_tag_res_data_default[105], 3, 34},
     {"fepointlight", (void *) &lxb_tag_res_data_default[76], 12, 0}, {"audio", (void *) &lxb_tag_res_data_default[21], 5, 0},
     {"#end-of-file", (void *) &lxb_tag_res_data_default[1], 12, 0}, {"noscript", (void *) &lxb_tag_res_data_default[139], 8, 0},
-    {"foreignobject", (void *) &lxb_tag_res_data_default[86], 13, 0}, {"spacer", (void *) &lxb_tag_res_data_default[167], 6, 0},
-    {"samp", (void *) &lxb_tag_res_data_default[160], 4, 0}, {"altglyphitem", (void *) &lxb_tag_res_data_default[12], 12, 0},
-    {"dt", (void *) &lxb_tag_res_data_default[53], 2, 0}, {"data", (void *) &lxb_tag_res_data_default[42], 4, 0},
+    {"foreignobject", (void *) &lxb_tag_res_data_default[86], 13, 77}, {"selectedcontent", (void *) &lxb_tag_res_data_default[165], 15, 0},
+    {"spacer", (void *) &lxb_tag_res_data_default[169], 6, 0}, {"samp", (void *) &lxb_tag_res_data_default[160], 4, 0},
+    {"altglyphitem", (void *) &lxb_tag_res_data_default[12], 12, 0}, {"data", (void *) &lxb_tag_res_data_default[42], 4, 0},
     {"mtext", (void *) &lxb_tag_res_data_default[132], 5, 0}, {"path", (void *) &lxb_tag_res_data_default[147], 4, 0},
-    {"input", (void *) &lxb_tag_res_data_default[106], 5, 0}, {"th", (void *) &lxb_tag_res_data_default[183], 2, 38},
-    {"p", (void *) &lxb_tag_res_data_default[145], 1, 0}, {"animatetransform", (void *) &lxb_tag_res_data_default[15], 16, 0},
-    {"datalist", (void *) &lxb_tag_res_data_default[43], 8, 0}, {"small", (void *) &lxb_tag_res_data_default[165], 5, 0},
+    {"input", (void *) &lxb_tag_res_data_default[106], 5, 0}, {"th", (void *) &lxb_tag_res_data_default[185], 2, 38},
+    {"p", (void *) &lxb_tag_res_data_default[145], 1, 0}, {"dt", (void *) &lxb_tag_res_data_default[53], 2, 0},
+    {"animatetransform", (void *) &lxb_tag_res_data_default[15], 16, 0}, {"datalist", (void *) &lxb_tag_res_data_default[43], 8, 0},
     {"b", (void *) &lxb_tag_res_data_default[22], 1, 46}, {"nextid", (void *) &lxb_tag_res_data_default[135], 6, 47},
-    {"noembed", (void *) &lxb_tag_res_data_default[137], 7, 0}, {"nav", (void *) &lxb_tag_res_data_default[134], 3, 0},
-    {"bgsound", (void *) &lxb_tag_res_data_default[27], 7, 0}, {"slot", (void *) &lxb_tag_res_data_default[164], 4, 0},
-    {"param", (void *) &lxb_tag_res_data_default[146], 5, 0}, {"font", (void *) &lxb_tag_res_data_default[84], 4, 53},
-    {"figure", (void *) &lxb_tag_res_data_default[83], 6, 0}, {"femerge", (void *) &lxb_tag_res_data_default[72], 7, 0},
-    {"femergenode", (void *) &lxb_tag_res_data_default[73], 11, 0}, {"feoffset", (void *) &lxb_tag_res_data_default[75], 8, 60},
-    {"#text", (void *) &lxb_tag_res_data_default[2], 5, 0}, {"ul", (void *) &lxb_tag_res_data_default[191], 2, 0},
+    {"noembed", (void *) &lxb_tag_res_data_default[137], 7, 0}, {"small", (void *) &lxb_tag_res_data_default[167], 5, 0},
+    {"nav", (void *) &lxb_tag_res_data_default[134], 3, 0}, {"slot", (void *) &lxb_tag_res_data_default[166], 4, 0},
+    {"search", (void *) &lxb_tag_res_data_default[162], 6, 0}, {"font", (void *) &lxb_tag_res_data_default[84], 4, 53},
+    {"bgsound", (void *) &lxb_tag_res_data_default[27], 7, 0}, {"param", (void *) &lxb_tag_res_data_default[146], 5, 0},
+    {"figure", (void *) &lxb_tag_res_data_default[83], 6, 0}, {"feoffset", (void *) &lxb_tag_res_data_default[75], 8, 60},
+    {"#text", (void *) &lxb_tag_res_data_default[2], 5, 0}, {"femerge", (void *) &lxb_tag_res_data_default[72], 7, 0},
     {"fespotlight", (void *) &lxb_tag_res_data_default[78], 11, 66}, {"form", (void *) &lxb_tag_res_data_default[87], 4, 72},
     {"#document", (void *) &lxb_tag_res_data_default[3], 9, 76}, {"fedistantlight", (void *) &lxb_tag_res_data_default[63], 14, 0},
-    {"track", (void *) &lxb_tag_res_data_default[188], 5, 0}, {"h3", (void *) &lxb_tag_res_data_default[93], 2, 77},
-    {"h1", (void *) &lxb_tag_res_data_default[91], 2, 0}, {"i", (void *) &lxb_tag_res_data_default[102], 1, 0},
-    {"altglyph", (void *) &lxb_tag_res_data_default[10], 8, 0}, {"legend", (void *) &lxb_tag_res_data_default[112], 6, 115},
-    {"tbody", (void *) &lxb_tag_res_data_default[177], 5, 0}, {"address", (void *) &lxb_tag_res_data_default[9], 7, 0},
-    {"caption", (void *) &lxb_tag_res_data_default[35], 7, 0}, {"option", (void *) &lxb_tag_res_data_default[143], 6, 0},
-    {"sup", (void *) &lxb_tag_res_data_default[174], 3, 0}, {"body", (void *) &lxb_tag_res_data_default[31], 4, 78},
-    {"progress", (void *) &lxb_tag_res_data_default[151], 8, 122}, {"acronym", (void *) &lxb_tag_res_data_default[8], 7, 0},
+    {"track", (void *) &lxb_tag_res_data_default[190], 5, 0}, {"h3", (void *) &lxb_tag_res_data_default[93], 2, 78},
+    {"femergenode", (void *) &lxb_tag_res_data_default[73], 11, 0}, {"i", (void *) &lxb_tag_res_data_default[102], 1, 0},
+    {"ul", (void *) &lxb_tag_res_data_default[193], 2, 0}, {"h1", (void *) &lxb_tag_res_data_default[91], 2, 0},
+    {"tbody", (void *) &lxb_tag_res_data_default[179], 5, 0}, {"altglyph", (void *) &lxb_tag_res_data_default[10], 8, 0},
+    {"legend", (void *) &lxb_tag_res_data_default[112], 6, 117}, {"address", (void *) &lxb_tag_res_data_default[9], 7, 0},
+    {"sup", (void *) &lxb_tag_res_data_default[176], 3, 0}, {"body", (void *) &lxb_tag_res_data_default[31], 4, 79},
+    {"caption", (void *) &lxb_tag_res_data_default[35], 7, 0}, {"acronym", (void *) &lxb_tag_res_data_default[8], 7, 0},
+    {"option", (void *) &lxb_tag_res_data_default[143], 6, 0}, {"progress", (void *) &lxb_tag_res_data_default[151], 8, 124},
     {"fegaussianblur", (void *) &lxb_tag_res_data_default[70], 14, 0}, {NULL, NULL, 0, 0},
-    {NULL, NULL, 0, 0}, {NULL, NULL, 0, 0},
-    {"mi", (void *) &lxb_tag_res_data_default[128], 2, 79}, {NULL, NULL, 0, 0},
-    {"dfn", (void *) &lxb_tag_res_data_default[48], 3, 0}, {"a", (void *) &lxb_tag_res_data_default[6], 1, 80},
-    {"listing", (void *) &lxb_tag_res_data_default[116], 7, 87}, {"span", (void *) &lxb_tag_res_data_default[168], 4, 0},
+    {"mi", (void *) &lxb_tag_res_data_default[128], 2, 80}, {NULL, NULL, 0, 0},
+    {"dfn", (void *) &lxb_tag_res_data_default[48], 3, 0}, {"a", (void *) &lxb_tag_res_data_default[6], 1, 87},
+    {"listing", (void *) &lxb_tag_res_data_default[116], 7, 88}, {"span", (void *) &lxb_tag_res_data_default[170], 4, 0},
     {"area", (void *) &lxb_tag_res_data_default[18], 4, 0}, {"clippath", (void *) &lxb_tag_res_data_default[38], 8, 0},
-    {"section", (void *) &lxb_tag_res_data_default[162], 7, 0}, {"li", (void *) &lxb_tag_res_data_default[113], 2, 88},
+    {"section", (void *) &lxb_tag_res_data_default[163], 7, 0}, {"li", (void *) &lxb_tag_res_data_default[113], 2, 89},
     {NULL, NULL, 0, 0}, {"html", (void *) &lxb_tag_res_data_default[101], 4, 0},
     {NULL, NULL, 0, 0}, {"fedropshadow", (void *) &lxb_tag_res_data_default[64], 12, 0},
     {"embed", (void *) &lxb_tag_res_data_default[55], 5, 0}, {NULL, NULL, 0, 0},
     {NULL, NULL, 0, 0}, {"multicol", (void *) &lxb_tag_res_data_default[133], 8, 0},
-    {"var", (void *) &lxb_tag_res_data_default[192], 3, 89}, {"rp", (void *) &lxb_tag_res_data_default[155], 2, 0},
+    {"var", (void *) &lxb_tag_res_data_default[194], 3, 93}, {"rp", (void *) &lxb_tag_res_data_default[155], 2, 0},
     {NULL, NULL, 0, 0}, {"link", (void *) &lxb_tag_res_data_default[115], 4, 0},
     {"mo", (void *) &lxb_tag_res_data_default[130], 2, 0}, {NULL, NULL, 0, 0},
     {NULL, NULL, 0, 0}, {"annotation-xml", (void *) &lxb_tag_res_data_default[16], 14, 0},
@@ -510,54 +514,54 @@ static const lexbor_shs_entry_t lxb_tag_res_shs_data_default[] =
     {"fefuncb", (void *) &lxb_tag_res_data_default[67], 7, 0}, {NULL, NULL, 0, 0},
     {NULL, NULL, 0, 0}, {NULL, NULL, 0, 0},
     {"meter", (void *) &lxb_tag_res_data_default[125], 5, 0}, {NULL, NULL, 0, 0},
-    {NULL, NULL, 0, 0}, {"tt", (void *) &lxb_tag_res_data_default[189], 2, 0},
-    {"big", (void *) &lxb_tag_res_data_default[28], 3, 93}, {NULL, NULL, 0, 0},
-    {"tfoot", (void *) &lxb_tag_res_data_default[182], 5, 0}, {"desc", (void *) &lxb_tag_res_data_default[46], 4, 0},
+    {NULL, NULL, 0, 0}, {"tt", (void *) &lxb_tag_res_data_default[191], 2, 0},
+    {"big", (void *) &lxb_tag_res_data_default[28], 3, 94}, {NULL, NULL, 0, 0},
+    {"tfoot", (void *) &lxb_tag_res_data_default[184], 5, 0}, {"desc", (void *) &lxb_tag_res_data_default[46], 4, 96},
     {"isindex", (void *) &lxb_tag_res_data_default[108], 7, 0}, {NULL, NULL, 0, 0},
     {"menu", (void *) &lxb_tag_res_data_default[123], 4, 0}, {"hgroup", (void *) &lxb_tag_res_data_default[99], 6, 0},
     {NULL, NULL, 0, 0}, {NULL, NULL, 0, 0},
-    {"wbr", (void *) &lxb_tag_res_data_default[194], 3, 0}, {NULL, NULL, 0, 0},
-    {"pre", (void *) &lxb_tag_res_data_default[150], 3, 94}, {NULL, NULL, 0, 0},
+    {"wbr", (void *) &lxb_tag_res_data_default[196], 3, 0}, {NULL, NULL, 0, 0},
+    {"pre", (void *) &lxb_tag_res_data_default[150], 3, 98}, {NULL, NULL, 0, 0},
     {NULL, NULL, 0, 0}, {NULL, NULL, 0, 0},
     {"picture", (void *) &lxb_tag_res_data_default[148], 7, 0}, {"h4", (void *) &lxb_tag_res_data_default[94], 2, 0},
     {NULL, NULL, 0, 0}, {NULL, NULL, 0, 0},
-    {"meta", (void *) &lxb_tag_res_data_default[124], 4, 96}, {NULL, NULL, 0, 0},
+    {"meta", (void *) &lxb_tag_res_data_default[124], 4, 99}, {NULL, NULL, 0, 0},
     {"rtc", (void *) &lxb_tag_res_data_default[157], 3, 0}, {NULL, NULL, 0, 0},
-    {"frame", (void *) &lxb_tag_res_data_default[88], 5, 0}, {"fetile", (void *) &lxb_tag_res_data_default[79], 6, 98},
-    {"feimage", (void *) &lxb_tag_res_data_default[71], 7, 99}, {NULL, NULL, 0, 0},
-    {"xmp", (void *) &lxb_tag_res_data_default[195], 3, 0}, {NULL, NULL, 0, 0},
-    {"fecomposite", (void *) &lxb_tag_res_data_default[59], 11, 100}, {"feturbulence", (void *) &lxb_tag_res_data_default[80], 12, 0},
-    {NULL, NULL, 0, 0}, {"summary", (void *) &lxb_tag_res_data_default[173], 7, 0},
+    {"frame", (void *) &lxb_tag_res_data_default[88], 5, 0}, {"fetile", (void *) &lxb_tag_res_data_default[79], 6, 100},
+    {"feimage", (void *) &lxb_tag_res_data_default[71], 7, 103}, {NULL, NULL, 0, 0},
+    {"xmp", (void *) &lxb_tag_res_data_default[197], 3, 0}, {NULL, NULL, 0, 0},
+    {"fecomposite", (void *) &lxb_tag_res_data_default[59], 11, 110}, {"feturbulence", (void *) &lxb_tag_res_data_default[80], 12, 0},
+    {NULL, NULL, 0, 0}, {"summary", (void *) &lxb_tag_res_data_default[175], 7, 0},
     {"mfenced", (void *) &lxb_tag_res_data_default[126], 7, 0}, {NULL, NULL, 0, 0},
-    {"sub", (void *) &lxb_tag_res_data_default[172], 3, 0}, {"colgroup", (void *) &lxb_tag_res_data_default[41], 8, 0},
+    {"sub", (void *) &lxb_tag_res_data_default[174], 3, 0}, {"colgroup", (void *) &lxb_tag_res_data_default[41], 8, 0},
     {NULL, NULL, 0, 0}, {NULL, NULL, 0, 0},
     {NULL, NULL, 0, 0}, {NULL, NULL, 0, 0},
     {NULL, NULL, 0, 0}, {NULL, NULL, 0, 0},
-    {NULL, NULL, 0, 0}, {"dd", (void *) &lxb_tag_res_data_default[44], 2, 103},
+    {NULL, NULL, 0, 0}, {"dd", (void *) &lxb_tag_res_data_default[44], 2, 112},
     {NULL, NULL, 0, 0}, {NULL, NULL, 0, 0},
     {NULL, NULL, 0, 0}, {NULL, NULL, 0, 0},
     {NULL, NULL, 0, 0}, {NULL, NULL, 0, 0},
-    {"div", (void *) &lxb_tag_res_data_default[51], 3, 0}, {"textarea", (void *) &lxb_tag_res_data_default[180], 8, 0},
+    {"div", (void *) &lxb_tag_res_data_default[51], 3, 0}, {"textarea", (void *) &lxb_tag_res_data_default[182], 8, 0},
     {"!doctype", (void *) &lxb_tag_res_data_default[5], 8, 0}, {"applet", (void *) &lxb_tag_res_data_default[17], 6, 0},
-    {NULL, NULL, 0, 0}, {"br", (void *) &lxb_tag_res_data_default[32], 2, 110},
+    {NULL, NULL, 0, 0}, {"br", (void *) &lxb_tag_res_data_default[32], 2, 113},
     {NULL, NULL, 0, 0}, {"keygen", (void *) &lxb_tag_res_data_default[110], 6, 0},
     {"kbd", (void *) &lxb_tag_res_data_default[109], 3, 0}, {NULL, NULL, 0, 0},
     {"plaintext", (void *) &lxb_tag_res_data_default[149], 9, 0}, {"s", (void *) &lxb_tag_res_data_default[159], 1, 0},
     {NULL, NULL, 0, 0}, {NULL, NULL, 0, 0},
-    {"bdo", (void *) &lxb_tag_res_data_default[26], 3, 0}, {"td", (void *) &lxb_tag_res_data_default[178], 2, 0},
+    {"bdo", (void *) &lxb_tag_res_data_default[26], 3, 0}, {"td", (void *) &lxb_tag_res_data_default[180], 2, 0},
     {"fefunca", (void *) &lxb_tag_res_data_default[66], 7, 0}, {"ol", (void *) &lxb_tag_res_data_default[141], 2, 0},
-    {"thead", (void *) &lxb_tag_res_data_default[184], 5, 0}, {"nobr", (void *) &lxb_tag_res_data_default[136], 4, 112},
-    {NULL, NULL, 0, 0}, {"tr", (void *) &lxb_tag_res_data_default[187], 2, 0},
+    {"thead", (void *) &lxb_tag_res_data_default[186], 5, 0}, {"nobr", (void *) &lxb_tag_res_data_default[136], 4, 115},
+    {NULL, NULL, 0, 0}, {"tr", (void *) &lxb_tag_res_data_default[189], 2, 0},
     {"map", (void *) &lxb_tag_res_data_default[119], 3, 0}, {NULL, NULL, 0, 0},
     {NULL, NULL, 0, 0}, {NULL, NULL, 0, 0},
-    {NULL, NULL, 0, 0}, {"#undef", (void *) &lxb_tag_res_data_default[0], 6, 113},
+    {NULL, NULL, 0, 0}, {"#undef", (void *) &lxb_tag_res_data_default[0], 6, 116},
     {"em", (void *) &lxb_tag_res_data_default[54], 2, 0}, {NULL, NULL, 0, 0},
     {"bdi", (void *) &lxb_tag_res_data_default[25], 3, 0}, {"femorphology", (void *) &lxb_tag_res_data_default[74], 12, 0},
-    {"ms", (void *) &lxb_tag_res_data_default[131], 2, 116}, {"footer", (void *) &lxb_tag_res_data_default[85], 6, 0},
-    {"fefuncr", (void *) &lxb_tag_res_data_default[69], 7, 0}, {"rt", (void *) &lxb_tag_res_data_default[156], 2, 117},
+    {"ms", (void *) &lxb_tag_res_data_default[131], 2, 120}, {"footer", (void *) &lxb_tag_res_data_default[85], 6, 0},
+    {"fefuncr", (void *) &lxb_tag_res_data_default[69], 7, 0}, {"rt", (void *) &lxb_tag_res_data_default[156], 2, 122},
     {NULL, NULL, 0, 0}, {NULL, NULL, 0, 0},
     {NULL, NULL, 0, 0}, {"h5", (void *) &lxb_tag_res_data_default[95], 2, 0},
-    {NULL, NULL, 0, 0}, {"ruby", (void *) &lxb_tag_res_data_default[158], 4, 120},
+    {NULL, NULL, 0, 0}, {"ruby", (void *) &lxb_tag_res_data_default[158], 4, 123},
     {"canvas", (void *) &lxb_tag_res_data_default[34], 6, 0}, {NULL, NULL, 0, 0},
     {NULL, NULL, 0, 0}
 };
diff --git a/ext/dom/lexbor/patches/0001-Expose-line-and-column-information-for-use-in-PHP.patch b/ext/dom/lexbor/patches/0001-Expose-line-and-column-information-for-use-in-PHP.patch
index 0da274053ec..32d9d42d2bf 100644
--- a/ext/dom/lexbor/patches/0001-Expose-line-and-column-information-for-use-in-PHP.patch
+++ b/ext/dom/lexbor/patches/0001-Expose-line-and-column-information-for-use-in-PHP.patch
@@ -1,4 +1,4 @@
-From 4c133fe5adfe4b8ccdd8b014d884b685143b9e66 Mon Sep 17 00:00:00 2001
+From 0cd2add6c46400b808329442f81451b369863983 Mon Sep 17 00:00:00 2001
 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
 Date: Sat, 26 Aug 2023 15:08:59 +0200
 Subject: [PATCH 1/6] Expose line and column information for use in PHP
@@ -15,10 +15,10 @@ Subject: [PATCH 1/6] Expose line and column information for use in PHP
  8 files changed, 48 insertions(+), 5 deletions(-)

 diff --git a/source/lexbor/dom/interfaces/node.h b/source/lexbor/dom/interfaces/node.h
-index b052cf5..b5d2c50 100644
+index 6c74ac5..b95373c 100644
 --- a/source/lexbor/dom/interfaces/node.h
 +++ b/source/lexbor/dom/interfaces/node.h
-@@ -83,6 +83,8 @@ struct lxb_dom_node {
+@@ -86,6 +86,8 @@ struct lxb_dom_node {

      lxb_dom_node_type_t    type;

@@ -41,10 +41,10 @@ index 79accd0..0b7f4fd 100644
      const lxb_char_t      *text_start;
      const lxb_char_t      *text_end;
 diff --git a/source/lexbor/html/tokenizer.c b/source/lexbor/html/tokenizer.c
-index 741bced..0bd9aec 100644
+index 22b88ed..1d9f378 100644
 --- a/source/lexbor/html/tokenizer.c
 +++ b/source/lexbor/html/tokenizer.c
-@@ -91,6 +91,7 @@ lxb_html_tokenizer_init(lxb_html_tokenizer_t *tkz)
+@@ -92,6 +92,7 @@ lxb_html_tokenizer_init(lxb_html_tokenizer_t *tkz)

      tkz->pos = tkz->start;
      tkz->end = tkz->start + LXB_HTML_TKZ_TEMP_SIZE;
@@ -52,7 +52,7 @@ index 741bced..0bd9aec 100644

      tkz->tree = NULL;
      tkz->tags = NULL;
-@@ -152,6 +153,8 @@ lxb_html_tokenizer_inherit(lxb_html_tokenizer_t *tkz_to,
+@@ -153,6 +154,8 @@ lxb_html_tokenizer_inherit(lxb_html_tokenizer_t *tkz_to,
      tkz_to->start = tkz_from->start;
      tkz_to->end = tkz_from->end;
      tkz_to->pos = tkz_to->start;
@@ -61,7 +61,7 @@ index 741bced..0bd9aec 100644

      return LXB_STATUS_OK;
  }
-@@ -312,7 +315,26 @@ lxb_html_tokenizer_chunk(lxb_html_tokenizer_t *tkz, const lxb_char_t *data,
+@@ -571,7 +574,26 @@ lxb_html_tokenizer_chunk(lxb_html_tokenizer_t *tkz, const lxb_char_t *data,
      tkz->last = end;

      while (data < end) {
@@ -90,10 +90,10 @@ index 741bced..0bd9aec 100644

      return tkz->status;
 diff --git a/source/lexbor/html/tokenizer.h b/source/lexbor/html/tokenizer.h
-index ba9602f..74bb55e 100644
+index 12b7c81..aa1ac37 100644
 --- a/source/lexbor/html/tokenizer.h
 +++ b/source/lexbor/html/tokenizer.h
-@@ -73,6 +73,8 @@ struct lxb_html_tokenizer {
+@@ -79,6 +79,8 @@ struct lxb_html_tokenizer {
      const lxb_char_t                 *end;
      const lxb_char_t                 *begin;
      const lxb_char_t                 *last;
@@ -103,7 +103,7 @@ index ba9602f..74bb55e 100644
      /* Entities */
      const lexbor_sbst_entry_static_t *entity;
 diff --git a/source/lexbor/html/tokenizer/state.h b/source/lexbor/html/tokenizer/state.h
-index 17939b9..5b095b4 100644
+index 5e91444..52eaa9a 100644
 --- a/source/lexbor/html/tokenizer/state.h
 +++ b/source/lexbor/html/tokenizer/state.h
 @@ -90,6 +90,8 @@ extern "C" {
@@ -116,10 +116,10 @@ index 17939b9..5b095b4 100644
      while (0)

 diff --git a/source/lexbor/html/tree.c b/source/lexbor/html/tree.c
-index ece26e9..91bfd17 100644
+index 062ea56..3f4c18d 100644
 --- a/source/lexbor/html/tree.c
 +++ b/source/lexbor/html/tree.c
-@@ -427,6 +427,9 @@ lxb_html_tree_create_element_for_token(lxb_html_tree_t *tree,
+@@ -431,6 +431,9 @@ lxb_html_tree_create_element_for_token(lxb_html_tree_t *tree,
          return NULL;
      }

@@ -129,7 +129,7 @@ index ece26e9..91bfd17 100644
      lxb_status_t status;
      lxb_dom_element_t *element = lxb_dom_interface_element(node);

-@@ -763,6 +766,11 @@ lxb_html_tree_insert_character_for_data(lxb_html_tree_t *tree,
+@@ -767,6 +770,11 @@ lxb_html_tree_insert_character_for_data(lxb_html_tree_t *tree,

      lxb_dom_interface_text(text)->char_data.data = *str;

@@ -141,7 +141,7 @@ index ece26e9..91bfd17 100644
      if (ret_node != NULL) {
          *ret_node = text;
      }
-@@ -802,6 +810,9 @@ lxb_html_tree_insert_comment(lxb_html_tree_t *tree,
+@@ -806,6 +814,9 @@ lxb_html_tree_insert_comment(lxb_html_tree_t *tree,
          return NULL;
      }

@@ -152,10 +152,10 @@ index ece26e9..91bfd17 100644
                                              tree->document->dom_document.text);
      if (tree->status != LXB_STATUS_OK) {
 diff --git a/source/lexbor/html/tree/error.c b/source/lexbor/html/tree/error.c
-index e6e43f4..88ad8c4 100644
+index ffdc55c..ef36eab 100644
 --- a/source/lexbor/html/tree/error.c
 +++ b/source/lexbor/html/tree/error.c
-@@ -21,8 +21,9 @@ lxb_html_tree_error_add(lexbor_array_obj_t *parse_errors,
+@@ -22,8 +22,9 @@ lxb_html_tree_error_add(lexbor_array_obj_t *parse_errors,
      }

      entry->id = id;
@@ -168,10 +168,10 @@ index e6e43f4..88ad8c4 100644
      return entry;
  }
 diff --git a/source/lexbor/html/tree/error.h b/source/lexbor/html/tree/error.h
-index 2fd06cb..ed1859f 100644
+index 7a212af..b186772 100644
 --- a/source/lexbor/html/tree/error.h
 +++ b/source/lexbor/html/tree/error.h
-@@ -97,8 +97,9 @@ lxb_html_tree_error_id_t;
+@@ -109,8 +109,9 @@ lxb_html_tree_error_id_t;

  typedef struct {
      lxb_html_tree_error_id_t id;
@@ -184,5 +184,5 @@ index 2fd06cb..ed1859f 100644
  lxb_html_tree_error_t;

 --
-2.49.0
+2.51.2

diff --git a/ext/dom/lexbor/patches/0002-Track-implied-added-nodes-for-options-use-in-PHP.patch b/ext/dom/lexbor/patches/0002-Track-implied-added-nodes-for-options-use-in-PHP.patch
index a2df20e3bae..1902abf96e3 100644
--- a/ext/dom/lexbor/patches/0002-Track-implied-added-nodes-for-options-use-in-PHP.patch
+++ b/ext/dom/lexbor/patches/0002-Track-implied-added-nodes-for-options-use-in-PHP.patch
@@ -1,4 +1,4 @@
-From eb5e3769950cd9c0bc59066d94d6da9291f43af8 Mon Sep 17 00:00:00 2001
+From a4c29ba8d1ea1065ce6bd4a34382d53140cf1924 Mon Sep 17 00:00:00 2001
 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
 Date: Mon, 14 Aug 2023 20:18:51 +0200
 Subject: [PATCH 2/6] Track implied added nodes for options use in PHP
@@ -11,7 +11,7 @@ Subject: [PATCH 2/6] Track implied added nodes for options use in PHP
  4 files changed, 8 insertions(+)

 diff --git a/source/lexbor/html/tree.h b/source/lexbor/html/tree.h
-index 9564608..8ad32a4 100644
+index 4912efb..7b2c620 100644
 --- a/source/lexbor/html/tree.h
 +++ b/source/lexbor/html/tree.h
 @@ -55,6 +55,9 @@ struct lxb_html_tree {
@@ -63,5 +63,5 @@ index 05fe738..1e09cda 100644

              break;
 --
-2.49.0
+2.51.2

diff --git a/ext/dom/lexbor/patches/0003-Patch-utilities-and-data-structure-to-be-able-to-gen.patch b/ext/dom/lexbor/patches/0003-Patch-utilities-and-data-structure-to-be-able-to-gen.patch
index 4c3cdc67a65..51f77483bc6 100644
--- a/ext/dom/lexbor/patches/0003-Patch-utilities-and-data-structure-to-be-able-to-gen.patch
+++ b/ext/dom/lexbor/patches/0003-Patch-utilities-and-data-structure-to-be-able-to-gen.patch
@@ -1,4 +1,4 @@
-From de74c24d95342280266ebdac6f8dabc70ccfacab Mon Sep 17 00:00:00 2001
+From 46fc776449252e74795569759a19d13857a59069 Mon Sep 17 00:00:00 2001
 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
 Date: Thu, 24 Aug 2023 22:57:48 +0200
 Subject: [PATCH 3/6] Patch utilities and data structure to be able to generate
@@ -8,10 +8,10 @@ Changed the generation script to check if everything fits in 32-bits.
 And change the actual field types to 32-bits. This decreases the hash
 tables in size.
 ---
- source/lexbor/core/shs.h             |   4 +-
- utils/lexbor/encoding/single-byte.py |   2 +-
- utils/lexbor/lexbor/LXB.py           |  12 +-
- 3 files changed, 12 insertions(+), 6 deletions(-)
+ source/lexbor/core/shs.h             |  4 ++--
+ utils/lexbor/encoding/single-byte.py |  4 ++--
+ utils/lexbor/lexbor/LXB.py           | 12 +++++++++---
+ 3 files changed, 13 insertions(+), 7 deletions(-)

 diff --git a/source/lexbor/core/shs.h b/source/lexbor/core/shs.h
 index 7a63a07..c84dfaa 100644
@@ -30,7 +30,7 @@ index 7a63a07..c84dfaa 100644
  lexbor_shs_hash_t;

 diff --git a/utils/lexbor/encoding/single-byte.py b/utils/lexbor/encoding/single-byte.py
-index 9a85d54..ec2023c 100755
+index d7d1bb2..5420c16 100755
 --- a/utils/lexbor/encoding/single-byte.py
 +++ b/utils/lexbor/encoding/single-byte.py
 @@ -128,7 +128,7 @@ class SingleByte:
@@ -42,6 +42,15 @@ index 9a85d54..ec2023c 100755

          return hash_key.create(rate = 1)

+@@ -161,7 +161,7 @@ def toHex(s):
+     lst = []
+
+     for ch in bytes(s, 'utf-8'):
+-        hv = hex(ch).replace('0x', '\\\\x')
++        hv = hex(ch).replace('0x', '\\x')
+         lst.append("'{}'".format(hv))
+
+     return ', '.join(lst)
 diff --git a/utils/lexbor/lexbor/LXB.py b/utils/lexbor/lexbor/LXB.py
 index 3e75812..2370c66 100755
 --- a/utils/lexbor/lexbor/LXB.py
@@ -84,5 +93,5 @@ index 3e75812..2370c66 100755
          result.append("};")

 --
-2.49.0
+2.51.2

diff --git a/ext/dom/lexbor/patches/0004-Remove-unused-upper-case-tag-static-data.patch b/ext/dom/lexbor/patches/0004-Remove-unused-upper-case-tag-static-data.patch
index c678146f2ad..6cb6658a164 100644
--- a/ext/dom/lexbor/patches/0004-Remove-unused-upper-case-tag-static-data.patch
+++ b/ext/dom/lexbor/patches/0004-Remove-unused-upper-case-tag-static-data.patch
@@ -1,4 +1,4 @@
-From 1837e6a296a2bac71e37e566435542f208b4fa23 Mon Sep 17 00:00:00 2001
+From ae9d7254ac129cc3be34de6fd34af27baf3bb396 Mon Sep 17 00:00:00 2001
 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
 Date: Wed, 29 Nov 2023 21:26:47 +0100
 Subject: [PATCH 4/6] Remove unused upper case tag static data
@@ -9,10 +9,10 @@ Subject: [PATCH 4/6] Remove unused upper case tag static data
  2 files changed, 4 insertions(+)

 diff --git a/source/lexbor/tag/res.h b/source/lexbor/tag/res.h
-index c7190c5..4ad1f37 100644
+index 604757f..5672d4a 100644
 --- a/source/lexbor/tag/res.h
 +++ b/source/lexbor/tag/res.h
-@@ -224,6 +224,7 @@ static const lxb_tag_data_t lxb_tag_res_data_default[LXB_TAG__LAST_ENTRY] =
+@@ -226,6 +226,7 @@ static const lxb_tag_data_t lxb_tag_res_data_default[LXB_TAG__LAST_ENTRY] =
      {{.u.short_str = "xmp", .length = 3, .next = NULL}, LXB_TAG_XMP, 1, true}
  };

@@ -20,13 +20,13 @@ index c7190c5..4ad1f37 100644
  static const lxb_tag_data_t lxb_tag_res_data_upper_default[LXB_TAG__LAST_ENTRY] =
  {
      {{.u.short_str = "#UNDEF", .length = 6, .next = NULL}, LXB_TAG__UNDEF, 1, true},
-@@ -423,6 +424,7 @@ static const lxb_tag_data_t lxb_tag_res_data_upper_default[LXB_TAG__LAST_ENTRY]
+@@ -427,6 +428,7 @@ static const lxb_tag_data_t lxb_tag_res_data_upper_default[LXB_TAG__LAST_ENTRY]
      {{.u.short_str = "WBR", .length = 3, .next = NULL}, LXB_TAG_WBR, 1, true},
      {{.u.short_str = "XMP", .length = 3, .next = NULL}, LXB_TAG_XMP, 1, true}
  };
 +#endif

- static const lexbor_shs_entry_t lxb_tag_res_shs_data_default[] =
+ static const lexbor_shs_entry_t lxb_tag_res_shs_data_default[263] =
  {
 diff --git a/source/lexbor/tag/tag.c b/source/lexbor/tag/tag.c
 index 780bc47..be5bb30 100644
@@ -49,5 +49,5 @@ index 780bc47..be5bb30 100644
  /*
   * No inline functions for ABI.
 --
-2.49.0
+2.51.2

diff --git a/ext/dom/lexbor/patches/0005-Shrink-size-of-static-binary-search-tree.patch b/ext/dom/lexbor/patches/0005-Shrink-size-of-static-binary-search-tree.patch
index bf2acce1a84..9ef6e305e49 100644
--- a/ext/dom/lexbor/patches/0005-Shrink-size-of-static-binary-search-tree.patch
+++ b/ext/dom/lexbor/patches/0005-Shrink-size-of-static-binary-search-tree.patch
@@ -1,4 +1,4 @@
-From 065923a993a004b8891ad3992c99e7e63e77bad3 Mon Sep 17 00:00:00 2001
+From 19cf6183813e013dfe0eb2303c15eaf6e01b9faf Mon Sep 17 00:00:00 2001
 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
 Date: Wed, 29 Nov 2023 21:29:31 +0100
 Subject: [PATCH 5/6] Shrink size of static binary search tree
@@ -7,10 +7,9 @@ This also makes it more efficient on the data cache.
 ---
  source/lexbor/core/sbst.h                   | 19 ++++++++++++++-----
  source/lexbor/html/tokenizer/state.c        |  2 +-
- utils/lexbor/html/tmp/tokenizer_res.h       |  2 +-
- utils/lexbor/html/tokenizer_entities_bst.py | 10 +++++-----
+ utils/lexbor/html/tokenizer_entities_bst.py |  8 ++++----
  utils/lexbor/lexbor/LXB.py                  |  2 +-
- 5 files changed, 21 insertions(+), 12 deletions(-)
+ 4 files changed, 20 insertions(+), 11 deletions(-)

 diff --git a/source/lexbor/core/sbst.h b/source/lexbor/core/sbst.h
 index b0fbc54..15a1d40 100644
@@ -48,10 +47,10 @@ index b0fbc54..15a1d40 100644
  lexbor_sbst_entry_static_t;

 diff --git a/source/lexbor/html/tokenizer/state.c b/source/lexbor/html/tokenizer/state.c
-index 158aade..207b909 100644
+index db362c6..6c3cbeb 100644
 --- a/source/lexbor/html/tokenizer/state.c
 +++ b/source/lexbor/html/tokenizer/state.c
-@@ -1820,7 +1820,7 @@ lxb_html_tokenizer_state_char_ref_named(lxb_html_tokenizer_t *tkz,
+@@ -1825,7 +1825,7 @@ lxb_html_tokenizer_state_char_ref_named(lxb_html_tokenizer_t *tkz,
              goto done;
          }

@@ -60,21 +59,8 @@ index 158aade..207b909 100644
              tkz->entity_end = (tkz->pos + (data - begin)) - tkz->start;
              tkz->entity_match = entry;
          }
-diff --git a/utils/lexbor/html/tmp/tokenizer_res.h b/utils/lexbor/html/tmp/tokenizer_res.h
-index b3701d5..73ab66e 100644
---- a/utils/lexbor/html/tmp/tokenizer_res.h
-+++ b/utils/lexbor/html/tmp/tokenizer_res.h
-@@ -6,7 +6,7 @@
-
- /*
-  * Caution!!! Important!!!
-- * This file generated by the script
-+ * This file is generated by the script
-  * "utils/lexbor/html/tokenizer_entities_bst.py"!
-  * Do not change this file!
-  */
 diff --git a/utils/lexbor/html/tokenizer_entities_bst.py b/utils/lexbor/html/tokenizer_entities_bst.py
-index 4fa0999..8bd83b2 100755
+index b34bca1..2bfea81 100755
 --- a/utils/lexbor/html/tokenizer_entities_bst.py
 +++ b/utils/lexbor/html/tokenizer_entities_bst.py
 @@ -1,6 +1,6 @@
@@ -112,15 +98,8 @@ index 4fa0999..8bd83b2 100755
          lst.append(hv)

      return ''.join(lst)
-@@ -210,5 +210,5 @@ def entities_bst_print(bst):
-
- if __name__ == "__main__":
-     entities_bst("tmp/tokenizer_res.h",
--                 "../../../source/lexbor/html/tokenizer_res.h",
-+                 "../../../source/lexbor/html/tokenizer/res.h",
-                  "data/entities.json");
 diff --git a/utils/lexbor/lexbor/LXB.py b/utils/lexbor/lexbor/LXB.py
-index 3e75812..b068ea3 100755
+index 2370c66..c41e645 100755
 --- a/utils/lexbor/lexbor/LXB.py
 +++ b/utils/lexbor/lexbor/LXB.py
 @@ -27,7 +27,7 @@ class Temp:
@@ -133,5 +112,5 @@ index 3e75812..b068ea3 100755
          fh.close()

 --
-2.49.0
+2.51.2

diff --git a/ext/dom/lexbor/patches/0006-Patch-out-unused-CSS-style-code.patch b/ext/dom/lexbor/patches/0006-Patch-out-unused-CSS-style-code.patch
index aa64d88ceb1..a643f971648 100644
--- a/ext/dom/lexbor/patches/0006-Patch-out-unused-CSS-style-code.patch
+++ b/ext/dom/lexbor/patches/0006-Patch-out-unused-CSS-style-code.patch
@@ -1,19 +1,17 @@
-From fbb1e8945c4b12d43e7fddc3c34670b5792e2dca Mon Sep 17 00:00:00 2001
+From 54399ee441d922d89c32909e2028f899f6091cd6 Mon Sep 17 00:00:00 2001
 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
 Date: Sun, 7 Jan 2024 21:59:28 +0100
 Subject: [PATCH 6/6] Patch out unused CSS style code

 ---
- source/lexbor/css/rule.h                       |  2 ++
- source/lexbor/style/dom/interfaces/document.c  | 12 ++++++++----
- source/lexbor/style/html/interfaces/document.h |  2 ++
- 3 files changed, 12 insertions(+), 4 deletions(-)
+ source/lexbor/css/rule.h | 2 ++
+ 1 file changed, 2 insertions(+)

 diff --git a/source/lexbor/css/rule.h b/source/lexbor/css/rule.h
-index 7cc4f0b..bd191f9 100644
+index 308dced..d192a01 100644
 --- a/source/lexbor/css/rule.h
 +++ b/source/lexbor/css/rule.h
-@@ -339,6 +339,7 @@ lxb_css_rule_ref_dec(lxb_css_rule_t *rule)
+@@ -361,6 +361,7 @@ lxb_css_rule_ref_dec(lxb_css_rule_t *rule)
  lxb_inline void
  lxb_css_rule_ref_dec_destroy(lxb_css_rule_t *rule)
  {
@@ -21,7 +19,7 @@ index 7cc4f0b..bd191f9 100644
      if (rule->ref_count > 0) {
          rule->ref_count--;
      }
-@@ -346,6 +347,7 @@ lxb_css_rule_ref_dec_destroy(lxb_css_rule_t *rule)
+@@ -368,6 +369,7 @@ lxb_css_rule_ref_dec_destroy(lxb_css_rule_t *rule)
      if (rule->ref_count == 0) {
          (void) lxb_css_rule_destroy(rule, true);
      }
@@ -29,96 +27,6 @@ index 7cc4f0b..bd191f9 100644
  }

  lxb_inline void
-diff --git a/source/lexbor/style/dom/interfaces/document.c b/source/lexbor/style/dom/interfaces/document.c
-index 8a63e8e..f885dc3 100644
---- a/source/lexbor/style/dom/interfaces/document.c
-+++ b/source/lexbor/style/dom/interfaces/document.c
-@@ -280,6 +280,7 @@ lxb_status_t
- lxb_dom_document_stylesheet_apply(lxb_dom_document_t *document,
-                                   lxb_css_stylesheet_t *sst)
- {
-+#if 0
-     lxb_status_t status = LXB_STATUS_OK;
-     lxb_css_rule_t *rule;
-     lxb_css_rule_list_t *list;
-@@ -310,7 +311,7 @@ lxb_dom_document_stylesheet_apply(lxb_dom_document_t *document,
-
-         rule = rule->next;
-     }
--
-+#endif
-     return LXB_STATUS_OK;
- }
-
-@@ -329,6 +330,7 @@ lxb_status_t
- lxb_dom_document_stylesheet_remove(lxb_dom_document_t *document,
-                                    lxb_css_stylesheet_t *sst)
- {
-+#if 0
-     size_t i, length;
-     lxb_status_t status = LXB_STATUS_OK;
-     lxb_css_rule_t *rule;
-@@ -372,13 +374,14 @@ lxb_dom_document_stylesheet_remove(lxb_dom_document_t *document,
-             length = lexbor_array_length(document->css->stylesheets);
-         }
-     }
--
-+#endif
-     return LXB_STATUS_OK;
- }
-
- lxb_status_t
- lxb_dom_document_element_styles_attach(lxb_dom_element_t *element)
- {
-+#if 0
-     lxb_status_t status = LXB_STATUS_OK;
-     lxb_css_rule_t *rule;
-     lexbor_array_t *ssts;
-@@ -413,7 +416,7 @@ lxb_dom_document_element_styles_attach(lxb_dom_element_t *element)
-             rule = rule->next;
-         }
-     }
--
-+#endif
-     return LXB_STATUS_OK;
- }
-
-@@ -521,6 +524,7 @@ lxb_dom_document_style_attach_cb(lxb_dom_node_t *node,
- lxb_status_t
- lxb_document_apply_stylesheets(lxb_dom_document_t *document)
- {
-+#if 0
-     size_t i, length;
-     lxb_status_t status;
-     lxb_css_stylesheet_t *sst;
-@@ -539,6 +543,6 @@ lxb_document_apply_stylesheets(lxb_dom_document_t *document)
-             return status;
-         }
-     }
--
-+#endif
-     return LXB_STATUS_OK;
- }
-diff --git a/source/lexbor/style/html/interfaces/document.h b/source/lexbor/style/html/interfaces/document.h
-index 0307cd9..127c4cd 100644
---- a/source/lexbor/style/html/interfaces/document.h
-+++ b/source/lexbor/style/html/interfaces/document.h
-@@ -134,6 +134,7 @@ lxb_html_document_stylesheet_destroy_all(lxb_html_document_t *document,
-                                             destroy_memory);
- }
-
-+#if 0
- lxb_inline lxb_status_t
- lxb_html_document_style_attach(lxb_html_document_t *document,
-                                lxb_css_rule_style_t *style)
-@@ -158,6 +159,7 @@ lxb_html_document_style_attach_by_element(lxb_html_document_t *document,
-     return lxb_dom_document_style_attach_by_element(lxb_dom_interface_document(document),
-                                                     element, style);
- }
-+#endif
-
- lxb_inline lxb_status_t
- lxb_html_document_apply_stylesheets(lxb_html_document_t *document)
 --
-2.49.0
+2.51.2

diff --git a/ext/dom/lexbor/patches/README.md b/ext/dom/lexbor/patches/README.md
index 93ca862c99c..8d2bceb1bc1 100644
--- a/ext/dom/lexbor/patches/README.md
+++ b/ext/dom/lexbor/patches/README.md
@@ -1,7 +1,10 @@
 # Lexbor patches

+> [!IMPORTANT]
+> This process was largely automated in update-lexbor.sh.
+
 Upon syncing the Lexbor sources, the patches in this directory need to be applied.
-The current Lexbor version is 2.5.0.
+The current Lexbor version is 2.7.0.

 ## Overview

diff --git a/ext/dom/lexbor/patches/update-lexbor.sh b/ext/dom/lexbor/patches/update-lexbor.sh
new file mode 100755
index 00000000000..7421d8e7d32
--- /dev/null
+++ b/ext/dom/lexbor/patches/update-lexbor.sh
@@ -0,0 +1,63 @@
+#!/usr/bin/env bash
+
+set -e
+
+PATCHES_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+LEXBOR_REPO="https://github.com/lexbor/lexbor"
+LEXBOR_REF="v2.7.0"
+LEXBOR_BASE="$(cd "$PATCHES_DIR/.." && pwd)"
+LEXBOR_DIR="$LEXBOR_BASE/lexbor"
+LEXBOR_TMP_DIR="$LEXBOR_BASE/lexbor_tmp"
+LEXBOR_COMPONENTS=(core css dom encoding html ns ports selectors tag)
+LEXBOR_PRESERVED_FILES=(
+    selectors-adapted/selectors.c
+    selectors-adapted/selectors.h
+)
+
+# Clone
+git clone "$LEXBOR_REPO" "$LEXBOR_TMP_DIR"
+(cd "$LEXBOR_TMP_DIR" && git checkout "$LEXBOR_REF")
+
+# Apply patches
+mapfile -t patches < <(ls "$PATCHES_DIR"/*.patch)
+cd "$LEXBOR_TMP_DIR"
+for patch in "${patches[@]}"; do
+    if ! git am -3 "$patch"; then
+        read -p "Patch $(basename "$patch") did not apply cleanly. Resolve, stage and press Enter to continue. "
+        git am --continue
+    fi
+done
+
+# Refresh patches
+NUM_PATCHES=${#patches[@]}
+git format-patch "HEAD~$NUM_PATCHES" -o "$PATCHES_DIR"
+
+# Run code-generation tools
+(cd "$LEXBOR_TMP_DIR/utils/lexbor/encoding" && python3 single-byte.py)
+(cd "$LEXBOR_TMP_DIR/utils/lexbor/html" && python3 tokenizer_entities_bst.py)
+
+# (Re)move files
+mv source/lexbor/encoding/multi_res.c  source/lexbor/encoding/multi.c
+mv source/lexbor/encoding/range_res.c  source/lexbor/encoding/range.c
+mv source/lexbor/encoding/single_res.c source/lexbor/encoding/single.c
+rm source/lexbor/html/serialize.c
+rm source/lexbor/ports/posix/lexbor/core/fs.c
+rm source/lexbor/ports/posix/lexbor/core/perf.c
+rm source/lexbor/ports/windows_nt/lexbor/core/fs.c
+rm source/lexbor/ports/windows_nt/lexbor/core/perf.c
+find . -name "*.cmake" -delete
+
+# Copy preserved files
+for f in "${LEXBOR_PRESERVED_FILES[@]}"; do
+    dst="source/lexbor/$f"
+    mkdir -p "$(dirname "$dst")"
+    cp "$LEXBOR_DIR/$f" "$dst"
+done
+
+# Replace components
+for dir in "${LEXBOR_COMPONENTS[@]}"; do
+    dst="$LEXBOR_DIR/$dir"
+    rm -rf "$dst"
+    cp -r "source/lexbor/$dir" "$dst"
+done
+rm -rf "$LEXBOR_TMP_DIR"
diff --git a/ext/dom/tests/modern/html/parser/Element_innerHTML.phpt b/ext/dom/tests/modern/html/parser/Element_innerHTML.phpt
index 058d4432b49..89574b7a631 100644
--- a/ext/dom/tests/modern/html/parser/Element_innerHTML.phpt
+++ b/ext/dom/tests/modern/html/parser/Element_innerHTML.phpt
@@ -60,6 +60,6 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <style xmlns="http://www.w3.org/1999/xhtml">&lt;p&gt;foo&lt;/p&gt;</style>
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<style xmlns="urn:a"><p xmlns="">foo</p></style>
+<style xmlns="urn:a"><p xmlns="http://www.w3.org/1999/xhtml">foo</p></style>
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <textarea xmlns="http://www.w3.org/1999/xhtml">&lt;/textarea&gt;�--&gt;</textarea>