Import maps a document's Arial to Liberation Sans (screenFontName) and the
model keeps it under that name, but only 'Arial' had an @font-face — so on a
machine without Liberation Sans installed every such run fell to the browser's
default serif. The bundled TTFs are now declared under their own family too,
as Liberation Serif already was.
Measured against LibreOffice on a 28-page fixture: its cover lines came out
7-16% narrow, 54 reports to 44.
The shape trigger stood 34px tall next to the 28px colour pickers, so its
caption sat a line below theirs; every captioned picker now shares one 32px
box and the border-width field centres on it. The shape menu was absolute
inside the band, which clips its overflow and stacks below the floating box
toolbar, so it is placed from the button's rect in the top layer, as the
colour picker already does. Its caret is the same chevron as theirs.
One button per kind shows or hides it and its caret says where its cards go —
balloons or the pane, which is why the two pane toggles are gone. Display for
review carries Word's four modes beside them, and the accept / reject / walk
pairs sit under each kind. The PDF path takes the mode as page attributes, so
a printout of a page in no markup reads as the page does.
public/ is copied verbatim into the build, src/assets/ is not - so the fonts
were deployed without the license texts that OFL-1.1 and Bitstream Vera require
to travel with them. Moving the texts to public/font-licenses/ fixes that with
no build step. The notices covered only Liberation and missed five bundled
dependencies; the commercial license now states what it cannot relicense, the
copyleft German dictionary and thesaurus above all.
The id said 'classic' while the UI called the ribbon Classic and the
island Modern (beta). Type, i18n keys, comments and docs now agree;
a stored legacy 'classic' still selects the island.
Under the ribbon it takes the same --w-* remap .ribbon gives its pickers: the
app's dark neutrals are bluer than Word's, so the two ends of the window did
not match. Classic keeps the themed set. --color-primary is the brand slate
now, so both chromes share one accent.
--w-accent is the logo's slate instead of Word's blue (5.1:1 on the chrome,
carries white), and the clay marks the contextual tabs — the pair meets where
those sit beside the normal ones. Both defined once from favicon.svg; the
label tone is darkened, the clay itself only 3.3:1 on white.
The band was a round 108px while its tallest control measured 65, so each tab
carried a strip of empty chrome above its buttons. Padding, gaps and the caret
slot come in, the band is cut to what the controls actually need, and the style
gallery stops short of the group label it was sitting on: 144px of chrome to
118px. Line-heights are pinned in px — as ratios they hand the band's height to
whatever font resolves, and the group footers hang out of it.
Rows & Columns follows Word: four big buttons carrying a 28px glyph and a
two-line label, with the three deletions folded into one Entfernen dropdown
beside them so the group keeps its width.
Two lines cost the band 12px (--w-ribbon-h 96 -> 108). The labels size to
min-content, not max-width, which a wrapped box ignores; and the inserts drop
the reserved caret slot, without which the group's foot label sits 8px below
every other group's.
Ten of the fifteen caret buttons ran the same toggleMenu from both halves,
so they were split for nothing. They are single buttons now, with the caret
under the label rather than beside it — 13px narrower each, and Word's own
Paste button.
The tint takes the whole button, label included: a row mixes buttons whose
label is inside the button with pickers whose caption is a sibling, so half
of them lit up under the words and half did not. `captionClicks` gives the
caption the click to match, and the picker's trigger takes the icon box's
34px so glyphs and words land on one line.
Word's dark palette on the same metrics: Fluent's dark neutrals, chrome
#1f1f1f, and the accent lightened because #185abd on a dark chrome is
unreadable. AllBlack goes on to Word's Black theme. The lightened accent
cannot carry white text, so the File pill and the pickers' --color-primary
take a second, filled accent — identical to the first in light mode.
Every reused picker anchors its panel to its own trigger, so the band clipped
it: the table grid showed one row of eight. `pinPanels`, one action on the
band, pins whatever panel mounts inside it, and panels now drop below the whole
band instead of over the controls under them.
Their triggers also kept the classic toolbar's compact box, so Table, Symbol
and Date & time were half the size of the buttons beside them. `.rb-captioned`
moves to global.css, replacing four copies, and gives the trigger the big
button's 34px box, a 28px glyph and the ribbon's own hover and open tints.
The shared pickers frame their trigger for the classic toolbar's island; in a
ribbon row of borderless buttons that reads as a different control, and at
27-28px it broke the row's line. Every trigger is 30px there now. Redrew the
change-case and highlighter glyphs, which were malformed and off-centre.
The dialog sized each row on its own, so a long label wrapped and "pt" vs "cm"
shifted the field beside it - fixed unit width, no wrap, one 2x3 grid.
Clipboard, Font, Paragraph, a style gallery of live tiles, and Find/Replace —
which had no button in either chrome before. So did change case, underline and
strikethrough line styles: the engine has carried them all along.
Two things the fixed-height band forced. Its own overflow clips a dropdown, so
a menu leaves the flow and pins itself under its trigger. And with one shared
open-menu id, each wrapper must name the menu it owns, or every sibling closes
it on mousedown and the click on a row never lands.
A second chrome, chosen by odf-editor-chrome and switchable from either side so
the two can be compared. The shell only — tab strip, File menu, quick-access
save/undo/redo; the tab bodies follow. The classic island stays untouched.
Word's palette lives in --w-* outside the theme blocks, and .ribbon remaps the
app's own tokens onto it, so a reused picker adopts the ribbon's look without
an edit of its own.
The sheet took the app's slate (#1e293b), so every uncoloured run
differed from LibreOffice — and from a run the same document colours
#000000 explicitly. Light and dark themes now paint the page black on
white; allBlack still inverts it, and the PDF export no longer has to
override anything.
A formula node stores only its LaTeX source; the MathML on screen, the ODF
formula object and Word's OMML are derived from it, and both importers parse
foreign markup back into that source, so an imported formula stays editable.
Word documents were losing their formulas outright: m:oMath sits beside the w:r
runs in its own namespace, past convertInline's `namespaceURI !== W` guard.
Word's default theme heading font, so every Word file with a Title or a
heading references it. Without a face it dropped to the browser's serif —
a serif heading at the wrong width.