/* ===========================================================
   UNAMIQ - home page ("coming soon" splash)

   The only page that does NOT load tokens.css: it is
   permanently dark and has no theme toggle, so it defines its
   own palette in the :root block below. Everything else in
   base / layout / components resolves against those values
   through their var(--x, fallback) defaults.

   Also the only page with no footer - see 'chrome' => false
   in includes/config.php.
=========================================================== */

:root{

    /* ---------------------------------------------------------
       The home page is the one page that does NOT load
       tokens.css - it is permanently dark and has no theme
       toggle. These are its palette, and they are what the
       var(--x, fallback) defaults across base/layout/components
       resolve against here.
       --------------------------------------------------------- */

    --bg-color: rgb(7,7,8);

    --cta-border: rgba(255,255,255,.4);
    --cta-color: #ffffff;
    --cta-hover-bg: #ffffff;
    --cta-hover-color: #000000;

    /* Desktop parallax offset, set by JS on mousemove */
    --parallax-x: 0px;
    --parallax-y: 0px;

    /* Mobile pan + pinch-zoom, set by JS on touch */
    --pan-x: 0px;
    --pan-y: 0px;
    --pan-scale: 1;

    /* Raw (smoothed) cursor position, used by the light-shift mask */
    --mouse-x: 50vw;
    --mouse-y: 50vh;

}

html, body{
    height:100%;
    overflow:hidden;
}

body{
    height:100dvh;
    touch-action:none; /* we handle pan/zoom ourselves */
}

/* ===========================================================
   BACKGROUND SCENES
   Four renders stacked exactly on top of each other (position
   + size set by JS from real pixel dimensions). Only one is
   opacity:1 at a time; JS toggles .active on a timer, and this
   transition is what produces the crossfade.
=========================================================== */

.bg-layer{
    position:fixed;
    top:50%;
    left:50%;
    z-index:1;

    max-width:none;
    max-height:none;

    pointer-events:none;
    user-select:none;
    -webkit-user-drag:none;

    opacity:0;
    transition:opacity 2s ease;

    will-change:transform, opacity;
}

.bg-layer.active{
    opacity:1;
}

/* ===========================================================
   LIGHT SHIFT
   A duplicate of the background, lifted slightly in brightness
   and contrast, masked to a soft circle that follows the
   cursor. Kept in exact alignment with .bg-layer by JS.
=========================================================== */

#lightshift{
    position:fixed;
    top:50%;
    left:50%;
    z-index:2;

    /* No background-image here on purpose: js/home.js sets it from
       the scene the browser actually picked out of the srcset, so
       hard-coding one would download a second copy of the same image. */
    background-repeat:no-repeat;
    background-position:center center;
    background-size:100% 100%;

    filter:brightness(1.14) contrast(1.06) saturate(1.04);

    -webkit-mask-image:
        radial-gradient(circle 280px at var(--mouse-x) var(--mouse-y), black 0%, transparent 100%);
    mask-image:
        radial-gradient(circle 280px at var(--mouse-x) var(--mouse-y), black 0%, transparent 100%);

    opacity:.55;

    pointer-events:none;
    will-change:transform;
}

/* ===========================================================
   VIGNETTE
=========================================================== */

#vignette{
    position:fixed;
    inset:0;
    z-index:3;
    pointer-events:none;

    background:
        radial-gradient(
            ellipse at center,
            rgba(0,0,0,0) 45%,
            rgba(0,0,0,.20) 75%,
            rgba(0,0,0,.50) 100%
        );
}

/* ===========================================================
   FILM GRAIN
=========================================================== */

#grain{
    position:fixed;
    inset:-50%;
    z-index:4;
    pointer-events:none;

    opacity:.04;

    background-image: radial-gradient(circle, white 1px, transparent 1px);
    background-size:5px 5px;

    mix-blend-mode:soft-light;

    animation: grainMove 10s steps(10) infinite;
}

@keyframes grainMove{
    0%   { transform:translate(0,0); }
    10%  { transform:translate(-2%,2%); }
    20%  { transform:translate(2%,-4%); }
    30%  { transform:translate(-4%,4%); }
    40%  { transform:translate(4%,-2%); }
    50%  { transform:translate(-2%,-4%); }
    60%  { transform:translate(4%,2%); }
    70%  { transform:translate(-4%,-2%); }
    80%  { transform:translate(2%,4%); }
    90%  { transform:translate(-2%,-2%); }
    100% { transform:translate(0,0); }
}

/* ===========================================================
   OVERLAY — just enough darkening at the bottom-left for the
   text to stay readable, nothing else.
=========================================================== */

#overlay{
    position:fixed;
    inset:0;
    z-index:5;
    pointer-events:none;

    background: linear-gradient(
        to top,
        rgba(0,0,0,.55),
        rgba(0,0,0,0) 45%
    );
}

/* ===========================================================
   HERO TEXT — fixed position, always on top, never moves.
   Reveals with a soft blur-to-sharp + fade-up on load.
=========================================================== */

.hero{
    position:fixed;
    left:70px;
    bottom:36px;
    z-index:10;

    display:flex;
    flex-direction:column;
    align-items:flex-start;
    user-select:none;
}

.hero h1{
    font-size:clamp(2.1rem, 4.6vw, 4.6rem);
    font-weight:700;
    line-height:.9;
    letter-spacing:.18em;
    text-transform:uppercase;

    opacity:0;
    animation: revealUpWordmark 1.4s cubic-bezier(.2,.8,.2,1) forwards;
    animation-delay:.15s;
}

.hero h2{
    margin-top:16px;
    font-size:clamp(.72rem, .85vw, .95rem);
    font-weight:300;
    letter-spacing:.55em;
    text-transform:uppercase;

    opacity:0;
    animation: revealUp 1.6s cubic-bezier(.2,.8,.2,1) forwards;
    animation-delay:.55s;
}

/* The button reveals with the same motion as the wordmark, staggered
   after it.

   .cta-button needs --cta-border / --cta-color / --cta-hover-bg /
   --cta-hover-color. This page does not load tokens.css, but the
   :root block at the top of this file already defined all four — they
   were sitting there unused, waiting for a button. Nothing new needed. */

.hero-cta{
    margin-top:26px;

    opacity:0;
    animation: revealUpFull 1.6s cubic-bezier(.2,.8,.2,1) forwards;
    animation-delay:1.15s;
}

@keyframes revealUp{
    from{ opacity:0; transform:translateY(24px); filter:blur(8px); }
    to{ opacity:.82; transform:translateY(0); filter:blur(0); }
}

@keyframes revealUpFull{
    from{ opacity:0; transform:translateY(24px); filter:blur(8px); }
    to{ opacity:1; transform:translateY(0); filter:blur(0); }
}

/* Same reveal as revealUpFull, but settles at .88 instead of full
   opacity — just enough softening that UNAMIQ reads as part of the
   photo rather than a label placed on top of it. */
@keyframes revealUpWordmark{
    from{ opacity:0; transform:translateY(24px); filter:blur(8px); }
    to{ opacity:.88; transform:translateY(0); filter:blur(0); }
}

/* ===========================================================
   REDUCED MOTION
   This page had no guard. The hero reveals slide and blur, and the
   grain translates on a loop — both are real motion and both are
   switched off here. The scene crossfade stays: it is a 2s opacity
   fade with no movement, which is what someone asking for reduced
   motion is still fine with.
=========================================================== */

@media (prefers-reduced-motion: reduce){

    .hero h1,
    .hero h2,
    .hero-cta{
        animation:none;
        opacity:1;
        transform:none;
        filter:none;
    }

    .hero h1{ opacity:.88; }
    .hero h2{ opacity:.82; }

    #grain{ animation:none; }

    .status-dot{ animation:none; }

    #telemetry-cursor{ animation:none; }

}

@media(max-width:900px){

    .hero{ left:32px; bottom:36px; }
    .hero h1{ letter-spacing:.13em; }
    .hero h2{ margin-top:12px; letter-spacing:.38em; }

}

@media(max-width:900px){

    .hero-cta{ margin-top:22px; }

}

@media(max-width:600px){

    /* Three elements tall, not two, so it is anchored a little
       higher and the button sits above the telemetry. */
    .hero{ left:22px; right:22px; bottom:54px; }
    .hero h1{ font-size:2rem; }
    .hero h2{ font-size:var(--fs-2xs); letter-spacing:.3em; }

    /* 44px tall, matching the touch target the footer's icon links
       use. The default .cta-button padding lands at 40px here. */
    .hero-cta{
        margin-top:18px;
        padding:13px 24px;
    }

}

/* ===========================================================
   STATUS BAR
=========================================================== */

#statusbar{
    position:fixed;
    right:32px;
    bottom:36px;
    z-index:10;

    display:flex;
    align-items:center;
    gap:10px;

    pointer-events:none;
}

#telemetry,
#telemetry-cursor{
    font-family:"Space Mono", monospace;
    font-size:var(--fs-2xs);
    letter-spacing:.08em;
    color:rgba(255,255,255,.55);
    white-space:nowrap;
}

#telemetry-cursor{
    animation: cursorBlink 1s steps(1) infinite;
}

@keyframes cursorBlink{
    0%, 49%  { opacity:1; }
    50%, 100%{ opacity:0; }
}

.status-dot{
    width:6px;
    height:6px;
    border-radius:50%;
    flex-shrink:0;

    background:rgba(255,255,255,.55);
    box-shadow:0 0 6px rgba(255,255,255,.35);

    animation: statusPulse 3.4s ease-in-out infinite;
}

@keyframes statusPulse{
    0%, 100% { opacity:.35; transform:scale(1); }
    50%      { opacity:.9;  transform:scale(1.3); }
}

@media(max-width:600px){

    #statusbar{ right:20px; bottom:20px; }

    #telemetry,
    #telemetry-cursor{ display:none; }

}
