/* THE RULES THAT MUST EXIST BEFORE THE FIRST PAINT.
 *
 * styles.css is half a megabyte (162KB gzipped). The browser blocks rendering
 * on it, but on a phone it still arrives late enough that the shell paints
 * UNSTYLED first -- and the service worker is network-first, so a cold launch
 * on cellular waits for the network before it has a stylesheet at all.
 * Measured: at +45ms the document had parsed and `document.styleSheets.length`
 * was still 0.
 *
 * This file is about a kilobyte and is linked BEFORE the main sheet, so what
 * has to be true on the first frame is true. Nothing else belongs here: every
 * rule in this file is one the main sheet cannot be trusted to deliver in time.
 */

/* THE CANVAS IS DARK BEFORE ANY STYLESHEET SAYS SO.
 *
 * This is the flash (operator, 2026-08-25: "fix the flashing splash screen").
 * iOS shows the dark launch image from the tap, hands over to the page, and the
 * page painted WHITE -- full screen, with light-chrome form controls -- until
 * the 162KB sheet landed a second or more later. Photographed by aborting
 * styles.css: a white page under a dark launch image and a dark app.
 *
 * Two separate causes, both fixed here:
 *
 *   `color-scheme` decides the colour the browser paints the canvas with before
 *   any author CSS applies, and the colour it renders native controls in.
 *   styles.css declared `light` -- a leftover from 2026-08-13, when the light
 *   half of the theme was deleted and the dark values were merged into :root.
 *   Nothing overrode it, so a dark-only app was telling the browser it was
 *   light. Declared here as well as there because the first frame happens
 *   before there.
 *
 *   The background then has to be the app's own, not just "some dark", or the
 *   handover from the launch image is still a visible step. #081416 is --page.
 *   Written as a literal on purpose: the token lives in styles.css, which by
 *   definition has not arrived yet. A test pins the two together.
 */
:root { color-scheme: dark; }
html { background: #081416; }
html[data-color-theme="forest"] { background: #10150f; }
html[data-color-theme="midnight"] { background: #081416; }
html[data-color-theme="graphite"] { background: #121211; }
html[data-color-theme="navy"] { background: #07111f; }
html[data-color-theme="arctic"] { background: #1b2029; }
html[data-color-theme="copper"] { background: #160d09; }

/* THE LOCK PANEL, WHEN IT IS ABOUT TO LIFT ANYWAY. first-paint.js sets this
   class only when the device is known-protected AND still inside the idle
   grace -- the exact case app.js suppresses a moment later. Without it the
   first painted frame is a full-screen padlock, because `.app-lock` ships
   visible (deliberately: it must fail CLOSED if app.js throws) and app.js is
   `defer`, so the document paints before it runs. See the note in
   first-paint.js; nothing here can expose the app, it can only stop a panel
   being drawn that was never going to stay. */
.lock-suppressed .app-lock { display: none; }

/* The in-app boot splash that lived here was removed on 2026-08-26; see
   index.html for why. Its inlined artwork was 17.5KB of this file, and this
   file is render-blocking -- so taking it out shortens the very wait it was
   painted to hide. */
/* THE MARK ARRIVES (operator, 2026-08-21: "on the splash page I see at least a
   second or two loading on a cold start -- maybe the logo starts really small
   and zooms out smoothly").
   NOT A SECOND SPLASH SCREEN. One was built and removed on 2026-08-17 for
   holding the finished app back half a second to show artwork iOS was already
   showing. This animates the mark that is ALREADY on the shell, so it costs
   nothing and delays nothing: the app paints when it paints, and the logo
   settles into place as it does.
   It runs on the first paint of a session only -- `is-arriving` is set once,
   never on a tab change -- so it reads as the app opening rather than as
   decoration that repeats. */
/* STATIC. NO OPENING ANIMATION ON THE MARK -- deliberately, and temporarily.
 *
 * Operator, 2026-08-27: "Let's reset back to a static screen and then slowly
 * work way back up into a interesting animation."
 *
 * The animation that was here (brand-arrive: scale 0.92 -> 1 over 520ms) was
 * already written to be harmless if it lost the race, and the frame-by-frame
 * measurement of his 2026-08-27 cold start says it was NOT the flash: the
 * bright frame at t=1883ms is a 7% white wash of the whole web view, present
 * while iOS's launch artwork is still on screen and the app has not painted.
 * The mark cannot brighten a page it is not on.
 *
 * It comes out anyway, because the point now is to establish a floor that is
 * known-clean and add motion back one step at a time, with each step measured
 * rather than argued about. zenith_boot_film_check.py is the measurement: it
 * films the boot from the compositor and fails on any frame brighter than the
 * settled ground.
 *
 * WHAT NOT TO REINTRODUCE. Two earlier versions started the mark at a fifth of
 * its size with opacity 0, and that IS visible as a flash: any frame drawn
 * before the rule applies shows the mark full size and opaque, and the
 * animation then yanks it down to nothing. Whatever comes back must be
 * harmless when it loses the race -- an opening state within a pixel or two of
 * the resting one, at full opacity.
 */


/* The "nothing is shown until it is styled" guard was removed on 2026-08-28
   with the media="print" trick it existed for. A render-blocking sheet cannot
   paint an unstyled frame, so there is nothing left to hide -- and a rule that
   hides the app on a condition that can no longer occur is one bad edit away
   from hiding it for ever. That very nearly happened: it left the LOGIN page
   permanently blank, because that page never had the deferred sheet. */

/* THE FADE LIVES IN styles.css, NOT HERE -- and that is the whole point.
 *
 * It was written in this file first and did not run. MEASURED by sampling the
 * rendered opacity of <main> on every animation frame through a cold boot:
 * 1.000 at every sample, from the first frame onward.
 *
 * WHY. This file applies as soon as it lands, which is EARLY. styles.css is
 * render-blocking, so nothing paints until IT lands, which is later. An
 * animation's clock starts when its rule applies, not when the page can be
 * seen -- so a 220ms fade declared here burns down entirely during the
 * render-blocked window and is already finished at the first painted frame.
 *
 * Declared in styles.css instead, it starts at the moment rendering unblocks,
 * which is the moment the app first appears. Same animation, correct clock.
 */
