/* ============================================================
   Florium — the entry scene's chrome (intro-scene.js).

   Everything here is class-based, not id-based, so the same sheet
   dresses the lookdev harness (desk.html) and the real thing on a
   site page. The scene itself is WebGL; these are the four flat
   layers around it.
   ============================================================ */

/* the loading screen is painted into the laptop's screen texture with
   canvas 2D, and canvas can only use a font the document has actually
   loaded — hence the face here even though no DOM node uses it */
@font-face {
    font-family: 'Geist Mono';
    src: url('geist-font-v1.7.2/geist-font/GeistMono/webfonts/GeistMono-Regular.woff2') format('woff2');
    font-weight: 400;
    font-display: block;
}

/* ---- the overlay root -------------------------------------------
   On a site page this sits over the real document until the flight
   lands. Opaque, so nothing of the page shows through early. */
.fx-root {
    position: fixed;
    inset: 0;
    z-index: 3000;        /* over the site loader (2000) and the consent bar (140) */
    background: #050505;
    overflow: hidden;
}

.fx-stage { position: absolute; inset: 0; }
.fx-stage canvas { display: block; width: 100%; height: 100%; }

/* first-paint cover — the scene fades in once the room is built */
.fx-veil {
    position: absolute;
    inset: 0;
    background: #050505;
    z-index: 2;
    transition: opacity .9s ease;
    pointer-events: none;
}
.fx-veil.gone { opacity: 0; }

/* ---- what the laptop screen shows --------------------------------
   Not a picture of the page — the page. `.fx-page` holds a clone of the
   site's own first viewport, laid out at the real window size, so it has
   the real layout; only afterwards is the whole thing mapped onto the
   panel by a homography (see the flight in intro-scene.js). When the
   transform reaches the identity there is nothing left to cut.

   `.fx-screen` wraps it with a Mac window bar on top. That bar is not
   decoration: its height is exactly W/1.5397 − H, which makes the
   composite match the panel's aspect, so the page underneath is never
   stretched to fit a screen of the wrong shape. The flight then aims the
   page part at the window and the bar runs off the top. */
.fx-screen {
    position: absolute;
    left: 0;
    top: 0;
    z-index: 3;
    transform-origin: 0 0;
    will-change: transform;
    overflow: hidden;
    background: #f1f1f1;
    display: none;
    /* it is the page's likeness, not the page: never let it take a click
       or a caret */
    pointer-events: none;
    user-select: none;
}
.fx-screen.on { display: block; }

.fx-page {
    position: relative;
    overflow: hidden;
    background: #f1f1f1;
    /* its own containing block, so the cloned fixed header pins to the
       PAGE area rather than to the wrapper (which includes the bar) */
    transform: translateZ(0);
}

/* ---- the desktop around the page ----------------------------------
   Three strips share the leftover height: the system menu bar, the
   window's own title bar, and the dock. Each is sized in JS and scales
   its contents off --h, its own height, so the whole thing reads right
   whether the leftover is 30 px or 170 px. The dock is there to balance
   the composition — with all the furniture piled above the page the
   screen looked top-heavy and the title bar had to be enormous. */
.fx-menubar,
.fx-chrome,
.fx-dock {
    position: relative;
    display: flex;
    align-items: center;
    overflow: hidden;
    font-family: "Geist Mono", ui-monospace, Menlo, monospace;
}

/* system menu bar */
.fx-menubar {
    background: rgba(238, 238, 240, .96);
    border-bottom: 1px solid rgba(0, 0, 0, .08);
    padding: 0 calc(var(--h) * .7);
    gap: calc(var(--h) * .7);
    font-size: calc(var(--h) * .42);
    line-height: 1;
    color: #2a2a2a;
    white-space: nowrap;
}
.fx-menubar b { font-weight: 600; }
.fx-menubar em { margin-left: auto; font-style: normal; }

/* the window's title bar */
.fx-chrome {
    background: linear-gradient(#f7f7f7, #e9e9e9);
    border-bottom: 1px solid #d2d2d2;
    padding: 0 calc(var(--h) * .34);
    gap: calc(var(--h) * .16);
}
.fx-chrome i {
    flex: 0 0 auto;
    width: calc(var(--h) * .17);
    height: calc(var(--h) * .17);
    border-radius: 50%;
    background: #ddd;
}
.fx-chrome i:nth-child(1) { background: #ff5f57; }
.fx-chrome i:nth-child(2) { background: #febc2e; }
.fx-chrome i:nth-child(3) { background: #28c840; }
.fx-chrome span {
    margin: 0 auto;
    display: block;
    min-width: 34%;
    text-align: center;
    background: #fff;
    border-radius: 999px;
    padding: calc(var(--h) * .07) calc(var(--h) * .3);
    font-size: calc(var(--h) * .21);
    line-height: 1.2;
    color: #5b5b5b;
    white-space: nowrap;
    overflow: hidden;
}

/* ---- the dock -----------------------------------------------------
   A strip of desktop with a floating translucent tray on it: the apps in
   the middle, live weather on the left, a live clock on the right. All of
   it is drawn — the app marks are inline SVG, so there is nothing to
   fetch and nothing to keep in sync. */
.fx-dock {
    justify-content: space-between;
    gap: calc(var(--h) * .2);
    padding: 0 calc(var(--h) * .34);
    background: linear-gradient(160deg, #2f3a4a, #131922 60%, #0d1117);
    color: rgba(255, 255, 255, .92);
}

.fx-dock-bar {
    display: flex;
    align-items: flex-end;
    gap: calc(var(--h) * .1);
    padding: calc(var(--h) * .09) calc(var(--h) * .12);
    border-radius: calc(var(--h) * .22);
    background: rgba(255, 255, 255, .17);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .18),
                0 calc(var(--h) * .05) calc(var(--h) * .14) rgba(0, 0, 0, .35);
}
.fx-dock-bar i {
    flex: 0 0 auto;
    display: block;
    width: calc(var(--h) * .66);
    height: calc(var(--h) * .66);
    filter: drop-shadow(0 calc(var(--h) * .02) calc(var(--h) * .045) rgba(0, 0, 0, .4));
}
.fx-dock-bar i svg,
.fx-dock-bar i img { display: block; width: 100%; height: 100%; object-fit: contain; }

/* weather, left */
.fx-wx,
.fx-clock {
    display: flex;
    flex: 0 0 auto;
    align-items: center;
    line-height: 1.15;
    white-space: nowrap;
}
.fx-wx { gap: calc(var(--h) * .12); }
.fx-wx-ico { display: block; width: calc(var(--h) * .46); height: calc(var(--h) * .46); }
.fx-wx-ico svg { display: block; width: 100%; height: 100%; }
.fx-wx b { font-size: calc(var(--h) * .3); font-weight: 500; }
.fx-wx-txt { font-size: calc(var(--h) * .19); opacity: .7; }

/* clock, right */
.fx-clock {
    flex-direction: column;
    align-items: flex-end;
}
.fx-clock b { font-size: calc(var(--h) * .3); font-weight: 500; font-variant-numeric: tabular-nums; }
.fx-clock span { font-size: calc(var(--h) * .19); opacity: .7; }


/* ---- flat entry ---------------------------------------------------
   Phones, tablets, odd window shapes, no WebGL, reduced motion: the same
   loading screen, laid out as DOM on black with no room around it. The
   3D never loads in this mode at all.

   --u is the design-pixel scale, written from JS. The block that gets
   centred is the drawn extent (design y 258 → 1010 = 752 tall), not the
   frame box, which has empty space above the first line. */
.fx-flat {
    position: absolute;
    inset: 0;
    display: grid;
    align-content: center;
    justify-items: center;
    background: #050505;
    font-family: "Geist Mono", ui-monospace, Menlo, monospace;
    font-weight: 400;
    color: #fff;
    text-align: center;
}
.fx-flat p {
    margin: 0;
    white-space: pre;
    font-size: calc(100 * var(--u) * 1px);
    line-height: calc(130 * var(--u) * 1px);
    letter-spacing: calc(-2 * var(--u) * 1px);
}
/* design gaps: line top 258 → pct top 480 → bars top 702 */
.fx-flat-pct { margin-top: calc(92 * var(--u) * 1px); }
.fx-flat-bars {
    margin-top: calc(92 * var(--u) * 1px);
    display: flex;
    gap: calc(124 * var(--u) * 1px);
    width: calc(2786 * var(--u) * 1px);
    height: calc(308 * var(--u) * 1px);
}
.fx-flat-bars { max-width: 100%; }
.fx-flat-bars i { flex: 1; min-width: 0; background: #282828; }
.fx-flat-bars i.on { background: #fff; }

/* in flat mode the overlay is the whole show — no room behind it */
html.fl-flat .fx-veil,
html.fl-flat .fx-stage,
html.fl-flat .fx-screen,
html.fl-flat .fx-enter,
html.fl-flat .fx-err { display: none !important; }

/* ---- how a site page wears all of this ---------------------------
   html.fl-intro is set pre-paint (see the gate in the page head) and pins
   the document while the scene owns the screen. It comes off when the
   flight lands.

   It used to mean "cold arrival" specifically. It no longer does: the
   homepage also sets it on a WARM desktop arrival, with fl-flat + fl-warm,
   because that is where its old grey progress bar used to play. Anything
   reading this class as "first visit" is wrong — read fl-warm. */
html.fl-intro body { overflow: hidden; }
#fl-intro { display: none; }
html.fl-intro #fl-intro { display: block; }

/* ---- the enter prompt --------------------------------------------
   60% of the work page's body copy (1.75rem against a root of
   min(0.83333vw, 16px)) — the full size read as an overlay rather than
   as something sitting on the desk.

   `left`, `top` and `transform` all come from JS: the label is anchored
   to a point in world space and re-projected every frame, scale and all,
   so it moves with the room and rushes past the camera during the flight
   instead of being switched off. transform-origin stays centred because
   the JS transform carries its own -50% recentring. */
.fx-enter {
    position: absolute;
    left: 50%;
    top: 82%;
    transform: translate(-50%, -50%);
    transform-origin: 50% 50%;
    z-index: 4;
    margin: 0;
    font-family: "Geist Mono", ui-monospace, Menlo, monospace;
    font-weight: 400;
    font-size: min(0.875vw, 16.8px);         /* 40% off 1.75rem */
    line-height: min(1vw, 19.2px);
    white-space: nowrap;                     /* mono: an anagram is the same width */
    color: #fff;
    /* on a dark room a 55%-black shadow was simply invisible; it needs to
       read as a soft dark pool under the type */
    text-shadow: 0 12px 20px rgba(0, 0, 0, .95), 0 3px 8px rgba(0, 0, 0, .7);
    opacity: 0;
    pointer-events: none;
    transition: opacity .7s ease;
    will-change: transform;
}
.fx-enter.in { opacity: 1; pointer-events: auto; }

.fx-err {
    position: absolute;
    inset: 0;
    display: none;
    place-items: center;
    z-index: 5;
    font: 400 11px/1.5 "Geist Mono", ui-monospace, Menlo, monospace;
    text-align: center;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: #7a736a;
}
html.no-webgl .fx-err { display: grid; }
html.no-webgl .fx-veil { opacity: 1; }
html.no-webgl .fx-enter { display: none; }
