@charset "UTF-8";

/* ===========================================================================
   Majori Manor — estate.css

   WHAT THIS FILE IS NOT. It is not a second design system. THE ESTATE loads
   home.css first and draws almost everything with it: the tokens, the two
   faces, the navigation, the hero, the bands, the plates, the invitation, the
   footer, the grain and the reveal states are all the Main Page's and are used
   here unchanged. head.php lists the two files together for exactly that
   reason — a token edited in home.css moves both pages, so they cannot drift.

   WHAT THIS FILE IS. Three things the Main Page has no use for:

     1. acts     the six grounds the page moves through, and the seams that
                 wash one into the next
     2. walk     the sticky scroll-driven sequence through the rooms
     3. ledger   the five settled facts, set as a drawing sheet

   …and, at the end, the mobile pass and the reduced-motion pass for those
   three. Nothing here restyles a component home.css already owns.

   THE PAGE IS NOT A BLACK PAGE. The Main Page holds one ground from the first
   screen to the last, which is right for a film that never brightens. This one
   is a walk through a house and it changes temperature as it goes — near-black
   at the gates, warm where the woodwork is, green out in the park, wine at the
   hearth, near-black again at the end. Every one of the six is still a dark
   ground; the difference between them is a few percent of hue, which is what
   makes it read as light changing rather than as a new page.
   =========================================================================== */


/* ===========================================================================
   1. Acts
   ---------------------------------------------------------------------------
   Six grounds, declared as overrides of --ground and nothing else. Every
   component below reads --ground through home.css's semantic layer, so an act
   is one custom property and the whole run of scenes inside it follows.

   THE VALUES ARE THE BRAND'S, DARKENED UNTIL THEY ARE GROUNDS. --mm-green and
   --mm-wine are the estate's own green and wine — the two colourways of the
   seal — taken down to the luminance of the Main Page's black. Measured on
   --ink (#F2ECE0) the worst of them is 15.8:1, so body text clears AAA on
   every act and the gold eyebrows clear AA on all six.

   THE SEAM IS A WASH, NOT A CUT. Each act after the first hangs a gradient of
   its own ground above itself, so the previous act's last screen darkens into
   the next act's colour over about a tenth of a viewport. It is the same idea
   as templates/components/seam.php on the other pages — a temperature change
   is walked through — done here in one pseudo-element because these scenes are
   full-bleed and a seam band between them would be a visible join.
   =========================================================================== */

:root {
    --mm-estate:   #0B0A08;   /* the gates — the Main Page's own black */
    --mm-heritage: #17110C;   /* the woodwork — mahogany over black */
    --mm-interior: #0D0B0A;   /* the pause before the park */
    --mm-park:     #0A1310;   /* the park — the seal's green, grounded */
    --mm-evening:  #150B0D;   /* the hearth — the seal's wine, grounded */
}

.c-act {
    position: relative;
    background-color: var(--ground);
}

.c-act--estate   { --ground: var(--mm-estate); }
.c-act--heritage { --ground: var(--mm-heritage); }
.c-act--interior { --ground: var(--mm-interior); }
.c-act--park     { --ground: var(--mm-park); }
.c-act--evening  { --ground: var(--mm-evening); }

/*
   The wash. It belongs to the act below it, which is why var(--ground) here is
   the arriving colour and not the departing one, and it is lifted clear of its
   own box by translateY so it lies over the tail of the act above.
*/
.c-act + .c-act::before {
    content: "";
    position: absolute;
    inset-inline: 0;
    top: 0;
    z-index: 1;
    height: clamp(5rem, 12vh, 12rem);
    transform: translateY(-100%);
    background-image: linear-gradient(to bottom, transparent, var(--ground));
    pointer-events: none;
}


/* ===========================================================================
   1b. The hero's copy band
   ---------------------------------------------------------------------------
   THE ONE THING THIS PAGE ADDS TO A COMPONENT HOME.CSS OWNS, and it is here
   because the two heroes stand on different photographs.

   The Main Page's hero is a stone house at blue hour and its copy sits over
   dark ashlar, which is why home.css leaves the scrim transparent from 26% to
   44% — there is nothing to protect there. THE ESTATE's hero is the real
   Majori Manor, and the real Majori Manor is white render. Cream type on a
   white wall measures about 1.2:1.

   HALF THE FIX IS IN THE PICTURE AND HALF IS HERE. The sequence is graded down
   about six percent in the mids and ten in the highlights before it is encoded
   — see GRADE in tools/photos/build_estate_media.py — and this adds a soft
   band behind the copy on top of that. Together they clear AA on the small
   lines; neither does it alone, and either alone taken far enough to do it
   would have cost the building.

   IT IS A LAYER, NOT A REPLACEMENT. Restating home.css's whole gradient stack
   with one more entry would mean the two files could drift the next time that
   stack is touched. This is a pseudo-element over it, so home.css stays the
   only place the hero's scrim is described.
   =========================================================================== */

.c-film-hero__scrim::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background-image: linear-gradient(to bottom,
        transparent 12%,
        color-mix(in srgb, var(--mm-black-900) 36%, transparent) 32%,
        color-mix(in srgb, var(--mm-black-900) 52%, transparent) 52%,
        color-mix(in srgb, var(--mm-black-900) 40%, transparent) 70%,
        transparent 86%);
}

/*
   Narrower screens need more of it, and for a reason that is about the crop
   rather than about the screen: a 16:9 film in a portrait window is covered to
   the height, so the facade fills the frame edge to edge and the copy has
   nowhere dark to stand at all.
*/
@media (max-width: 899px) {
    .c-film-hero__scrim::after {
        background-image: linear-gradient(to bottom,
            transparent 8%,
            color-mix(in srgb, var(--mm-black-900) 40%, transparent) 28%,
            color-mix(in srgb, var(--mm-black-900) 54%, transparent) 52%,
            color-mix(in srgb, var(--mm-black-900) 46%, transparent) 72%,
            transparent 88%);
    }
}


/* ===========================================================================
   1c. The page the reader is standing on
   ---------------------------------------------------------------------------
   film-nav.php now writes aria-current="page" and .is-current onto whichever
   link names the current page. On the Main Page that is never a link in the
   bar — home is in NAV_EXCLUDE and is not one of them — so the markup there is
   unchanged and these two rules match nothing. THE ESTATE is the first page to
   have a bar that can point at itself.

   IT IS THE HOVER STATE, HELD. The rule under a link is already the bar's one
   piece of feedback; the current page simply keeps it drawn instead of drawing
   it on hover. No new colour, no new weight, no pill, no dot — the same gold
   hairline the design already uses, not moving. That is why this is nine lines
   and not a component.

   THE STYLING LIVES HERE RATHER THAN IN home.css for the reason the head of
   this file gives: home.css is now shared by two pages and asset_url()
   cache-busts on filemtime, so an edit there re-versions the stylesheet in the
   Main Page's markup for a rule the Main Page cannot use.
   =========================================================================== */

.c-film-nav__links a.is-current {
    color: var(--ink);
}

.c-film-nav__links a.is-current::after {
    transform: scaleX(1);
}

/* In the sheet the links are display type on a dark ground, so the same idea
   is carried by the number beside the label rather than by a rule under it. */
.c-film-menu__list a.is-current .c-film-menu__n {
    color: var(--gold-bright);
}

.c-film-menu__list a.is-current {
    color: var(--gold-bright);
}


/* ===========================================================================
   2. The walk
   ---------------------------------------------------------------------------
   THE DEFAULT STATE IS A GALLERY AND IT IS A COMPLETE ONE. Everything in this
   block up to the html.is-walking rules is what a reader sees with no
   JavaScript, with a blocked CDN, or under prefers-reduced-motion: seven
   full-width photographs in content order, each with its own caption under it.
   Nothing is at opacity 0 and nothing is stacked, so the failure mode of the
   most complicated thing on this page is a long quiet gallery.

   estate.js adds html.is-walking at the moment it takes responsibility for the
   stage. Only then does the stack become a viewport, and only then is a frame
   allowed to be invisible. This is §13 of home.css applied to a component that
   home.css does not know about.
   =========================================================================== */

.c-walk {
    padding-block: var(--scene) 0;
    background-color: var(--ground);
}

.c-walk__head {
    max-width: var(--shell);
    margin-inline: auto;
    padding-inline: var(--gutter);
    padding-bottom: var(--scene-tight);
}

.c-walk__index {
    display: block;
    font-size: 0.6875rem;
    letter-spacing: 0.26em;
    text-transform: uppercase;
    color: var(--gold-ink);
    margin-bottom: 0.9rem;
}

.c-walk__eyebrow {
    margin: 0 0 1.1rem;
    font-size: 0.6875rem;
    letter-spacing: 0.26em;
    text-transform: uppercase;
    color: var(--ink-muted);
}

.c-walk__title {
    margin: 0;
    max-width: 20ch;
    font-size: clamp(2.1rem, 5.4vw, 4.4rem);
}

.c-walk__frames {
    display: grid;
    gap: var(--scene-tight);
}

.c-walk__frame {
    position: relative;
    margin: 0;
}

.c-walk__img {
    display: block;
}

/*
   WHERE THE CROP IS TAKEN FROM. The stage is the viewport and the frames are
   16:9, so on a phone two thirds of the width is cut away and which two thirds
   is a design decision — see film-walk.php. The default is the centre, which
   is right for the frames that were composed around their subject.
*/
.c-walk__img img {
    object-position: var(--focus, 50% 50%);
}

.c-walk__video {
    display: none;   /* the stage turns it on; the gallery is stills */
}

.c-walk__figcaption {
    display: flex;
    align-items: baseline;
    gap: 0.9rem;
    padding: 0.9rem var(--gutter) 0;
    font-size: 0.75rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--ink-muted);
}

.c-walk__fign {
    color: var(--gold-ink);
    font-variant-numeric: tabular-nums;
}

.c-walk__mark {
    margin-left: 0.9rem;
    color: var(--ink-faint);
}

/* The legend and the rule are the stage's instruments; the gallery has the
   captions instead and does not need them twice. */
.c-walk__legend,
.c-walk__rule,
.c-walk__scrim {
    display: none;
}


/* -- the stage ------------------------------------------------------------ */

/*
   ONE STATION IS ROUGHLY ONE SCREEN OF SCROLL, plus one screen of run-out so
   the last station is readable before the section releases. Below 900px it is
   shortened — see §5: a seven-screen sticky section on a phone is a long time
   to be holding one thumb still.
*/
html.is-walking .c-walk {
    height: calc((var(--stations) + 1) * 92vh);
    padding-bottom: 0;
}

html.is-walking .c-walk__head {
    position: relative;
    z-index: 3;
}

html.is-walking .c-walk__stage {
    position: sticky;
    top: 0;
    height: 100vh;
    height: 100svh;
    overflow: clip;
}

html.is-walking .c-walk__frames {
    position: absolute;
    inset: 0;
    display: block;
    gap: 0;
}

html.is-walking .c-walk__frame {
    position: absolute;
    inset: 0;
    opacity: 0;
    will-change: opacity;
}

/*
   The first station is painted. If estate.js sets the class and then throws
   before it reaches the stations, the reader is looking at the first room
   rather than at a black rectangle.
*/
html.is-walking .c-walk__frame:first-child {
    opacity: 1;
}

/*
   The picture fills the viewport rather than its declared ratio. --img-ratio
   is still on the element and is still what the gallery uses; here it is
   overridden so a 16:9 frame covers a portrait window.
*/
html.is-walking .c-walk__img {
    position: absolute;
    inset: 0;
    block-size: 100%;
    aspect-ratio: auto;
}

html.is-walking .c-walk__video {
    display: block;
    position: absolute;
    inset: 0;
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
    /* The same crop as the poster under it, or the frame would jump sideways
       the moment the film faded up. */
    object-position: var(--focus, 50% 50%);
    opacity: 0;
    transition: opacity 0.9s var(--ease);
}

html.is-walking .c-walk__video.is-playing {
    opacity: 1;
}

html.is-walking .c-walk__figcaption {
    display: none;
}

html.is-walking .c-walk__scrim {
    display: block;
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    background-image:
        linear-gradient(to top, color-mix(in srgb, var(--ground) 92%, transparent) 0%,
                                color-mix(in srgb, var(--ground) 34%, transparent) 34%,
                                transparent 62%),
        linear-gradient(to bottom, color-mix(in srgb, var(--ground) 58%, transparent), transparent 30%);
}

/* -- the legend ------------------------------------------------------------
   The seven labels occupy one place at the foot of the stage and cross-fade
   with the frames, so the reader always has the name of the room they are
   standing in and never a list of six they are not. */

html.is-walking .c-walk__legend {
    display: block;
    position: absolute;
    z-index: 3;
    left: var(--gutter);
    right: var(--gutter);
    bottom: clamp(3.5rem, 8vh, 6rem);
    margin: 0;
    padding: 0;
    list-style: none;
    max-width: var(--shell);
    margin-inline: auto;
}

html.is-walking .c-walk__station {
    position: absolute;
    inset-inline: 0;
    bottom: 0;
    opacity: 0;
    display: grid;
    gap: 0.5rem;
    will-change: opacity, transform;
}

html.is-walking .c-walk__station:first-child {
    opacity: 1;
}

html.is-walking .c-walk__n {
    display: flex;
    align-items: baseline;
    gap: 1.1rem;
    font-size: 0.6875rem;
    letter-spacing: 0.26em;
    color: var(--gold-ink);
    font-variant-numeric: tabular-nums;
}

/* The "Generated image" mark, set quieter than the number it sits beside: it
   is a statement about the picture, not part of the caption. */
html.is-walking .c-walk__mark {
    margin-left: 0;
    font-size: 0.5625rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--ink-faint);
}

html.is-walking .c-walk__label {
    font-family: var(--font-display, "Playfair Display", Georgia, serif);
    font-weight: 400;
    font-synthesis-weight: none;
    font-size: clamp(1.9rem, 4.6vw, 3.6rem);
    line-height: 1.06;
    letter-spacing: -0.012em;
    color: var(--ink);
}

html.is-walking .c-walk__note {
    max-width: 34ch;
    font-size: 0.8125rem;
    line-height: 1.6;
    color: var(--ink-muted);
}

/* -- the rule --------------------------------------------------------------
   How far through the house the reader is, as one hairline. It is the only
   progress indicator on the site and it is deliberately not a scrollbar. */

html.is-walking .c-walk__rule {
    display: block;
    position: absolute;
    z-index: 3;
    left: var(--gutter);
    right: var(--gutter);
    bottom: clamp(2rem, 4vh, 3rem);
    height: 1px;
    background-color: var(--hairline);
}

html.is-walking .c-walk__rule i {
    display: block;
    height: 100%;
    width: 100%;
    background-color: var(--gold-ink);
    transform: scaleX(0);
    transform-origin: left center;
}


/* ===========================================================================
   3. The ledger
   ---------------------------------------------------------------------------
   Five rows, and the type does the work: a small tracked label on the left, a
   display value on the right, a hairline under each. It is the title block of
   a drawing sheet rather than a row of cards, which is the difference between
   a house describing itself and a website listing features.
   =========================================================================== */

.c-ledger {
    padding-block: var(--scene);
    background-color: var(--ground);
}

.c-ledger__inner {
    max-width: var(--shell);
    margin-inline: auto;
    padding-inline: var(--gutter);
}

.c-ledger__head {
    margin-bottom: clamp(2.5rem, 5vw, 4.5rem);
}

.c-ledger__index {
    display: block;
    font-size: 0.6875rem;
    letter-spacing: 0.26em;
    text-transform: uppercase;
    color: var(--gold-ink);
    margin-bottom: 0.9rem;
}

.c-ledger__eyebrow {
    margin: 0 0 1.1rem;
    font-size: 0.6875rem;
    letter-spacing: 0.26em;
    text-transform: uppercase;
    color: var(--ink-muted);
}

.c-ledger__title {
    margin: 0;
    max-width: 18ch;
    font-family: var(--font-display, "Playfair Display", Georgia, serif);
    font-weight: 400;
    font-synthesis-weight: none;
    letter-spacing: -0.012em;
    line-height: 1.06;
    text-wrap: balance;
    font-size: clamp(2.1rem, 5.4vw, 4.4rem);
}

.c-ledger__sheet {
    margin: 0;
}

.c-ledger__row {
    position: relative;
    display: grid;
    grid-template-columns: minmax(9rem, 22%) 1fr;
    align-items: baseline;
    gap: clamp(1rem, 4vw, 3rem);
    padding-block: clamp(1.4rem, 3vw, 2.4rem);
}

.c-ledger__label {
    margin: 0;
    font-size: 0.6875rem;
    letter-spacing: 0.26em;
    text-transform: uppercase;
    color: var(--ink-faint);
}

.c-ledger__value {
    margin: 0;
    font-family: var(--font-display, "Playfair Display", Georgia, serif);
    font-weight: 400;
    font-synthesis-weight: none;
    letter-spacing: -0.012em;
    line-height: 1.1;
    color: var(--ink);
    font-size: clamp(1.5rem, 3.4vw, 2.6rem);
}

/*
   The rule is painted here and is full width on the first paint. estate.js
   only ever animates its scaleX, so a reader with no motion layer gets a
   finished sheet rather than five rows with no lines under them.
*/
.c-ledger__rule {
    position: absolute;
    inset-inline: 0;
    bottom: 0;
    height: 1px;
    overflow: hidden;
}

.c-ledger__rule i {
    display: block;
    height: 100%;
    width: 100%;
    background-color: var(--hairline);
    transform-origin: left center;
}

.c-ledger__note {
    margin: clamp(2rem, 4vw, 3rem) 0 0;
    max-width: var(--text);
    font-size: 0.9375rem;
    line-height: 1.75;
    color: var(--ink-muted);
}


/* ===========================================================================
   4. Motion
   ---------------------------------------------------------------------------
   The same rule as home.css §13: an element is hidden only by the script that
   has taken responsibility for showing it, and only once that script is
   running. Under prefers-reduced-motion no library is fetched at all, so
   html.is-walking is never set, the walk stays a gallery, and every rule that
   could hide anything below matches nothing.
   =========================================================================== */

html.is-walking .c-walk__frame,
html.is-walking .c-walk__station {
    will-change: opacity, transform;
}

@media (prefers-reduced-motion: reduce) {
    .c-walk__frame,
    .c-walk__station,
    .c-ledger__row {
        opacity: 1 !important;
        transform: none !important;
    }

    .c-ledger__rule i {
        transform: none !important;
    }

    .c-walk__video {
        display: none !important;
    }
}


/* ===========================================================================
   5. Narrow — the real mobile pass
   ---------------------------------------------------------------------------
   Three decisions rather than a shrink:

   - THE WALK IS SHORTER. Seven screens of sticky scroll is a long time to hold
     a thumb still on a phone, so a station gets two thirds of a screen instead
     of a whole one. The sequence is the same seven rooms at the same order and
     the same cross-fade; only the distance between them changes.
   - THE LEGEND MOVES UP AND LOSES ITS NOTE. At 390px the note is four lines
     over a photograph and the label is what the reader needs; the note is in
     the markup either way and the gallery fallback still prints it.
   - THE LEDGER STACKS. A 9rem label column beside a 2.6rem value at 390px
     leaves eleven characters of measure for the value. Label over value, with
     the rule under the pair.
   =========================================================================== */

@media (max-width: 899px) {

    html.is-walking .c-walk {
        height: calc((var(--stations) + 1) * 68vh);
    }

    html.is-walking .c-walk__legend {
        bottom: clamp(3rem, 9vh, 5rem);
    }

    html.is-walking .c-walk__note {
        display: none;
    }

    .c-ledger__row {
        grid-template-columns: 1fr;
        gap: 0.55rem;
    }

    .c-walk__figcaption {
        flex-wrap: wrap;
        gap: 0.5rem 0.9rem;
    }
}

/*
   The stage is measured in svh above so an address bar sliding away does not
   resize it mid-scroll. Where svh is not understood the vh fallback beside it
   applies and the only cost is that resize.
*/
@supports not (height: 100svh) {
    html.is-walking .c-walk__stage {
        height: 100vh;
    }
}
