/* ═══════════════════════════════════════════════════════════════════════════
 * Entangled Text — homepage masthead.
 *
 * The rest of the site's header is an instrument: black, a hairline, links,
 * and a teal readout along the bottom edge (et-public-studio.css §Header
 * detailing). That is right everywhere you are reading or working — and wrong
 * for the one screen whose job is to say what this place is before anyone has
 * read a word.
 *
 * So the public header is painted into the field rather than boxed on top of
 * it. Same black as the entanglement animation below, a quiet teal wash, and
 * a ragged fade at the bottom so the painting dissolves into the scenery. As
 * you scroll it sinks back into being the instrument: the bleed closes, the
 * hairline and the teal readout take over.
 *
 * SCOPE
 * -----
 * Everything is keyed on body.et-public-site. The public header template loads
 * this sheet on every public page.
 *
 * COST
 * ----
 * No canvas and no animation loop of its own. The scene is layered gradients
 * plus two star tiles as inline SVG; the scroll response is one custom
 * property (--et-head-scroll) written by the rAF handler that was already
 * running for the readout. The only running animations are two long, slow
 * drifts, and prefers-reduced-motion stops both and freezes the parallax.
 * ═══════════════════════════════════════════════════════════════════════════ */

body.et-public-site {
    /* 0 at the top of the page, 1 once the masthead has finished compacting.
       Written by public-studio-chrome.js; the fallback keeps the scene in its
       open state if the script never runs. */
    --hh-p: var(--et-head-scroll, 0);

    --hh-open: 7.75rem;   /* height at rest */
    --hh-shut: 4.15rem;   /* height once compacted */
    --hh-h: calc(var(--hh-open) - (var(--hh-open) - var(--hh-shut)) * var(--hh-p));

    /* Same ground as the hero (--es-void) and the studio, not a second black. */
    --hh-void: #050508;
    --hh-violet: #8b5cf6;
    --hh-teal: var(--et-accent-primary, #2dd4bf);
    --hh-rim: #2dd4bf;
    /* How far the painting hangs into the hero. Long enough that the fade
       cannot read as a cut. Closes as the strip compacts. */
    --hh-bleed: calc(11rem * (1 - var(--hh-p)));
}

/* ── The strip ────────────────────────────────────────────────────────────
 * public-nav.css already makes this sticky; only the skin changes here.
 * Height is set rather than padding so the scene has a box to fill. */
body.et-public-site .et-navbar {
    position: sticky;
    min-height: var(--hh-h);
    padding-top: 0;
    padding-bottom: 0;
    display: flex;
    align-items: center;
    /* Fully clear at rest so the entanglement field is the scenery, the way
       Fable floats its nav over the illustration. A filled bar — even a
       fading one — still has a rectangular bottom that reads as a join.
       --hh-p opaques it to the studio black as the strip shuts. */
    background: transparent !important;
    background-image: linear-gradient(
        rgb(5 5 8 / var(--hh-p)),
        rgb(5 5 8 / var(--hh-p))
    ) !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    border-bottom: 0;
    box-shadow: none !important;
    /* The limb is 240vw, so a visible x-axis pushes the whole document
       sideways. `clip` cuts it at the viewport edge — where it is invisible
       anyway — without becoming a scroll container, which lets y stay
       visible so the glow keeps hanging into the hero. */
    overflow-x: clip;
    overflow-y: visible;
    transition: min-height 0.35s cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* The studio skin paints .is-scrolled as solid #000 with an inset hairline.
   Same clear-to-black as the rest state, and kill the hairline — ::before
   is the only ruled edge, and it stays at opacity --hh-p. */
body.et-public-site .et-navbar.is-scrolled {
    background: transparent !important;
    background-image: linear-gradient(
        rgb(5 5 8 / var(--hh-p)),
        rgb(5 5 8 / var(--hh-p))
    ) !important;
    box-shadow: none !important;
}

body.et-public-site .et-navbar > .container {
    position: relative;
    z-index: 3;
}

/* ── The scene ────────────────────────────────────────────────────────────
 * Stars and a quiet wash, hanging into the hero. The bottom edge is a
 * painterly fade — several overlapping lobes, not a straight cut — so it
 * reads as the same scenery as the animation, not a boxed header. */
body.et-public-site .et-masthead-sky {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: calc(-1 * var(--hh-bleed));
    z-index: 0;
    pointer-events: none;
    background-image:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='760' height='150'%3E%3Ccircle cx='133.0' cy='69.0' r='1.46' fill='%23a5f3fc' opacity='0.53'/%3E%3Ccircle cx='369.3' cy='39.8' r='0.91' fill='%23fff' opacity='0.52'/%3E%3Ccircle cx='751.6' cy='101.4' r='1.39' fill='%23fff' opacity='0.86'/%3E%3Ccircle cx='258.9' cy='33.6' r='1.27' fill='%23a5f3fc' opacity='0.72'/%3E%3Ccircle cx='437.6' cy='52.5' r='1.33' fill='%23a5f3fc' opacity='0.87'/%3E%3Ccircle cx='372.5' cy='137.1' r='1.34' fill='%23a5f3fc' opacity='0.83'/%3E%3Ccircle cx='572.0' cy='50.9' r='1.02' fill='%23fff' opacity='0.57'/%3E%3Ccircle cx='551.4' cy='54.5' r='0.92' fill='%23a5f3fc' opacity='0.71'/%3E%3Ccircle cx='480.0' cy='124.8' r='0.87' fill='%23fff' opacity='0.56'/%3E%3Ccircle cx='470.9' cy='130.5' r='1.4' fill='%23a5f3fc' opacity='0.56'/%3E%3Ccircle cx='59.9' cy='108.4' r='1.39' fill='%23a5f3fc' opacity='0.87'/%3E%3Ccircle cx='166.0' cy='33.6' r='1.49' fill='%23fff' opacity='0.94'/%3E%3Ccircle cx='391.7' cy='33.7' r='1.11' fill='%23a5f3fc' opacity='0.83'/%3E%3Ccircle cx='301.3' cy='137.2' r='0.79' fill='%23a5f3fc' opacity='0.7'/%3E%3Ccircle cx='434.5' cy='16.7' r='1.32' fill='%23fff' opacity='0.91'/%3E%3Ccircle cx='496.8' cy='148.0' r='0.89' fill='%23a5f3fc' opacity='0.58'/%3E%3Ccircle cx='263.1' cy='142.7' r='0.82' fill='%23a5f3fc' opacity='0.86'/%3E%3Ccircle cx='498.3' cy='145.3' r='1.35' fill='%23a5f3fc' opacity='0.7'/%3E%3Ccircle cx='626.1' cy='128.9' r='1.04' fill='%23fff' opacity='0.73'/%3E%3Ccircle cx='213.5' cy='12.9' r='1.22' fill='%23fff' opacity='0.52'/%3E%3Ccircle cx='204.3' cy='7.2' r='1.12' fill='%23fff' opacity='0.62'/%3E%3Ccircle cx='378.3' cy='31.1' r='0.85' fill='%23a5f3fc' opacity='0.62'/%3E%3C/svg%3E"),
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='480' height='150'%3E%3Ccircle cx='445.6' cy='136.6' r='0.53' fill='%23fff' opacity='0.43'/%3E%3Ccircle cx='118.8' cy='38.6' r='0.72' fill='%23fff' opacity='0.2'/%3E%3Ccircle cx='79.3' cy='135.5' r='0.71' fill='%23fff' opacity='0.43'/%3E%3Ccircle cx='7.0' cy='55.8' r='0.67' fill='%23fff' opacity='0.49'/%3E%3Ccircle cx='57.7' cy='9.0' r='0.35' fill='%23fff' opacity='0.2'/%3E%3Ccircle cx='14.4' cy='38.8' r='0.62' fill='%23fff' opacity='0.35'/%3E%3Ccircle cx='161.6' cy='147.1' r='0.45' fill='%23fff' opacity='0.18'/%3E%3Ccircle cx='46.8' cy='65.9' r='0.69' fill='%23fff' opacity='0.49'/%3E%3Ccircle cx='104.6' cy='0.7' r='0.47' fill='%23fff' opacity='0.28'/%3E%3Ccircle cx='177.5' cy='53.9' r='0.65' fill='%23fff' opacity='0.5'/%3E%3Ccircle cx='31.1' cy='121.8' r='0.57' fill='%23fff' opacity='0.38'/%3E%3Ccircle cx='75.5' cy='23.6' r='0.74' fill='%23bca9ff' opacity='0.28'/%3E%3Ccircle cx='11.5' cy='15.6' r='0.8' fill='%23fff' opacity='0.37'/%3E%3Ccircle cx='333.5' cy='47.4' r='0.58' fill='%23fff' opacity='0.27'/%3E%3Ccircle cx='37.9' cy='42.9' r='0.62' fill='%23fff' opacity='0.25'/%3E%3Ccircle cx='406.7' cy='40.4' r='0.54' fill='%23fff' opacity='0.16'/%3E%3Ccircle cx='277.0' cy='18.9' r='0.51' fill='%23fff' opacity='0.36'/%3E%3Ccircle cx='204.1' cy='74.7' r='0.35' fill='%23fff' opacity='0.22'/%3E%3Ccircle cx='396.4' cy='135.6' r='0.6' fill='%23fff' opacity='0.49'/%3E%3Ccircle cx='184.2' cy='25.0' r='0.4' fill='%23fff' opacity='0.45'/%3E%3Ccircle cx='142.3' cy='105.9' r='0.63' fill='%23bca9ff' opacity='0.45'/%3E%3Ccircle cx='448.5' cy='123.6' r='0.65' fill='%23fff' opacity='0.43'/%3E%3Ccircle cx='335.0' cy='9.1' r='0.49' fill='%23fff' opacity='0.29'/%3E%3Ccircle cx='264.6' cy='43.5' r='0.46' fill='%23fff' opacity='0.47'/%3E%3Ccircle cx='232.3' cy='91.9' r='0.63' fill='%23fff' opacity='0.5'/%3E%3Ccircle cx='353.8' cy='22.4' r='0.43' fill='%23fff' opacity='0.43'/%3E%3Ccircle cx='350.8' cy='103.7' r='0.43' fill='%23fff' opacity='0.21'/%3E%3Ccircle cx='79.4' cy='137.8' r='0.68' fill='%23bca9ff' opacity='0.32'/%3E%3Ccircle cx='321.1' cy='132.4' r='0.58' fill='%23fff' opacity='0.42'/%3E%3Ccircle cx='400.6' cy='63.7' r='0.77' fill='%23bca9ff' opacity='0.35'/%3E%3Ccircle cx='360.6' cy='71.6' r='0.55' fill='%23fff' opacity='0.32'/%3E%3Ccircle cx='266.9' cy='100.6' r='0.79' fill='%23fff' opacity='0.28'/%3E%3Ccircle cx='216.9' cy='114.7' r='0.5' fill='%23fff' opacity='0.39'/%3E%3Ccircle cx='324.2' cy='33.3' r='0.64' fill='%23fff' opacity='0.47'/%3E%3Ccircle cx='128.4' cy='121.3' r='0.44' fill='%23fff' opacity='0.45'/%3E%3Ccircle cx='106.3' cy='142.3' r='0.48' fill='%23fff' opacity='0.17'/%3E%3Ccircle cx='52.3' cy='66.5' r='0.58' fill='%23bca9ff' opacity='0.36'/%3E%3Ccircle cx='470.4' cy='10.9' r='0.79' fill='%23fff' opacity='0.26'/%3E%3Ccircle cx='362.0' cy='101.3' r='0.39' fill='%23fff' opacity='0.32'/%3E%3Ccircle cx='138.7' cy='73.6' r='0.38' fill='%23fff' opacity='0.23'/%3E%3Ccircle cx='154.1' cy='49.2' r='0.6' fill='%23fff' opacity='0.21'/%3E%3Ccircle cx='411.2' cy='39.5' r='0.44' fill='%23fff' opacity='0.17'/%3E%3Ccircle cx='28.8' cy='148.8' r='0.7' fill='%23fff' opacity='0.25'/%3E%3Ccircle cx='107.1' cy='141.1' r='0.59' fill='%23fff' opacity='0.28'/%3E%3Ccircle cx='382.5' cy='35.2' r='0.5' fill='%23bca9ff' opacity='0.17'/%3E%3Ccircle cx='9.4' cy='122.5' r='0.58' fill='%23bca9ff' opacity='0.27'/%3E%3Ccircle cx='322.2' cy='118.7' r='0.79' fill='%23fff' opacity='0.49'/%3E%3Ccircle cx='131.2' cy='13.9' r='0.7' fill='%23fff' opacity='0.49'/%3E%3Ccircle cx='219.1' cy='77.5' r='0.75' fill='%23fff' opacity='0.36'/%3E%3Ccircle cx='35.0' cy='108.8' r='0.77' fill='%23fff' opacity='0.37'/%3E%3Ccircle cx='227.3' cy='113.6' r='0.54' fill='%23fff' opacity='0.46'/%3E%3Ccircle cx='101.0' cy='74.7' r='0.78' fill='%23fff' opacity='0.33'/%3E%3Ccircle cx='453.1' cy='7.5' r='0.69' fill='%23fff' opacity='0.31'/%3E%3Ccircle cx='126.4' cy='19.9' r='0.52' fill='%23fff' opacity='0.26'/%3E%3Ccircle cx='326.4' cy='138.1' r='0.67' fill='%23fff' opacity='0.23'/%3E%3Ccircle cx='444.8' cy='12.8' r='0.76' fill='%23bca9ff' opacity='0.24'/%3E%3Ccircle cx='212.9' cy='98.7' r='0.37' fill='%23fff' opacity='0.42'/%3E%3Ccircle cx='279.2' cy='120.4' r='0.6' fill='%23fff' opacity='0.39'/%3E%3C/svg%3E"),
        radial-gradient(85% 140% at 16% -55%, rgba(45, 212, 191, 0.22), transparent 58%),
        radial-gradient(70% 120% at 86% -35%, rgba(20, 184, 166, 0.16), transparent 62%);
    background-repeat: repeat-x, repeat-x, no-repeat, no-repeat;
    background-size: 760px 150px, 480px 150px, auto, auto;
    /* The near plane moves about twice as far as the far one — the whole of
       the parallax, and the reason the strip reads as depth rather than
       wallpaper. Both also drift on their own so the sky is never still. */
    background-position:
        calc(var(--hh-drift, 0px) * 2.2) calc(-14px * var(--hh-p)),
        var(--hh-drift, 0px) calc(-6px * var(--hh-p)),
        0 0, 0 0;
    animation: hh-drift 240s linear infinite;
    opacity: calc(0.45 - 0.4 * var(--hh-p));
    /* A path-cut mask still draws a contour. This is only a long fade —
       already thinning at the top of the nav — plus lobes at staggered
       heights so the iso-opacity line is never a ruler. */
    -webkit-mask-image:
        linear-gradient(180deg,
            rgba(0, 0, 0, 0.55) 0%,
            rgba(0, 0, 0, 0.28) 22%,
            rgba(0, 0, 0, 0.12) 48%,
            rgba(0, 0, 0, 0.04) 72%,
            transparent 100%),
        radial-gradient(ellipse 30% 6.5rem at 6% 42%, #000 0%, transparent 74%),
        radial-gradient(ellipse 26% 7.2rem at 27% 68%, #000 0%, transparent 72%),
        radial-gradient(ellipse 34% 5.4rem at 52% 38%, #000 0%, transparent 76%),
        radial-gradient(ellipse 38% 8rem at 74% 88%, #000 0%, transparent 70%),
        radial-gradient(ellipse 28% 6rem at 96% 58%, #000 0%, transparent 73%);
    mask-image:
        linear-gradient(180deg,
            rgba(0, 0, 0, 0.55) 0%,
            rgba(0, 0, 0, 0.28) 22%,
            rgba(0, 0, 0, 0.12) 48%,
            rgba(0, 0, 0, 0.04) 72%,
            transparent 100%),
        radial-gradient(ellipse 30% 6.5rem at 6% 42%, #000 0%, transparent 74%),
        radial-gradient(ellipse 26% 7.2rem at 27% 68%, #000 0%, transparent 72%),
        radial-gradient(ellipse 34% 5.4rem at 52% 38%, #000 0%, transparent 76%),
        radial-gradient(ellipse 38% 8rem at 74% 88%, #000 0%, transparent 70%),
        radial-gradient(ellipse 28% 6rem at 96% 58%, #000 0%, transparent 73%);
    -webkit-mask-composite: source-over;
    mask-composite: add;
    -webkit-mask-size: 100% 100%;
    mask-size: 100% 100%;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
}

@property --hh-drift {
    syntax: '<length>';
    inherits: true;
    initial-value: 0px;
}

@keyframes hh-drift {
    from { --hh-drift: 0px; }
    to   { --hh-drift: -760px; }
}

/* Browsers without @property cannot animate a custom length; they get the
   static sky, which is the point of the layer anyway. */

/* ── The planet ───────────────────────────────────────────────────────────
 * A body far wider than the viewport, so only its limb crosses the strip: the
 * curve reads as scale. It is a wash now, not a rim-lit disc — the hard 1px
 * crest was the "consistent border" against the animation. Soft teal
 * atmosphere, same black as the hero, and it sinks on scroll. */
body.et-public-site {
    --hh-limb-h: 34rem;
    /* Where the limb's crest sits inside the strip, as a share of its height
       measured UP FROM THE BOTTOM edge — so a low horizon is a small number.
       Two ways to get this wrong, and the first draft managed both. Too high
       and the crest is above the strip, so all you ever see is the flat middle
       of a very large ellipse — a slab, not a limb. Too near the middle and the
       rim light draws a bright line straight through the nav links, which is
       what "Start your novel free" was sitting on. It belongs low: the strip is
       mostly sky, the planet is the horizon under the type, and on scroll it
       sinks past the bottom edge and leaves its atmosphere as the hairline. */
    --hh-crest: calc(0.22 - 0.3 * var(--hh-p));
}

body.et-public-site .et-masthead-limb {
    position: absolute;
    left: 50%;
    /* bottom = crest - height, so the top edge lands at crest × strip height
       and the rest of the body hangs below the strip where it is clipped. */
    bottom: calc(var(--hh-h) * var(--hh-crest) - var(--hh-limb-h));
    width: 240vw;
    height: var(--hh-limb-h);
    transform: translateX(-50%);
    border-radius: 50%;
    z-index: 1;
    pointer-events: none;
    background:
        radial-gradient(55% 200% at 30% 1%, rgba(45, 212, 191, 0.10), transparent 52%),
        radial-gradient(42% 160% at 80% 0%, rgba(20, 184, 166, 0.08), transparent 55%);
    /* Glow only — no black fill. A filled limb is another horizon line
       against the field. */
    box-shadow:
        inset 0 18px 40px -18px rgba(45, 212, 191, 0.12),
        0 -22px 70px -28px rgba(45, 212, 191, calc(0.18 * (1 - var(--hh-p))));
    opacity: calc(0.08 - 0.08 * var(--hh-p));
    transition: bottom 0.35s cubic-bezier(0.22, 0.61, 0.36, 1), opacity 0.35s ease;
    -webkit-mask-image: linear-gradient(180deg, #000 0%, rgba(0, 0, 0, 0.45) 38%, transparent 88%);
    mask-image: linear-gradient(180deg, #000 0%, rgba(0, 0, 0, 0.45) 38%, transparent 88%);
}

/* ── Horizon ──────────────────────────────────────────────────────────────
 * At rest there is no line — the painting is the edge. As the strip
 * compacts this fades in as the hairline every other page wears, and the
 * teal readout draws over it. */
body.et-public-site .et-navbar::before {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 1px;
    z-index: 2;
    pointer-events: none;
    opacity: var(--hh-p);
    background: linear-gradient(
        90deg,
        transparent,
        rgba(45, 212, 191, 0.35) 22%,
        rgba(45, 212, 191, 0.55) 78%,
        transparent
    );
}

/* The readout is a 1px teal rule on the strip's bottom edge — a join at rest.
   It belongs to the instrument, so it arrives with --hh-p, same as ::before. */
body.et-public-site .et-navbar::after {
    z-index: 4;
    opacity: var(--hh-p);
}

/* ── Registration ticks ───────────────────────────────────────────────────
 * The same 9px corner Ls the studio panels wear, so the window is framed by
 * the site's own vocabulary rather than a new one. They open outward while the
 * strip is tall and close in as it compacts. */
body.et-public-site .et-navbar > .container::before,
body.et-public-site .et-navbar > .container::after {
    top: calc(-0.55rem + 0.3rem * var(--hh-p));
    width: 11px;
    height: 11px;
    opacity: calc(0.2 + 0.25 * var(--hh-p));
    border-color: rgba(45, 212, 191, calc(0.45 - 0.2 * var(--hh-p)));
}

/* ── Brand ────────────────────────────────────────────────────────────────
 * A wordmark on a lit sky needs its own contrast; it cannot borrow the bar's. */
body.et-public-site .et-navbar .et-brand-name-montserrat {
    text-shadow: 0 1px 14px rgba(4, 4, 10, 0.95), 0 0 2px rgba(4, 4, 10, 0.8);
}

body.et-public-site .et-navbar .nav-link {
    text-shadow: 0 1px 10px rgba(4, 4, 10, 0.9);
}

/* ── Motion ───────────────────────────────────────────────────────────────
 * Drift and parallax are both decoration. Stopped, the scene is still a scene. */
@media (prefers-reduced-motion: reduce) {
    body.et-public-site .et-masthead-sky {
        animation: none;
        background-position: 0 0, 0 0, 0 0, 0 0;
    }
    body.et-public-site .et-navbar,
    body.et-public-site .et-masthead-limb {
        transition: none;
    }
}

/* ── Narrow ───────────────────────────────────────────────────────────────
 * Less room for a horizon, and an open mobile menu has to sit on something
 * solid rather than on a planet. */
@media (max-width: 991.98px) {
    body.et-public-site {
        --hh-open: 5.4rem;
        --hh-shut: 4rem;
    }
    body.et-public-site .et-navbar .navbar-collapse.show,
    body.et-public-site .et-navbar .navbar-collapse.collapsing {
        position: relative;
        z-index: 3;
        background: var(--hh-void);
        box-shadow: 0 0 0 100vmax var(--hh-void);
        clip-path: inset(0 -100vmax -100vmax -100vmax);
    }
    /* An expanded menu makes the strip a panel, so the scene steps back. */
    body.et-public-site .et-navbar:has(.navbar-collapse.show) {
        overflow-x: clip;
        overflow-y: visible;
    }
    body.et-public-site .et-navbar:has(.navbar-collapse.show) .et-masthead-limb {
        opacity: 0.35;
    }
}

/* ── Field + page ground ────────────────────────────────────────────────
 * The entanglement canvas lives in the public header so every page sits in
 * the same scenery. z-index 0 puts it above the body's void and behind the
 * sticky nav / main / footer. Inner pages tuck under the strip the way the
 * homepage hero does, so the painting hangs into the first section rather
 * than sitting in a boxed band above it. */
body.et-public-site {
    background: var(--hh-void, #050508);
}

body.et-public-site .et-public-field {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
    pointer-events: none;
    z-index: 0;
    opacity: 0.64;
}

body.et-public-site #main-content {
    position: relative;
    z-index: 1;
    background: transparent;
}

body.et-public-site:not(.et-home-page) #main-content {
    margin-top: calc(-1 * var(--hh-h, 7.75rem));
    padding-top: var(--hh-h, 7.75rem);
}

body.et-public-studio.et-public-site footer.et-site-footer {
    position: relative;
    z-index: 1;
    background: linear-gradient(180deg, transparent, rgba(0, 0, 0, 0.45) 55%) !important;
    border-top: 0 !important;
    box-shadow: none !important;
    overflow: visible;
}
