/* ============================================================
   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, only on a cold arrival (see the gate
   in the page head). It hides the page's own loader — the desk scene IS
   the loader now — and pins the document while the scene owns the
   screen. Both come off when the flight lands. */
html.fl-intro body { overflow: hidden; }
html.fl-intro #site-loader { display: none !important; }
#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; }
