/* ==========================================================================
   Sehat — protótipo expresso
   Fonte da verdade: .vortex/ui-sehat-prancha.html
   Paleta: navy #253952 · branco #FFFFFF · branco quente #FAF8F5
           neutro quente #E9E2D7 · muted #6B7A8D · overlay #16243C/#0F1A2E
   Tipografia: Fraunces (títulos) + DM Sans (interface/corpo)
   Breakpoints: mobile <768 · tablet 768–1023 · desktop 1024+
   ========================================================================== */

:root{
  --navy:#253952;
  --white:#FFFFFF;
  --warm-white:#FAF8F5;
  --warm-neutral:#E9E2D7;
  --muted:#6B7A8D;
  --accent-warm:#D97757;
  --line:rgba(37,57,82,.10);
  --serif:'Fraunces',Georgia,'Times New Roman',serif;
  --sans:'DM Sans',-apple-system,'Segoe UI',Roboto,Arial,sans-serif;

  --ease-move:.5s ease-out;
  --header-h:96px;
}

@media (max-width:767px){
  :root{--header-h:72px}
}
@media (min-width:768px) and (max-width:1023px){
  :root{--header-h:84px}
}

*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth}
body{
  margin:0;
  font-family:var(--sans);
  color:var(--navy);
  background:var(--warm-white);
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
img{max-width:100%;display:block}
h1,h2,h3,p{margin:0}

/* ---------- foco visível (base) ---------- */
:focus-visible{outline:2px solid var(--navy);outline-offset:3px}

/* ---------- skip link ---------- */
.skip-link{
  position:absolute;left:16px;top:-60px;z-index:100;
  background:var(--navy);color:var(--white);
  padding:12px 18px;border-radius:8px;
  font-family:var(--sans);font-size:14px;font-weight:500;
  text-decoration:none;
  transition:top .2s ease;
}
.skip-link:focus{top:16px}

/* ==========================================================================
   CABEÇALHO
   ========================================================================== */
.site-header{
  position:fixed;
  top:0;left:0;right:0;
  z-index:60;
  height:var(--header-h);
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:16px;
  padding:0 40px;
  background:transparent;
  transition:background-color .35s ease,box-shadow .35s ease;
}
@media (max-width:1023px){
  .site-header{padding:0 20px}
  /* .btn-header some do fluxo do header no mobile/tablet: com a nav virando
     drawer fixo (fora do fluxo), manter o botão (mesmo invisível até o
     scroll) desalinharia o hambúrguer do canto direito via space-between
     (viraria 3 itens: logo/hambúrguer/botão-fantasma, empurrando o
     hambúrguer pro meio) e, rolada a página, o botão real (mesmo com
     opacity/visibility escondendo-o só visualmente) ainda ocupava espaço
     de layout e vazava ~25px pra fora da viewport em 320px. O CTA "Fazer
     pedido" já existe dentro do drawer (.menu-drawer__cta).
     Seletor `a.btn-header` (elemento+classe, especificidade 0-1-1) em vez
     de `.btn-header` (0-1-0): a regra base `.btn{display:inline-block}`
     (mais abaixo no arquivo) tem a MESMA especificidade que `.btn-header`
     sozinho e, por vir depois no arquivo, vencia a cascata mesmo dentro
     desta media query — o botão nunca chegava a sumir de verdade. Isso
     causava os 2 bugs (5 e 7) na mesma raiz. */
  a.btn-header{display:none}
}
@media (min-width:1024px){
  .site-header{gap:24px}
}
.site-header.is-scrolled{
  background:var(--navy);
  box-shadow:0 4px 24px rgba(15,26,46,.16);
}
/* Logo e botão ficam sempre no fluxo flex (nunca display:none) para não
   deslocar a nav (posicionada em absolute, centralizada de forma
   independente) — apenas opacity/visibility/transform escondem o
   conteúdo visualmente enquanto a hero ainda está visível. */
.site-header__logo{
  display:flex;
  align-items:center;
  line-height:0;
  flex-shrink:0;
  opacity:0;
  visibility:hidden;
  transform:translateY(-8px);
  pointer-events:none;
  transition:opacity .4s ease,transform .4s ease,visibility 0s linear .4s;
}
.site-header.is-scrolled .site-header__logo{
  opacity:1;
  visibility:visible;
  transform:translateY(0);
  pointer-events:auto;
  transition:opacity .4s ease,transform .4s ease;
}
.site-header__logo img{
  height:44px;
  width:auto;
  filter:drop-shadow(0 1px 6px rgba(15,26,46,.35));
}
.site-header__nav{
  display:flex;
  align-items:center;
  gap:40px;
  position:absolute;
  left:50%;
  top:50%;
  transform:translate(-50%,-50%);
}
.site-header__nav a{
  position:relative;
  font-family:var(--sans);
  font-size:15px;
  font-weight:500;
  letter-spacing:.03em;
  color:var(--white);
  text-decoration:none;
  text-shadow:0 1px 4px rgba(15,26,46,.4);
  opacity:.92;
  transition:opacity .2s ease,color .25s ease;
}
.site-header__nav a::after{
  content:'';
  position:absolute;
  left:0;
  right:0;
  bottom:-7px;
  height:2px;
  background:var(--accent-warm);
  transform:scaleX(0);
  transform-origin:center;
  transition:transform .3s ease;
}
.site-header__nav a:hover{color:var(--accent-warm);opacity:1}
.site-header__nav a:hover::after{transform:scaleX(1)}
.site-header__nav a.is-current::after{transform:scaleX(1)}
.site-header__nav a:focus-visible{
  outline:2px solid var(--white);
  outline-offset:4px;
  border-radius:2px;
}

/* ---------- Menu hambúrguer (mobile/tablet <1024px) ---------- */
.menu-toggle{
  display:none;
  flex-shrink:0;
  width:44px;height:44px;
  align-items:center;justify-content:center;
  background:transparent;border:none;padding:0;cursor:pointer;
  position:relative;
  z-index:110;
}
.menu-toggle span{
  position:absolute;left:50%;top:50%;
  width:22px;height:2px;
  background:var(--white);
  border-radius:2px;
  transform:translate(-50%,-50%);
  box-shadow:0 1px 4px rgba(15,26,46,.4);
  transition:transform .3s ease,opacity .3s ease;
}
.menu-toggle span:nth-child(1){transform:translate(-50%,calc(-50% - 7px))}
.menu-toggle span:nth-child(3){transform:translate(-50%,calc(-50% + 7px))}
.menu-toggle[aria-expanded="true"] span:nth-child(1){transform:translate(-50%,-50%) rotate(45deg)}
.menu-toggle[aria-expanded="true"] span:nth-child(2){opacity:0}
.menu-toggle[aria-expanded="true"] span:nth-child(3){transform:translate(-50%,-50%) rotate(-45deg)}
.menu-toggle:focus-visible{outline:2px solid var(--white);outline-offset:4px;border-radius:4px}
/* Com o drawer aberto, o X dedicado do painel (.menu-drawer__close) assume
   sozinho o fechamento — ele fica ancorado à borda real do painel, já o
   toggle do header (mesma posição/tamanho aproximados, por causa do
   padding do header) ficava fisicamente sobreposto a ele, interceptando
   cliques (bug real encontrado ao testar). Esconder o toggle enquanto
   aberto elimina a duplicidade/sobreposição sem remover a animação de
   abrir (hambúrguer→X só é visível durante a transição de abertura). */
.menu-toggle[aria-expanded="true"]{
  opacity:0;
  pointer-events:none;
  transition:opacity .2s ease;
}

.site-header__nav-scrim{
  display:none;
  position:fixed;inset:0;
  background:rgba(15,26,46,.5);
  opacity:0;pointer-events:none;
  transition:opacity .3s ease;
  z-index:105;
}
.site-header__nav-scrim.is-open{opacity:1;pointer-events:auto}

/* Mesmo problema de especificidade do `.btn-header` acima: `.btn` (mais
   abaixo no arquivo) empatava em especificidade com `.menu-drawer__cta`
   sozinho e vencia por ordem de cascata, fazendo um 2º botão "Fazer
   pedido" (navy sobre navy) vazar para a nav desktop (1024px+), quebrando
   em 2 linhas e desalinhando a nav já aprovada. `a.menu-drawer__cta`
   (0-1-1) resolve. */
a.menu-drawer__cta{display:none}

/* Mesmo padrão: o X do drawer só existe dentro do @media mobile, então
   fora dele cai no estilo padrão do navegador e vaza pra nav desktop. */
button.menu-drawer__close{display:none}

body.nav-open{overflow:hidden}

@media (max-width:1023px){
  .menu-toggle{display:inline-flex}
  .site-header__nav-scrim{display:block}
  .site-header__nav{
    position:fixed;
    top:0;right:0;bottom:0;
    left:auto;
    transform:translateX(100%);
    width:min(320px,86vw);
    height:100dvh;
    height:100vh;
    background:var(--navy);
    display:flex;
    flex-direction:column;
    align-items:flex-start;
    justify-content:flex-start;
    gap:2px;
    padding:calc(var(--header-h) + 12px) 28px 32px;
    transition:transform .35s ease;
    overflow-y:auto;
    z-index:106;
    box-shadow:-12px 0 40px rgba(15,26,46,.3);
  }
  .site-header__nav.is-open{transform:translateX(0)}
  .site-header__nav a{
    width:100%;
    padding:14px 2px;
    font-size:17px;
    border-bottom:1px solid rgba(250,248,245,.14);
    text-shadow:none;
    opacity:1;
    min-height:44px;
    display:flex;
    align-items:center;
  }
  .site-header__nav a::after{display:none}
  /* X próprio do drawer, ancorado ao PAINEL (não ao header): o hambúrguer
     do header também vira X ao abrir, mas ele fica na posição do header
     (que tem padding lateral próprio, `right:0` do drawer não bate com
     o `right:20px` efetivo do toggle) — parecia "flutuar" fora do painel
     em vez de pertencer a ele. Este botão fica de verdade no canto
     superior direito do drawer, sempre alinhado com sua borda real. */
  button.menu-drawer__close{
    display:inline-flex;
    position:absolute;
    top:18px;right:20px;
    width:36px;height:36px;
    align-items:center;justify-content:center;
    background:transparent;border:none;padding:0;cursor:pointer;
    color:var(--warm-white);
  }
  .menu-drawer__close:focus-visible{outline:2px solid var(--white);outline-offset:3px;border-radius:4px}
  a.menu-drawer__cta{
    display:inline-flex;
    align-items:center;
    justify-content:center;
    width:100%;
    margin-top:22px;
    border:none;
  }
}
/* ==========================================================================
   HERO
   ========================================================================== */
.hero{
  position:sticky;
  top:0;
  z-index:1;
  height:100vh;
  height:100svh;
  height:100dvh;
  display:flex;
  overflow:hidden;
  background:#16243C url('data:image/webp;base64,UklGRoAAAABXRUJQVlA4IHQAAAAQBgCdASogABUAPu1kqU2ppaQiMAgBMB2JZACdMxEABggH6Ae//dgAFM1TCypWr6tfD6Jv4VLRacAA/uny1tISKvydaH2f0l6eQvWt9kXYh0Gyqy6DIW4hfFVIzSqW5g3fdbR+hE1THDGvrQquPmqe+NaAAA==') 50% 45%/cover no-repeat;
  scroll-margin-top:0;
}
@media (min-width:768px){
  .hero{
    /* Camada 1 (topo): imagem real; enquanto não decodifica, fica transparente
       e a camada 2 (LQIP embutido, sem requisição de rede) fica visível por baixo. */
    background-image:url('hero-sehat-prototipo.webp'), url('data:image/webp;base64,UklGRoAAAABXRUJQVlA4IHQAAAAQBgCdASogABUAPu1kqU2ppaQiMAgBMB2JZACdMxEABggH6Ae//dgAFM1TCypWr6tfD6Jv4VLRacAA/uny1tISKvydaH2f0l6eQvWt9kXYh0Gyqy6DIW4hfFVIzSqW5g3fdbR+hE1THDGvrQquPmqe+NaAAA==');
    background-position:50% 45%;
    background-size:cover;
    background-repeat:no-repeat;
  }
}
@media (max-width:767px){
  .hero-orders-transition{
    /* Wrapper que limita o efeito "Mais pedidos sobe por cima da hero
       parada" apenas a essas duas seções. Altura = altura da hero (sticky,
       100svh) + altura de #mais-pedidos, automaticamente (soma do fluxo
       normal dos dois filhos — não precisamos calcular/forçar height). A
       .hero, sticky dentro deste wrapper, gruda em top:0 só até o wrapper
       acabar; passado isso ela é liberada normalmente, ANTES do início de
       "Sobre nós" (que fica fora do wrapper, fluxo comum). Isso evita o bug
       antigo: aqui a hero NUNCA fica presa atrás de #sobre-nos/#avaliacoes/
       rodapé, porque o limite de sticky é este wrapper, não a página. */
    position:relative;
    isolation:isolate;
  }
  .hero{
    /* Sticky restrito ao wrapper acima (não mais à página inteira — essa
       era a causa do bug "seção vazia/vídeo atrás durante scroll rápido":
       sticky-página-inteira mantinha a hero pinada atrás de TODO o resto).
       Sticky preservado em tablet/desktop via bloco acima (min-width:768px). */
    position:sticky;
    top:0;
    height:100vh;
    height:100svh;
    z-index:0;
    contain:paint;
    isolation:isolate;
    /* LQIP mobile: camada única, sempre presente desde o 1º paint até o
       poster real (.hero__poster-picture, elemento <picture> por cima) chegar. */
    background-image:url('data:image/webp;base64,UklGRnQAAABXRUJQVlA4IGgAAAAQBQCdASoYACsAPtFMoU2oJCMiOrzIAQAaCWMAyjPWBfqVCPrArqlnidaepS8wzsbAAP7xQ7KBpzJbjxSweJUXraQzmuYMF1t60Iv1Y2yQgGK5uWC4+aJ/vB9sJh/f+PRkaSj/1+GAAA==');
    background-position:50% 45%;
    background-size:cover;
    background-repeat:no-repeat;
  }
  /* Reforço defensivo contra o padrão de bug já visto neste projeto
     (sticky + siblings com transform/will-change podendo ser promovidos a
     uma camada de composição isolada, pintando por cima da seção seguinte
     mesmo com z-index CSS correto no código-fonte — visto em engines
     WebKit reais). `.orders` já é `position:relative;z-index:2;
     isolation:isolate` (stacking context próprio), o que corrige isso em
     teoria; `contain:paint` reforça na prática, garantindo que NENHUM
     filho (carrossel, card, ::before do fundo) possa pintar fora da caixa
     de `.orders` nem ser composto numa camada separada que escape da
     ordem de pintura do elemento pai. Investigação real (Playwright,
     Chromium touch-fling via CDP em várias velocidades + WebKit + rede
     lenta/cache vazio, .vortex/status.md) NÃO reproduziu o bug do card
     sozinho no estado atual — fundo, título, carrossel e botão sempre
     sobem juntos em todas as medições. Mantido como reforço preventivo,
     sem custo (não altera layout, não quebra o scroll horizontal do
     carrossel, que usa translateX apenas no eixo X). */
  .orders{contain:paint}
}
.hero__poster-picture{
  position:absolute;inset:0;
  pointer-events:none;
}
.hero__poster-picture-img{
  display:block;
  width:100%;
  height:100%;
  object-fit:cover;
  object-position:50% 45%;
}
.hero__video-mobile{
  display:none;
  position:absolute;inset:0;
  width:100%;height:100%;
  object-fit:cover;
  opacity:0;
  transition:opacity .3s ease;
  pointer-events:none;
}
@media (max-width:767px){
  .hero__video-mobile.is-active{display:block}
  .hero__video-mobile.is-active.is-ready{opacity:1}
}
.hero__overlay{
  position:absolute;inset:0;
  background:#16243C;
  opacity:.44;
}
.hero__overlay::after{
  content:'';
  position:absolute;inset:0;
  background:radial-gradient(ellipse 64% 52% at 50% 46%,
    rgba(15,26,46,.46) 0%,
    rgba(15,26,46,.30) 50%,
    rgba(15,26,46,0) 78%);
}
/* Reforço discreto de legibilidade: degradê linear adicional, mais forte
   na base (onde tende a haver texto/UI) e se dissolvendo em direção ao
   centro, sem escurecer a foto como um todo. */
.hero__overlay::before{
  content:'';
  position:absolute;inset:0;
  background:linear-gradient(to top,
    rgba(15,26,46,.38) 0%,
    rgba(15,26,46,.12) 30%,
    rgba(15,26,46,0) 55%);
  pointer-events:none;
}
.hero__content{
  position:relative;
  z-index:2;
  width:100%;
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  text-align:center;
  padding:0 24px;
}
.hero__logo{
  width:340px;
  height:auto;
  opacity:0;
  animation:heroIn .32s ease-out 0s forwards;
}
.hero__tag{
  font-family:var(--sans);
  font-weight:500;
  font-size:17px;
  letter-spacing:.20em;
  text-transform:uppercase;
  color:var(--white);
  margin-top:26px;
  opacity:0;
  animation:heroIn .32s ease-out .06s forwards;
}
.hero__content .btn{
  margin-top:38px;
  opacity:0;
  animation:heroIn .32s ease-out .12s forwards;
}

@keyframes heroIn{
  from{opacity:0;transform:translateY(16px)}
  to{opacity:1;transform:translateY(0)}
}

/* Mobile: entrada praticamente imediata, sem stagger sequencial */
@media (max-width:767px){
  .hero__logo{animation:heroIn .28s ease-out 0s forwards}
  .hero__tag{animation:heroIn .28s ease-out 0s forwards}
  .hero__content .btn{animation:heroIn .28s ease-out 0s forwards}
}

/* Tablet: hero segue centralizado, logo intermediária */
@media (min-width:768px) and (max-width:1023px){
  .hero__logo{width:280px}
  .hero__tag{font-size:15px;letter-spacing:.18em}
}

/* Mobile: bloco desloca para o terço superior (área calma do prato) */
@media (max-width:767px){
  .hero__overlay::after{
    background:radial-gradient(ellipse 96% 34% at 50% 30%,
      rgba(15,26,46,.46) 0%,
      rgba(15,26,46,.30) 50%,
      rgba(15,26,46,0) 80%);
  }
  /* Centralizado verticalmente, mesma composição do tablet/desktop —
     `justify-content:flex-start;padding-top:17%` (versão anterior) deixava
     498-641px de vazio abaixo do bloco logo/subtítulo/botão em telas
     ≤767px, porque empurrava o conteúdo pro terço superior sem nada
     ocupando o espaço abaixo. Centralizar elimina o vazio e mantém a
     identidade igual à do desktop, sem alterar a imagem/crop. */
  .hero__content{
    justify-content:center;
  }
  .hero__logo{width:210px}
  .hero__tag{font-size:13px;letter-spacing:.16em;margin-top:20px}
  .hero__content .btn{margin-top:30px}
}

/* ==========================================================================
   TÍTULOS DE SEÇÃO
   ========================================================================== */
.section-title{
  position:relative;
  z-index:1;
  font-family:var(--serif);
  font-weight:400;
  font-size:44px;
  line-height:1.15;
  letter-spacing:-.01em;
  color:var(--navy);
  text-align:center;
}

@media (min-width:768px) and (max-width:1023px){
  .section-title{font-size:36px}
}
@media (max-width:767px){
  .section-title{font-size:30px}
}

/* ==========================================================================
   BOTÃO — sistema de inversão (pílula)
   ========================================================================== */
.btn{
  display:inline-block;
  font-family:var(--sans);
  font-size:15px;
  font-weight:500;
  letter-spacing:.06em;
  padding:16px 38px;
  border-radius:999px;
  border:1.5px solid transparent;
  cursor:pointer;
  text-decoration:none;
  transition:background-color .25s ease,color .25s ease,border-color .25s ease,transform .25s ease;
}

.btn-onphoto{
  background:rgba(255,255,255,.14);
  color:var(--white);
  border-color:rgba(255,255,255,.4);
  backdrop-filter:blur(12px);
  -webkit-backdrop-filter:blur(12px);
  box-shadow:0 4px 20px rgba(15,26,46,.14);
  transform-origin:center;
  transition:transform .25s ease;
}
.btn-onphoto:hover{
  transform:scale(1.05);
}
.btn-onphoto:focus-visible{
  outline:2px solid var(--white);
  outline-offset:4px;
  box-shadow:0 0 0 4px rgba(15,26,46,.55);
}

.btn-primary{
  background:var(--navy);
  color:var(--white);
  border-color:var(--navy);
}
.btn-primary:hover{
  background:transparent;
  color:var(--navy);
  border-color:var(--navy);
}
.btn-primary:focus-visible{
  outline:2px solid var(--navy);
  outline-offset:4px;
}
.btn-primary:active{
  transform:translateY(1px);
}

/* .btn-header vem DEPOIS de .btn no arquivo de propósito: como .btn tem
   border:1.5px solid transparent no shorthand e ambas as regras têm a
   mesma especificidade, a ordem no arquivo decide — precisa vir depois
   para que border-color:var(--white) não seja sobrescrita. */
.btn-header{
  flex-shrink:0;
  padding:12px 28px;
  font-size:14px;
  background:var(--white);
  color:var(--navy);
  border-color:rgba(255,255,255,.6);
  opacity:0;
  visibility:hidden;
  transform:translateY(-8px);
  pointer-events:none;
  transition:opacity .4s ease,transform .4s ease,visibility 0s linear .4s,box-shadow .25s ease;
}
.btn-header:hover{
  background:var(--white);
  color:var(--navy);
  border-color:rgba(255,255,255,.6);
  box-shadow:0 8px 22px rgba(15,26,46,.2);
}
.site-header.is-scrolled .btn-header{
  opacity:1;
  visibility:visible;
  transform:translateY(0);
  pointer-events:auto;
  transition:opacity .4s ease,transform .4s ease,box-shadow .25s ease;
}
.site-header.is-scrolled .btn-header:hover{
  transform:translateY(0) scale(1.045);
}
.btn-header:focus-visible{
  outline:2px solid var(--white);
  outline-offset:4px;
  box-shadow:0 0 0 4px rgba(15,26,46,.55);
}

/* ==========================================================================
   MAIS PEDIDOS
   ========================================================================== */
.orders{
  position:relative;
  z-index:2;
  isolation:isolate;
  background:var(--warm-white) url('palmeiras-fundo-site.webp') 50% 50% / cover no-repeat;
  padding:112px 24px;
  scroll-margin-top:var(--header-h);
}
@media (max-width:1023px){
  .orders{padding:72px 16px}
}
.orders::before{
  content:'';
  position:absolute;
  inset:0;
  /* .orders já tem cor opaca direto no elemento (background shorthand
     acima); este ::before é só o véu translúcido decorativo por cima da
     imagem. z-index:0 (não negativo) — os filhos abaixo recebem
     position:relative;z-index:1 para ficar por cima desta camada. */
  z-index:0;
  pointer-events:none;
  background:rgba(250,248,245,.78);
}
/* ---------- Carrossel ---------- */
.carousel{
  position:relative;
  z-index:1;
  max-width:1464px;
  margin:56px auto 0;
  padding:0 66px;
}
@media (min-width:768px) and (max-width:1127px){
  /* Limite estendido a 1127px (não 1023px como o resto do layout): com
     card de 460px + gap 28px + padding do carrossel/orders, 2 cards
     completos só cabem a partir de ~1128px de janela. Entre 1024-1127px
     (ainda "desktop" para header/grid/about), o carrossel usa o mesmo
     tratamento do tablet (1 card central) para nunca ficar numa "zona
     morta" sem nenhum card totalmente visível — ver visibleFullCards()
     em script.js, que usa o mesmo limiar de 1128px. */
  .carousel{padding:0 54px;margin-top:40px}
}
@media (max-width:767px){
  /* Goteira real reservada para as setas (não mais overlay sobre o card):
     com só 1 card ativo visível no mobile (ver visibleFullCards() em
     script.js) a área de "peek" nas bordas é estreita demais para uma
     seta de 38px não tocar o card ativo — reservar 40px de cada lado
     garante zero interseção com foto/texto em qualquer largura ≥320px. */
  .carousel{padding:0 40px;margin-top:28px}
  /* Reforço explícito (defensivo, mesmo valor de `overflow:hidden` já
     aplicado abaixo): o "peek" lateral dos cards é efeito só HORIZONTAL
     (trilho translateX). Declarar os dois eixos por extenso documenta a
     intenção e evita que uma futura edição solte `overflow-y` sem querer
     (ex.: trocando `overflow:hidden` por `overflow-x:visible` sozinho),
     o que permitiria um card vazar verticalmente para fora de `.orders`. */
  .carousel__viewport{overflow-x:hidden;overflow-y:hidden}
}
.carousel__viewport{
  overflow:hidden;
  position:relative;
}
.carousel__viewport::before,
.carousel__viewport::after{
  content:'';
  position:absolute;
  top:0;bottom:0;
  width:150px;
  z-index:4;
  pointer-events:none;
  opacity:0;
  transition:opacity .3s ease;
}
@media (max-width:1127px){
  .carousel__viewport::before,
  .carousel__viewport::after{width:56px}
}
.carousel__viewport::before{
  left:0;
  background:linear-gradient(to right, rgba(250,248,245,.55) 0%, rgba(250,248,245,0) 100%);
}
.carousel__viewport::after{
  right:0;
  background:linear-gradient(to left, rgba(250,248,245,.55) 0%, rgba(250,248,245,0) 100%);
}
/* Fade só aparece quando há de fato um card cortado naquela borda
   (classes alternadas via JS em update(), a cada troca de parada). */
.carousel__viewport.has-cut-start::before{ opacity:1; }
.carousel__viewport.has-cut-end::after{ opacity:1; }
.carousel__track{
  display:flex;
  gap:28px;
  will-change:transform;
  transition:transform .55s cubic-bezier(.4,0,.2,1);
}
.carousel__arrow{
  position:absolute;
  top:50%;
  transform:translateY(-50%);
  z-index:10;
  width:48px;
  height:48px;
  border-radius:50%;
  border:1px solid var(--line);
  background:var(--white);
  color:var(--navy);
  display:flex;
  align-items:center;
  justify-content:center;
  cursor:pointer;
  box-shadow:0 6px 18px rgba(37,57,82,.14);
  transition:background-color .2s ease,color .2s ease,transform .2s ease,opacity .2s ease;
}
.carousel__arrow:hover{
  background:var(--navy);
  color:var(--white);
}
.carousel__arrow:focus-visible{
  outline:2px solid var(--navy);
  outline-offset:3px;
}
.carousel__arrow[disabled]{
  opacity:.35;
  cursor:default;
  pointer-events:none;
}
.carousel__arrow--prev{left:0}
.carousel__arrow--next{right:0}

@media (min-width:768px) and (max-width:1127px){
  .carousel__arrow{width:44px;height:44px}
}
@media (max-width:767px){
  /* Alinhada ao centro da FAIXA DA FOTO (altura fixa 160px, ver .card
     abaixo), não ao centro do card inteiro — como o card ativo (com
     texto) e os cards peek (só foto) têm alturas totais diferentes no
     layout empilhado do mobile, `top:50%` do container inteiro deriva
     para dentro da área de texto do card ativo. Fixar em 80px (metade de
     160px) garante que a seta fique sempre sobre a foto, nunca sobre
     h3/p, em qualquer estado. */
  .carousel__arrow{width:38px;height:38px;top:80px}
  .carousel__arrow--prev{left:2px}
  .carousel__arrow--next{right:2px}
}

.card{
  flex:0 0 460px;
  width:460px;
  height:322px;
  background:var(--white);
  border:1px solid var(--line);
  border-radius:12px;
  overflow:hidden;
  display:flex;
  align-items:stretch;
}
@media (min-width:768px) and (max-width:1127px){
  .card{
    flex-basis:min(58vw,420px);
    width:min(58vw,420px);
  }
}
@media (max-width:767px){
  /* Empilha foto em cima / texto embaixo (em vez de lado a lado): com o
     layout imagem-esquerda(42%)/texto-direita(58%) original, a coluna de
     texto ficava espremida a ~110-150px de largura em telas estreitas,
     ilegível. Empilhado, o texto usa a largura quase total do card.
     Largura do card = viewport disponível (janela − padding de .orders
     16px×2 − goteira das setas 40px×2) menos uma pequena folga de "peek"
     nas laterais, com teto de 380px perto do limite de 767px (onde o
     layout tablet assume). */
  .card{
    flex-direction:column;
    align-items:stretch;
    flex-basis:min(calc(100vw - 128px),380px);
    width:min(calc(100vw - 128px),380px);
    height:auto;
    min-height:0;
  }
}
.card__photo{
  flex:0 0 42%;
  width:42%;
  height:100%;
  object-fit:cover;
  object-position:50% 50%;
  transition:flex-basis .3s ease,width .3s ease;
}
/* Camarão Thai Crispy: o arquivo camarao-sehat.png tem uma linha escura de
   ~3px colada na borda DIREITA da foto, embutida no próprio arquivo
   (confirmado pixel a pixel). Sem poder trocar/editar o arquivo, um leve
   zoom (scale) dentro do .card com overflow:hidden empurra a linha pra
   fora da área visível — variação imperceptível de enquadramento. */
img[src*="camarao-sehat"]{transform:scale(1.03)}
/* Camarão Thai Crispy (card "Mais pedidos"): mesmo arquivo
   camarao-thai-crispy-cardapio.png usado no cardápio/modal, com a mesma
   linha escura de ~3px embutida na borda direita da imagem (confirmado
   pixel a pixel, ver cardapio.css). Esta página (index.html) carrega
   style.css, não cardapio.css — por isso precisa da MESMA regra aqui,
   senão o artefato reaparece quando esse card passa a usar este arquivo.
   .card já tem overflow:hidden, então o leve zoom não vaza. */
img[src*="camarao-thai-crispy-cardapio"]{transform:scale(1.025)}
.card__body{
  flex:1 1 58%;
  min-width:0;
  padding:24px 24px 24px 22px;
  display:flex;
  flex-direction:column;
  justify-content:center;
  overflow-y:auto;
  background:var(--warm-white);
  /* Revelado por GEOMETRIA (flex-basis/padding + overflow:hidden), nunca
     por opacity. Uma versão anterior usava opacity:0→1 (com e sem delay)
     para revelar o painel: em QUALQUER ponto intermediário dessa
     transição, a caixa já tinha largura real mas opacity<1 — o fundo
     branco solido do .card (var(--white)) aparecia through o painel
     semitransparente, lido pelo usuário como um "flash branco" no card
     durante toda transição (não só no wrap). Com opacity sempre em 1, o
     painel entra/sai só pela largura (flex-basis) crescendo/encolhendo,
     sempre 100% opaco — nunca há uma janela de transparência para o
     branco do card aparecer. Ver .vortex/status.md — causa raiz do bug
     de cards piscando. */
  opacity:1;
  transition:flex-basis .3s ease,padding .3s ease;
}
/* Só os 2 cards totalmente visíveis/centrais de cada posição do
   carrossel mostram nome + descrição — os cards "peek" (parcialmente
   visíveis nas bordas) mostram só a foto, para nunca correr o risco de
   cortar uma palavra no meio (ver script.js, seção 4). Para não sobrar
   um painel branco vazio nos cards peek, a foto ocupa o card inteiro e
   o painel de texto colapsa a largura zero quando o card não está ativo. */
.card:not(.is-active) .card__photo{
  flex-basis:100%;
  width:100%;
}
.card:not(.is-active) .card__body{
  flex-basis:0;
  padding-left:0;
  padding-right:0;
  overflow:hidden;
}

/* Reposicionamento silencioso do carrossel (clone → card real equivalente,
   ver script.js wrapTo/onEnd): suspende TODAS as transições do trilho e do
   conteúdo interno dos cards (foto/corpo), não só o transform do trilho.
   Sem isso, o card recém-trocado (que acabou de ganhar/perder .is-active
   no mesmo instante do salto) reanimaria sozinho suas próprias transições
   de flex-basis/opacity logo após o salto — um crescimento/fade visível
   bem no momento em que o usuário não deveria perceber nada. */
.carousel__track.is-snapping,
.carousel__track.is-snapping .card,
.carousel__track.is-snapping .card__photo,
.carousel__track.is-snapping .card__body{
  transition:none !important;
}
.card h3{
  font-family:var(--serif);
  font-weight:600;
  font-size:21px;
  line-height:1.22;
  color:var(--navy);
  flex-shrink:0;
}
.card p{
  font-family:var(--sans);
  font-size:13.5px;
  line-height:1.55;
  color:var(--muted);
  margin-top:9px;
  /* Texto completo permanece no DOM (útil para um futuro cardápio) —
     só é cortado visualmente em 4 linhas dentro do card. */
  display:-webkit-box;
  -webkit-box-orient:vertical;
  -webkit-line-clamp:4;
  line-clamp:4;
  overflow:hidden;
}
.card p em{
  font-style:normal;
  color:var(--navy);
  opacity:.7;
}

@media (max-width:767px){
  .card__photo{
    width:100%;
    height:160px;
    flex:0 0 160px;
  }
  /* Card peek (não ativo): no layout empilhado, flex-basis controla ALTURA
     (eixo principal virou vertical) — sobrescreve o "100%" da regra base
     (pensada para o eixo horizontal do desktop) para travar a foto em
     160px fixos, e a régua de texto fecha inteiramente (altura 0 +
     padding 0), sem faixa colorida residual. */
  .card:not(.is-active) .card__photo{
    flex-basis:160px;
  }
  .card:not(.is-active) .card__body{
    flex-basis:0;
    height:0;
    padding:0;
    overflow:hidden;
  }
  .card__body{padding:14px 16px 16px;overflow-y:visible}
  .card h3{font-size:17px;min-height:0}
  .card p{font-size:12.5px;-webkit-line-clamp:5;line-clamp:5}
}

.orders__cta{
  position:relative;
  z-index:1;
  text-align:center;
  margin-top:48px;
}
@media (max-width:767px){
  .orders__cta{margin-top:32px}
}

/* ==========================================================================
   SOBRE NÓS
   ========================================================================== */
.about{
  position:relative;
  z-index:2;
  isolation:isolate;
  /* Cor sólida direto no elemento (não só no ::before abaixo): garante um
     fundo opaco mesmo se a textura/imagem de fundo ainda não carregou ou se
     o ::before por qualquer razão não renderizar — a seção nunca fica
     transparente durante o scroll. */
  background-color:#253952;
  max-width:1180px;
  margin:0 auto;
  padding:112px 24px;
  display:grid;
  grid-template-columns:1fr;
  gap:40px;
  scroll-margin-top:var(--header-h);
}
/* .about é uma caixa centralizada (max-width:1180px), diferente de .orders
   (full-bleed). Como a hero fica sticky/pinada atrás por toda a rolagem
   restante da página, sem um fundo opaco cobrindo TODA a largura da viewport
   a foto da hero vazaria nas laterais (fora dos 1180px) mesmo com z-index
   correto. Breakout full-bleed via ::before para cobrir viewport inteira
   com o mesmo tom de fundo do body, atrás do conteúdo (z-index:-1 dentro do
   contexto de empilhamento isolado do .about, ou seja, ainda acima da hero).
   Fundo navy (mesmo tom de .reviews) para contraste com os textos em branco
   quente abaixo. Textura de papel/fibra navy já embutida na própria imagem
   (fundo-sobre-nos.webp), por isso não há mais um ::after de ruído
   procedural separado sobreposto — evita duas texturas duplicadas.
   `background-image` só é aplicado quando `.about` ganha a classe
   `.bg-loaded` (via IntersectionObserver em script.js, rootMargin 200px) —
   até lá fica só o `background-color` sólido, evitando buscar essa imagem
   de fundo (mais distante da 1ª tela) no load inicial da página. */
.about::before{
  content:'';
  position:absolute;
  top:0;
  bottom:0;
  left:50%;
  width:100vw;
  transform:translateX(-50%);
  /* Cor sólida já garantida direto em .about (acima) — aqui fica só a
     camada decorativa de imagem/textura, POR CIMA dessa cor. z-index:0 (não
     negativo): o conteúdo (.about__text/.about__mosaic, logo abaixo) recebe
     position:relative;z-index:1 para ficar por cima desta camada. */
  background-size:cover;
  background-position:center;
  background-repeat:no-repeat;
  z-index:0;
  pointer-events:none;
}
.about.bg-loaded::before{
  background-image:url("fundo-sobre-nos.webp");
}
/* Chegada direta (âncora do cabeçalho na carga inicial, restauração nativa
   de scroll do navegador no reload no meio da página, retorno via bfcache
   do cardápio) — ver script.js, seção 2z. Enquanto <body> tiver esta
   classe (removida pouco depois de 'load'/'pageshow'), qualquer elemento
   com transição de revelação (cards, avaliações, "Sobre nós") aparece no
   estado final imediatamente, sem a transição normal de scroll — pedido
   explícito do cliente: o estado padrão é visível, a animação é só um
   "enhancement" durante scroll real, nunca motivo para esconder algo que
   já deveria estar na tela. */
body.reveal-instant .about-step,
body.reveal-instant .card.reveal-init,
body.reveal-instant .review-card.reveal-init{
  transition:none !important;
}
/* Estado inicial de animação: sequência de 8 passos atrelada ao scroll
   (ver script.js, seção 2b). Cada elemento marcado com [data-about-step]
   recebe .about-step via JS e alterna .is-visible conforme o progresso
   de scroll cruza seu limiar — reversível nos dois sentidos. */
.about-step{
  opacity:0;
  transform:translateY(28px);
  transition:opacity .9s ease-out,transform .9s ease-out;
}
.about-step--fade-only{
  transform:none;
}
.about-step.is-visible{
  opacity:1;
  transform:translateY(0);
}
/* Imagens do mosaico: fade+translateY puro, sem scale (evita efeito de
   "aparecer e depois crescer"). Transição única cobrindo todas as
   propriedades juntas. */
.about-step--img{
  transform:translateY(20px);
  filter:blur(3px);
}
/* Especificidade elevada (.about__card.about-step--img, 0-2-0) de propósito:
   sem isso, a regra ".about__card" (0-1-0, declarada mais abaixo no arquivo)
   venceria a cascata e sobrescreveria esta transition inteira (shorthand),
   deixando opacity/filter sem transição e o transform em .4s em vez de 1.2s. */
.about__card.about-step--img{
  transition:opacity 1.2s cubic-bezier(0.16,1,0.3,1),transform 1.2s cubic-bezier(0.16,1,0.3,1),filter 1.2s cubic-bezier(0.16,1,0.3,1);
}
.about-step--img.is-visible{
  transform:translateY(0);
  filter:blur(0);
}
/* Rede de segurança PURA CSS (não depende de script.js ter rodado a
   tempo): no celular, o cliente pediu conteúdo visível por padrão. A
   lógica em script.js (isMobileNoAnim) já evita adicionar .reveal-init/
   .about-step nesse viewport, mas se por qualquer motivo (JS ainda não
   executado nesse instante, erro de execução, corrida de tempo com CSS/
   fontes carregando de forma assíncrona) uma dessas classes acabar
   presente com opacity:0 no mobile, esta regra garante que o texto/
   imagem nunca fique oculto durante o scroll — sobrepõe qualquer opacity/
   visibility/filter/transform vindo das regras acima. Custo desprezível,
   nunca esconde nada que já deveria estar visível. */
@media (max-width:767px){
  .about-step,
  .card.reveal-init,
  .review-card.reveal-init{
    opacity:1 !important;
    visibility:visible !important;
    filter:none !important;
    transform:none !important;
  }
}
.about__text{
  position:relative;
  z-index:1;
  align-self:center;
}
/* Especificidade elevada (.about__text .about__eyebrow, 0-2-0) de propósito:
   o eyebrow também é um <p> dentro de .about__text, então fica sujeito à
   regra ".about__text p" (0-1-1) definida mais abaixo — sem isso, aquela
   regra vence e sobrescreve font-size/color mesmo vindo depois no arquivo. */
.about__text .about__eyebrow{
  font-family:var(--sans);
  font-size:12px;
  font-weight:500;
  letter-spacing:.09em;
  text-transform:uppercase;
  color:var(--accent-warm);
  margin:0;
}
.about__text h2{
  font-family:var(--serif);
  font-weight:400;
  font-size:44px;
  line-height:1.15;
  letter-spacing:-.01em;
  color:var(--warm-white);
  margin-top:6px;
}
.about__text p{
  font-size:17px;
  line-height:1.75;
  color:rgba(250,248,245,.85);
  margin-top:22px;
  max-width:44ch;
}
.about__cta{
  margin-top:32px;
}
/* Botão "Ver Cardápio" sobre o novo fundo navy de .about: mesmo padrão
   fundo branco / texto navy já usado em .btn-header sobre a hero, em vez
   do .btn-primary padrão (navy sobre navy ficaria ilegível aqui). Escopo
   restrito a .about__cta para não afetar o outro uso de .btn-primary
   (seção "Mais pedidos", sobre fundo claro). */
.about__cta.btn-primary{
  background:var(--white);
  color:var(--navy);
  border-color:var(--white);
}
.about__cta.btn-primary:hover{
  background:transparent;
  color:var(--warm-white);
  border-color:var(--warm-white);
}
.about__cta.btn-primary:focus-visible{
  outline:2px solid var(--warm-white);
}

/* ---------- Mosaico de imagens ---------- */
.about__mosaic{
  position:relative;
  z-index:1;
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:20px;
}
.about__col{
  display:flex;
  flex-direction:column;
  gap:20px;
}
.about__col--b{
  margin-top:-48px;
  transition:transform .2s linear;
  will-change:transform;
}
.about__card{
  width:100%;
  height:260px;
  object-fit:cover;
  border-radius:16px;
  box-shadow:0 8px 18px rgba(37,57,82,.10);
  display:block;
  transition:transform .4s ease,box-shadow .4s ease;
}
.about__card:hover{
  transform:scale(1.03);
  box-shadow:0 12px 26px rgba(37,57,82,.18);
}
.about__card.about-step--img.is-visible:hover{
  transform:translateY(0) scale(1.03);
  box-shadow:0 12px 26px rgba(37,57,82,.18);
}

@media (min-width:1024px){
  .about{
    grid-template-columns:1fr 1fr;
    gap:72px;
    align-items:center;
    padding:112px 24px;
  }
  .about__card{height:300px}
}
@media (min-width:768px) and (max-width:1023px){
  .about{padding:88px 24px}
  .about__text h2{font-size:36px}
}
@media (max-width:767px){
  .about{padding:64px 20px}
  .about__text h2{font-size:30px}
  .about__text p{font-size:16px}
  .about__col--b{margin-top:-24px}
}

/* ==========================================================================
   AVALIAÇÕES
   ========================================================================== */
.reviews{
  position:relative;
  z-index:2;
  isolation:isolate;
  background-color:#F5EDE4;
  background-repeat:no-repeat;
  background-position:right top;
  background-size:cover;
  padding:112px 24px;
  scroll-margin-top:var(--header-h);
}
/* `background-image` só é aplicado quando `.reviews` ganha a classe
   `.bg-loaded` (IntersectionObserver, rootMargin 200px) — mesma técnica de
   carregamento adiado usada em `.about::before` acima, já que esta seção
   também fica distante da 1ª tela. */
.reviews.bg-loaded{
  background-image:url("fundo-avaliacoes-cores-palmeiras.webp");
}
@media (min-width:768px) and (max-width:1023px){
  .reviews{padding:80px 24px}
}
@media (max-width:767px){
  .reviews{padding:64px 18px}
  .reviews__title{font-size:28px}
}
.reviews__eyebrow{
  font-family:var(--sans);
  font-size:12px;
  font-weight:500;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--accent-warm);
  text-align:center;
}
.reviews__title{
  font-family:var(--serif);
  font-weight:400;
  font-size:38px;
  line-height:1.2;
  letter-spacing:-.01em;
  color:var(--navy);
  text-align:center;
  margin-top:10px;
}
.reviews__grid{
  max-width:1180px;
  margin:56px auto 0;
  display:grid;
  grid-template-columns:repeat(3,1fr);
  gap:28px;
}
.review-card{
  padding:36px 32px;
  border:1px solid rgba(37,57,82,.12);
  border-radius:16px;
  background:var(--white);
  box-shadow:0 8px 18px rgba(37,57,82,.08);
  display:flex;
  flex-direction:column;
}
.review-card__quote{
  font-family:var(--serif);
  font-size:40px;
  line-height:1;
  color:var(--accent-warm);
  opacity:.85;
}
.review-card__stars{
  font-size:15px;
  letter-spacing:.12em;
  color:var(--accent-warm);
  margin-top:10px;
}
.review-card__text{
  font-family:var(--sans);
  font-size:15.5px;
  line-height:1.65;
  color:var(--muted);
  margin-top:18px;
  flex-grow:1;
}
.review-card__name{
  font-family:var(--sans);
  font-size:15px;
  font-weight:700;
  color:var(--navy);
  margin-top:24px;
}
.review-card__source{
  font-family:var(--sans);
  font-size:12.5px;
  color:rgba(37,57,82,.55);
  margin-top:3px;
}
/* Entrada única (não bidirecional) via IntersectionObserver, mesmo padrão
   dos cards de "Mais pedidos" — classe de estado inicial só é aplicada
   via JS, então sem JS o conteúdo permanece visível por padrão. */
.review-card.reveal-init{
  opacity:0;
  transform:translateY(16px);
  transition:opacity .5s ease,transform .5s ease;
}
.review-card.is-visible{
  opacity:1;
  transform:translateY(0);
}

@media (max-width:1023px){
  .reviews__grid{grid-template-columns:1fr;margin-top:40px;gap:20px}
}
@media (max-width:767px){
  .review-card{padding:26px 22px}
}

/* Defesa em profundidade (mobile): o JS (script.js) já evita aplicar o
   estado inicial oculto no celular, mas esta regra garante que, mesmo que
   alguma dessas classes acabe presente, NUNCA sobra filter:blur nem
   transição longa (>400ms) num elemento em largura <=767px — pedido
   explícito do cliente após o relatório citar blur/1.2s no mobile. */
@media (max-width:767px){
  .about-step,
  .about-step--img,
  .about__card.about-step--img,
  .card.reveal-init,
  .review-card.reveal-init{
    opacity:1;
    transform:none;
    filter:none;
    transition:opacity .3s ease-out,transform .3s ease-out;
  }
  .about-step.is-visible,
  .about-step--img.is-visible,
  .card.is-visible,
  .review-card.is-visible{
    opacity:1;
    transform:none;
    filter:none;
  }
}

/* RODAPÉ — extraído para footer.css (componente compartilhado com cardapio.html) */

/* ==========================================================================
   MOVIMENTO — prefers-reduced-motion
   ========================================================================== */
@media (prefers-reduced-motion: reduce){
  html{scroll-behavior:auto}
  .hero__logo,.hero__tag,.hero__content .btn{
    animation:none !important;
    opacity:1 !important;
    transform:none !important;
  }
  .card.reveal-init,.about-step,.about-step--img,.review-card.reveal-init{
    transition:opacity .01ms !important;
    transform:none !important;
    opacity:1 !important;
  }
  .btn,.card,.about__card,.site-header__logo,.btn-header,.site-header__nav a::after{
    transition-duration:.01ms !important;
  }
  .about__col--b{
    transform:none !important;
  }
}
