Theme
The app comes light or dark. The user chooses with the sun/moon toggle at
the top of every screen, or under Appearance in the study preferences,
where a third choice, "As my browser", follows prefers-color-scheme
(and keeps following it as it changes). Until anything is chosen, that
is what the app does.
Where the choice is kept
The diagram's source
flowchart LR
accTitle: Where the theme is kept
accDescr: A theme choice is kept on this device, and in the instance's preferences when one is open, which set the device's choice when the instance is opened.
choose["A choice"] --> device["This device<br/>localStorage solid-memo:theme"]
choose -->|"an instance is open<br/>and has preferences"| pod["preferences.ttl<br/>sm:theme"]
pod -->|"the instance is opened"| device- In the pod, as
sm:themein the instance's preferences (preferences format 4): a concept ofsm:Themes(sm:systemTheme,sm:lightTheme,sm:darkTheme). This is the choice that counts, and it follows the user to every device. It is written once the instance has preferences: a new instance is made with them, the theme shown at the time among them; an instance made before has them after the user's first save of the study preferences (which saves the theme shown at the time), and until then a choice is kept on the device alone. - On the device, by the
ThemePreferenceport (localStorageThemePreference.ts, keysolid-memo:theme; "As my browser" is no key at all). It is what the sign-in screens and the first paint have, before any pod is reached. Opening an instance whose preferences say otherwise copies their choice here (instanceTheme).
A write to the pod that fails (another device saved the preferences meanwhile, say) is undone: the app reads the preferences back and shows what they hold.
Showing it
The stylesheet's dark colors hang off <html data-theme="dark">. A small
script in apps/web/index.html (the page the Studio is
in too) sets the attribute from the device's
choice, else the browser's, before the first paint, so a page never
flashes in the other theme; packages/ui/src/ui/theme.tsx takes over from there and also
sets the theme-color meta tags for the browser's own chrome.
Korean text
Korean, on a Korean page or in card text marked lang="ko" on another,
has its own :lang(ko) rules in style.css: Korean fonts (Apple SD
Gothic Neo, Malgun Gothic, Noto Sans KR) ahead of the Japanese ones,
which hold Hangul too but draw it with Japanese shapes and metrics;
Fredoka and Bangers stay first for the Latin letters. Lines break between
words, not syllables (word-break: keep-all). Headings, which Bangers
cannot draw in Korean, are bold, and neither they nor the uppercase
labels are tracked apart. Code, kbd, samp and pre keep the
monospace font (--font-mono), which the Korean font rule would
otherwise take from them.
Arabic text
Arabic in card text marked lang="ar" has its own :lang(ar) rules in
style.css: Noto Naskh Arabic, a book hand that draws the vowel marks
clearly, bundled like Fredoka (only its Arabic files are fetched, and
only for Arabic text), after Fredoka for the Latin letters and before
the systems' Arabic fonts (Geeza Pro, Segoe UI, Tahoma). Arabic letters
join, so no Arabic text is tracked apart: not headings, not the card's
question (tightened for Latin letters), not the uppercase labels.
Headings, which Bangers cannot draw in Arabic, are bold in the Arabic
font, and code keeps the monospace font, as in Korean. Arabic, like any
language written right to left, runs right to left in its own isolated
box (i18n.md).
German text
German, on a German page or in card text marked lang="de" on another,
is hyphenated at line ends (hyphens: auto under :lang(de)), so a
long compound word ("Wiederholungsintervall") breaks at a syllable with
a hyphen rather than at any letter. Spanish and French need no rules of
their own: Fredoka and Bangers draw their letters.