* feat: Enhance the Rect API.
* feat: Add support for sorting IBoundedElements in general.
* fix: Improve typings of getTopElement/Comment methods.
* feat: Add classes to represent comment icons.
* refactor: Use comment icons in comment view.
* feat: Update navigation policies to support workspace comments.
* feat: Make the navigator and workspace handle workspace comments.
* feat: Visit workspace comments when navigating with the up/down arrows.
* chore: Make the linter happy.
* chore: Rename comment icons to bar buttons.
* refactor: Rename CommentIcons to CommentBarButtons.
* chore: Improve docstrings.
* chore: Clarify unit type.
* refactor: Remove workspace argument from `navigateStacks()`.
* fix: Fix errant find and replace in CSS.
* fix: Fix issue that could cause delete button to become misaligned.
## The basics
- [x] I [validated my changes](https://developers.google.com/blockly/guides/contribute/core#making_and_verifying_a_change)
## The details
### Resolves
Fixes#9155
### Proposed Changes
In cases when an ID is missing for an element passed to `FocusableTreeTraverser.findFocusableNodeFor()`, always return `null`.
Additionally, the new short-circuit logic exposed that `Toolbox` actually wasn't being set up correctly (that is, its root element was not being configured with a valid ID). This has been fixed.
### Reason for Changes
These are cases when a valid node should never be matched (and it's technically possible to incorrectly match if an `IFocusableNode` is set up incorrectly and is providing a focusable element with an unset ID). This avoids the extra computation time of potentially calling deep into `WorkspaceSvg` and exploring all possible nodes for an ID that should never match.
Note that there is a weird quirk with `null` IDs actually being the string `"null"`. This is a side effect of how `setAttribute` and attributes in general work with HTML elements. There's nothing really that can be done here, so it's now considered invalid to also have an ID of string `"null"` just to ensure the `null` case is properly short-circuited.
Finally, the issue with toolbox being configured incorrectly was discovered with the introducing of a new hard failure in `FocusManager.registerTree()` when a tree with an invalid root element is registered. From testing there are no other such trees that need to be updated.
A new warning was also added if `focusNode()` is used on a node with an element that has an invalid ID. This isn't a hard failure to follow the convention of other invalid `focusNode()` situations. It's much more fragile for `focusNode()` to throw than `registerTree()` since the former generally happens much earlier in a page lifecycle, and is less prone to dynamic behaviors.
### Test Coverage
New tests were added to validate the various empty ID cases for `FocusableTreeTraverser.findFocusableNodeFor()`, and to validate the new error check for `FocusManager.registerTree()`.
### Documentation
No new documentation should be needed.
### Additional Information
Nothing to add.
* refactor(build): Rename "package" gulp task (but not npm script) to "pack"
This is to avoid an issue due to "package" being a reserved word
in JavaScript, and therefore not a valid export identifier.
* refactor(build): Convert gulpfile.js from CJS to ESM.
* refactor(build): Convert scripts/gulpfiles/*.js from CJS to ESM
* fix(build): Fix eslint warning for @license tag in gulpfile.mjs
* chore(build): Remove unused imports
* fix(build): Fix incorrect import of gulp-gzip
* fix(build): Fix incorrect sourcemaps import reference