/* ══════════════════════════════════════════════════════════════════
   WINE SUPPLY — Base: reset, type, primitives
══════════════════════════════════════════════════════════════════ */

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html {
  -webkit-text-size-adjust: 100%;
  /* A nav é fixa: sem isto todo link de âncora para debaixo dela. */
  scroll-padding-top: calc(var(--nav-h) + 1rem);
}
/* scroll-behavior: smooth só onde há mouse. No celular o Safari rola melhor
   sozinho, e a rolagem programada briga com o dedo. */
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

body {
  background: var(--void);
  color: var(--cream);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  /* `hidden` faria do body um container de rolagem e quebraria
     position:sticky. `clip` corta igual sem criar scroller. */
  overflow-x: clip;
}

::selection { background: var(--crimson-deep); color: var(--cream); }

img, svg { display: block; max-width: 100%; }

a { color: inherit; text-decoration: none; }

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  cursor: pointer;
  /* o iPhone dá zoom quando se toca duas vezes rápido num botão */
  touch-action: manipulation;
}
a, [role="button"], label, .add-btn, .btn-ghost,
[data-open] { touch-action: manipulation; }

input, select { font: inherit; color: inherit; touch-action: manipulation; }


:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
  border-radius: 2px;
}

/* ── Type primitives ──────────────────────────────────── */
.eyebrow {
  font-family: var(--font-body);
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .32em;
  text-transform: uppercase;
  color: var(--atmo, var(--gold));
}

.display {
  font-family: var(--font-display);
  font-weight: 400;
  line-height: .92;
  letter-spacing: -.015em;
}

.serif-italic {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
}

/* Huge outlined ghost text */
.ghost {
  -webkit-text-stroke: 1px var(--cream-25);
  color: transparent;
  font-family: var(--font-display);
  font-weight: 500;
  user-select: none;
}

/* ── Buttons ──────────────────────────────────────────── */
.add-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  background: var(--gold);
  color: #16100A;
  font-weight: 700;
  font-size: .8rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  padding: .85rem 1.6rem;
  border-radius: 99px;
  white-space: nowrap;
  transition: transform .35s var(--ease-back), box-shadow .35s ease, background .25s ease;
}
/* will-change só onde o hover pode existir — senão são 64 camadas
   promovidas de graça no iPhone. */
@media (hover: hover) and (pointer: fine) {
  .add-btn { will-change: transform; }
  .add-btn:hover {
    background: var(--gold-bright);
    transform: translateY(-2px) scale(1.03);
    box-shadow: 0 8px 32px rgba(192, 160, 99, .35);
  }
}
.add-btn:active { transform: scale(.97); }
.add-btn:disabled, .add-btn.is-disabled {
  background: var(--surface-2);
  color: var(--cream-45);
  box-shadow: none;
  transform: none;
  cursor: not-allowed;
}

.btn-ghost {
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  border: 1px solid var(--line);
  color: var(--cream-70);
  font-size: .8rem;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  padding: .8rem 1.5rem;
  border-radius: 99px;
  transition: border-color .3s ease, color .3s ease, background .3s ease;
}
.btn-ghost:hover { border-color: var(--gold); color: var(--gold-bright); background: rgba(192, 160, 99,.06); }

/* ── Qty control ──────────────────────────────────────── */
.qty-ctrl {
  display: inline-flex;
  align-items: center;
  /* Os três alvos eram contíguos: 0px entre − e o campo, 0px entre o campo
     e +. Encostar no meio foca um input[type=number] e abre o teclado. */
  gap: 2px;
  padding-inline: 2px;
  border: 1px solid var(--line);
  border-radius: 99px;
  overflow: hidden;
  background: rgba(239, 233, 221, .04);
}
.qty-btn {
  width: 2.3rem;
  height: 2.55rem;
  display: grid;
  place-items: center;
  font-size: 1.05rem;
  color: var(--cream-70);
  transition: color .2s, background .2s;
}
.qty-btn:hover { color: var(--gold-bright); background: rgba(239, 233, 221,.05); }
.qty-input {
  width: 2.4rem;
  text-align: center;
  background: none;
  border: 0;
  font-weight: 600;
  font-size: .95rem;
  color: var(--cream);
  -moz-appearance: textfield;
  appearance: textfield;
}
.qty-input::-webkit-outer-spin-button,
.qty-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

.buy {
  display: flex;
  align-items: center;
  gap: .8rem;
  flex-wrap: wrap;
}

/* Celular: a linha de compra não quebra — preço, quantidade e botão juntos.
   (As regras por seção ficam em sections.css/components.css, que carregam
   depois deste arquivo e venceriam por ordem.) */
@media (max-width: 899px), (hover: none) and (pointer: coarse) and (max-height: 540px) {
  .buy { flex-wrap: nowrap; gap: .45rem; flex: 1 1 auto; min-width: 0; }
  .qty-ctrl { flex: 0 0 auto; }
  /* Abaixo de 16px o Safari do iPhone dá zoom ao focar o campo. */
  .qty-input { width: 2.1rem; font-size: 16px; }
}

/* ── Badges ───────────────────────────────────────────── */
.badge {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  font-size: .62rem;
  font-weight: 700;
  letter-spacing: .18em;
  text-transform: uppercase;
  padding: .32rem .7rem;
  border-radius: 99px;
  border: 1px solid var(--line);
  color: var(--cream-70);
  background: rgba(239, 233, 221,.03);
}
/* Uma cor, um sentido. Ouro = comprar. Vermelho = acabando. Verde = indicado.
   O carmim media 3.35:1 como texto — reprovava AA. Virou --danger (6.52:1). */
.badge--best      { border-color: rgba(192, 160, 99, .5);  color: var(--gold-bright); }
.badge--limited   { border-color: rgba(226, 122, 114, .45); color: var(--danger); }
.badge--sommelier { border-color: rgba(143, 184, 155, .42); color: var(--sage); }

/* ── Moeda ────────────────────────────────────────────
   O JS emite <span class="cur">R$</span>. O projeto tinha seis regras
   para `sup` — nenhuma delas casava com coisa alguma, e o "R$" saía do
   tamanho cheio do preço, em dourado. */
.cur {
  font-size: .48em;
  font-weight: 600;
  letter-spacing: .06em;
  color: var(--cream-45);
  margin-right: .26em;
  vertical-align: .82em;
}

/* ── Estoque ──────────────────────────────────────────
   O estoque vem do Supabase e chega DEPOIS da primeira pintura — a
   requisição nem começou quando a carta já está na tela, porque ela
   depende do SDK vindo de um terceiro domínio. Entre 300ms e 1,5s no
   4G do celular: exatamente a janela em que o dedo já está rolando.

   Com `:empty { display: none }`, cada linha que ganhava rótulo crescia
   23,2px de uma vez (18,43 da caixa de texto + 4,8 do gap do grid pai).
   Espalhado por dezenas de vinhos, isso empurrava tudo abaixo do dedo
   entre 400 e 1.300px. E como acontece depois da janela de medição de
   carregamento, o CLS continuava marcando zero.

   Agora a caixa nasce com a altura final e nunca muda: o dado chegar
   virou troca de texto, não mudança de layout. O preço é espaço em
   branco invisível; o troco é a página parar de andar sozinha. */
.stock {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  font-size: .72rem;
  line-height: 1.6;                /* travado: não herdar do body */
  min-height: calc(.72rem * 1.6);  /* 18,432px reservados desde sempre */
  font-weight: 600;
  letter-spacing: .08em;
  color: var(--cream-45);
}
/* Sem texto, sem bolinha — senão sobram dezenas de pontos cinza antes do
   dado chegar, e ficam para sempre nos vinhos de estoque normal. */
.stock:empty::before { content: none; }
.stock::before {
  content: '';
  flex: 0 0 auto;                  /* o ponto nunca vira oval espremido */
  width: 7px; height: 7px;
  border-radius: 50%;
  background: currentColor;
}
.stock[data-state="ok"]       { color: var(--sage); }
.stock[data-state="baixo"]    { color: var(--gold-bright); }
.stock[data-state="esgotado"] { color: var(--danger); }

/* ── Reveal on scroll ─────────────────────────────────── */
.reveal {
  opacity: 0;
  transition: opacity .5s var(--ease-out);
  transition-delay: var(--reveal-delay, 0s);
}
.reveal.is-in { opacity: 1; }

/* Rede de segurança: se o IntersectionObserver não rodar — aba em segundo
   plano, Safari limitando durante o embalo da rolagem, JS falhando — o
   conteúdo APARECE. Blocos de 3.000px invisíveis ocupando espaço é o que
   faz o dedo tocar no nada. */
.no-js .reveal,
html:not(.reveals-ok) .reveal { opacity: 1; }

/* No celular não há reveal nenhum: o conteúdo já nasce visível. */
@media (max-width: 899px), (hover: none) and (pointer: coarse) and (max-height: 540px) {
  .reveal { opacity: 1 !important; transition: none; }
}

/* Real product photography — the star of the site.
   Bottles are sized by HEIGHT (photos vary in aspect ratio). */
.wine-photo {
  object-fit: contain;
  -webkit-user-drag: none;
  user-select: none;
}


@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ── Utility ──────────────────────────────────────────── */
.is-hidden { display: none !important; }

/* O atributo hidden perde para qualquer display do autor (grid/flex).
   Sem isso, cupom e desconto reaparecem mesmo marcados como hidden. */
[hidden] { display: none !important; }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.no-results {
  display: none;
  text-align: center;
  padding: 5rem var(--gutter);
  color: var(--cream-45);
}
.no-results.is-visible { display: block; }
.no-results p:first-child {
  font-family: var(--font-display);
  font-size: 1.6rem;
  color: var(--cream-70);
  margin-bottom: .5rem;
}

/* "Avise quando chegar" — o botão de um vinho esgotado.
   Não é uma compra, então não usa o dourado do comprar; mas também não é
   um beco, então não usa o cinza de desabilitado. É um convite. */
.add-btn.is-aviso,
.add-btn.is-disabled.is-aviso {
  background: none;
  border: 1px solid rgba(143, 184, 155, .45);
  color: var(--sage);
  cursor: pointer;
  font-size: .72rem;
  letter-spacing: .1em;
  box-shadow: none;
  transform: none;
}
.add-btn.is-aviso:hover { border-color: var(--sage); background: rgba(143,184,155,.07); }
