/* Public (no-login) front-page styling — home, listings, careers. Loaded
   alongside css/style.css so it can reuse the existing design tokens
   (--ors-*, --rowb-*) without redefining them; internal workspace pages
   never load this file, so nothing here affects them. */

/* "Editorial hospitality" palette — inspired by the restaurants' own event
   marketing (data/campaigns/): warm dark photography, gold and deep-red
   accents, a serif display headline paired with a script accent word. This
   is now the shared identity for the whole app (public pages and internal
   dashboard alike), so the --public-* tokens themselves live in
   css/style.css's :root (loaded before this file on every page, public
   pages included) rather than being redefined here. */

/* Targets body.public-page (set on all 3 public HTML files), not bare
   `body` -- style.css's own body background rules are `body:not(.login-page)`
   at (0,0,1,1) specificity with !important; since !important only moves a
   declaration into a higher-priority tier and doesn't suspend specificity
   *within* that tier, a plain `body {...} !important` (0,0,0,1) still loses
   to it regardless of load order. Matching the specificity with a real
   class is what actually wins the tie-break by source order. */
body.public-page {
    background: var(--public-cream) !important;
    color: var(--public-ink) !important;
}

.public-nav {
    background: var(--public-ink);
}

/* The bar itself (.public-nav) stays full-bleed for the background color,
   but its content lines up with the same 1080px column as the hero and
   every section below it -- without this, brand/links drift out to the
   raw viewport edges on wide screens while everything else stays centered. */
.public-nav__inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    max-width: 1080px;
    margin: 0 auto;
    padding: 16px 24px;
}

.public-nav__brand {
    font-family: var(--public-font-display);
    font-weight: 600;
    font-size: 20px;
    color: var(--public-cream);
    text-decoration: none;
}

.public-nav__links {
    display: flex;
    gap: 12px;
    align-items: center;
    flex-wrap: wrap;
}

/* !important required: style.css's own .btn-secondary/.btn-tertiary set
   color with !important (same pattern as .btn-primary below), so without
   it these were rendering in --public-ink -- nearly invisible against the
   nav's own --public-ink background. */
.public-nav .btn-secondary,
.public-nav .btn-tertiary {
    color: var(--public-cream) !important;
}

.public-nav .btn-secondary:hover,
.public-nav .btn-tertiary:hover {
    color: var(--public-gold) !important;
}

/* Scales with viewport height (not a guessed pixel banner height), while
   staying full-bleed width -- deliberately plain `height`, not
   `aspect-ratio`: aspect-ratio combined with max-height on a full-width
   box makes the browser shrink the *width* to preserve the ratio once
   height gets capped (correct per spec, but not what a full-bleed photo
   band wants -- it left a bare strip down the right side on wide screens
   instead of the photo reaching the edge). background-size:cover on the
   photo layer doesn't care what ratio the box ends up at. */
.public-hero {
    position: relative;
    overflow: hidden;
    height: clamp(340px, 44vh, 620px);
    display: flex;
    align-items: center;
}

.public-hero__inner {
    position: relative;
    z-index: 2;
    width: 100%;
    max-width: 1080px;
    margin: 0 auto;
    padding: 32px 34px;
}

.public-hero__copy {
    display: flex;
    flex-direction: column;
    gap: 16px;
    max-width: 580px;
    /* Entrance animation -- a small, one-time lift-and-fade on load gives
       the hero a moment of motion instead of appearing as a static, inert
       banner the instant the page paints. */
    animation: public-hero-rise 0.7s cubic-bezier(0.16, 1, 0.3, 1) both;
}

@keyframes public-hero-rise {
    from {
        opacity: 0;
        transform: translateY(14px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.public-hero__eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    align-self: flex-start;
    margin: 0;
    padding: 7px 16px;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--public-gold);
    background: rgba(20, 11, 6, 0.55);
    border: 1px solid rgba(201, 151, 63, 0.55);
    border-radius: 999px;
    backdrop-filter: blur(4px);
}

.public-hero__eyebrow::before {
    content: '';
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--public-gold);
    box-shadow: 0 0 8px 1px rgba(201, 151, 63, 0.8);
}

.public-hero h1 {
    font-family: var(--public-font-display);
    font-weight: 600;
    font-size: clamp(32px, 4.4vw, 54px);
    line-height: 1.1;
    letter-spacing: -0.01em;
    margin: 0;
    color: #fff;
    max-width: 18ch;
    /* Insurance against the scrim below not being dark enough under a
       particular photo -- some curated photos are much brighter than
       others, and a soft shadow keeps white text readable over any of
       them without having to hand-tune the scrim per photo. */
    text-shadow: 0 4px 24px rgba(0, 0, 0, 0.6);
}

.public-hero__accent {
    font-family: var(--public-font-script);
    font-weight: 600;
    font-size: 1.2em;
    color: var(--public-gold);
}

.public-hero__copy p {
    max-width: 46ch;
    margin: 0;
    color: rgba(255, 255, 255, 0.92);
    font-size: 17px;
    line-height: 1.6;
    text-shadow: 0 1px 10px rgba(0, 0, 0, 0.5);
}

.public-hero__actions {
    display: flex;
    gap: 12px;
    flex-wrap: wrap;
    margin-top: 10px;
}

.public-hero__actions .btn-primary {
    padding: 13px 26px;
    font-weight: 700;
    letter-spacing: 0.02em;
    box-shadow: 0 10px 26px rgba(0, 0, 0, 0.35);
    transition: transform 0.18s ease, box-shadow 0.18s ease;
}

.public-hero__actions .btn-primary:hover {
    transform: translateY(-2px);
    box-shadow: 0 14px 30px rgba(0, 0, 0, 0.4);
}

/* Fills the hero as a photographic background layer -- absolutely
   positioned against .public-hero itself (which carries the explicit
   min-height above) rather than sized by grid/content, so it can never be
   stretched or squashed by how tall the copy column happens to render. */
.public-hero__media {
    position: absolute;
    inset: 0;
    z-index: 0;
    background: var(--public-ink);
}

/* Two stacked layers cross-fade between the current restaurant's curated
   photos (js/home.js + js/restaurant_hero_media.js) — background-image
   rather than <img src> swaps so the transition never flashes/reflows. */
.public-hero__media-layer {
    position: absolute;
    inset: 0;
    background-size: cover;
    /* Biased toward the top rather than dead-center: the hero band is much
       wider than it is tall, so `cover` crops a lot of vertical height off
       a curated photo, and center-cropping was cutting into logos/plating
       detail that sits near the top of the frame in these photos. */
    background-position: center 22%;
    opacity: 0;
    transition: opacity 1.1s ease;
}

.public-hero__media-layer.is-active {
    opacity: 1;
}

.public-hero__scrim {
    position: absolute;
    inset: 0;
    z-index: 1;
    background: var(--public-scrim);
    pointer-events: none;
}

/* On narrow screens the photo is mostly hidden behind the copy anyway, so
   this stays a small bottom-right tag. On desktop, where the copy column
   only fills the left half of the hero and the photo's right side would
   otherwise be bare, this becomes a proper right-anchored info card --
   the same move the campaign flyers make with their white date/time box
   sitting on top of the photo, not just a caption tucked in a corner. */
.public-hero__media-caption {
    position: absolute;
    right: 24px;
    bottom: 20px;
    z-index: 2;
    text-align: right;
    color: #fff;
    padding: 10px 18px;
    background: rgba(20, 11, 6, 0.5);
    border: 1px solid rgba(201, 151, 63, 0.4);
    border-radius: 12px;
    backdrop-filter: blur(4px);
}

.public-hero__media-caption-eyebrow {
    margin: 0 0 2px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--public-gold);
}

.public-hero__media-caption-name {
    margin: 0;
    font-family: var(--public-font-display);
    font-size: 18px;
    font-weight: 600;
    line-height: 1.25;
    /* max-width in vw (not %) is deliberate: this caption sits inside a
       hero column that can end up wider than the true viewport on some
       layouts (a sibling section forcing horizontal overflow), so a
       percentage-based max-width would inherit that oversized containing
       block and never actually wrap. vw always reflects the real viewport. */
    max-width: 60vw;
    white-space: normal;
    word-break: break-word;
    overflow-wrap: break-word;
}

@media (min-width: 721px) {
    .public-hero__media-caption {
        right: 48px;
        bottom: auto;
        top: 50%;
        transform: translateY(-50%);
        text-align: left;
        min-width: 200px;
        max-width: 260px;
        padding: 22px 26px;
        border-radius: 14px;
        border-top: 3px solid var(--public-gold);
    }

    .public-hero__media-caption-eyebrow {
        font-size: 12px;
    }

    .public-hero__media-caption-name {
        font-size: 22px;
        max-width: none;
    }
}

.public-hero__media-dots {
    position: absolute;
    top: 20px;
    right: 24px;
    z-index: 2;
    display: flex;
    gap: 6px;
}

.public-hero__media-dots span {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.45);
    transition: background 0.3s ease, transform 0.3s ease;
}

.public-hero__media-dots span.is-active {
    background: var(--public-gold);
    transform: scale(1.2);
}

@media (max-width: 720px) {
    /* Override style.css's global @media(720px) ".btn { width: 100% }" —
       nav-level actions should stay compact and sit side by side, not
       stack into a tall column of full-width buttons above the hero. */
    .public-nav__links .btn {
        width: auto;
        flex: 0 1 auto;
    }

    .public-hero {
        height: clamp(300px, 50vh, 460px);
    }

    .public-hero__inner {
        padding: 28px 20px;
    }

    /* Hidden rather than shrunk further: the copy stack (eyebrow, 3-line
       headline, paragraph, button) already nearly fills the mobile hero's
       height, so a bottom-corner caption card collides with the button
       instead of sitting cleanly below it. It's a decorative bonus, not
       load-bearing content -- the restaurant name is already on the page
       via the "Featured Events"/"Latest" cards below. */
    .public-hero__media-caption {
        display: none;
    }

    .public-hero h1 {
        max-width: none;
    }
}

.public-page-header {
    background: linear-gradient(120deg, var(--public-ink) 0%, #3a2c22 100%);
    padding: 40px 24px 36px;
}

.public-page-header__inner {
    max-width: 1080px;
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.public-page-header h1 {
    font-family: var(--public-font-display);
    font-weight: 600;
    font-size: clamp(26px, 3.2vw, 36px);
    line-height: 1.15;
    margin: 0;
    color: #fff;
}

.public-page-header p {
    max-width: 62ch;
    margin: 0;
    color: rgba(255, 255, 255, 0.75);
    font-size: 15px;
    line-height: 1.6;
}

.public-section {
    max-width: 1080px;
    margin: 0 auto;
    padding: 40px 24px;
}

.public-section h2 {
    position: relative;
    font-family: var(--public-font-display);
    font-weight: 600;
    font-size: 26px;
    margin: 0 0 16px;
    padding-bottom: 12px;
    color: var(--public-ink);
}

.public-section h2::after {
    content: '';
    position: absolute;
    left: 0;
    bottom: 0;
    width: 46px;
    height: 3px;
    border-radius: 999px;
    background: var(--public-gold);
}

.public-section__intro {
    color: var(--public-ink-soft);
    margin: 0 0 24px;
    max-width: 720px;
}

.public-listing-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 20px;
}

.public-listing-card {
    background: #fff;
    border: 1px solid var(--public-border);
    border-radius: 12px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    box-shadow: var(--public-shadow);
}

.public-listing-card__image {
    width: 100%;
    aspect-ratio: 16 / 9;
    /* contain, not cover: the uploaded poster can be any aspect ratio (no
       upload-time resize/validation), so cropping to fill a fixed 16:9 box
       was cutting off part of the image. contain letterboxes against the
       background below instead, so the full poster is always visible,
       across Featured, Latest, and the full Listings page (they all share
       this one class). */
    object-fit: contain;
    background: var(--public-cream-soft);
    cursor: zoom-in;
}

.public-listing-card__body {
    padding: 16px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    flex: 1;
}

.public-listing-card__kind {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--public-gold-dark);
    font-weight: 700;
}

.public-listing-card__title {
    font-family: var(--public-font-display);
    font-size: 19px;
    font-weight: 600;
    color: var(--public-ink);
    margin: 0;
}

.public-listing-card__meta {
    font-size: 13px;
    color: var(--public-ink-soft);
}

.public-listing-card__body-text {
    font-size: 14px;
    line-height: 1.55;
    color: var(--public-ink-soft);
    flex: 1;
}

.public-listing-card__link {
    align-self: flex-start;
    color: var(--public-red);
    font-weight: 600;
    text-decoration: none;
    font-size: 14px;
}

.public-events-carousel {
    position: relative;
    display: flex;
    align-items: center;
    gap: 8px;
}

.public-events-carousel__track {
    display: flex;
    gap: 20px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    padding-bottom: 8px;
    -webkit-overflow-scrolling: touch;
    flex: 1 1 auto;
    min-width: 0;
}

.public-events-carousel__nav {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    border: 1px solid var(--public-border);
    background: #fff;
    color: var(--public-ink);
    font-size: 20px;
    line-height: 1;
    cursor: pointer;
}

.public-events-carousel__nav:hover {
    background: var(--public-gold);
    color: var(--public-ink);
    border-color: var(--public-gold);
}

.public-events-carousel__track .public-listing-card {
    flex: 0 0 auto;
    /* Smaller than Latest/Listings cards (which size via .public-listing-grid's
       minmax(280px, 1fr)) now that the carousel lives in the narrower hero
       copy column instead of a full-width section. */
    width: 240px;
    scroll-snap-align: start;
}

.public-listing-card__badge {
    align-self: flex-start;
    background: var(--public-red);
    color: #fff;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    padding: 3px 10px;
    border-radius: 999px;
}

.public-filter-bar {
    display: flex;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 24px;
}

.public-filter-bar select {
    min-width: 200px;
}

/* Full-size image lightbox — Featured/Latest/All Listings poster images are
   scaled down to fit the card grid (see .public-listing-card__image above),
   which makes the poster text unreadable. Clicking one opens it here at
   full size instead of navigating away. */
.public-image-lightbox-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1700;
    display: grid;
    place-items: center;
    padding: var(--sp-5, 24px);
    background: rgba(20, 14, 10, 0.82);
    animation: rowb-fade-in 140ms ease;
}

.public-image-lightbox {
    position: relative;
    max-width: min(1100px, 96vw);
    max-height: 92vh;
}

.public-image-lightbox img {
    display: block;
    max-width: min(1100px, 96vw);
    max-height: 92vh;
    width: auto;
    height: auto;
    border-radius: 8px;
    box-shadow: 0 20px 48px rgba(0, 0, 0, 0.4);
}

.public-image-lightbox__close {
    position: absolute;
    top: -18px;
    right: -18px;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    border: 1px solid var(--public-border);
    background: #fff;
    color: var(--public-ink);
    font-size: 20px;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

.public-image-lightbox__close:hover {
    background: var(--public-gold);
    color: var(--public-ink);
    border-color: var(--public-gold);
}

.public-form {
    max-width: 640px;
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.public-form label {
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-size: 14px;
    color: var(--public-ink);
}

.public-form input,
.public-form select,
.public-form textarea {
    padding: 10px 12px;
    border: 1px solid var(--public-border);
    border-radius: 6px;
    font: inherit;
}

.public-form__honeypot {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

.public-captcha {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}

.public-captcha img {
    border: 1px solid var(--public-border);
    border-radius: 4px;
}

#login-modal {
    position: relative;
}

.rowb-modal__close {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 32px;
    height: 32px;
    border: 1px solid var(--public-border);
    border-radius: 6px;
    background: #fff;
    color: var(--public-ink-soft);
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
}

.rowb-modal__close:hover {
    color: var(--public-ink);
    border-color: var(--public-ink-soft);
}

/* Public pages get their own warm gold/espresso button treatment instead
   of the internal dashboard's steel-blue -- scoped to this file only,
   which internal workspace pages never load, so .btn-primary/.btn-secondary
   there are untouched. style.css's own .btn-primary/.btn-secondary rules
   set background/border/color with !important (guarding those buttons
   against inline styles elsewhere in the dashboard), so matching that here
   is required, not optional -- a plain override of equal specificity can
   never beat an !important rule regardless of load order. */
/* The second branch mirrors style.css's own selector exactly (not just
   `.btn-primary`) -- that rule's `form button[type="submit"]:not(...):not(...)`
   branch has far higher specificity than a plain class, so it was still
   winning for the login modal's Sign In button (a <button type="submit">
   inside a <form>) even with !important on both sides. Matching the same
   selector text is what lets source order (this file loads after
   style.css) actually decide the tie. */
.btn-primary,
form button[type="submit"]:not(.btn-secondary):not(.btn-danger) {
    background: var(--public-gold) !important;
    border-color: var(--public-gold) !important;
    color: var(--public-ink) !important;
}

.btn-primary:hover,
form button[type="submit"]:not(.btn-secondary):not(.btn-danger):hover {
    background: var(--public-gold-dark) !important;
    border-color: var(--public-gold-dark) !important;
    color: var(--public-ink) !important;
}

.btn-secondary {
    background: transparent !important;
    border-color: var(--public-border) !important;
    color: var(--public-ink) !important;
}

.btn-secondary:hover {
    border-color: var(--public-gold) !important;
    color: var(--public-gold-dark) !important;
}

/* !important required: style.css sets .app-footer's dark-navy background
   with !important (same pattern as body/.btn-* above). */
.app-footer {
    background: var(--public-cream-soft) !important;
    border-top: 1px solid var(--public-border) !important;
}

.app-footer__copy,
.app-footer__links a {
    color: var(--public-ink-soft) !important;
}

.app-footer__links a:hover {
    color: var(--public-gold-dark) !important;
}
