/* ============================================================
   BEWARE THE MOON — landing page
   One screen, no scrolling on desktop. Everything is stacked in
   depth around a single moon: sky, glow, moon, cloud, land, fog,
   then the plate of type. Tokens match the main site so the two
   read as the same product.
   ============================================================ */

/* ---------- 1. TOKENS ---------- */
:root {
    --ink-950: #05080f;
    --ink-900: #080d17;
    --ink-850: #0b1220;
    --ink-800: #101a2c;

    --moon: #f2ad50;
    --moon-hi: #f9cd82;
    --moon-pale: #fbe6bd;

    --bone: #ece6d8;
    --bone-dim: #9fa3a6;
    --bone-faint: #8a919b;
    --blood-hi: #c3384f;

    --font-display: 'Cinzel', 'Times New Roman', serif;
    --font-label: 'IM Fell English SC', 'Cinzel', serif;
    --font-body: 'EB Garamond', Georgia, 'Times New Roman', serif;

    --gutter: clamp(1.15rem, 4vw, 2.5rem);
    --ease-out: cubic-bezier(0.16, 1, 0.3, 1);

    /* Where the moon's centre sits. Everything else is composed around it.
       An svh length rather than a percentage so the plate can be laid out from
       it arithmetically instead of being bottom-aligned and hoping. */
    --moon-y: 30svh;
    --moon-size: clamp(260px, 42vmin, 460px);
}

/* ---------- 2. RESET ---------- */
*, *::before, *::after { box-sizing: border-box; }
html, body { height: 100%; }
body {
    margin: 0;
    min-height: 100svh;
    background: var(--ink-950);
    color: var(--bone);
    font-family: var(--font-body);
    /* The whole page is one viewport-sized composition; nothing should scroll
       sideways, and on desktop nothing should scroll at all. */
    overflow-x: hidden;
    -webkit-font-smoothing: antialiased;
}
img { display: block; max-width: 100%; }
button, input { font: inherit; color: inherit; }

/* ---------- 3. SKY ---------- */
.sky {
    position: fixed;
    inset: 0;
    z-index: -10;
    /* Warmer toward the moon, colder at the edges, near-black at the top. */
    background:
        radial-gradient(ellipse 70% 52% at 50% var(--moon-y),
            rgba(58, 44, 30, 0.85) 0%,
            rgba(26, 28, 34, 0.55) 34%,
            rgba(8, 13, 23, 0) 68%),
        linear-gradient(180deg,
            #03050b 0%,
            #060b16 26%,
            #0a1220 52%,
            #101a2c 78%,
            #16233a 100%);
}

/* Two star fields at different scales. Each is a small tile of stops repeated
   across the sky — as a handful of fixed stops they read as dust on the screen
   rather than as a sky, and there has to be enough of them to be a field.
   Masked off toward the horizon so stars never appear inside the land. */
.stars {
    position: absolute;
    inset: 0;
    background-image:
        radial-gradient(1.4px 1.4px at 18% 24%, rgba(255, 248, 230, 0.9), transparent 62%),
        radial-gradient(1.2px 1.2px at 74% 9%,  rgba(255, 248, 230, 0.75), transparent 62%),
        radial-gradient(1.6px 1.6px at 41% 46%, rgba(255, 248, 230, 0.8), transparent 62%),
        radial-gradient(1.1px 1.1px at 88% 31%, rgba(255, 248, 230, 0.7), transparent 62%),
        radial-gradient(1.3px 1.3px at 8% 68%,  rgba(255, 248, 230, 0.65), transparent 62%),
        radial-gradient(1.5px 1.5px at 62% 78%, rgba(255, 248, 230, 0.85), transparent 62%),
        radial-gradient(1.2px 1.2px at 30% 86%, rgba(255, 248, 230, 0.7), transparent 62%),
        radial-gradient(1.4px 1.4px at 95% 57%, rgba(255, 248, 230, 0.6), transparent 62%),
        radial-gradient(1.1px 1.1px at 52% 17%, rgba(255, 248, 230, 0.55), transparent 62%),
        radial-gradient(1.3px 1.3px at 6% 41%,  rgba(255, 248, 230, 0.6), transparent 62%);
    background-size: 27% 38%;
    -webkit-mask-image: linear-gradient(180deg, #000 0%, #000 38%, transparent 66%);
            mask-image: linear-gradient(180deg, #000 0%, #000 38%, transparent 66%);
    animation: twinkle 7s ease-in-out infinite;
}
.stars--far {
    background-image:
        radial-gradient(1px 1px at 26% 20%, rgba(220, 228, 245, 0.55), transparent 62%),
        radial-gradient(1px 1px at 55% 61%, rgba(220, 228, 245, 0.5), transparent 62%),
        radial-gradient(1px 1px at 81% 22%, rgba(220, 228, 245, 0.45), transparent 62%),
        radial-gradient(1px 1px at 13% 79%, rgba(220, 228, 245, 0.5), transparent 62%),
        radial-gradient(1px 1px at 68% 34%, rgba(220, 228, 245, 0.4), transparent 62%),
        radial-gradient(1px 1px at 46% 91%, rgba(220, 228, 245, 0.35), transparent 62%),
        radial-gradient(1px 1px at 92% 68%, rgba(220, 228, 245, 0.42), transparent 62%);
    background-size: 19% 29%;
    -webkit-mask-image: linear-gradient(180deg, #000 0%, #000 34%, transparent 62%);
            mask-image: linear-gradient(180deg, #000 0%, #000 34%, transparent 62%);
    animation: twinkle 11s ease-in-out infinite reverse;
}
@keyframes twinkle {
    0%, 100% { opacity: 0.75; }
    50%      { opacity: 1; }
}

/* ---------- 4. MOON ---------- */
/* Above .weather, so the sky's cloud banks pass BEHIND the disc. Only the one
   veil inside this stage crosses in front of it. */
.moon-stage {
    position: fixed;
    inset: 0;
    z-index: -7;
    pointer-events: none;
}

/* The glow is three stacked falloffs: a tight hot rim, a broad amber haze and
   a very wide lift that keeps the moon from sitting on the sky like a sticker.
   Its strength is driven by --lume, which script.js raises as the cycle runs. */
/* Offset toward the lit limb. Every phase in this cycle is waxing, so the light
   is always on the right; at full the moon lights evenly and the offset closes.
   Without this the halo sits centred behind a crescent and reads as an eclipse
   corona — light coming from behind the shadowed side. */
.moon-glow {
    position: absolute;
    left: calc(50% + (var(--moon-size) * 0.16) * (1 - var(--lume, 0)));
    top: var(--moon-y);
    transform: translate(-50%, -50%);
    width: calc(var(--moon-size) * 5.2);
    aspect-ratio: 1;
    opacity: calc(0.34 + 0.66 * var(--lume, 0));
    background:
        radial-gradient(circle,
            rgba(255, 214, 150, 0.50) 0%,
            rgba(249, 205, 130, 0.26) 9%,
            rgba(242, 173, 80, 0.13) 17%,
            rgba(242, 173, 80, 0.05) 28%,
            rgba(242, 173, 80, 0) 46%),
        radial-gradient(circle,
            rgba(180, 150, 210, 0.10) 0%,
            rgba(120, 110, 170, 0.05) 30%,
            rgba(80, 90, 140, 0) 58%);
    animation: breathe 9s ease-in-out infinite;
}
@keyframes breathe {
    0%, 100% { transform: translate(-50%, -50%) scale(1); }
    50%      { transform: translate(-50%, -50%) scale(1.045); }
}

.moon-wrap {
    position: absolute;
    left: 50%;
    top: var(--moon-y);
    transform: translate(-50%, -50%);
    width: var(--moon-size);
    aspect-ratio: 1;
}

/* A rim of light around the disc's edge.
   Without this the page opens on a new moon, which is a dark brown circle on
   a dark blue sky — astronomically correct and visually nothing. The rim reads
   as the sun catching the limb, so an unlit moon still reads as a sphere
   hanging there. It fades out as the moon fills and lights itself.
   Measured against the art: every plate paints a 301px disc inside a 320px
   box, centred at 50.6% / 48.8%, so the ring sits exactly on the painted edge. */
.moon-wrap::after {
    content: '';
    position: absolute;
    left: 50.6%;
    top: 48.8%;
    width: 94.1%;
    aspect-ratio: 1;
    transform: translate(-50%, -50%);
    border-radius: 50%;
    pointer-events: none;
    /* Floor kept high: on a phone the new moon's disc is darker than the sky
       behind it, so without a rim there is literally nothing to see. */
    opacity: calc(0.92 - 0.62 * var(--lume, 0));
    box-shadow:
        0 0 0 1px rgba(255, 214, 150, 0.5),
        0 0 calc(var(--moon-size) * 0.05) rgba(249, 205, 130, 0.45),
        0 0 calc(var(--moon-size) * 0.14) rgba(242, 173, 80, 0.3);
}
.moon {
    width: 100%;
    height: 100%;
    object-fit: contain;
    /* drop-shadow follows the PNG's alpha, not its brightness, so this haloes
       the whole disc whatever the phase. Kept deliberately weak and leaning on
       --lume: on a crescent a strong even halo would light the shadowed limb
       from behind and read as an eclipse. The directional light is the offset
       .moon-glow behind; this is only the near scatter. */
    filter:
        drop-shadow(0 0 calc(var(--moon-size) * 0.05) rgba(249, 205, 130, calc(0.20 + 0.45 * var(--lume, 0))))
        drop-shadow(0 0 calc(var(--moon-size) * 0.16) rgba(242, 173, 80, calc(0.09 + 0.32 * var(--lume, 0))));
    transition: opacity 0.9s var(--ease-out);
}

/* ---------- 5. CLOUD + FOG ---------- */
/* Behind the moon. These used to sit in front of it at flat opacity, which cut
   a hard-edged slab out of the disc — a circle that stops being a circle reads
   as a rendering fault, not as weather. */
.weather {
    position: fixed;
    inset: 0;
    z-index: -9;
    pointer-events: none;
    overflow: hidden;
}

/* Each bank is one whole copy of the painted cloud strip, drifting across and
   round again — NOT a tiled background. The strip's left and right ends do not
   match, so repeating it would show a hard join every tile; the only ways to
   tile it are to repaint its ends transparent or to stop tiling. Separate
   elements at different speeds, sizes and heights keep the sky occupied with
   the artwork exactly as painted.
   Negative delays start each one part-way across so the sky is never empty
   on first paint. */
.cloud {
    position: absolute;
    width: 76vw;
    aspect-ratio: 1469 / 183;
    background-image: url('assets/art/clouds.png');
    background-repeat: no-repeat;
    background-size: 100% 100%;
    will-change: transform;
}
@keyframes cross {
    from { transform: translate3d(-110%, 0, 0); }
    to   { transform: translate3d(242%, 0, 0); }
}

.cloud--high {
    top: calc(var(--moon-y) - 21%);
    width: 58vw;
    opacity: 0.42;
    filter: blur(1.5px);
    animation: cross 196s linear infinite;
    animation-delay: -70s;
}
.cloud--mid {
    top: calc(var(--moon-y) - 4%);
    width: 88vw;
    opacity: 0.4;
    filter: blur(2px);
    animation: cross 150s linear infinite;
    animation-delay: -112s;
}
.cloud--low {
    top: calc(var(--moon-y) + 17%);
    width: 104vw;
    opacity: 0.34;
    filter: blur(3px);
    animation: cross 248s linear infinite;
    animation-delay: -30s;
}

/* The only bank in front of the disc. screen-blended so it adds light rather
   than subtracting it, and scaled by --lume: a new moon has no light for a
   cloud to catch, a full one sets it glowing as it drifts past. Flat-opacity
   cloud over the disc cut a hard-edged slab out of it, which read as a
   rendering fault rather than as weather. */
.cloud--veil {
    position: absolute;
    top: calc(var(--moon-y) - 6%);
    width: 82vw;
    aspect-ratio: 1469 / 183;
    background-image: url('assets/art/clouds.png');
    background-repeat: no-repeat;
    background-size: 100% 100%;
    filter: blur(3px) sepia(0.4) hue-rotate(-12deg) saturate(1.6);
    mix-blend-mode: screen;
    opacity: calc(0.06 + 0.36 * var(--lume, 0));
    animation: cross 168s linear infinite;
    animation-delay: -54s;
    will-change: transform;
}

/* Fog is CSS, not art: flat elongated gradients that sit between the land
   layers and give the moor its depth. */
.fog {
    position: absolute;
    left: -10%;
    width: 120%;
    pointer-events: none;
}
.fog--far {
    bottom: 26%;
    height: 22vmin;
    background: linear-gradient(180deg,
        rgba(120, 132, 158, 0) 0%,
        rgba(126, 138, 165, 0.14) 46%,
        rgba(112, 124, 152, 0.07) 78%,
        rgba(100, 112, 140, 0) 100%);
    filter: blur(9px);
    animation: roll 71s ease-in-out infinite;
}
.fog--mid {
    bottom: 14%;
    height: 20vmin;
    z-index: 2;
    background: linear-gradient(180deg,
        rgba(140, 150, 175, 0) 0%,
        rgba(146, 156, 182, 0.19) 50%,
        rgba(130, 142, 170, 0.09) 82%,
        rgba(120, 132, 158, 0) 100%);
    filter: blur(12px);
    animation: roll 89s ease-in-out infinite reverse;
}
.fog--near {
    bottom: 2%;
    height: 17vmin;
    z-index: 5;
    background: linear-gradient(180deg,
        rgba(150, 160, 185, 0) 0%,
        rgba(154, 164, 190, 0.20) 54%,
        rgba(140, 150, 178, 0.10) 84%,
        rgba(128, 140, 168, 0) 100%);
    filter: blur(14px);
    animation: roll 61s ease-in-out infinite;
}
@keyframes roll {
    0%, 100% { transform: translate3d(-4%, 0, 0); }
    50%      { transform: translate3d(4%, 0, 0); }
}

/* ---------- 6. LAND ---------- */
.land {
    position: fixed;
    inset: 0;
    z-index: -5;
    pointer-events: none;
    overflow: hidden;
}

/* The four art layers are each a finished 1920x1080 frame, composed against
   one another before they ever reached this stylesheet. So they are not
   positioned individually — they are stacked inside one 16:9 box that scales
   to COVER the viewport and is pinned to the bottom. Whatever the window, the
   house, the deer, the headstone and the grass hold exactly the relationship
   they were drawn in; a wider window simply reveals more sky, a narrower one
   crops the sides. */
.scene {
    position: absolute;
    left: 50%;
    bottom: 0;
    transform: translateX(-50%);
    /* Fit to WIDTH so the whole composition is always visible — covering the
       height instead crops the sides, and the deer is the first thing to go.
       The second term is a floor for narrow windows, where fitting to width
       alone would squash the land into a thin strip: the scene never gets
       shorter than 62% of the viewport, growing past the edges instead. */
    width: max(100vw, calc(62svh * 16 / 9));
    aspect-ratio: 16 / 9;
}
.layer {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    max-width: none;
    will-change: transform;
}

/* Values only, saturation held low: the moon stays the one thing on this page
   allowed to have a colour. Each layer is darkened a little less than the one
   behind it, which is what sells the depth more than the parallax does. */

/* Far hill with the house, smallest and coldest. */
.layer--house {
    z-index: 1;
    filter: brightness(0.34) saturate(0.4) blur(1px);
    opacity: 0.88;
}
/* The deer, standing on the moor between the hill and the near ground. Already
   near-black in the art, so it needs almost no help. */
.layer--deer {
    z-index: 3;
    filter: brightness(0.46) saturate(0.5);
}
/* Near ground carrying the Owl Dark headstone and the tree. */
.layer--estate {
    z-index: 4;
    filter: brightness(0.28) saturate(0.34);
}
/* Grass silhouettes along the very bottom edge. */
.layer--grass {
    z-index: 6;
    filter: brightness(0.15) saturate(0.22);
    opacity: 0.92;
}

/* Sinks the foot of the page to black so the type at the bottom always has
   ground to sit on, whatever the land layers are doing behind it. */
.land::after {
    content: '';
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 34%;
    z-index: 7;
    pointer-events: none;
    background: linear-gradient(180deg,
        rgba(3, 5, 11, 0) 0%,
        rgba(3, 5, 11, 0.45) 46%,
        rgba(3, 5, 11, 0.82) 100%);
}

/* ---------- 7. STUDIO MARK ---------- */
.studio {
    position: fixed;
    top: var(--gutter);
    right: var(--gutter);
    z-index: 10;
    display: block;
    width: clamp(54px, 5.4vw, 78px);
    opacity: 0.85;
    transition: opacity 0.4s var(--ease-out);
}
.studio img { width: 100%; height: auto; }
.studio:hover, .studio:focus-visible { opacity: 1; }

/* ---------- 8. PLATE ---------- */
/* Bottom-anchored, and the wordmark is meant to cross the bottom of the disc —
   that overlap is the composition, not a collision. What has to be guaranteed
   is that the moon always stays visibly larger than the logo sitting on it,
   which is a job for the breakpoints below, not for this box. */
.stage {
    position: relative;
    z-index: 6;
    min-height: 100svh;
    display: grid;
    place-items: end center;
    padding: calc(var(--gutter) * 2) var(--gutter) clamp(2.5rem, 6vh, 4.5rem);
}
.plate {
    width: min(100%, 640px);
    margin-inline: auto;
    text-align: center;
    /* Lifts the type off the ridge without drawing a visible box. */
    filter: drop-shadow(0 4px 26px rgba(0, 0, 0, 0.85));
}

.wordmark {
    margin: 0 auto;
    width: min(100%, 420px);
}
.wordmark img { width: 100%; height: auto; }


/* ---------- 9. SIGN-UP ---------- */
.signup { margin-top: clamp(1.1rem, 2.6vh, 1.9rem); }
.signup-label {
    display: block;
    margin-bottom: 0.6rem;
    font-family: var(--font-label);
    font-size: clamp(0.78rem, 0.72rem + 0.24vw, 0.92rem);
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--bone-dim);
}
.signup-row {
    display: flex;
    gap: 0.5rem;
    max-width: 420px;
    margin-inline: auto;
}
.signup-input {
    flex: 1;
    min-width: 0;
    padding: 0.72rem 0.9rem;
    background: rgba(5, 8, 15, 0.55);
    border: 0;
    border-bottom: 1px solid rgba(242, 173, 80, 0.38);
    border-radius: 2px 2px 0 0;
    color: var(--bone);
    font-size: 0.98rem;
    transition: border-color 0.3s var(--ease-out), background 0.3s var(--ease-out);
}
.signup-input::placeholder { color: rgba(138, 145, 155, 0.75); }
.signup-input:hover { border-bottom-color: rgba(242, 173, 80, 0.62); }
.signup-input:focus-visible {
    outline: none;
    border-bottom-color: var(--moon);
    background: rgba(5, 8, 15, 0.82);
    box-shadow: 0 2px 0 -1px rgba(242, 173, 80, 0.5);
}
.signup-input[aria-invalid="true"] { border-bottom-color: var(--blood-hi); }

.signup-btn {
    flex: 0 0 auto;
    padding: 0.72rem 1.5rem;
    background: var(--moon);
    border: 1px solid var(--moon);
    border-radius: 3px;
    color: #1a1206;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 0.86rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    cursor: pointer;
    transition: background 0.3s var(--ease-out), transform 0.3s var(--ease-out);
}
.signup-btn:hover { background: var(--moon-hi); border-color: var(--moon-hi); }
.signup-btn:active { transform: translateY(1px); }
.signup-btn:focus-visible { outline: 2px solid var(--moon-pale); outline-offset: 3px; }
.signup-btn[disabled] { opacity: 0.6; cursor: default; }

.signup-msg {
    margin: 0.5rem 0 0;
    min-height: 1.2em;
    font-size: 0.88rem;
    color: var(--moon-hi);
}
.signup-msg[data-state="error"] { color: var(--blood-hi); }

/* Off-screen rather than display:none — a hidden field a bot can still find
   and fill, which is the point. */
.hp {
    position: absolute;
    left: -9999px;
    width: 1px; height: 1px;
    overflow: hidden;
}

/* ---------- 10. FOOT ---------- */
.foot {
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 7;
    padding: 0 var(--gutter) clamp(0.7rem, 1.6vh, 1.1rem);
    text-align: center;
    pointer-events: none;
}
.foot p {
    margin: 0;
    font-size: 0.72rem;
    letter-spacing: 0.06em;
    color: rgba(138, 145, 155, 0.6);
}

/* ---------- 11. RESPONSIVE ---------- */
/* Short and wide — 1280x720 is the common case. The rule here used to shrink
   the moon to 190px while the wordmark stayed at 330px, so the hero ended up
   smaller than the logo sitting on it. When height runs out the strapline goes
   first; the moon is the last thing to give ground. */
@media (max-height: 800px) and (min-width: 700px) {
    :root {
        /* lowered so the phase line clears the top of the disc */
        --moon-y: 33svh;
        --moon-size: clamp(260px, 46vmin, 380px);
    }
    .wordmark { width: min(100%, 300px); }
}

@media (max-width: 700px) {
    :root {
        --moon-y: 24svh;
        --moon-size: clamp(230px, 62vmin, 320px);
    }
    .stage { padding-bottom: clamp(2rem, 5vh, 3.5rem); }
    .wordmark { width: min(100%, 290px); }
    .signup-row { flex-direction: column; }
    .signup-btn { padding: 0.8rem 1.5rem; }
    /* The scene is one composed 16:9 frame now, so it is scaled and shifted as
       a whole rather than layer by layer. At phone width it has to grow a long
       way past the viewport to stay 16:9, and it is pushed right so the house
       sits off to the left of the moon instead of running up through it. */
    /* Pushed right so the house sits left of the moon rather than running up
       through it, and grown so the land still reads at phone width. */
    /* At phone width only a narrow slice of a 16:9 frame can be seen at all,
       so the scene is sized by height and centred on the slice that carries
       the house on one side and the headstone on the other. The land sits
       well below the moon, so the two never collide despite overlapping in x. */
    .scene {
        width: max(222vw, calc(58svh * 16 / 9));
        left: 103%;
        bottom: 2%;
    }
    /* Lifted well above the desktop values. At phone size the land is a
       narrow band competing with the form on top of it, and at near-
       silhouette it reads as nothing at all — the house and the deer are
       the whole point of the composition down here. */
    .layer--house  { filter: brightness(0.62) saturate(0.6); opacity: 1; }
    .layer--deer   { filter: brightness(0.7) saturate(0.65); }
    .layer--estate { filter: brightness(0.44) saturate(0.45); }
    .layer--grass  { filter: brightness(0.26) saturate(0.3); }
    .fog--mid, .fog--near { opacity: 0.45; }
    .land::after { height: 20%; }
    .cloud--high, .cloud--low { display: none; }
}

/* Very short phones: everything optional is already gone, so trim the hero. */
@media (max-height: 640px) and (max-width: 700px) {
    :root { --moon-size: clamp(165px, 38vmin, 230px); --moon-y: 21svh; }
}

/* ---------- 12. REDUCED MOTION ---------- */
@media (prefers-reduced-motion: reduce) {
    .stars, .stars--far, .moon-glow, .cloud, .fog {
        animation: none !important;
    }
    * { transition-duration: 0.01ms !important; }
}
