/* ============================================================================
   Page structure for the Lion's Bites site, on top of design-system.css.
   Only layout that the design system does not ship lives here; every colour,
   space and size comes from a --lb-* token.
   ========================================================================== */

.skip-link {
    position: absolute;
    left: var(--lb-space-4);
    top: -56px;
    z-index: 100;
    background: var(--lb-gold);
    color: var(--lb-gold-ink);
    padding: 10px 16px;
    border-radius: 0 0 var(--lb-r-md) var(--lb-r-md);
    text-decoration: none;
    transition: top var(--lb-ease);
}

.skip-link:focus {
    top: 0;
}

/* --- sticky bar around the design-system header --- */
.site-topbar {
    position: sticky;
    top: 0;
    z-index: 50;
    background: rgba(10, 20, 16, .86);
    backdrop-filter: saturate(150%) blur(10px);
    border-bottom: 1px solid var(--lb-ink-600);
}

/* On a page with a cover hero the bar leaves the flow so the photograph starts at the
   very top of the page and runs behind it.

   No bar is drawn over the photograph. A tinted rectangle, frosted or not, puts a straight
   horizontal edge across the picture at the point where it is most obviously a photograph,
   and that edge is what reads as heavy, not the darkness itself. Instead the veil below is
   a gradient that reaches past the bar and dissolves, so the top of the frame simply gets
   darker the way a photograph's own vignette would. */
.site-topbar--cover {
    position: fixed;
    inset-inline: 0;
    background-color: transparent;
    backdrop-filter: none;
    border-bottom-color: transparent;
}

/* The veil. It hangs 5rem below the bar, holds its tint across the height the navigation
   actually occupies, and then spends the whole overhang fading to nothing, so there is no
   edge anywhere.

   The numbers are measured, not chosen. Behind this bar the photograph has a bright
   coastline and a sky, and the darkest thing on the strip is what sets the ratio. Sampling
   the whole strip at the height of the links, through the hero scrim that already sits
   between the photograph and this veil, champagne text clears 4.5:1 on every pixel from a
   veil of about 0.56 upward; the stops below put 0.57 at that line. Gold does not clear it
   at any tint worth having: it would need an opaque bar, because gold sits mid-luminance
   and darkening what is behind it walks the background towards the text rather than away
   from it. Hence the rule underneath.

   No backdrop-filter here on purpose. Frosting reads as a slab of glass laid over the
   picture, which is the thing this replaces, and it buys nothing measurable: the sky
   behind the bar is large and evenly bright, so blurring it moves the brightest five
   percent from 241 to 243. The tint does all of the work; the blur only came back once
   the bar has left the photograph. */
.site-topbar--cover::before {
    content: "";
    position: absolute;
    inset: 0 0 -5rem;
    z-index: -1;
    pointer-events: none;
    background: linear-gradient(to bottom,
        rgba(10, 20, 16, .60) 0,
        rgba(10, 20, 16, .54) 48%,
        rgba(10, 20, 16, .26) 76%,
        rgba(10, 20, 16, 0) 100%);
}

/* Gold cannot be made legible on this photograph, so over the cover the current page is
   marked in the same champagne as the rest and its underline carries the state. Colour
   alone should not carry meaning anyway, so this is the better pattern rather than a
   concession, and an underline that matches the text is a 4.8:1 mark instead of a 2.2:1
   one. */
.site-topbar--cover .lb-nav a[aria-current="page"] {
    color: var(--lb-champagne);
    border-bottom-color: var(--lb-champagne);
}

/* Everything else in the bar that is gold or faint has the same problem for the same
   reason, so over the cover it steps up to a light neutral: the tagline, both language
   links, and the hover state of a nav link. The pill outline and the underline keep
   carrying which one is current, so nothing is lost but the colour. */
.site-topbar--cover .lb-logo__tagline,
.site-topbar--cover .lb-lang a[aria-current="true"],
.site-topbar--cover .lb-nav a:hover {
    color: var(--lb-cream);
}

.site-topbar--cover .lb-nav a:hover {
    border-bottom-color: var(--lb-cream);
}

.site-topbar--cover .lb-lang a {
    color: var(--lb-champagne);
}

.site-topbar--cover .lb-lang a[aria-current="true"] {
    border-color: rgba(236, 227, 209, .45);
}

/* An open mobile menu is a panel, not a moment of veil. It pushes the bar down to some
   500px, which is far past the point where the gradient has thinned out, and measured
   against the photograph the links in the middle of it were sitting under 4:1. So for as
   long as it is open the bar takes a ground of its own.
   A second layer rather than a background on the bar itself: the bar's own
   background-color is driven by the scroll animation above, and an animation outranks a
   normal declaration, so setting it here would simply be ignored. */
.site-topbar--cover:has(.lb-nav-toggle:checked)::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background: rgba(10, 20, 16, .9);
}

/* Off the photograph the bar closes to the normal solid one: the veil fades out and the
   bar itself fades in underneath it. Preferred path: the scroll position drives both
   directly, so there is no listener and no frame showing a stale state.
   The backdrop-filter starts at blur(0px) rather than none, because none is not a filter
   list and will not interpolate. */
@supports (animation-timeline: scroll()) {
    /* Longhands: the shorthand would set a 0s duration, and a scroll-driven animation
       needs `auto` to stretch across animation-range. */
    .site-topbar--cover {
        animation-name: topbar-fill;
        animation-duration: auto;
        animation-timing-function: linear;
        animation-fill-mode: both;
        animation-timeline: scroll(root block);
        animation-range: 0 40vh;
    }

    .site-topbar--cover::before {
        animation-name: topbar-veil-out;
        animation-duration: auto;
        animation-timing-function: linear;
        animation-fill-mode: both;
        animation-timeline: scroll(root block);
        animation-range: 0 40vh;
    }

    @keyframes topbar-fill {
        from {
            background-color: rgba(10, 20, 16, 0);
            backdrop-filter: saturate(100%) blur(0px);
            border-bottom-color: transparent;
        }

        to {
            background-color: rgba(10, 20, 16, .92);
            backdrop-filter: saturate(150%) blur(10px);
            border-bottom-color: var(--lb-ink-600);
        }
    }

    @keyframes topbar-veil-out {
        from {
            opacity: 1;
        }

        to {
            opacity: 0;
        }
    }
}

/* Fallback for browsers without scroll-driven animation, switched on by site.js. The
   veil above is already the safe state, so nothing here is needed for legibility; this
   only closes the bar once the photograph is out of the way. */
.site-topbar--cover.site-topbar--js,
.site-topbar--cover.site-topbar--js::before {
    transition: background-color var(--lb-ease), border-bottom-color var(--lb-ease), backdrop-filter var(--lb-ease), opacity var(--lb-ease);
}

.site-topbar--cover.site-topbar--js.site-topbar--filled {
    background-color: rgba(10, 20, 16, .92);
    backdrop-filter: saturate(150%) blur(10px);
    border-bottom-color: var(--lb-ink-600);
}

.site-topbar--cover.site-topbar--js.site-topbar--filled::before {
    opacity: 0;
}

/* --- breadcrumb --- */
.breadcrumb {
    padding-top: var(--lb-space-6);
    font-size: var(--lb-fs-xs);
    letter-spacing: var(--lb-tracking-wide);
    color: var(--lb-faint);
}

.breadcrumb ol {
    display: flex;
    flex-wrap: wrap;
    gap: var(--lb-space-2);
    list-style: none;
    margin: 0;
    padding: 0;
}

.breadcrumb a {
    color: var(--lb-faint);
    text-decoration: none;
}

.breadcrumb a:hover {
    color: var(--lb-gold-bright);
}

.breadcrumb li + li::before {
    content: "/";
    margin-right: var(--lb-space-2);
    color: var(--lb-ink-500);
}

/* --- page head for the inner pages --- */
.page-head {
    padding-block: var(--lb-space-7) var(--lb-space-6);
}

.page-head__inner {
    display: grid;
    grid-template-columns: 1.1fr .9fr;
    gap: var(--lb-space-7);
    align-items: center;
}

/* --- framed photograph: gold hairline just inside the edge --- */
.photo {
    position: relative;
    display: block;
    border-radius: var(--lb-r-lg);
    overflow: hidden;
    box-shadow: var(--lb-shadow-lg);
}

.photo img {
    display: block;
    width: 100%;
    height: auto;
}

.photo::after {
    content: "";
    position: absolute;
    inset: 10px;
    border: 1px solid rgba(200, 144, 67, .38);
    border-radius: var(--lb-r-md);
    pointer-events: none;
}

.photo--tall img {
    aspect-ratio: 4 / 5;
    object-fit: cover;
}

.photo--wide img {
    aspect-ratio: 3 / 2;
    object-fit: cover;
}

/* --- cut-out: a silhouette, not a framed photograph --- */
/* Must come after --tall and --wide, which set the crop this variant undoes.
   For a transparent PNG the box, the gold hairline and the aspect-ratio crop all
   have to go, because they would draw a rectangle around a shape that is meant to
   float on the page. drop-shadow follows the alpha instead of the element box, so
   the object still lifts off the background without a visible edge. */
.photo--cutout {
    border-radius: 0;
    overflow: visible;
    box-shadow: none;
}

.photo--cutout::after {
    content: none;
}

/* Sized by height, not width. A bottle is roughly 1:3, so letting it fill the
   column would make it tower over the copy beside it. */
.photo--cutout img {
    aspect-ratio: auto;
    width: auto;
    max-width: 100%;
    max-height: var(--lb-cutout-h, 20rem);
    margin-inline: auto;
    object-fit: contain;
    filter: drop-shadow(0 18px 34px rgba(0, 0, 0, .55));
}

/* Fixed height rungs, the same idea as the lb-ill-* illustration steps: three
   choices instead of a per-page number, so two cut-outs on different pages stay
   comparable in size. Default is the smallest, --lg is for a page head. */
.photo--cutout-md {
    --lb-cutout-h: 27rem;
}

.photo--cutout-lg {
    --lb-cutout-h: 34rem;
}

/* A dark subject on a dark page needs the opposite of a drop shadow. The olive-oil
   bottle is bottle-green glass on pine green: measured against the page colour, its
   neck and the bare glass below the label sit at or under the background's own
   luminance, so it reads as a hole instead of an object. The gold halo follows the
   alpha, not the element box, so it hugs the silhouette rather than smudging a
   rectangle behind it. Opt-in: the limoncello bottle is bright and needs none. */
.photo--cutout-lift img {
    filter:
        drop-shadow(0 0 14px rgba(var(--lb-gold-rgb), .3))
        drop-shadow(0 18px 30px rgba(0, 0, 0, .5));
}

.photo__caption {
    margin: var(--lb-space-3) 0 0;
    font-family: var(--lb-font-voice);
    font-style: italic;
    font-size: var(--lb-fs-sm);
    color: var(--lb-faint);
    text-align: center;
}

/* --- story pages --- */
.story__body {
    display: grid;
    grid-template-columns: 1.15fr .85fr;
    gap: var(--lb-space-8);
    align-items: start;
}

.story__aside {
    position: sticky;
    top: 104px;
    display: grid;
    gap: var(--lb-space-5);
    justify-items: center;
}

/* --- menu (breads and dips) --- */
.menu-item {
    display: grid;
    gap: var(--lb-space-2);
    padding-block: var(--lb-space-4);
    border-bottom: 1px solid var(--lb-ink-600);
}

.menu-item:last-child {
    border-bottom: 0;
}

.menu-item__head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--lb-space-3);
}

.menu-item__name {
    font-family: var(--lb-font-display);
    font-size: var(--lb-fs-md);
    color: var(--lb-champagne);
    letter-spacing: 0.03em;
}

.menu-item__price {
    margin-left: auto;
    color: var(--lb-gold-bright);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.menu-item p {
    margin: 0;
    color: var(--lb-muted);
}

/* --- order form --- */
.order-form {
    max-width: 720px;
}

.form-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--lb-space-5);
}

.form-row > .lb-field {
    margin-bottom: 0;
}

.form-row + .form-row,
.form-row + .lb-field,
.lb-field + .form-row {
    margin-top: var(--lb-space-5);
}

.choice-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
    gap: var(--lb-space-2) var(--lb-space-5);
}

/* --- contact --- */
.contact-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: var(--lb-space-4);
}

.contact-list dt {
    font-family: var(--lb-font-display);
    font-size: var(--lb-fs-xs);
    letter-spacing: var(--lb-tracking-caps);
    text-transform: uppercase;
    color: var(--lb-gold);
    margin-bottom: var(--lb-space-1);
}

.contact-list dd {
    margin: 0;
    color: var(--lb-champagne);
}

/* --- the village band closing a story page --- */
.band {
    display: grid;
    place-items: center;
    padding-block: var(--lb-space-7);
    opacity: .5;
}

/* --- error page --- */
.error-page {
    text-align: center;
    padding-block: var(--lb-space-10);
}

@media (max-width: 900px) {
    .page-head__inner,
    .story__body {
        grid-template-columns: 1fr;
    }

    .page-head__inner .photo {
        max-width: 460px;
    }

    .story__aside {
        position: static;
        max-width: 420px;
    }

    .form-row {
        grid-template-columns: 1fr;
    }
}
