/* Ambrosia DC — white ground.
   Loaded last so it wins over the theme without editing the theme's own stylesheets.

   Deliberately surgical: an earlier version forced the header and footer white too,
   which punched a white block through the transparent header sitting over the hero
   image. The header is left to the theme; only page surfaces are repainted.

   CONTRAST PASS (QA): the theme was built for a dark ground, so a lot of its type is
   white. On the white ground that type vanished. The rules below are section-aware —
   text on the light ground is forced dark, and the handful of bands the theme keeps
   dark (the hero, the reservation and testimonial bands, the footer) keep light text.
   The home page is Elementor-built and, unlike the interior pages, is NOT wrapped in
   .qodef-content-page — it uses .qodef-page-content-section. The old rules keyed only
   off .qodef-content-page, so none of them reached the home page; every scope below
   now covers both. */
:root{
  --ambrosia-white:#ffffff;
  --ambrosia-gold:#b58a3a;
  --ambrosia-gold-lite:#c9a24b;   /* gold for the dark bands */
  --ambrosia-gold-deep:#8a6a1e;   /* deeper gold that clears AA on the white ground */
  --ambrosia-forest:#193d31;
  --ambrosia-ink:#33352f;
  --ambrosia-cream:#f4ecdd;      /* light type for the dark bands */
}
html, body,
.qodef-page-wrapper, .qodef-page-outer, .qodef-page-inner,
.qodef-content-page, .qodef-content-inner, .qodef-page-content-section{
  background-color:var(--ambrosia-white) !important;
}

/* =========================================================================
   0. EDGE TO EDGE — the page fills the screen

   Elementor gives every container a default inline padding of 20px, carried on
   --padding-inline-start/end. On the outermost container of a page that is not
   spacing, it is a 20px gutter down both sides of the whole site: the hero
   video ran 20..1885 on a 1905px viewport while the header bar ran the full
   width, and the mismatch is what made the site look like it was not filling
   the screen.

   The variable is overridden rather than the padding property, and only on
   top-level containers, because that is precisely the default and nothing else.
   Containers that ask for real padding write the `padding` shorthand under their
   own id — Gallery's 80px band, Contact's 50px, Book A Table's 245px indent —
   and those win over this and keep what they were given. Verified by measuring
   every top-level container on all seven pages before and after.
   ========================================================================= */
.e-con.e-parent{
  --padding-inline-start:0px;
  --padding-inline-end:0px;
}
/* content bands the demo paints near-black, lifted onto the white ground */
.qodef-content-page .elementor-section:not(.qodef-title):not([class*="qodef-hero"]),
.qodef-content-page .elementor-container{
  background-color:transparent !important;
}

/* =========================================================================
   1. TEXT ON THE LIGHT GROUND — must read dark
   ========================================================================= */
body, p, li, .qodef-e-description, .qodef-e-text{ color:var(--ambrosia-ink) !important; }

/* Headings, titles and the theme's decorative labels. The trailing :not() chain must
   hug the :is() with no whitespace, or the space reads as a descendant combinator and
   the rule ends up targeting children of headings instead of the headings themselves.
   The exclusions keep this light-ground rule off every dark surface, so §2 governs
   those uncontested (no specificity tug-of-war). The excluded surfaces are the
   page-title band (§4), the interactive showcase (labels on a dark hover overlay) and
   every dark content band / the footer (§2 — same list). */
:is(.qodef-content-page, .qodef-page-content-section)
  :is(h1,h2,h3,h4,h5,h6,.qodef-m-title,.qodef-m-title-text,.qodef-e-title,.qodef-e-subtitle):not(.qodef-title *):not(.qodef-page-title *):not(.qodef-interactive-link-showcase *):not(.elementor-element-04fd0aa *):not(.elementor-element-02b3b39 *):not(.elementor-element-67021e7 *):not(.elementor-element-2aa05c4 *):not(.elementor-element-6e83b5d *):not(.elementor-element-c61b4ed *):not(.elementor-element-bf639ef *):not(footer *):not(.qodef--has-appear *):not(.am-book-plate *){
  color:var(--ambrosia-forest) !important;
}

/* Outline buttons: the theme gives them a gold border and white label, which leaves
   only the border visible on white. Repaint the label dark on the light ground. */
:is(.qodef-content-page, .qodef-page-content-section)
  .qodef-button:not(.elementor-element-04fd0aa *):not(.elementor-element-bf639ef *) .qodef-m-text{
  color:var(--ambrosia-forest) !important;
}

/* ...and put it back to cream the moment the button fills.
   "rê chuột vào bị tối" — hovering it goes dark. The theme's outlined button
   fills forest green on hover and switches its own colour to cream to suit; the
   rule above then held the *inner span* — which is what actually carries the
   word — at forest, with `important`, in both states. Forest on forest:

       button  rest rgb(25,61,49)   hover rgb(244,236,221)   <- changes
       span    rest rgb(25,61,49)   hover rgb(25,61,49)      <- did not

   The word never left the button; it was painted in the fill colour, which is
   why the control looked like an empty green box. Contact Us's Submit was the
   one that showed it, but the rule is site-wide, so this is too.

   `inherit` rather than a literal, so the span follows whatever the button's own
   state has decided — including the focus ring a keyboard user gets, which the
   theme styles the same way and which a hard-coded cream would break on any
   button whose hover fill is light. */
:is(.qodef-content-page, .qodef-page-content-section)
  .qodef-button:not(.elementor-element-04fd0aa *):hover .qodef-m-text,
:is(.qodef-content-page, .qodef-page-content-section)
  .qodef-button:not(.elementor-element-04fd0aa *):focus-visible .qodef-m-text{
  color:inherit !important;
}

/* ...except that `inherit` is only safe on a button that actually fills, and the
   outlined ones do not.

   Reported as "các button khi hover vào thì gặp vấn đề, không có màu sắc" — hovering a
   button and getting no colour. Measured on the white ground, hovered:

       READ MORE     ink rgb(255,255,255)  ground rgb(255,255,255)   1.00:1
       ENTIRE MENU   ink rgb(255,255,255)  ground rgb(255,255,255)   1.00:1

   White on white. The word does not dim on hover, it *leaves*.

   The premise of the rule above is wrong, and it is worth writing down because the
   comment on it asserts the opposite. The theme's outlined button does not fill forest
   on hover. It does not fill at all:

       .qodef-button.qodef-layout--outlined:hover{
         color:#fff; background-color:transparent }

   Its whole hover affordance is the `:after` pseudo-element, a hairline border that
   draws itself in from two corners (`background-size:0 1px` -> `100% 1px`). The colour
   going to `#fff` is not part of that gesture — it is there because the Fidalgo demo is
   a dark site, where white is simply what type is. Port the same CSS onto a white page
   and `#fff` is the one colour the label must not be, and `inherit` copies it faithfully.

   So outlined buttons are given the fill the rule above already assumed they had. That
   keeps the label's cream reading, keeps the drawn border, and makes the hover state
   read as a state rather than as a disappearance. The filled layouts still take
   `inherit` from the rule above, which is correct for them — they really do change
   ground underneath their own label.

   This also settles the footer's BOOK A TABLE, which was hovering to
   rgb(201,162,75) on white — 2.40:1, under AA at any size. It is inside a
   `.qodef--has-appear` widget, and §2 hands anything under that class the gold meant
   for the dark bands. `.qodef--has-appear` is an animation hook, not a ground; the
   buttons opt out of it here rather than the whole rule being loosened, because plenty
   of appear-animated widgets genuinely are dark. */
:is(.qodef-content-page, .qodef-page-content-section)
  .qodef-button.qodef-layout--outlined:not(.elementor-element-04fd0aa *):hover,
:is(.qodef-content-page, .qodef-page-content-section)
  .qodef-button.qodef-layout--outlined:not(.elementor-element-04fd0aa *):focus-visible{
  background-color:var(--ambrosia-forest) !important;
  border-color:var(--ambrosia-forest) !important;
  color:var(--ambrosia-cream) !important;
}
/* `.qodef-btn-text` as well as `.qodef-m-text`: the label inside a button is one class
   on a link and a different one inside a form. The reservation form's BOOK NOW is the
   second kind, and it is the case that proves the rule above is not enough on its own —
   filling the button forest while its label kept the ink §2 gives form controls left it
   at rgb(25,61,49) on rgb(25,61,49), 1.00:1. Exactly the bug this section is fixing,
   reintroduced one element to the left. */
:is(.qodef-content-page, .qodef-page-content-section)
  .qodef-button.qodef-layout--outlined:not(.elementor-element-04fd0aa *):hover
  :is(.qodef-m-text, .qodef-btn-text),
:is(.qodef-content-page, .qodef-page-content-section)
  .qodef-button.qodef-layout--outlined:not(.elementor-element-04fd0aa *):focus-visible
  :is(.qodef-m-text, .qodef-btn-text){
  color:var(--ambrosia-cream) !important;
}

/* Event date / time / reservation labels the theme paints near-white (#ced8d8). */
.qodef-e-date, .qodef-e-reservation, .qodef-e-reservation-label, .qodef-e-time{ color:var(--ambrosia-forest) !important; }

.qodef-content-page a, .qodef-page-content-section a{ color:var(--ambrosia-forest); }
.qodef-content-page a:hover, .qodef-page-content-section a:hover{ color:var(--ambrosia-gold); }
/* Prices are the brand accent. On the white ground the theme's gold sits at ~3.1:1, so
   the menu carries a deeper gold that clears AA; §2 restores the lighter gold on dark. */
.qodef-e-price{ color:var(--ambrosia-gold-deep) !important; }

/* Theme components the demo painted for a dark ground — booking form, contact widgets,
   social links, "light-hover" links, form placeholders — go dark on the white ground.
    bows out wherever the contrast guard finds a real dark
   ground (e.g. the same contact widget in the navy footer), where §2 keeps them light. */
.qodef-reservation-form :is(.qodef-btn-text,.qodef-btn,.select2-selection__rendered,.qodef-m-field,.qodef-m-field-book,input,select),
.select2-results__option,
.qodef-social-links-group a,
.qodef-widget-holder .widget_block,
.qodef-widget-holder .widget_block a,
.qodef-widget-holder .widget_block p,
a.qodef--light-hover,
/* ...except inside the book-a-table band, which is a dark band (§23). This rule is
   three classes deep and §2's is two, so without the exclusion it wins on specificity
   and the opening hours alone stayed at --ambrosia-ink while every other line in the
   band went cream — the two lines are a text-editor widget and the rest are not. */
.qodef-page-content-section .elementor-widget-text-editor:not(.elementor-element-bf639ef *),
.qodef-page-content-section .elementor-widget-text-editor:not(.elementor-element-bf639ef *) :is(p,a,span,li){ color:var(--ambrosia-ink) !important; }
:is(.wpcf7-text,.wpcf7-textarea,.wpcf7-form-control){ color:var(--ambrosia-ink) !important; }
:is(.wpcf7-text,.wpcf7-textarea,.wpcf7-form-control)::placeholder{ color:var(--ambrosia-ink) !important; opacity:.65; }

/* Every <option> on the site, everywhere. A native select hands its own colour
   down to the list the browser renders, and this theme's selects are painted for
   whichever ground they sit on — so a cream-on-dark reservation control opened a
   popup of cream text on a cream sheet, and a dark-on-white one did the reverse.
   Neither is visible. Options are given both halves explicitly, once, rather than
   per form: there are three reservation forms on this site and they were drifting
   apart. */
option, optgroup{
  background-color:#fbf9f4 !important;
  color:#1b2c27 !important;
  text-shadow:none !important;
}

/* =========================================================================
   2. THE DARK BANDS — must read light
   Repainted after §1; §1 excludes exactly this scope, so light type wins here with
   no specificity fight. The theme's dark content bands are set per-Elementor-id in
   each page's inline <style> (they carry no shared class), so they are addressed by
   id — a finite, complete set for this frozen static build. The footer green
   (#042726) comes from a theme variable, so the footer is addressed semantically and
   holds on every page:
     .elementor-element-04fd0aa  home — hero (black / background video)
     .elementor-element-02b3b39  home — "Book a table" + private-dining band (#1f3634)
     .elementor-element-67021e7  home — testimonials band (#1f3634)
     .elementor-element-2aa05c4  about-us — "our food philosophy" band (#1f3634)
     .elementor-element-6e83b5d  meet-the-chef — dark band (#1f3634)
     .elementor-element-c61b4ed  gallery-slider — testimonials band (#00061d, navy skin)
     .elementor-element-bf639ef  book-a-table — the address/hours band (see §23)
     footer / .qodef--has-appear footer (#042726 / #00061d), every page
   This static list is the no-JavaScript baseline. It cannot cover everything — a dark
   band on a class-less container, a widget that is navy on one page and white on the
   next, or type over a photograph — so ambrosia-contrast.js measures the real ground
   behind every piece of text at runtime and repairs whatever still fails. Enumerating
   the exceptions here is what kept missing cases; measurement is what catches them. */
:is(.elementor-element-04fd0aa,
    .elementor-element-02b3b39, .elementor-element-67021e7,
    .elementor-element-2aa05c4, .elementor-element-6e83b5d, .elementor-element-c61b4ed,
    .elementor-element-bf639ef,
    footer, .qodef--has-appear)
  :is(h1,h2,h3,h4,h5,h6,p,span,a,li,
      .qodef-m-title,.qodef-m-title-text,.qodef-e-title,.qodef-e-subtitle,
      .qodef-e-text,.qodef-e-description,.qodef-m-text,.qodef-e-inner,.qodef-btn-text,
      .qodef-e-author-name,.qodef-e-author-job,.qodef-e-date,.qodef-e-reservation,.qodef-e-reservation-label){
  color:var(--ambrosia-cream) !important;
}
/* Gold accents stay gold on the dark bands (prices, hovered links). */
:is(.elementor-element-02b3b39,.elementor-element-67021e7,.elementor-element-2aa05c4,.elementor-element-6e83b5d,.elementor-element-c61b4ed,.elementor-element-bf639ef,footer,.qodef--has-appear) .qodef-e-price{ color:var(--ambrosia-gold-lite) !important; }
/* `:not(.am-social-link)`, because the social discs are the one link down here whose
   hover changes its *ground* rather than its ink. They fill gold and put dark ink on it
   (§ "The social row"). This rule is `!important` and that one is not, so the icon was
   being repainted gold at the exact moment its disc became gold:

       .am-social-link:hover   ink rgb(201,162,75)  ground rgb(201,162,75)   1.00:1

   — a plain gold coin with nothing on it, on every page, which is what the review's
   screenshot of the footer shows. The icons are single-colour SVG paths on
   `fill:currentColor`, so `color` is the whole of their appearance and there was
   nothing left to see. */
:is(.elementor-element-02b3b39,.elementor-element-67021e7,.elementor-element-2aa05c4,.elementor-element-6e83b5d,.elementor-element-c61b4ed,.elementor-element-bf639ef,footer,.qodef--has-appear) a:hover:not(.am-social-link){ color:var(--ambrosia-gold-lite) !important; }

/* Two things the runtime guard cannot measure, because they are never on screen when it
   looks: a slider's parked duplicate slides, and drop-down panels that only exist on
   hover. Both have a stable structure, so they are pinned here.
   The testimonial type rides over whichever photograph the slide is showing, so it takes
   a shadow rather than a colour — that reads on a bright frame and a dark one alike. */
.qodef-e-static-title, .qodef-e-author-name, .qodef-e-author-job,
.qodef-testimonials-list .qodef-e-text{
  text-shadow:0 1px 12px rgba(0,0,0,.62), 0 1px 3px rgba(0,0,0,.5);
}
/* The top bar rides over the page-title photograph on every interior page, so its
   contact line, hours and social links keep light type with a shadow to hold them. */
/* `#qodef-top-area` is here because the rule above it did not cover the pages that
   needed it most. Book A Table and Contact Us build this strip as `#qodef-top-area >
   #qodef-top-area-inner` — no `.qodef-top-bar`, no `.qodef-header-top-area` — so on the
   two pages where the bar sits over a bright page-title photograph it matched neither
   selector and kept `--ambrosia-ink`: rgb(51,53,47) over a plate of noodles. The
   runtime guard had reached the same conclusion from the other side and hung a *white*
   glow off it, so the line was dark ink wearing a light halo on a bright photograph,
   which is the worst of both. Naming the id fixes it in the same breath as the class. */
.qodef-top-bar, .qodef-top-bar :is(p,a,span,li),
.qodef-header-top-area, .qodef-header-top-area :is(p,a,span,li),
#qodef-top-area, #qodef-top-area :is(p,a,span,li){
  color:var(--ambrosia-cream) !important;
  text-shadow:0 1px 8px rgba(0,0,0,.55), 0 0 3px rgba(0,0,0,.6) !important;
}
/* ...and the shadow is not enough on its own, which is worth stating plainly because
   the note in "Known limits" says to reach for a shadow rather than the guard when text
   moves over a photograph. That is right when the photograph is dark. This bar rides
   over the *page-title* image, which is a different picture per page: measured against
   the pixels actually behind each line, cream sat at 12.77:1 on Contact Us's and 1.03:1
   on Book A Table's, and forest sat at 1.32:1 on the same bar. No single ink colour
   answers both, because the question is not which ink — it is that there is no reliable
   ground. So the bar is given one. A translucent forest strip costs two pages one shade
   of contrast against their photograph and buys every page a floor that does not depend
   on which dish the header happens to be showing.

   Only /book-a-table/ and /contact-us/ carry this element; the other five have no top
   bar at all, so nothing else is affected. */
#qodef-top-area, .qodef-top-bar, .qodef-header-top-area{
  background-image:linear-gradient(rgba(4,26,22,.82), rgba(4,26,22,.62)) !important;
}
/* Drop-down menu panels stay on the theme's dark green, so their type stays light. */
.qodef-drop-down-second, .qodef-drop-down-second-inner, ul.sub-menu,
.qodef-drop-down-second :is(a,span,li), ul.sub-menu :is(a,span,li){
  color:var(--ambrosia-cream) !important;
}
.qodef-drop-down-second a:hover, ul.sub-menu a:hover{ color:var(--ambrosia-gold-lite) !important; }

/* =========================================================================
   3. HERO — a slideshow of bright dishes, not the kitchen clip

   Asked for: a slideshow on arrival, built from bright dishes, because the video
   was "trong tối và u ám quá". The frames are picked by measuring luminance and
   saturation across all twenty photographs (tools/hero_slides.py) and cycled by
   ambrosia-hero.js, which also removes the <video> so its 3 MB is never fetched.

   Each slide is a background-image on its own layer rather than an <img>: the
   Ken Burns drift is then a transform on a box with no intrinsic size, so it
   cannot letterbox at any aspect ratio, and the crossfade is one opacity
   transition per layer instead of a stacking-order problem.

   The scrim is the part that has to be right. These frames are bright — that is
   the point of them — and the corner links, the address block and the reserve
   badge are all light type laid over them. A flat dim would undo the brightness
   the restaurant asked for, so the weight goes where the type is: stronger at
   the top and bottom edges, nearly clear across the middle where the food is.
   ========================================================================= */
.elementor-element-04fd0aa{ position:relative; overflow:hidden; }
.am-hero-slides{
  position:absolute; inset:0; z-index:0;
  background-size:cover; background-position:center;
  pointer-events:none;
}
.am-hero-slide{
  position:absolute; inset:0;
  background-size:cover; background-position:center;
  opacity:0;
  transition:opacity 1.4s ease-in-out;
  will-change:opacity;
}
.am-hero-slide.is-current{
  opacity:1;
  animation:am-hero-drift 13s ease-out both;
}
/* A slow push-in, restarted per slide. 1.06 is deliberately small: enough to
   keep the frame alive, not enough to soften a 1920px photograph visibly. */
@keyframes am-hero-drift{
  from{ transform:scale(1.005); }
  to{ transform:scale(1.06); }
}
.am-hero--still .am-hero-slide.is-current{ animation:none; transform:none; }

/* The scrim, and the weighting described above.

   Neutral black, not forest. The first version used rgba(4,26,24) — the brand
   green — and at any useful alpha that does not darken a photograph, it tints
   it: five bright dishes came out under a uniform green wash, which is the
   opposite of the "sáng sủa" that was asked for. Black takes light out without
   taking colour with it.

   And very little of it. The headline carries its own gold plate (§12) and the
   navigation now carries its own bar (§11), so the only light type left on the
   bare photograph is the address block and the reserve badge, both at the
   bottom. That is where the weight goes; across the middle the food is left
   alone. */
.am-hero-slides::after{
  content:""; position:absolute; inset:0; pointer-events:none;
  background:
    linear-gradient(180deg,
      rgba(0,0,0,.30) 0%,
      rgba(0,0,0,.06) 22%,
      rgba(0,0,0,.04) 55%,
      rgba(0,0,0,.34) 82%,
      rgba(0,0,0,.62) 100%);
}
/* The address and the badge sit on the photograph itself, so they keep a shadow
   as well — a gradient cannot know which frame is showing. */
.elementor-element-04fd0aa :is(#SR7_2_1-1-3, #SR7_2_1-1-4, .qodef-custom-font) ,
.elementor-element-04fd0aa #SR7_2_1-1-4 a{
  text-shadow:0 1px 10px rgba(0,0,0,.75), 0 1px 3px rgba(0,0,0,.6);
}
/* Everything the hero draws — headline, corner links, reserve badge — sits above
   the slideshow. RevSlider gives its own layers a z-index, so this only has to
   lift the container's other children clear of the stage at z-index 0. */
.elementor-element-04fd0aa > *:not(.am-hero-slides){ position:relative; z-index:1; }

@media (prefers-reduced-motion: reduce){
  .am-hero-slide{ transition:none; }
  .am-hero-slide.is-current{ animation:none; transform:none; }
}
/* A shadow lets the white hero type read over any frame — the bright bún included —
   without dimming the food further. */
.elementor-element-04fd0aa :is(h1,h2,h3,h4,h5,h6,p,span,a,.qodef-m-title,.qodef-m-title-text,.qodef-e-title){
  text-shadow:0 2px 20px rgba(0,0,0,.55), 0 1px 4px rgba(0,0,0,.5);
}

/* =========================================================================
   4. PAGE-TITLE BAND — light type over the photo, with a scrim so it always reads
   ========================================================================= */
.qodef-page-title, .qodef-page-title *,
.qodef-title .qodef-m-title, .qodef-title .qodef-m-subtitle, .qodef-title .qodef-m-content *{
  color:#fff !important;
  text-shadow:0 1px 18px rgba(0,0,0,.55), 0 1px 3px rgba(0,0,0,.4);
}
.qodef-title.qodef-title--standard .qodef-m-content::before,
.qodef-page-title::before{
  content:""; position:absolute; inset:0; pointer-events:none;
  background:linear-gradient(180deg, rgba(0,0,0,.28) 0%, rgba(0,0,0,.42) 100%);
}
.qodef-title .qodef-m-content{ position:relative; z-index:1; }

/* The Google Map needs a paid API key the capture does not carry, so it renders a grey
   "Oops! Something went wrong" panel on the contact page. Hidden until a key is wired
   up, with the address block beside it doing the job in the meantime. */
.qodef-google-map, .qodef-m-map, .elementor-widget-fidalgo_core_google_map{
  display:none !important;
}
/* Hiding the map was not enough. Elementor sets min-height:600px on the container
   that held it, so /contact-us/ opened on 600px of blank white between the header
   and "Write to us" — the map was gone and the hole it left was not. The
   container is collapsed with it, and comes back the moment a key is wired up
   and the display:none above is lifted. */
.elementor-element:has(> .elementor-widget-container > .qodef-google-map),
.elementor-element:has(> .elementor-widget-container > .qodef-m-map),
.e-con:has(> .elementor-widget-fidalgo_core_google_map),
.e-con-full:has(> .elementor-widget-fidalgo_core_google_map){
  min-height:0 !important;
  height:auto !important;
}


/* =========================================================================
   5. PARALLAX CUSTOM-FONT LINES — a shadow, because measuring them cannot work

   qodef--has-scroll marks the decorative lines GSAP drifts as the page scrolls.
   "Book private dining & banquet rooms" is one: set in cream, laid at an angle across
   the seam between the dark reservation band and a white-plated lobster, and moving
   relative to both. ambrosia-contrast.js judges an element once, when it comes into
   view, and that is right for everything that holds still — but this one's ground is a
   function of scroll position, so any single reading of it is wrong somewhere. Logged
   in the act, the guard sampled it at a moment when all three points fell on forest,
   scored 10.94, and correctly left it alone; a reader arriving later sees the half over
   the plate. So it is not measured, it is shadowed. Dark, because these lines are light
   type: over the forest the shadow costs nothing, over the plate it is what holds them.
   ========================================================================= */
.qodef-custom-font.qodef--has-scroll,
.qodef-custom-font.qodef--has-scroll .qodef-e-inner{
  text-shadow:0 1px 14px rgba(0,0,0,.55), 0 1px 4px rgba(0,0,0,.45);
}


/* =========================================================================
   6. THE PHOTO STRIP — landscape rectangles, at the size the food deserves

   Asked for by the restaurant: bigger, and a horizontal rectangle. The theme ran this
   five across as tall arches and set object-fit: fill on the picture inside, which
   stretches a 600x696 photograph into a 205x238 hole — every dish in the strip was
   quietly squashed. Three across in 3:2 is both the shape their photographs were taken
   in and roughly twice the area. cover, not fill, so nothing is distorted again.
   ========================================================================= */
.qodef-image-gallery.qodef-border-radius-predefined-2 .qodef-round-borders-wrapper,
.qodef-image-gallery.qodef-border-radius-predefined-2 .qodef-round-borders-wrapper-inner{
  border-radius:0 !important;
  aspect-ratio:3 / 2;
  height:auto !important;
}
.qodef-image-gallery.qodef-border-radius-predefined-2 .qodef-round-borders-wrapper-inner{
  overflow:hidden;
}
.qodef-image-gallery.qodef-border-radius-predefined-2 img{
  width:100% !important;
  height:100% !important;
  object-fit:cover !important;
  border-radius:0 !important;
}


/* =========================================================================
   7. THE OVERLAP COLLAGE — bigger, because the food is the point

   Two spots on the home page lay a small photograph over a large one. The theme sized the
   small one at 202x281 and served it from the matching thumbnail: 19 KB of picture asked
   to carry half a composition. It now points at the full-size file (see stage_overlap)
   and is set at a size that can hold its own beside the plate behind it — a little over
   half the large photograph rather than a quarter of it.
   ========================================================================= */
.elementor-element:has(> .elementor-widget-container > .qodef-shortcode img[src*="h1-img1.jpg"]),
.elementor-element:has(> .elementor-widget-container > .qodef-shortcode img[src*="h1-img10.png"]){
  width:auto !important; max-width:none !important;
}
img[src*="h1-img1.jpg"],
img[src*="h1-img10.png"]{
  width:clamp(230px, 26vw, 380px) !important;
  height:auto !important;
  max-width:none !important;
}

@media (max-width:880px){
  img[src*="h1-img1.jpg"],
  img[src*="h1-img10.png"]{ width:clamp(150px, 40vw, 240px) !important; }
}


/* =========================================================================
   8. THE FILMS PAGE — a gallery of tiles, the way a YouTube channel looks

   Asked for: "làm dạng danh sách Video nhúng Utube nhen" — a list of embedded
   YouTube videos. So: a grid of posters, each with the red play badge and a
   title under it, and a lightbox that opens on click.

   The player behind a tile is whatever that tile's entry in FILMS names — a
   YouTube id if one has been pasted in, the self-hosted mp4 otherwise. Both
   play in the same lightbox, so the page has the shape asked for today, on the
   two clips the restaurant actually sent, and switches to real embeds without
   being rebuilt. See tools/films_page.py and ambrosia-films.js.

   Nothing is fetched from youtube.com until somebody presses play. The poster
   is served from here, so a reader who never watches anything is not announced
   to Google — which is the same reasoning that took the vendor's Tag Manager
   container off every page in this site.
   ========================================================================= */
.am-films-page{
  /* The page is built from the gallery template, which carries a full-bleed photograph
     behind its content — fine for a gallery, but it left the heading here sitting on a
     lime. A white ground, edge to edge, and the films are the only picture on the page.

     width:100% and no negative margin. This used to be `width:100vw` with
     `margin-left:calc(50% - 50vw)` to break out of a padded parent — but 100vw
     counts the scrollbar, so the page ran 8px wider than the viewport and /video/
     was the one route with a horizontal scrollbar. The parent is full-bleed on
     its own now (§0), so the breakout is not needed at all. */
  position:relative; z-index:1;
  width:100%;
  background:var(--ambrosia-white, #fff);
  padding:clamp(3rem,8vw,6rem) clamp(1.15rem,4vw,2.25rem);
}
.am-films-page > *{ max-width:1180px; margin-inline:auto; }
.am-films-head{ text-align:center; margin-bottom:clamp(2rem,5vw,3.5rem); }
.am-films-title{
  margin:0;
  font-family:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
  font-size:clamp(2rem,4.5vw,3.1rem); font-weight:700; letter-spacing:0;
  color:var(--ambrosia-forest) !important;
}
.am-films-sub{
  margin:.5rem 0 0;
  font-family:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
  font-style:italic; font-size:clamp(1rem,1.6vw,1.25rem);
  color:var(--ambrosia-gold-deep) !important;
}
/* Asked for as "layout center for page video": the grid sat 94px to the left of
   its own heading — head at 130-1310, films at 36-1216, both 1180 wide.

   The selector carries the fix, not the value. The theme resets lists with
   `ol:not(.wp-block), ul:not(.wp-block){margin:0 0 1.5em}`, and a type plus a
   class in :not() is (0,1,1) — which outranks a bare `.am-films` at (0,1,0) and
   the `.am-films-page > *{margin-inline:auto}` above it just the same. So the
   head, a div, centred, and the films, a ul, never could. `.am-films-page >
   ul.am-films` is (0,2,1) and settles it. */
.am-films-page > ul.am-films{
  display:grid; grid-template-columns:repeat(auto-fill, minmax(min(100%, 300px), 1fr));
  gap:clamp(1.5rem, 3vw, 2.25rem);
  list-style:none; margin:0 auto; padding:0;
}
.am-film-card{ margin:0; }
.am-film-open{
  display:block; width:100%; padding:0; border:0; background:none;
  text-align:left; cursor:pointer; color:inherit; font:inherit;
}
.am-film-thumb{
  position:relative; display:block; overflow:hidden;
  border-radius:4px; background:var(--ambrosia-forest);
}
/* 16:9, like a channel page, even though both clips are 9:16 phone footage. The
   poster is centre-cropped to the tile and the clip itself plays uncropped in
   the lightbox — a grid of portrait tiles reads as a phone gallery, not as a
   list of films. */
.am-film-thumb img{
  display:block; width:100%; aspect-ratio:16 / 9; height:auto;
  object-fit:cover;
  transition:transform .5s cubic-bezier(.2,.7,.3,1), filter .35s ease;
}
.am-film-open:hover .am-film-thumb img,
.am-film-open:focus-visible .am-film-thumb img{
  transform:scale(1.035); filter:brightness(.86);
}
.am-film-play{
  position:absolute; inset:0; display:grid; place-items:center; pointer-events:none;
}
.am-film-play svg{ width:66px; height:47px; }
.am-film-play-bg{ fill:#1e1e1e; opacity:.82; transition:fill .25s ease, opacity .25s ease; }
.am-film-play-arrow{ fill:#fff; }
.am-film-open:hover .am-film-play-bg,
.am-film-open:focus-visible .am-film-play-bg{ fill:#e02f2f; opacity:1; }
.am-film-open:focus-visible .am-film-thumb{
  outline:2px solid var(--ambrosia-gold-deep); outline-offset:3px;
}
.am-film-meta{ display:block; padding:.85rem .1rem 0; }
.am-film-title{
  display:block;
  font-family:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
  font-size:1.12rem; font-weight:700; line-height:1.3;
  color:var(--ambrosia-forest) !important;
}
.am-film-sub{
  display:block; margin-top:.2rem;
  font-family:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
  font-style:italic; font-size:.95rem;
  color:var(--ambrosia-gold-deep) !important;
}

/* ---- the lightbox ---- */
.am-film-modal[hidden]{ display:none; }
.am-film-modal{
  position:fixed; inset:0; z-index:1000;
  display:grid; place-items:center;
  padding:clamp(1rem, 4vw, 3rem);
}
.am-film-modal-backdrop{
  position:absolute; inset:0;
  background:rgba(3,20,18,.88);
  backdrop-filter:blur(6px); -webkit-backdrop-filter:blur(6px);
}
/* fit-content, so a 9:16 clip does not sit in the middle of a 1000px black
   letterbox. A YouTube frame has no intrinsic width, so it is given one below
   and the inner grows to it. */
.am-film-modal-inner{
  position:relative;
  width:fit-content;
  max-width:min(1000px, 100%);
  max-height:100%;
}
.am-film-stage{
  display:grid; place-items:center;
  border-radius:4px; overflow:hidden;
  box-shadow:0 30px 80px rgba(0,0,0,.5);
}
/* The self-hosted clips are 9:16, so the stage is sized by the video rather than
   forced to 16:9 — the earlier version of this page cropped a horizontal strip
   out of the middle of a portrait shot and threw the dish away. A YouTube frame
   has no intrinsic size, so that one is given the ratio. */
.am-film-stage video{
  display:block; width:auto; max-width:100%;
  max-height:min(78vh, 900px); height:auto;
}
.am-film-stage iframe{
  display:block; width:min(1000px, 92vw); aspect-ratio:16 / 9; height:auto; border:0;
}
.am-film-close{
  position:absolute; top:-2.6rem; right:0;
  width:2.2rem; height:2.2rem; padding:0;
  display:grid; place-items:center;
  font-size:1.9rem; line-height:1;
  color:var(--ambrosia-cream); background:none; border:0; cursor:pointer;
}
.am-film-close:hover{ color:var(--ambrosia-gold-lite); }
body.am-film-open-lock{ overflow:hidden; }


/* =========================================================================
   9. THE HERO ADDRESS BLOCK — stop the label sitting on the street

   RevSlider pins "/ FIND US" absolutely at top: 689px and lets the address below it sit
   in flow at a fixed width of 190 px. That worked for the demo's one-line address. Ours
   is three lines — and the 190 px box broke the phone number across two of them, so the
   card read "…DC 20001 571-" then "233-5001" — and the block grew up into the label,
   overlapping it by 19 px.

   Wider, so the number stays whole; each link on its own line, so the address and the
   phone read as two facts; and pushed clear of the label rather than the label moved,
   because the label is the thing the slider positions and the address is not.
   ========================================================================= */
#SR7_2_1-1-4{
  width:320px !important;
  margin-top:30px !important;
}
#SR7_2_1-1-4 p{ margin:0 !important; }
#SR7_2_1-1-4 a{ display:block; }

@media (max-width:680px){
  #SR7_2_1-1-4{ width:min(320px, 76vw) !important; }
}


/* =========================================================================
   10. ONE SKIN, SEVEN PAGES — the footer is Ambrosia forest everywhere

   Asked for: the footer on /gallery/ "suddenly changes to this colour" — a dark
   brown, where every other page is forest green.

   It is not the footer. The demo shipped a per-layout skin on <body>, and the
   capture kept whichever one each borrowed page happened to carry:

     home, menu, about-us   qodef-skin--viridian-green   #042726  forest
     gallery, video         qodef-skin--dark-maroon      #1C100D  brown
     contact-us, book-a-table  qodef-skin--midnight-blue #000720  navy

   Each redefines --qode-additional-background-color, which is the variable the
   footer paints itself with — so four of the seven pages were quietly wearing
   another restaurant's colour scheme. The restaurant only caught the brown one.

   Normalised here rather than by editing the class out of four <body> tags,
   because the same classes also skin the sticky header and the testimonial
   bands: redefining the variables fixes every one of those in the same stroke,
   and a page that later arrives carrying a fifth skin is covered too.
   ========================================================================= */
body,
body[class*="qodef-skin--"],
body .qodef-skin--dark-maroon, body.qodef-skin--dark-maroon,
body .qodef-skin--midnight-blue, body.qodef-skin--midnight-blue,
body .qodef-skin--midnight-green, body.qodef-skin--midnight-green,
body .qodef-skin--reseda-green, body.qodef-skin--reseda-green,
body .qodef-skin--eclipse, body.qodef-skin--eclipse,
body .qodef-skin--indigo, body.qodef-skin--indigo{
  --qode-background-color:#102B2A;
  --qode-additional-background-color:#042726;
  --qode-box-background-color:#1F3634;
  --qode-paragraph-color:#CED8D8;
  --qode-border-color:#C9A581;
  --qode-transparent-box-background-color:rgba(0,0,0,.45);
}


/* =========================================================================
   11. THE HEADER — a ground of its own, so the navigation is always readable

   Asked for: "cho cái nền đằng sau mờ mờ cố định luôn để thấy thanh menu" —
   give the bar behind the navigation a permanent dimmed ground so the menu is
   always visible.

   Two separate elements were failing, for the same reason and in different places:

   - The sticky bar the theme drops in on scroll is rgba(0,0,0,.2) over a 40px
     blur. Over the dark hero that is enough; over the photo strip and the white
     content bands it resolves to pale grey, and the bar carries *light* type —
     which is the screenshot the restaurant sent, with the wordmark and every
     nav item washed out to near-invisible.
   - It also carried qodef-appearance--up, so it only slid down when the reader
     scrolled *back up*. Scrolling down the page — the normal direction — there
     was no navigation on screen at all. That class is now off the markup on all
     seven pages, which drops the theme's own JS back to "visible once past the
     header", the behaviour asked for.

   A forest wash rather than plain black: it is the brand ground, it is dark
   enough for cream type at any scroll position, and the blur behind it keeps the
   photography reading through instead of boxing the page off. The static header
   at the top of the page gets a soft top-down gradient for the same reason —
   over the pale page-title photographs on the interior pages the nav had nothing
   behind it either.
   ========================================================================= */
.qodef-header-sticky{
  background-color:rgba(4,39,38,.82) !important;
  backdrop-filter:blur(18px) saturate(1.1);
  -webkit-backdrop-filter:blur(18px) saturate(1.1);
  border-bottom:1px solid rgba(201,162,75,.22);
}
.qodef-header-sticky :is(a,span,li,.qodef-m-text){
  color:var(--ambrosia-cream) !important;
  text-shadow:none;
}
.qodef-header-sticky a:hover,
.qodef-header-sticky .qodef-menu-item--active > a{
  color:var(--ambrosia-gold-lite) !important;
}
/* The static header gets the same bar as the sticky one, on every page.

   Two earlier attempts were wrong in opposite directions. A gradient behind it
   smudged grey across the top of Contact, which opens on white. Removing the
   gradient then left Gallery unreadable: #qodef-page-outer is pulled up 121px
   under the header on every page, so on Gallery the navigation lands on a rust
   photograph, and the contrast guard — correctly, by its own measure — repainted
   it near-black. Dark navigation on one page, cream on the next, is exactly the
   inconsistency the restaurant kept pointing at.

   One bar, everywhere, is the answer to both: the same forest wash as the sticky
   header, so the navigation reads the same on white, on a rust photograph and on
   the hero video, and scrolling changes nothing about it. The guard is told to
   leave the header alone (CARRIES_ITS_OWN_GROUND) so it cannot undo this. */
#qodef-page-header-inner{
  background-color:rgba(4,39,38,.82);
  backdrop-filter:blur(18px) saturate(1.1);
  -webkit-backdrop-filter:blur(18px) saturate(1.1);
  border-bottom:1px solid rgba(201,162,75,.22);
  /* The theme sets margin-top:30px here for its split header. That gap was
     invisible while the bar was transparent; giving the bar a ground of its own
     turned it into a 30px strip of bare page above the navigation, across the
     top of every screen. */
  margin-top:0 !important;
}
#qodef-page-header-inner :is(a,span,li,.qodef-m-text){
  color:var(--ambrosia-cream) !important;
  text-shadow:none !important;
}
#qodef-page-header-inner a:hover,
#qodef-page-header-inner .qodef-menu-item--active > a{
  color:var(--ambrosia-gold-lite) !important;
}


/* =========================================================================
   12. THE HERO HEADLINE — dark type on a gold plate

   Asked for: "dùng chữ đen, nền xám xám trắng hoặc nền vàng vàng theo màu cái
   logo (giảm Alpha xuống nha)" — black type, on a grey-white or a logo-gold
   ground, alpha turned down.

   Gold of the two, because it is the emblem's own colour and the line it sits
   under is "A Taste of Vietnam's Golden Table"; a grey plate would read as a
   fix rather than as part of the mark.

   Painted on ::before rather than as the layer's own background. RevSlider
   writes left/top/width onto this element inline on every resize, and it
   measures the text: giving the layer padding moves the headline sideways by
   the padding amount at every breakpoint, and the slider then re-measures and
   fights it. A pseudo-element with negative insets paints outside the text box
   without touching the box, so the slider goes on positioning exactly what it
   positioned before. The insets are uneven on purpose — 8px of letter-spacing
   hangs off the last letter, so the right side needs less.

   z-index:-1 keeps it behind the text and still inside this layer's own
   stacking context (the layer is z-index:9, position:absolute), so it cannot
   fall behind the background video.
   ========================================================================= */
#SR7_2_1-1-1{
  color:#14100a !important;
  text-shadow:none !important;
}
#SR7_2_1-1-1::before{
  content:""; position:absolute; z-index:-1;
  inset:-14px -26px -12px -34px;
  /* Alpha turned down as asked, but not past the point where the plate stops
     working. Measured at the worst frame the loop reaches — gold this thin over
     near-black resolves to about #ab986d, which holds #14100a at 6.8:1, clear of
     AA. Much below .76 and the kitchen behind starts showing through the letters
     rather than around them. */
  background:linear-gradient(100deg,
             rgba(214,187,132,.80) 0%,
             rgba(201,162,75,.76) 52%,
             rgba(214,187,132,.80) 100%);
  border-radius:3px;
  box-shadow:0 10px 34px rgba(0,0,0,.30);
}

@media (max-width:680px){
  #SR7_2_1-1-1::before{ inset:-10px -14px -8px -18px; }
}


/* =========================================================================
   13. "AMBROSIA IS FOR EVERYONE WHO COLLECTS BEAUTIFUL MOMENTS" — two lines

   Asked for: "cho làm 2 dòng thui em".

   It ran to three because Jost was not loading (see tools/fontfix.py) and the
   line was being set in the fallback sans, which is wider — so fixing the fonts
   dropped it to two on its own. That is not something to leave to chance: the
   restaurant asked for two lines, and a line that only lands on two because of
   one typeface's metrics goes back to three the moment anything nudges them.

   text-wrap:balance evens the two lines rather than leaving a long one over a
   short one, and the max-width holds the break where it is. Released below
   680px, where two lines of this at 28px would run off the screen and three is
   the right answer.
   ========================================================================= */
:is(.qodef-content-page, .qodef-page-content-section)
  .qodef-section-title .qodef-m-title:has(.qodef-m-title-text){
  text-wrap:balance;
}
.qodef-m-title-text{ text-wrap:balance; }

@media (min-width:681px){
  .elementor-element-2aec73e .qodef-m-title,
  .qodef-section-title .qodef-m-title:has(.qodef-m-title-text){
    max-width:34ch;
    margin-inline:auto;
  }
}


/* =========================================================================
   14. THE GUEST REVIEWS — an avatar, a rating, and a ground to read them on

   Asked for: a guest avatar, the Comic Sans gone, and a dimmed dark or green
   box under the text so the words can be read.

   The Comic Sans was never chosen — the theme asks for "Mrs Saint Delafield",
   the vendored copy of it was being served with the wrong MIME type, and the
   declared fallback is `cursive`, which on Windows is Comic Sans MS. That is
   fixed at the source in tools/fontfix.py, so the script face now loads. The
   heading is still moved off it, because the restaurant asked for that font to
   go and a 55px calligraphic script laid across a photograph of a laid table is
   hard to read whatever it is. It goes onto the same old-style serif the menu
   card is set in, which is the one typographic voice this site already has.

   The panel is `--qode-transparent-box-background-color` deepened rather than a
   new colour: forest at .72 over any frame of that photograph clears AA for the
   cream type, and the blur keeps the picture reading as a ground instead of
   being boxed out of the section.

   The avatar is a monogram disc — see tools/reviews.py for why it is not a
   photograph.
   ========================================================================= */
.qodef-e-static-title{
  font-family:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif !important;
  font-style:italic;
  font-size:clamp(1.6rem, 2.6vw, 2.3rem) !important;
  line-height:1.25 !important;
  letter-spacing:.01em;
  text-transform:none;
  /* On the home page it is pinned over the photograph at a -6deg tilt, so there
     it needs a plate for the same reason the reviews do — and the guard is told
     to leave it alone (CARRIES_ITS_OWN_GROUND in ambrosia-contrast.js), because
     it was sampling the napkin through the plate and repainting the words dark
     with an "important" no stylesheet could answer.

     On About Us there is no photograph, so no plate: a dark tablet floating on
     a white page was half of what made that section look wrong. */
  color:var(--ambrosia-forest) !important;
  text-shadow:none !important;
  padding:0 !important;
}
.qodef-testimonials-slider-advance .qodef-e-static-title{
  color:var(--ambrosia-cream) !important;
  background:rgba(6,42,38,.80);
  backdrop-filter:blur(6px);
  -webkit-backdrop-filter:blur(6px);
  border:1px solid rgba(201,162,75,.28);
  border-radius:3px;
  padding:.5em .85em !important;
}

/* The review card. .qodef-e-content is the theme's own wrapper for the quote and
   its author, so the panel goes there and no extra element is needed.

   TWO GROUNDS, TWO CARDS. The dark panel exists because on the home page these
   reviews are laid over a photograph of a set table. About Us runs the same
   widget with **no photograph behind it at all** — and there the dark panel was
   a black-green slab dropped on a white page under a 48px shadow, which is what
   "đổ bóng ở trang này kém quá, thật sự rất kỳ" was pointing at. It was not the
   shadow's fault; the shadow was doing what a shadow does for a panel that had
   no business being dark.

   The discriminator is in the theme's own markup: the photo-backed layout carries
   .qodef-testimonials-slider-advance and a sibling .qodef-testimonials--additional-slider.
   Plain .qodef-testimonials-slider-holder means white behind. */
.qodef-testimonials-list .qodef-e-content{
  position:relative;
  /* "phóng to ra" — the card was 44rem of quiet grey in the middle of a wide
     band and read as a caption rather than as the section it is. */
  max-width:58rem;
  margin-inline:auto;
  padding:clamp(2.25rem,4vw,3.25rem) clamp(2rem,4vw,3.5rem);
  border-radius:4px;
  /* the light card — the default, because white is the site's ground */
  background:#fbf9f4;
  border:1px solid rgba(138,106,30,.28);
  box-shadow:0 2px 10px rgba(13,46,40,.06);
}
.qodef-testimonials-slider-advance .qodef-testimonials-list .qodef-e-content{
  background:rgba(6,42,38,.72);
  backdrop-filter:blur(9px) saturate(1.05);
  -webkit-backdrop-filter:blur(9px) saturate(1.05);
  border-color:rgba(201,162,75,.30);
  box-shadow:0 18px 48px rgba(0,0,0,.34);
}
/* The panel sets its own type colour rather than leaning on §2's list of dark
   bands. §2 names the home page's testimonial container by Elementor id, so the
   home cards came out cream and the *same component* on About Us — a different
   id, not on the list — fell through to §1 and rendered dark grey on this dark
   green. A panel that brings its own ground has to bring its own ink with it.

   With a ground of its own the type also no longer needs the shadow §2 gives it
   for riding bare over a photograph; left on, it reads as smudged. */
/* Ink to match the ground, light card and dark alike. */
.qodef-testimonials-list .qodef-e-content,
.qodef-testimonials-list .qodef-e-content :is(p,span,h6,.qodef-e-text,.qodef-e-author,.qodef-e-author-name,.qodef-e-author-job){
  color:var(--ambrosia-ink) !important;
  text-shadow:none !important;
}
.qodef-testimonials-slider-advance .qodef-testimonials-list .qodef-e-content,
.qodef-testimonials-slider-advance .qodef-testimonials-list .qodef-e-content :is(p,span,h6,.qodef-e-text,.qodef-e-author,.qodef-e-author-name,.qodef-e-author-job){
  color:var(--ambrosia-cream) !important;
}
.qodef-testimonials-list .qodef-e-text{
  font-family:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
  font-size:clamp(1.15rem,1.75vw,1.45rem);
  line-height:1.62;
  margin:0 0 1.4rem;
}
.qodef-testimonials-list .qodef-e-author{ margin:0; }
.qodef-testimonials-list .qodef-e-author-name{
  font-size:.82rem; letter-spacing:.16em; text-transform:uppercase;
  color:var(--ambrosia-gold-deep) !important;
}
.qodef-testimonials-slider-advance .qodef-testimonials-list .qodef-e-author-name{
  color:var(--ambrosia-gold-lite) !important;
}
.qodef-testimonials-list .qodef-e-author-job{
  font-size:.78rem; letter-spacing:.14em; text-transform:uppercase;
  opacity:.72;
}

.am-review-head{
  display:flex; align-items:center; justify-content:center;
  gap:1.1rem; margin-bottom:1.5rem;
}
/* The avatar is an <img> slot with a monogram behind it: give a review a `photo`
   in REVIEWS (tools/reviews.py) and the photograph covers the disc; leave it out
   and the monogram shows through. That way real guest portraits drop in without
   the markup or this rule changing, and nothing here invents a face in the
   meantime — see the note at the top of tools/reviews.py. */
.am-review-avatar{
  position:relative; overflow:hidden;
  flex:0 0 auto;
  width:76px; height:76px; border-radius:50%;
  display:grid; place-items:center;
  font-family:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
  font-size:2rem; line-height:1; font-weight:700;
  color:#0d2622 !important;
  background:linear-gradient(145deg, #e0c98e 0%, #c9a24b 60%, #b58a3a 100%);
  box-shadow:0 4px 16px rgba(13,32,28,.30), inset 0 1px 0 rgba(255,255,255,.45);
  text-shadow:none !important;
}
.am-review-avatar img{
  position:absolute; inset:0;
  width:100%; height:100%;
  object-fit:cover;
  border-radius:50%;
  /* Above the guest figure below, so a real portrait wins on its own terms and
     not only because `:has()` removed the figure. Without this the fallback
     would paint over the photograph anywhere `:has()` is unsupported — the one
     failure mode of this pattern that would be invisible in testing here. */
  z-index:1;
}
/* THE GUEST FIGURE — what stands in until a photograph arrives.

   Reported twice: "currently, i don't see avatar of customer". The disc was
   there and so was the monogram, but a single letter was not reading as an
   avatar — the slot looked like a decorative initial rather than a person.

   So the fallback is a figure, which is what an empty avatar looks like
   everywhere else on the web. It is drawn here rather than fetched: a head and
   a pair of shoulders in the same ink as the monogram, on the same gold disc.
   It depicts nobody. That is the whole point of it — the reviews it sits beside
   are still the demo's invented names, and a stock face next to an invented
   name would be inventing a person as well as a review.

   `:has(img)` retires the figure the moment a real portrait is given a `photo`
   in REVIEWS (tools/reviews.py), and `font-size:0` retires the monogram, so the
   three states are photograph > figure, with nothing overlapping. */
.am-review-avatar{
  font-size:0;
}
.am-review-avatar::after{
  content:"";
  position:absolute; inset:0;
  background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Ccircle cx='24' cy='17.5' r='8.5' fill='%230d2622'/%3E%3Cpath d='M24 29c-8.6 0-15.5 5.2-15.5 11.8V44h31v-3.2C39.5 34.2 32.6 29 24 29z' fill='%230d2622'/%3E%3C/svg%3E")
    center 58% / 58% no-repeat;
  opacity:.88;
  z-index:0;
}
.am-review-avatar:has(img)::after{ display:none; }
.am-review-stars{
  font-size:1.25rem; letter-spacing:.24em;
  color:var(--ambrosia-gold-deep) !important;
  text-shadow:none !important;
}
.qodef-testimonials-slider-advance .am-review-stars{
  color:var(--ambrosia-gold-lite) !important;
}

/* The theme prints the section's own name behind the slider at 100px and 10%
   opacity. Over the new panel it shows through the type as grey ghosting, so it
   sits behind the panel instead of over it. */
.qodef-testimonials-list-wrapper{ position:relative; }
.qodef-e-static-text{ position:relative; z-index:0; }
.qodef-testimonials-list{ position:relative; z-index:1; }

/* The band is a half-and-half split — photograph left, reviews right — and the
   right column is laid out to a 1440px grid while the viewport is 1425 with a
   scrollbar. The card therefore ran 15px past the edge and was sliced down its
   right-hand side. Holding it inside the column is enough; the theme's own
   padding does the rest. */
.qodef-testimonials-list{
  max-width:100%;
  padding-right:clamp(.75rem, 2vw, 1.75rem);
  box-sizing:border-box;
}

/* On About Us there is no photograph beside the reviews, so the slider is not
   sharing the band with anything and has no reason to sit in a 576px column in
   the middle of a 1400px page. "Phóng to ra" — the whole block widens, not just
   the card inside it, which was the thing capping it at 529px however large its
   own max-width was. Swiper sizes slidesPerView:1 slides from the container, so
   widening the container is enough; ambrosia-reviews.js nudges it to re-measure
   after the fact. */
.qodef-testimonials-slider-holder:not(.qodef-testimonials-slider-advance) .qodef-testimonials-list{
  /* display:block and width:100% as well as the max-width. The theme ships this
     widget as an inline-block, so it sizes to its content: the max-width was
     applied and ignored, and the block stayed at 557px inside a 1302px parent. */
  display:block;
  width:100%;
  max-width:min(64rem, 92%);
  margin-inline:auto;
  padding-right:0;
}
.qodef-testimonials-slider-holder:not(.qodef-testimonials-slider-advance) .qodef-e-static-title{
  display:block;
  text-align:center;
  margin-inline:auto;
}

@media (max-width:680px){
  .am-review-avatar{ width:56px; height:56px; font-size:1.4rem; }
  .am-review-stars{ font-size:1.05rem; }
}


/* =========================================================================
   15. THE FOOTER'S SOCIAL ICONS — bigger, and on the centre line

   Asked for: "thêm mấy cái icon Social to 1 chút đặt ở giữa đây / hoặc đặt ở
   đây" — bigger social icons, centred, with two places pointed at. They go
   under the wordmark, which is the second of the two and already the footer's
   centre line.

   They were three small uppercase words in the bottom-left corner, and they
   pointed at the theme vendor's own accounts — see tools/social.py.

   Gold on forest, at 44px, with the disc filling on hover rather than the icon
   changing colour: the icons are single-colour SVG paths that inherit
   currentColor, so one rule moves both states and nothing has to be redrawn.
   ========================================================================= */
.am-social{
  display:flex; justify-content:center; align-items:center;
  gap:clamp(.85rem, 2vw, 1.4rem);
  margin:1.6rem auto .4rem;
  padding:0 8%;
}
.am-social-link{
  display:grid; place-items:center;
  width:44px; height:44px;
  border-radius:50%;
  color:var(--ambrosia-gold-lite);
  border:1px solid rgba(201,162,75,.45);
  transition:background-color .25s ease, color .25s ease, border-color .25s ease,
             transform .25s ease;
}
.am-social-link svg{
  width:21px; height:21px;
  fill:currentColor;
  display:block;
}
/* `!important` on the colour, and only the colour. §2 paints every `a`, `span` and `li`
   under `footer` cream with `important` so the dark bands read — correct for the
   copyright line beside these icons, wrong for an icon whose own disc has just turned
   gold underneath it. Without this the hovered coin was cream on gold, 2.04:1: legible
   enough to prove the disc was working, not enough to see which network it was. */
.am-social-link:hover,
.am-social-link:focus-visible{
  background:var(--ambrosia-gold-lite);
  border-color:var(--ambrosia-gold-lite);
  color:#06231f !important;
  transform:translateY(-2px);
}
.am-social-link:focus-visible{ outline:2px solid var(--ambrosia-cream); outline-offset:3px; }

/* With the icons lifted onto their own row the bottom bar holds one thing, so it
   centres rather than keeping the two-column split it had for links + copyright.
   grid-template-columns directly, not --qode-col-num: the theme reads that
   variable when it builds the class, but .qodef-col-num--2 then writes the two
   tracks out literally, so setting the variable to 1 left the copyright sitting
   in the first of two 583px columns — still off to the left. */
#qodef-page-footer-bottom-area .qodef-grid .qodef-grid-inner{
  grid-template-columns:1fr !important;
}
#qodef-page-footer-bottom-area .qodef-copyright{ text-align:center; }

/* ---- 15b. CLOSE THE HOLE IN THE MIDDLE OF THE FOOTER --------------------
   "ủa chứ cái lạ footer đi đâu hết rồi" — where has the rest of the footer
   gone. Nothing had gone anywhere: the crest, the icons and the copyright were
   all present, on all seven pages, and measured identically. What the reader
   met was the gap above them.

   Measured on the home page at 1920x1000: the top band is 392px tall and holds
   100px of type. 135px of padding above it, and 131px of empty forest below the
   last line before the bottom band begins. Scroll into that, and the three
   columns look like the end of the page — the screenshot that came with the
   complaint is cropped exactly at the top of the crest, about 40px before it
   would have appeared.

   So the band is pulled in around its contents: 88/48 rather than 135/105,
   which is 104px off the footer's height and brings the crest that much sooner.
   The contact details keep room to breathe from the photograph above them; what
   goes is the dead ground between the columns and the wordmark, so the footer
   reads as one block instead of two strangers.
   ---------------------------------------------------------------------- */
#qodef-page-footer-top-area-inner{
  padding-top:clamp(56px, 6vw, 88px) !important;
  padding-bottom:clamp(32px, 3.4vw, 48px) !important;
}

@media (max-width:680px){
  .am-social-link{ width:40px; height:40px; }
  .am-social-link svg{ width:19px; height:19px; }
}


/* =========================================================================
   17. OUR GOALS & HISTORY — the chef beside it

   Asked for: the section reworked so there is a picture of the head chef next
   to it. The band held one 420px column of text in a 614px row and nothing
   else; the photograph goes in beside it and the pair becomes a two-column row.
   tools/chef_frame.py explains where the picture comes from and why it is a
   frame from Ambrosia's own kitchen footage rather than a portrait.

   Photograph first in the source order, so a narrow screen stacks picture over
   words — which is the order the section reads in.
   ========================================================================= */
.elementor-element-b704042{
  display:grid !important;
  grid-template-columns:minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap:clamp(1.5rem, 4vw, 3rem);
  align-items:center;
  width:100% !important;
  max-width:none !important;
}
/* Elementor sets a per-widget width on the text — 420px, which was correct when
   it had a row to itself and is a third of a column now. */
.elementor-element-b704042 > .elementor-element{
  width:100% !important;
  max-width:none !important;
}
.am-chef{
  margin:0;
  align-self:stretch;
}
.am-chef img{
  display:block;
  width:100%;
  aspect-ratio:4 / 5;
  height:auto;
  object-fit:cover;
  border-radius:3px;
  box-shadow:0 16px 40px rgba(0,0,0,.16);
}
.am-chef-caption{
  margin-top:.6rem;
  font-family:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
  font-style:italic;
  font-size:.95rem;
  /* Not --ambrosia-gold-deep. That token is 5.05:1 on white and clears AA
     everywhere it is used — but this caption is not on white. It sits on the
     pale grey strip under the photograph, and measured against the strip's own
     pixels it came out at 4.23:1, just under the 4.5 it needs. A 15px italic
     serif is the least forgiving text on the page to lose that margin on.
     #725716 is the same gold carried two steps deeper: 6.80:1 on white and
     still 5.50:1 against the darkest grey in the strip. */
  color:#725716 !important;
}

@media (max-width:880px){
  .elementor-element-b704042{ grid-template-columns:1fr; }
  .am-chef img{ aspect-ratio:16 / 10; }
}


/* =========================================================================
   18. FORM FIELDS — give them their frames back

   Asked for: "mất tiêu hết mấy cái khung, chỉnh lại" — the boxes have all
   vanished; put them back.

   They had not vanished. Contact Form 7 draws each field as a single underline,
   and the theme sets that underline to rgba(255,255,255,.5) because it drew
   these forms on a dark ground. The port put them on white, so the line is a
   half-transparent white rule on a white page. The words "Name", "E mail" and
   "Message" were floating with nothing under them and no way to tell where to
   click.

   The contrast guard could not have caught this: it measures text against its
   ground and repairs the *text*, and the text here was already dark and legible.
   Nothing in it looks at borders.

   Underlines rather than full boxes, because that is the form the theme drew and
   the shape the rest of the site's inputs keep — the booking form on the home
   page is the same. Gold, at the weight the menu's hairlines use, so the field
   reads as part of this site rather than as a browser default.
   ========================================================================= */
:is(.qodef-content-page, .qodef-page-content-section)
  :is(.wpcf7-form-control, .wpcf7-text, .wpcf7-textarea,
      input[type="text"], input[type="email"], input[type="tel"], textarea){
  border-bottom:1px solid rgba(138,106,30,.45) !important;
  background-color:transparent !important;
  transition:border-color .22s ease, box-shadow .22s ease;
}
:is(.qodef-content-page, .qodef-page-content-section)
  :is(.wpcf7-form-control, .wpcf7-text, .wpcf7-textarea,
      input[type="text"], input[type="email"], input[type="tel"], textarea):focus{
  border-bottom-color:var(--ambrosia-gold-deep) !important;
  box-shadow:0 1px 0 0 var(--ambrosia-gold-deep);
  outline:none;
}
/* The submit button was drawn for the same dark ground — a white label inside a
   white-bordered box. */
:is(.qodef-content-page, .qodef-page-content-section)
  .wpcf7 :is(input[type="submit"], button){
  border:1px solid var(--ambrosia-gold-deep) !important;
  color:var(--ambrosia-forest) !important;
  background-color:transparent !important;
  transition:background-color .22s ease, color .22s ease;
}
:is(.qodef-content-page, .qodef-page-content-section)
  .wpcf7 :is(input[type="submit"], button):hover{
  background-color:var(--ambrosia-forest) !important;
  color:var(--ambrosia-cream) !important;
}


/* =========================================================================
   19. THE DISH EFFECT — recovered from the earlier Ambrosia build

   Asked for by name: the effect Alex built for the previous Ambrosia site,
   applied to the dishes here. Recovered from Total Recall — observer-sessions,
   24 July 2026, extracted from that site's `globals.css .dish` (lines 961-1017):

     hover lifts the card 6px, adds a 30px shadow at 24px blur, the border
     becomes gold rgba(181,138,58,.6), the image scales to 1.08 over 1s on
     cubic-bezier(.16,1,.3,1), and an ::after sheen — linear-gradient(115deg) of
     semi-transparent gold — sweeps translateX from -120% to 120% over .9s.
     Everything else transitions on .5s.

   Reproduced to those numbers. rgba(181,138,58) is #b58a3a, which is this
   project's --ambrosia-gold exactly, so the effect was built against this
   palette and needs no retuning.

   ---- Second pass: everywhere, not just the gallery -----------------------

   "tôi thấy các hình ảnh khác chưa được có hiệu ứng đổ kính chỉ mới gallary có
   thôi" — the other pictures have not got the glass effect, only the gallery
   has. Counted in the browser rather than argued about, and quite right:

       /menu/      5 / 5      /gallery/  20 / 20
       /           0 / 16     /about-us/  0 / 7      /video/  0 / 2

   The first cut named the three containers the menu strip and the gallery
   happen to use. Everything the theme itself renders — the arch photographs,
   the stacked pair, the event cards, the showcase slider — uses different ones
   and was never reached.

   Two things had to be handled before the list could simply be widened, both
   found by reading the computed styles rather than the markup:

   1. **The arches must not be squared off.** .qodef-single-image .qodef-m-image
      carries border-radius of 300px, 288px, 204px, 193px and 30% on this site —
      those are the tall arch-topped photographs, and the original rule's flat
      `border-radius:2px` would have cut every one of them into a rectangle. So
      the radius is now set only on the frames that were in the first cut, and
      the sweep takes `border-radius:inherit` so it follows whatever shape the
      frame already has. A gold arch outline on hover, not a gold box.

   2. **Two frames already own their transform**, so they get the frame — lift,
      gold edge, shadow, sweep — and keep their own motion, while every other
      frame gets the picture zoom as well. Read off the settled computed style
      rather than assumed:

        .qodef-single-image img       animation:qodef-appear-image,
                                      animation-fill-mode:both
        .qodef-stacked-images
          .qodef-m-main-image img     style="transform:translate(0px,40px)
                                      scale(1.06,1.06)"  (inline, from the
                                      theme's parallax handler, rewritten on
                                      every scroll)

      fill-mode:both means the last keyframe holds after the animation ends, and
      a running animation beats a transition on the same property; an inline
      style beats a stylesheet outright. A hover zoom on either would not have
      failed loudly — it would have done nothing at all, which is worse.

   Not applied to the hero slideshow, which is a background rather than a card,
   and not to the map or the video widget, which are not photographs.
   ========================================================================= */

/* Every frame that takes the effect. :is() rather than five hand-copied
   selector lists — the first version repeated its list six times and adding one
   container meant six edits, which is how the film tiles came to be missed. */
:is(
  .am-dish,
  .am-menu-shot,
  .am-film-thumb,
  .am-chef,
  .qodef-e-media-image,
  .qodef-stacked-images .qodef-m-image,
  .qodef-stacked-images .qodef-m-main-image,
  .qodef-single-image .qodef-m-image,
  .qodef-image-gallery.qodef-border-radius-predefined-2 .qodef-round-borders-wrapper-inner,
  .qodef-gallery-masonry .qodef-e-inner,
  .qodef-e.qodef-image-wrapper .qodef-round-borders-wrapper-inner
){
  overflow:hidden;
  transition:transform .5s cubic-bezier(.16,1,.3,1),
             box-shadow .5s cubic-bezier(.16,1,.3,1);
}

/* ---- why the gold edge is a shadow and not a border --------------------
   It was a border, with box-sizing:border-box to stop the extra 2px pushing
   the gallery's masonry grid past the viewport. That works on a container
   built for it and costs something on every container that was not: a border
   under border-box eats 2px of content width, so each theme photograph came
   back 2-3px shorter and the stacked pair on the home page re-flowed around
   it. Measured at 1500px wide, eight boxes moved.

   An inset box-shadow draws the same 1px line inside the same rounded corner
   and is not part of the box model at all, so nothing anywhere resizes. It
   also lets box-sizing go, which was only ever there to pay for the border.
   ---------------------------------------------------------------------- */

/* The other half of that: .qodef-m-images is an inline-block with a 28px
   line-height, so it sits on a text baseline. Giving its child overflow:hidden
   moves where that baseline is taken from and opens an 8px descender gap under
   each stacked pair — +16px on the home page, from a rule that is supposed to
   do nothing until the pointer arrives. Aligning it to the top takes the
   baseline out of the question. It is the only child of its parent, so this
   changes nothing else. */
.qodef-stacked-images .qodef-m-images{ vertical-align:top; }

/* The sweep needs a positioned ancestor. .qodef-stacked-images .qodef-m-image is
   deliberately absent: the theme positions it absolutely to overlap its pair,
   and relative would drop it back into the flow. It is already a containing
   block, so it needs nothing from here. */
:is(
  .am-dish,
  .am-menu-shot,
  .am-film-thumb,
  .am-chef,
  .qodef-e-media-image,
  .qodef-stacked-images .qodef-m-main-image,
  .qodef-single-image .qodef-m-image,
  .qodef-image-gallery.qodef-border-radius-predefined-2 .qodef-round-borders-wrapper-inner,
  .qodef-gallery-masonry .qodef-e-inner,
  .qodef-e.qodef-image-wrapper .qodef-round-borders-wrapper-inner
){
  position:relative;
}

/* Only the frames that had no shape of their own. See note 1 above. */
:is(
  .am-dish,
  .am-menu-shot,
  .qodef-image-gallery.qodef-border-radius-predefined-2 .qodef-round-borders-wrapper-inner,
  .qodef-gallery-masonry .qodef-e-inner,
  .qodef-e.qodef-image-wrapper .qodef-round-borders-wrapper-inner
){
  border-radius:2px;
}

/* the sweep */
:is(
  .am-dish,
  .am-menu-shot,
  .am-film-thumb,
  .am-chef,
  .qodef-e-media-image,
  .qodef-stacked-images .qodef-m-image,
  .qodef-stacked-images .qodef-m-main-image,
  .qodef-single-image .qodef-m-image,
  .qodef-image-gallery.qodef-border-radius-predefined-2 .qodef-round-borders-wrapper-inner,
  .qodef-gallery-masonry .qodef-e-inner,
  .qodef-e.qodef-image-wrapper .qodef-round-borders-wrapper-inner
)::after{
  content:""; position:absolute; inset:0; z-index:2;
  pointer-events:none;
  border-radius:inherit;
  background:linear-gradient(115deg,
             transparent 28%,
             rgba(201,162,75,.00) 34%,
             rgba(235,205,140,.30) 48%,
             rgba(201,162,75,.00) 62%,
             transparent 68%);
  transform:translateX(-120%);
}

/* the lift. A film tile is opened from its <button>, so the keyboard has to
   reach the same state the pointer does — hence the focus-visible pair. */
:is(
  .am-dish,
  .am-menu-shot,
  .am-film-thumb,
  .am-chef,
  .qodef-e-media-image,
  .qodef-stacked-images .qodef-m-image,
  .qodef-stacked-images .qodef-m-main-image,
  .qodef-single-image .qodef-m-image,
  .qodef-image-gallery.qodef-border-radius-predefined-2 .qodef-round-borders-wrapper-inner,
  .qodef-gallery-masonry .qodef-e-inner,
  .qodef-e.qodef-image-wrapper .qodef-round-borders-wrapper-inner
):hover,
.am-film-open:focus-visible .am-film-thumb{
  transform:translateY(-6px);
  /* the lift's shadow, and the gold edge — see the note above on why the edge
     is an inset shadow rather than a border */
  box-shadow:0 30px 24px -18px rgba(13,32,28,.45),
             inset 0 0 0 1px rgba(181,138,58,.6);
}

:is(
  .am-dish,
  .am-menu-shot,
  .am-film-thumb,
  .am-chef,
  .qodef-e-media-image,
  .qodef-stacked-images .qodef-m-image,
  .qodef-stacked-images .qodef-m-main-image,
  .qodef-single-image .qodef-m-image,
  .qodef-image-gallery.qodef-border-radius-predefined-2 .qodef-round-borders-wrapper-inner,
  .qodef-gallery-masonry .qodef-e-inner,
  .qodef-e.qodef-image-wrapper .qodef-round-borders-wrapper-inner
):hover::after,
.am-film-open:focus-visible .am-film-thumb::after{
  transform:translateX(120%);
  /* 1.6s, up from the .9s the original was built at — "giảm tốc độ hiệu ứng
     gương xuống hiện tại hơi nhanh", the mirror sweep is a touch fast. At .9s
     it crossed a 300px tile before the 6px lift had finished settling, so the
     two halves of the effect read as separate events. At 1.6s the sweep is
     still travelling as the card comes to rest, and on the gallery's wider
     tiles it no longer flicks past. */
  transition:transform 1.6s cubic-bezier(.16,1,.3,1);
}

/* the picture inside. Everything except the two frames that already own their
   transform — see note 2 above. */
:is(
  .am-dish,
  .am-menu-shot,
  .am-film-thumb,
  .am-chef,
  .qodef-e-media-image,
  .qodef-stacked-images .qodef-m-image,
  .qodef-image-gallery.qodef-border-radius-predefined-2 .qodef-round-borders-wrapper-inner,
  .qodef-gallery-masonry .qodef-e-inner,
  .qodef-e.qodef-image-wrapper .qodef-round-borders-wrapper-inner
) img{
  transition:transform 1s cubic-bezier(.16,1,.3,1);
  will-change:transform;
}
:is(
  .am-dish,
  .am-menu-shot,
  .am-film-thumb,
  .am-chef,
  .qodef-e-media-image,
  .qodef-stacked-images .qodef-m-image,
  .qodef-image-gallery.qodef-border-radius-predefined-2 .qodef-round-borders-wrapper-inner,
  .qodef-gallery-masonry .qodef-e-inner,
  .qodef-e.qodef-image-wrapper .qodef-round-borders-wrapper-inner
):hover img,
.am-film-open:focus-visible .am-film-thumb img{
  transform:scale(1.08);
}

/* The sweep is decoration; the lift and the zoom are the affordance. Under
   reduced motion the card still answers the pointer, quietly. */
@media (prefers-reduced-motion: reduce){
  :is(
    .am-dish, .am-menu-shot, .am-film-thumb, .am-chef,
    .qodef-e-media-image,
    .qodef-stacked-images .qodef-m-image,
    .qodef-stacked-images .qodef-m-main-image,
    .qodef-single-image .qodef-m-image,
    .qodef-image-gallery.qodef-border-radius-predefined-2 .qodef-round-borders-wrapper-inner,
    .qodef-gallery-masonry .qodef-e-inner,
    .qodef-e.qodef-image-wrapper .qodef-round-borders-wrapper-inner
  )::after{ display:none; }
  :is(
    .am-dish, .am-menu-shot, .am-film-thumb, .am-chef,
    .qodef-e-media-image,
    .qodef-stacked-images .qodef-m-image,
    .qodef-stacked-images .qodef-m-main-image,
    .qodef-single-image .qodef-m-image,
    .qodef-image-gallery.qodef-border-radius-predefined-2 .qodef-round-borders-wrapper-inner,
    .qodef-gallery-masonry .qodef-e-inner,
    .qodef-e.qodef-image-wrapper .qodef-round-borders-wrapper-inner
  ){ transition:box-shadow .3s ease; }
  :is(
    .am-dish, .am-menu-shot, .am-film-thumb, .am-chef,
    .qodef-e-media-image,
    .qodef-stacked-images .qodef-m-image,
    .qodef-stacked-images .qodef-m-main-image,
    .qodef-single-image .qodef-m-image,
    .qodef-image-gallery.qodef-border-radius-predefined-2 .qodef-round-borders-wrapper-inner,
    .qodef-gallery-masonry .qodef-e-inner,
    .qodef-e.qodef-image-wrapper .qodef-round-borders-wrapper-inner
  ):hover{ transform:none; }
  :is(
    .am-dish, .am-menu-shot, .am-film-thumb, .am-chef,
    .qodef-e-media-image,
    .qodef-stacked-images .qodef-m-image,
    .qodef-image-gallery.qodef-border-radius-predefined-2 .qodef-round-borders-wrapper-inner,
    .qodef-gallery-masonry .qodef-e-inner,
    .qodef-e.qodef-image-wrapper .qodef-round-borders-wrapper-inner
  ):hover img{ transform:none; }
}


/* =========================================================================
   20. OUR FOOD PHILOSOPHY — the photograph sits inside its band

   Asked for: "nó trồi lên vậy" — it juts up out of the band.

   Measured: the band is 740px tall and the photograph is 790px, sitting 160px
   above the band's top edge and stopping 110px short of its bottom. That is not
   a bug in the port — the demo does it on purpose, with
   `margin-top:-96px` on the image widget (and -50px, -70px, -120px at the other
   breakpoints) so the picture overlaps whatever section came before. In the
   demo that section was another dark band and the overlap read as a deliberate
   step. Here the section above is white, so the photograph appears to have
   slipped its frame.

   The negative margins go, and the picture is centred in the band and held
   inside it.
   ========================================================================= */
.elementor-element-2aa05c4 .elementor-element-f480d20 > .elementor-widget-container{
  margin-top:0 !important;
}
.elementor-element-2aa05c4{
  align-items:center !important;
  padding-block:clamp(2rem, 4vw, 3.5rem) !important;
}
.elementor-element-2aa05c4 .elementor-element-f480d20 img{
  display:block;
  width:100%;
  height:auto;
  max-height:min(74vh, 620px);
  object-fit:cover;
}


/* =========================================================================
   21. THE BAND REVEALS AS YOU REACH IT

   Asked for by pointing at the horizontal showcase strip — COCKTAILS, WINE
   LIST, MENU — and at the reference site: do what ambrosia-dc-pi.vercel.app
   does when you scroll down to its "A5 Wagyu" banner.

   The source for that site was handed over rather than left to be guessed at
   (github.com/TinNK3/ambrosia-dc), so these are its numbers, copied out of
   app/globals.css `.rv`, not an impression of them:

       opacity     0 -> 1
       transform   translateY(26px) -> none
       duration    .9s, both properties
       easing      cubic-bezier(.16, 1, .3, 1)

   That easing is already all over this stylesheet — it is the same curve the
   dish effect uses — so the band and the tiles move in the same hand.

   The observer that adds .is-in is ambrosia-reveal.js, also to the reference's
   numbers: threshold .12, rootMargin 0 0 -8% 0, and unobserved once it has
   fired so it plays on arrival and never repeats.

   Delays are here for stacking several elements in one band, in the reference's
   steps of 90ms. Nothing uses them yet; adding .am-rv-2 to a child is the whole
   change if a staggered reveal is wanted later.

   Two things not taken from that site:

   - **Lenis.** The reference lerps the entire document with a smooth-scroll
     library. It is most of what gives that page its feel, and it is also a
     dependency that rewrites scrolling everywhere, overrides anchor jumps and
     the keyboard, and cannot be opted out of by a reader who dislikes it. The
     reveal was what was pointed at.
   - **The banner's hover zoom** (`transition:transform 6s; :hover img{ scale(1.06) }`).
     These photographs already drift — ambrosia-cinema.css runs am-kenburns on
     them for 26s on an infinite alternate — and a hover transform on the same
     property would simply be overridden by the running animation, exactly as
     it would have been on the arch photographs in §19.
   ========================================================================= */
.am-rv{
  opacity:0;
  transform:translateY(26px);
  transition:opacity .9s cubic-bezier(.16,1,.3,1),
             transform .9s cubic-bezier(.16,1,.3,1);
}
.am-rv.is-in{
  opacity:1;
  transform:none;
}
.am-rv-2{ transition-delay:.09s; }
.am-rv-3{ transition-delay:.18s; }
.am-rv-4{ transition-delay:.27s; }

/* Never leave a band invisible because a decoration did not run. The script has
   a 2600ms failsafe of its own; this covers the case where it never loads. */
@media (prefers-reduced-motion: reduce){
  .am-rv{ opacity:1 !important; transform:none !important; transition:none !important; }
}

/* =========================================================================
   23. BOOK A TABLE — the address band was half a page of white

   Reported as "nhấn vào book table thì cái quái gì đang diễn ra vậy". The band under
   the reservation form opened as a blank white left half, an enormous plate filling the
   right, the kitchen clip floating over the middle of it, and the address, hours and
   VIEW MAP button set in black on top of the photograph.

   None of it is a stacking bug. It is one decorative background doing what the theme
   asks, on a ground the theme never had.

   `h3-bcgr-img.jpg` is 1207x1147 and the theme sets it, on this container only:

       background-position: center right;   background-size: auto;

   `auto` means natural size, so on any viewport wider than the image it paints the
   right 1207px and leaves the rest empty. On the Fidalgo demo "empty" was the dark
   maroon body colour and the band read as a deliberate two-tone split. Here the body
   is white, so it reads as a page that failed to load. There is a second rule under
   `@media(max-width:1514px)` that switches to `cover` at `34vw 0vh` — same split, drawn
   a different way, and the reason the fault changes shape with the window: above 1514px
   the seam sits where the image ends, below it the seam sits at 34% of the viewport.

   So the image is given the whole band, and once it has the whole band the type on top
   of it needs a ground of its own. `--qode-additional-background-color` is not involved
   here — this container paints itself — so the scrim is a gradient layer stacked above
   the photograph in the same `background-image`, rather than a `::before`: the section
   is `display:flex` with positioned children of its own, and adding a pseudo-element
   would have put a fifth thing into a stacking order that already has four.

   The band then joins the dark-band list in §2 like every other one, which is what
   turns the address, the hours and the button label cream. §1's light-ground rules
   exclude it by id in the same breath, so there is no specificity fight — the same
   arrangement the hero (04fd0aa) already uses.
   ========================================================================= */
.elementor-4861 .elementor-element.elementor-element-bf639ef:not(.elementor-motion-effects-element-type-background),
.elementor-element-bf639ef:not(.elementor-motion-effects-element-type-background){
  background-image:
    /* .72 rather than a lighter veil, measured rather than judged: the photograph is a
       table under warm light and its bright quarter is what light type has to clear.
       Sampling the painted pixels behind each of the seven lines, .62 put the address on
       4.78:1 against the brightest tenth of its own ground — over AA, but with almost
       nothing in hand, and the band cycles no images so that margin never improves. */
    linear-gradient(rgba(6,35,31,.72), rgba(6,35,31,.72)),
    url("/wp-content/uploads/2023/10/h3-bcgr-img.jpg") !important;
  background-size:cover !important;
  background-position:center !important;
  background-repeat:no-repeat !important;
}
/* The outlined VIEW MAP button sits on the band now, so it takes the dark-band
   treatment: gold hairline, cream label, and the forest fill on hover that §1 gives
   every other outlined button. */
.elementor-element-bf639ef .qodef-button.qodef-layout--outlined{
  border-color:var(--ambrosia-gold-lite) !important;
}
.elementor-element-bf639ef .qodef-button.qodef-layout--outlined:hover,
.elementor-element-bf639ef .qodef-button.qodef-layout--outlined:focus-visible{
  background-color:var(--ambrosia-gold-lite) !important;
  border-color:var(--ambrosia-gold-lite) !important;
}
.elementor-element-bf639ef .qodef-button.qodef-layout--outlined:hover .qodef-m-text,
.elementor-element-bf639ef .qodef-button.qodef-layout--outlined:focus-visible .qodef-m-text{
  color:#06231f !important;
}

/* =========================================================================
   9. CONTACT US ON THE RIGHT OF THE LOGO
   Asked for by the client so the wordmark reads as the centre of the header:
   with all six items on the left the logo looked pushed right even though it is
   centred to the pixel. Contact Us now lives in the right-hand widget holder
   (see tools/contact_right.py), which the theme lays out as a flex row ending
   flush right.

   The theme's own rule gives every .qodef-header-navigation inside the header
   width:100% and justify-content:flex-start, which strands this one item hard
   against the logo and overflows the holder. Shrink it to its content and let
   the holder's flex-end do the placing; the margin is the 44px the left-hand
   menu uses between its own items, so the gap before the button matches the
   menu's rhythm.

   The .qodef-header--split-left-to-right prefix is not decoration: without it
   this rule is a class short of the theme's and loses on specificity, which is
   exactly how the first attempt failed — flex and margin took, width and
   justify-content did not.
   ========================================================================= */
.qodef-header--split-left-to-right #qodef-page-header-inner .qodef-header-navigation--right,
.qodef-header--split-left-to-right .qodef-header-sticky-inner .qodef-header-navigation--right{
  width:auto;
  flex:0 0 auto;
  justify-content:flex-end;
  margin-right:44px;
}

/* =========================================================================
   10. THE OVERSIZED WATERMARK WORDS
   CHEF'S, CUISINE, RESERVE, THEY SAY — 90–100px Cormorant ghost words set
   behind each section's real heading, split per character into
   `.qodef--word > .qode--char-inner` for the theme's reveal animation. They
   are the only elements on the site using `.qode--char-inner`, so that class
   is a safe handle.

   They were cream, which is right on the ground the theme was built for and
   invisible on the one this port lifted the pages onto: measured 1.17:1 on the
   white page, i.e. not there at all. That is not a designed watermark, it is
   an accident of the port — "CHEF'S" simply vanished above its own heading.

   So they take the brand gold, which measures 3.15:1 on white — over the 3.0
   large text needs, and no further. A watermark that cleared 4.5 would stop
   being a watermark and start competing with the heading it sits behind, so
   passing by a small margin is the point here, not a compromise.
   ========================================================================= */
.qodef--word .qode--char-inner{
  color:var(--ambrosia-gold) !important;
}
/* RESERVE and THEY SAY are on the dark bands, where cream was never the
   problem — 10.94:1 on the band's own green. What breaks THEY SAY is the
   photograph showing through the top of the testimonials band, which is bright
   enough in places to take the same cream down to 1.32:1. A shadow in the
   band's own forest holds it over both without changing the colour. */
:is(.elementor-element-60c14a5, .elementor-element-67021e7)
  .qodef--word .qode--char-inner{
  color:var(--ambrosia-cream) !important;
  text-shadow:0 1px 14px rgba(6,35,31,.78), 0 1px 4px rgba(6,35,31,.62);
}

/* =========================================================================
   11. THE TESTIMONIALS BAND IS A PHOTOGRAPH, NOT THE DARK COLOUR §8 CLAIMS
   §8 lists .elementor-element-67021e7 as "testimonials band (#1f3634)" and
   paints everything inside it cream on that basis. The band really does carry
   background-color:#1f3634 — and then paints
   h1-testtimonials-bc-img.jpg straight over it, a bright banquet table that
   the port swapped in for the demo's dark original. background-image covers
   background-color, so the colour §8 keyed off has not been visible since.

   Every cream thing on the band was therefore sitting on a bright photograph:
   the THEY SAY watermark measured 1.32-2.74:1, the review stars 1.73:1, the
   avatar initials 1.86:1. Exactly the failure §23 fixed on book-a-table, from
   exactly the same cause, so it takes the same treatment and the same veil.

   .72 is not copied for tidiness, it is measured on this photograph: sampling
   the image itself, a .72 forest veil puts cream at 7.80:1 on the median
   ground and still 6.58:1 against the brightest tenth, which is the part that
   decides whether the watermark survives. .55 would leave that brightest tenth
   at 4.03:1, under AA.

   The veil is on the band's OWN background only, so the testimonial
   photographs and the dark review cards laid on top of it are untouched — the
   band goes back to being the dark ground its design assumes, and the food
   stays bright.
   ========================================================================= */
.elementor-4861 .elementor-element.elementor-element-67021e7:not(.elementor-motion-effects-element-type-background),
.elementor-element-67021e7:not(.elementor-motion-effects-element-type-background){
  background-image:
    linear-gradient(rgba(6,35,31,.72), rgba(6,35,31,.72)),
    url("/wp-content/uploads/2023/11/h1-testtimonials-bc-img.jpg") !important;
  background-size:cover !important;
  background-position:center !important;
  background-repeat:no-repeat !important;
}

/* The review cards carry their own designed colours — a dark monogram on the
   gold disc, gold stars on the card — and both were being repainted cream.

   Worth writing down which rule actually won, because the obvious suspect did
   not. It looks like §8's blanket "everything on this band is cream", and
   scoping these to the band id to outrank it changed nothing. Asking the
   browser to list every rule setting `color` on the avatar named the real
   winner:

       .qodef-testimonials-slider-advance .qodef-testimonials-list
       .qodef-e-content :is(p, span, …)          four classes deep

   — against which both `.am-review-avatar` (one) and the band-scoped version
   (two) were never in the running. Matching those four and landing later in
   the file is what decides it. Measured on the disc's own gold, the monogram
   goes from 2.00:1 to 4.93:1. */
.qodef-testimonials-slider-advance .qodef-testimonials-list .qodef-e-content .am-review-avatar{
  color:#0d2622 !important;
}
.qodef-testimonials-slider-advance .qodef-testimonials-list .qodef-e-content .am-review-stars{
  color:var(--ambrosia-gold-lite) !important;
}

/* =========================================================================
   12. THE BOOK A TABLE BAND, WITHOUT ITS VIDEO
   Asked for: "in page booktable plz remove video on it." The clip is gone from
   the markup (tools/book_video.py) — this is the hole it left.

   The band was built as two columns, a portrait kitchen clip on the left and
   the address block on the right, and Elementor sized it to the clip:
   --min-height:1140px. With the video out, the address, hours and VIEW MAP come
   to 287px of content inside a 1140px band — seven hundred pixels of empty
   photograph underneath, which reads as a page that failed to load rather than
   one that was tidied.

   Overriding the custom property rather than min-height itself, because that is
   how Elementor sets it and the cascade then needs no argument. 560px is the
   content plus the 140px it already sits down from the top of the band, and the
   same again below it, so the block keeps its position and the photograph keeps
   a margin on both sides of it. Only book-a-table carries this id.
   ========================================================================= */
.elementor-element-bf639ef{
  --min-height:560px !important;
}

/* =========================================================================
   13. REAL REVIEWS — the author line, and Google's credit
   Both of these only show up once tools/google_reviews.py has put real reviews
   on the page, which is why they were not needed before.

   The theme prints a "/" before the author's NAME and another before their JOB.
   That reads as "/ BY DORA JOHNS / SOMALIER" — fine for the demo, where every
   invented guest was given an invented job title. A Google reviewer has no job
   title, so the script blanks it, and the theme was left drawing a slash before
   nothing: "/ BY FIXTURE REVIEWER TWO /", a separator separating one thing.
   `:empty` retires it exactly when there is nothing to separate.

   The credit is required: Google's terms want their review data attributed
   wherever it is shown. It deliberately sets no colour of its own — this line
   lands on the white ground on About Us and inside the dark testimonials band on
   the home page, so it inherits whichever the section already uses and stays
   readable on both without a second rule.
   ========================================================================= */
.qodef-testimonials-list .qodef-e-author-job:empty:before{ content:none; }

.am-review-credit{
  margin:0 0 .35rem;
  text-align:center;
  font-size:.78rem; letter-spacing:.12em; text-transform:uppercase;
  opacity:.62;
}
.am-review-credit a{ color:inherit; text-decoration:underline; text-underline-offset:3px; }
