/**
 * Tư-Trà Hero Header Suppress
 *
 * Keeps the header at full size while a "fullsize hero" section is
 * visible above the header. .scrolling only activates once the next
 * section's top crosses the bottom of the header — i.e., the moment
 * the next section actually starts sliding under the sticky header.
 *
 * Usage:
 *   In Bricks Builder, add the CSS class `tt-fullsize-hero` to the
 *   hero section. The script automatically pairs it with the next
 *   sibling section to detect when the hero region ends.
 *
 * Architecture:
 *   - Threshold: next-sibling.rect.top vs header.rect.bottom
 *     > 0  : hero region dominant — suppress .scrolling
 *     <= 0 : next section overlapping header — allow .scrolling
 *
 *   - Synchronous scroll listener (no rAF throttle): runs in the same
 *     event tick as Bricks's handler, so .scrolling is stripped before
 *     the browser paints. No frame-ordering race, no hesitation on iOS
 *     momentum scroll.
 *
 *   - MutationObserver on body + header class attribute: backup for
 *     when Bricks toggles .scrolling outside of scroll events (rAF,
 *     setTimeout, transitionend). Fires as a microtask, before paint —
 *     the briefly-added class is gone before the user sees it.
 *
 *   - Auto-no-op on pages without a hero (early return).
 *   - No CSS changes required.
 *
 * Version: 1.2.0
 * Author: Charlie + Claude
 *
 * History
 * v1.0.0: IntersectionObserver on hero. Broke for sticky heroes —
 *         IO reports the hero as intersecting for its entire stuck
 *         duration because the bounding rect stays at top:0.
 * v1.1.0: Switched to next-sibling rect check. Fixed sticky case.
 *         Worked on desktop, but rAF throttle exposed a frame-ordering
 *         race against Bricks's own rAF on iOS momentum scroll —
 *         visible hesitation when scrolling back to top.
 * v1.2.0: Synchronous scroll handler eliminates the rAF race.
 *         MutationObserver covers Bricks's non-scroll additions of
 *         .scrolling. Threshold raised from y=0 to header.bottom so
 *         shrink begins at the correct visual moment (next section
 *         meeting the header, not crossing the viewport top).
 */
(function () {
  'use strict';

  var HERO_SELECTOR   = '.tt-fullsize-hero';
  var SCROLLING_CLASS = 'scrolling';
  var HEADER_SELECTOR = '#brx-header, header.brxe-header';

  function init() {
    var heroes = document.querySelectorAll(HERO_SELECTOR);
    if (heroes.length === 0) return;

    // Pair each hero with its next sibling. Next sibling acts as the
    // visual signal for "hero region has ended" — works for both
    // sticky and non-sticky heroes.
    var pairs = [];
    for (var i = 0; i < heroes.length; i++) {
      pairs.push({ hero: heroes[i], next: heroes[i].nextElementSibling });
    }

    var headerEls = document.querySelectorAll(HEADER_SELECTOR);
    var heroActive = false;

    function isHeroActive() {
      // Read header bottom each call. The header may itself shrink
      // (changing its height) when .scrolling is on, but we only ever
      // need this measurement at the threshold moment, where the
      // header is still full-size.
      var headerBottom = 0;
      if (headerEls.length > 0) {
        headerBottom = headerEls[0].getBoundingClientRect().bottom;
      }
      for (var j = 0; j < pairs.length; j++) {
        var p = pairs[j];
        var endRef = p.next
          ? p.next.getBoundingClientRect().top
          : p.hero.getBoundingClientRect().bottom;
        if (endRef > headerBottom) return true;
      }
      return false;
    }

    function clearScrolling() {
      if (document.body.classList.contains(SCROLLING_CLASS)) {
        document.body.classList.remove(SCROLLING_CLASS);
      }
      for (var k = 0; k < headerEls.length; k++) {
        headerEls[k].classList.remove(SCROLLING_CLASS);
      }
    }

    function update() {
      heroActive = isHeroActive();
      if (heroActive) clearScrolling();
    }

    // Synchronous scroll listener: no rAF. Runs in the same tick as
    // Bricks's handler; ordering doesn't matter because the
    // MutationObserver below catches any add we miss.
    window.addEventListener('scroll', update, { passive: true });
    window.addEventListener('resize', update);

    // Backup: if anything (Bricks's rAF, a transitionend handler, etc.)
    // adds .scrolling while heroActive, strip it immediately as a
    // microtask, before the next paint.
    var classObserver = new MutationObserver(function () {
      if (heroActive) clearScrolling();
    });
    classObserver.observe(document.body, {
      attributes: true,
      attributeFilter: ['class']
    });
    for (var m = 0; m < headerEls.length; m++) {
      classObserver.observe(headerEls[m], {
        attributes: true,
        attributeFilter: ['class']
      });
    }

    update(); // Handle reload-mid-page
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', init);
  } else {
    init();
  }
})();
La Fleur

Ô long Sữa Hoa nhài

Mang hương nhài trắng, vị tươi nhẹ và hậu béo sữa dịu dàng.
Thức uống này được phục vụ với hai kích cỡ
Order on GrabFood 45,000₫

Chiều muộn dịu dàng trên vùng trà Bảo Lộc. Những cơn gió nhẹ lướt qua cánh đồng hoa nhài ven đồi, mang theo hương thơm thanh khiết lan khắp không gian tĩnh lặng.

Trà Ô Long được ủ cùng cánh hoa nhài tươi, sau đó chiết xuất bằng phương pháp ủ nóng chậm, hoà quyện với lớp kem sữa mịn màng — tạo nên một tổng thể nhẹ tênh nhưng đầy cuốn hút.

Ô Long Sữa Nhài mang đến cảm giác trong trẻo như sương sớm, thoảng mùi hoa trắng, dịu mát như bóng râm ngày hạ, và hậu vị mềm mại vương lại trên đầu lưỡi.

Một bản giao hưởng tinh khôi giữa thiên nhiên và thời gian — tĩnh tại, thư thả, gợi nhắc về sự giản đơn nhưng đầy chiều sâu của những phút nghỉ ngơi thật sự.