/* The Observatory page. One viewport, never scrolls: a shaded loop of the Observatory itself
   behind a short statement. Loaded after style.css for fonts, tokens and the nav.

   The composition works off three vertical axes:
     left edge    — the title, its subline stepped in just off it, and at the foot the
                    live status
     centre line  — the paragraph, then the Index link, centred under the title
     right side   — the press credit, a colophon set a little in from the edge
   The left-set title against a centred body keeps it from reading as one centred funnel,
   and the status and credit close the page as a pair. Below 900px wide it all
   collapses into one left-aligned column.

   The video and poster carry their own light blur (baked into the files), so there is no CSS
   filter here. The shade brings them to about 70% of their brightness. */

html:has(body.page-observatory), body.page-observatory { height: 100%; overflow: hidden; }
body.page-observatory { background: #000; color: var(--t1); }

.ob {
    --amber: #C79238;   /* the Observatory's own amber (its --warn) */
    --mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    --pad: clamp(1.25rem, 3.4vw, 3rem);
    position: relative; isolation: isolate;
    height: 100vh; height: 100dvh;
    padding: 68px var(--pad) clamp(1.5rem, 5vh, 3rem);
    font-family: 'Red Hat Display', sans-serif;
    display: flex; flex-direction: column; align-items: flex-start;
}

/* ── background ── */
.ob-bg {
    position: absolute; inset: 0; z-index: -1; overflow: hidden;
    background: #000 url('/observatory-poster.jpg') center / cover no-repeat;
}
/* Portrait screens get their own recording and still, framed for a phone. */
@media (orientation: portrait) {
    .ob-bg { background-image: url('/observatory-poster-mobile.jpg'); }
}
.ob-video { width: 100%; height: 100%; object-fit: cover; display: block; }
.ob-bg::after { content: ''; position: absolute; inset: 0; background: rgba(0,0,0,0.3); }
@media (prefers-reduced-motion: reduce) {
    .ob-video { display: none; }
}

/* A tight dark glow, sized in em so it follows each line's own scale, lifts the type off a
   lighter patch of footage; the wide soft one keeps each block clean on it. Set per
   element because an inherited text-shadow keeps the parent's em. */
.ob > :not(.ob-bg), .ob-hero > * {
    text-shadow: 0 0 0.12em rgba(0,0,0,0.85), 0 0 0.35em rgba(0,0,0,0.55), 0 1px 18px rgba(0,0,0,0.6);
}

/* ── type ── */
.ob-title {
    margin: auto 0 0;
    font-weight: 800; font-size: clamp(2.5rem, min(5.6vw, 11vh), 6.25rem);
    line-height: 1; letter-spacing: -0.025em;
    text-wrap: balance;
}
.ob-sub {
    margin: clamp(0.75rem, 2.2vh, 1.4rem) 0 0;
    font-style: italic; font-weight: 400;
    font-size: clamp(1.2rem, min(2vw, 3.4vh), 1.75rem); line-height: 1.35;
    color: var(--t2); max-width: 36ch; text-wrap: balance;
}
.ob-text {
    margin: clamp(1.5rem, 5vh, 4.5rem) 0 0;
    font-weight: 400; font-size: clamp(1.05rem, min(1.45vw, 2.5vh), 1.35rem); line-height: 1.6;
    color: var(--t1); max-width: 46ch; text-wrap: pretty;
}

/* ── status ── */
.ob-status {
    display: inline-flex; align-items: center; gap: 0.75em; white-space: nowrap;
    margin: calc(clamp(1.25rem, 3.5vh, 2.75rem) - 1.1em) 0 -1.1em -1.6em;
    font-family: var(--mono); font-size: clamp(0.9rem, min(1.15vw, 2.1vh), 1.12rem); letter-spacing: 0.04em;
    color: var(--t1);
    /* A soft dark pool behind the readout, fading out on every side (no edges, no card), so
       it never melts into a bright patch of footage. The padding gives the fade room. */
    padding: 1.1em 1.6em;
    background: radial-gradient(closest-side, rgba(0,0,0,0.7), rgba(0,0,0,0.45) 55%, transparent);
}
/* Heavier than the glow the other lines get; the selector has to outrank that rule. */
.ob > .ob-status {
    text-shadow: 0 0 0.15em rgba(0,0,0,0.95), 0 0 0.5em rgba(0,0,0,0.8), 0 0 1.2em rgba(0,0,0,0.6);
}
.ob-status[hidden] { display: none; }
.ob-status time { color: var(--amber); }
.ob-dot {
    width: 0.8em; height: 0.8em; border-radius: 50%; flex: none;
    background: var(--amber);
    box-shadow: 0 0 0.3em rgba(0,0,0,0.9), 0 0 14px rgba(199,146,56,0.85);
    animation: ob-pulse 2s ease-in-out infinite;
}
@keyframes ob-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.2; } }
@media (prefers-reduced-motion: reduce) { .ob-dot { animation: none; } }

/* ── the way on, and the press credit ── */
.ob-link { margin: clamp(1.25rem, 3.5vh, 2.5rem) 0 0; }
.ob-link a, .ob-credit a {
    color: var(--t1); text-decoration: none;
    border-bottom: 1px solid rgba(255,255,255,0.35); padding-bottom: 0.15em;
    transition: border-color 0.2s;
}
.ob-link a { font-weight: 500; font-size: clamp(1.05rem, min(1.35vw, 2.4vh), 1.25rem); }
.ob-link a:hover, .ob-link a:focus-visible,
.ob-credit a:hover, .ob-credit a:focus-visible { border-color: #fff; outline: none; }
.ob-credit {
    margin: auto 0 0; padding-top: clamp(1rem, 3vh, 2.5rem);
    font-size: clamp(0.85rem, min(1vw, 1.9vh), 0.98rem); line-height: 1.7; color: var(--t2);
}
.ob-credit span { display: block; }
/* The link and, under it, the holdings note. The note is sized off the link: width 0 keeps
   it out of the box's intrinsic width, min-width 100% then stretches it to the link's. */
.ob-link { display: flex; flex-direction: column; width: fit-content; }
.ob-disclose {
    display: block; width: 0; min-width: 100%;
    margin-top: 0.7em;
    font-size: clamp(0.56rem, min(0.62vw, 1.2vh), 0.66rem); font-weight: 300;
    line-height: 1.45; letter-spacing: 0.01em; color: var(--t3);
}

/* Title on one line wherever the width allows it. After its `text-wrap`, a shorthand that
   would switch wrapping back on. */
@media (min-width: 760px) { .ob-title { white-space: nowrap; } }

/* ── phones and narrow windows: a title card ──
   Small type. The statement (title, subline, paragraph and its Index link) hangs from the
   upper third; the status and the press credit sit together at the foot, as on desktop.
   The gaps grow with the screen's height (dvh), so a tall phone spreads out and a short
   one (Safari with its bars showing) still fits. Sized in vw so a 390px phone and a 360px
   one keep the same proportions; everything fits in a Safari viewport with its bars showing
   (about 390×660 on an iPhone 12). */
@media (max-width: 899px) {
    .ob { padding-bottom: calc(1.25rem + env(safe-area-inset-bottom, 0px)); }
    /* Plain wrapping: balance would split it "The First / Light Observatory". */
    .ob-title { margin-top: clamp(1rem, 16dvh, 9rem); font-size: clamp(1.75rem, 8.2vw, 2.6rem); text-wrap: wrap; }
    .ob-sub   { margin-top: clamp(0.7rem, 2.4dvh, 1.4rem); font-size: clamp(0.88rem, 3.9vw, 1.1rem); }
    .ob-text  { margin-top: clamp(1.5rem, 6.5dvh, 3.5rem); font-size: clamp(0.8rem, 3.45vw, 0.98rem); line-height: 1.5; max-width: 42ch; }
    .ob-status {
        /* auto pushes status + credit to the foot; the halo's own padding is the gap. */
        margin: auto 0 -1.1em -1.6em;
        font-size: clamp(0.62rem, 2.75vw, 0.78rem); letter-spacing: 0.02em;
    }
    .ob-link { margin: clamp(0.9rem, 3dvh, 1.75rem) 0 clamp(1.25rem, 4dvh, 2.5rem); }
    .ob-link a { font-size: clamp(0.85rem, 3.7vw, 1rem); }
    .ob-disclose { font-size: clamp(0.5rem, 2.2vw, 0.6rem); }
    .ob-credit { margin-top: clamp(0.5rem, 1.4dvh, 0.9rem); padding-top: 0; font-size: clamp(0.64rem, 2.8vw, 0.78rem); line-height: 1.6; }
}

/* Very short phone screens (a small iPhone with Safari's bars showing, ~375×550): the
   title comes up under the nav so the credit still fits. */
@media (max-width: 899px) and (max-height: 600px) {
    .ob-title { margin-top: 0.75rem; }
    .ob-text  { margin-top: 1.25rem; }
}

/* ── the composition, where there is room for it ── */
@media (min-width: 900px) and (min-height: 560px) {
    .ob {
        display: grid;
        grid-template-columns: repeat(12, minmax(0, 1fr));
        column-gap: clamp(1rem, 2vw, 2rem);
        /* spacer · title · subline · paragraph · link · spacer · foot (status | credit).
           The top spacer is the smaller one, so the statement sits a little above the middle. */
        grid-template-rows: 0.8fr auto auto auto auto 1fr auto;
        align-items: start;
        padding-bottom: clamp(2.5rem, 8vh, 5rem);
    }
    .ob-hero   { grid-column: 1 / -1; grid-row: 2 / span 4; }
    .ob-title  { margin: 0; }
    .ob-sub    { white-space: nowrap; max-width: none; padding-left: 0.6em; }
    .ob-text   {
        align-self: center; text-align: center;
        margin-top: clamp(3rem, 9vh, 6rem); max-width: 48ch;
    }
    .ob-link   { align-self: center; text-align: center; }
    .ob-status { grid-column: 1 / span 6; grid-row: 7; align-self: center; justify-self: start; margin: -1.1em 0 -1.1em -1.6em; }
    .ob-credit {
        grid-column: 7 / span 5; grid-row: 7; justify-self: end; align-self: center;
        margin: 0; padding: 0; text-align: right;
    }
}

/* A phone on its side or a very short window cannot hold the page in one screen; scrolling
   beats clipping the text. */
@media (max-height: 520px) {
    html:has(body.page-observatory), body.page-observatory { height: auto; overflow: auto; }
    .ob { height: auto; min-height: 100dvh; }
    .ob-bg { position: fixed; }
}

/* ── methodology: collapsed by default, so the page keeps its sparse look ──
   The toggle sits just under the hero paragraph. Opening it (.ob.is-open) lifts the hero and
   shrinks it a little, grows the three paragraphs out of the toggle's place as a continuation
   of the hero paragraph (same face, same line height, same measure), and slides the Index link
   down into the bottom band between the status line and the press credit. The status line and
   the credit never move. observatory.js measures the real room and picks the shrink factors
   (--hk title and subline, --tk hero paragraph, --pk new text: always 1.5px smaller), the measure (--tw) and the link's
   offsets (--lk-dx/--lk-dy/--lk-h), so nothing scrolls and no text drops under 13px.
   This is only the styling. */
.ob-hero { display: flex; flex-direction: column; align-items: flex-start; position: relative; }
.ob-method { align-self: center; margin-top: 0.5rem; line-height: 1.6; color: var(--t3);
    font-size: clamp(0.8125rem, min(0.85vw, 1.6vh), 0.9rem); text-align: center; }
.ob-method-toggle {
    appearance: none; background: none; border: 0; padding: 0; margin: 0 auto; font: inherit; color: inherit;
    display: block; cursor: pointer; width: fit-content; font-weight: 300; letter-spacing: 0.04em;
    opacity: 0.75; transition: opacity 0.2s;
}
.ob-method-toggle::after { content: ' +'; }
.ob-method-toggle[aria-expanded="true"]::after { content: ' \2212'; }
.ob-method-toggle:hover, .ob-method-toggle:focus-visible { opacity: 1; outline: none; color: var(--t1); }
.ob-method-toggle:focus-visible { text-decoration: underline; text-underline-offset: 0.25em; }
.ob-link { margin-top: clamp(1.75rem, 5.5vh, 3.25rem); }

/* The text: the hero paragraph's own type, in a box that grows from nothing. */
.ob-panel {
    display: grid; grid-template-rows: 0fr; align-self: center; width: 100%;
    opacity: 0; visibility: hidden;
    transition: grid-template-rows 0.4s ease, opacity 0.3s ease, visibility 0s linear 0.4s;
}
.ob-panel.is-open { grid-template-rows: 1fr; opacity: 1; visibility: visible;
    transition: grid-template-rows 0.4s ease, opacity 0.35s ease 0.1s, visibility 0s; }
.ob-panel-clip { min-height: 0; overflow: hidden; }
.ob-panel:focus { outline: none; }
.ob-panel-in {
    margin: 0 auto; text-align: center; text-wrap: pretty;
    font-weight: 300; font-size: clamp(1.05rem, min(1.45vw, 2.5vh), 1.35rem); line-height: 1.6;
    color: var(--t1); max-width: var(--tw, 48ch);
    padding-top: 0.8em; zoom: var(--pk, 1);
}
.ob-panel-in p { margin: 0.8em 0 0; max-width: none; }
.ob-panel-in p:first-child { margin-top: 0; }
@media (max-width: 899px) {
    .ob-panel-in { text-align: left; font-size: clamp(0.8rem, 3.45vw, 0.98rem); line-height: 1.5; max-width: none; }
    .ob-panel { align-self: stretch; }
    .ob-method { align-self: flex-start; margin-top: 0.45rem; }
}

.ob-title, .ob-sub, .ob-text, .ob-link, .ob-method, .ob-panel-in {
    transition: zoom 0.4s ease, margin 0.4s ease, transform 0.4s ease, max-width 0.4s ease;
}
.ob.is-open { grid-template-rows: 0fr auto auto auto auto 1fr auto; transition: grid-template-rows 0.4s ease; }
.ob.is-open .ob-hero { margin-top: 0.5rem; }
.ob.is-open .ob-title { zoom: var(--hk, 0.7); }
.ob.is-open .ob-sub   { zoom: var(--sk, 0.7); margin-top: 0.5rem; }
.ob.is-open .ob-text  { zoom: var(--tk, 0.8); margin-top: 0.9rem; }
.ob.is-open .ob-method { margin-top: 0.5rem; }
.ob.is-open .ob-link  { margin-top: 0; margin-bottom: calc(-1 * var(--lk-h, 0px));
    transform: translate(var(--lk-dx, 0px), var(--lk-dy, 0px)); }
.ob.is-open.ob-narrow .ob-title { margin-top: 0.5rem; }
.ob.is-open.ob-narrow .ob-sub   { margin-top: 0.4rem; }
.ob.is-open.ob-narrow .ob-text  { margin-top: 0.6rem; }
.ob.is-open.ob-narrow .ob-text, .ob.is-open.ob-narrow .ob-panel-in { line-height: 1.38; }
.ob.is-open.ob-narrow .ob-hero { margin-top: 0; }
.ob.is-open.ob-narrow .ob-method { margin-top: 0.3rem; }
.ob-panel.is-narrow .ob-panel-in { padding-top: 0.55em; }
.ob-panel.is-narrow .ob-panel-in p { margin-top: 0.55em; }
.ob-panel.is-narrow .ob-panel-in p:first-child { margin-top: 0; }
.ob.ob-measuring, .ob.ob-measuring * { transition: none !important; }
@media (max-width: 899px) { .ob-hero { width: 100%; } }
@media (prefers-reduced-motion: reduce) {
    .ob.is-open, .ob-title, .ob-sub, .ob-text, .ob-link, .ob-method, .ob-panel, .ob-panel.is-open, .ob-panel-in { transition: none; }
}

/* The way into the full methodology: inside the collapsed panel, so the landing view stays as it is. */
.ob-panel-in .ob-panel-more { margin-top: 1.2em; }
.ob-panel-more a { color: #fff; text-decoration: none; border-bottom: 1px solid rgba(255, 255, 255, 0.35); transition: border-color 0.2s; }
.ob-panel-more a:hover, .ob-panel-more a:focus-visible { border-color: #fff; outline: none; }
