/* assets/store.css — LSR Digital Store: classes compartilhadas por
   store.html (vitrine) e store-product.html (ficha de produto). Extends
   assets/theme.css (tokens var(--...) já carregados por quem inclui este
   arquivo) — nunca duplicar aqui o que theme.css já cobre (.btn, .badge,
   .tag-soon, .kv-grid, .eyebrow, .wrap, dialog.lsr-modal etc.).

   Camada cinematográfica (Time T20, docs/cinematic-store-redesign/): os
   tokens --cine-* abaixo estendem os tokens de theme.css — nenhum hex novo,
   cada um é composição (gradiente/sombra/número) ou valor específico de
   página. Ver 02-design-system.md/04-motion-spec.md para a origem de cada
   valor. */

/* Real bug, confirmed live, not cosmetic: theme.css's admin/client shell rule
   "main{padding:clamp(22px,3vw,40px) clamp(22px,4vw,48px) 60px}" is a bare
   `main` type selector meant for `.shell main` (admin-*.html/client-*.html) —
   but it also matches the plain <main> these 3 store pages use, stacking
   with .wrap's own padding-inline and silently eating up to ~80px of width.
   Measured at a 320px viewport: #storeResults ended up 226px wide instead of
   ~266px, which is why the mobile grid below needed such a small minmax to
   still fit 2 columns. All 3 store pages already get their real spacing from
   a child element (.wrap's padding-inline, .access-wrap's padding-block, or
   <main class="pad">'s own inline padding-block) — resetting the leak here
   removes only the redundant, unintended padding. NOT fixed by narrowing the
   shared rule's own selector in theme.css instead: privacy-policy.html and
   terms-of-service.html's .legal-body only sets padding-bottom, so they
   genuinely depend on that same rule for their top/left/right padding —
   touching theme.css would regress pages outside this task's scope. */
main{padding:0;}

:root{
  --cine-nav-h: 64px; /* .nav .wrap padding-block:12px + logo 38px + borda 1px, confirmado no navegador */

  /* spacing */
  --cine-space-band: clamp(64px, 9vw, 104px);
  --cine-space-section: clamp(44px, 6vw, 64px);

  /* sticky */
  --cine-toolbar-sticky-top: var(--cine-nav-h);
  --cine-gallery-sticky-top: calc(var(--cine-nav-h) + 24px);
  --cine-gallery-max-h: calc(100vh - var(--cine-gallery-sticky-top) - 24px);
  --cine-z-toolbar: 40;

  /* typography scale */
  --cine-display-hero: clamp(2.75rem, 6vw, 5.5rem);
  --cine-display-pdp: clamp(2.2rem, 4.5vw, 3.4rem);
  --cine-h2: clamp(1.6rem, 3.2vw, 2.3rem);
  --cine-h3: clamp(1.3rem, 2vw, 1.6rem);
  --cine-pullquote: clamp(1.25rem, 2.2vw, 1.6rem);
  --cine-leading-display: 1.05;
  --cine-leading-pdp: 1.08;
  --cine-leading-h2: 1.15;
  --cine-leading-quote: 1.35;

  /* film grain — SVG inline, 0 requisições */
  --cine-grain-svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.4 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  --cine-grain-size: 120px 120px;
  --cine-grain-opacity: .05;
  --cine-grain-blend: overlay;

  /* vignette + glow */
  --cine-vignette: radial-gradient(125% 100% at 50% 0%, transparent 58%, rgba(5,6,10,.6) 100%);
  --cine-glow-band: radial-gradient(60% 140% at 50% 50%, var(--accent-soft) 0%, transparent 70%);

  /* card hover intensify */
  --cine-card-hover-lift: -4px;
  --cine-card-hover-shadow: 0 22px 50px -20px rgba(59,116,255,.55);
  --cine-card-hover-border: rgba(92,139,255,.55);
  --cine-card-image-scale: 1.04;

  /* glass */
  --cine-glass-pad: 16px 20px;

  /* motion */
  --cine-motion-fast: .12s;
  --cine-motion-card: .5s;
  --cine-motion-spring: cubic-bezier(.34,1.56,.64,1);
  --cine-stagger-step: 60ms;
}

/* ---------- product card (grid da vitrine + Related Products da PDP) ---------- */
.store-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:24px;}
.store-card{
  background:var(--ink-soft);border:1px solid var(--line);border-radius:var(--radius);
  overflow:hidden;display:flex;flex-direction:column;
  transition:border-color .25s var(--ease),box-shadow .25s var(--ease);
}
.store-card:hover{border-color:var(--cine-card-hover-border);box-shadow:var(--cine-card-hover-shadow);}
/* Correção obrigatória (02-design-system.md, "Achados fora do escopo" #2):
   antes desta entrega .store-card:hover animava transform FORA de
   @media(prefers-reduced-motion:no-preference) — inconsistente com
   .btn:hover de theme.css. border-color/box-shadow (cor/luz, não é
   "movimento" no sentido vestibular do WCAG) seguem sempre ativos; lift e
   zoom de imagem só entram sob no-preference. */
@media (prefers-reduced-motion:no-preference){
  .store-card{transition:border-color .25s var(--ease),box-shadow .25s var(--ease),transform .25s var(--ease);}
  .store-card:hover{transform:translateY(var(--cine-card-hover-lift));}
  .store-card-cover img{transition:transform .35s var(--ease);}
  .store-card:hover .store-card-cover img{transform:scale(var(--cine-card-image-scale));}
}
/* aspect-ratio 3/4 + object-fit:contain (not the old 4/3 + cover): real covers
   ship as 1024x1536 (2:3, book-style) — a 4:3 landscape frame with `cover`
   cropped the top/bottom of every cover, losing title art. 3/4 is close
   enough to 2:3 that the letterbox gap is a few px per side, and it still
   holds up for a wider (template/course screenshot) cover without the huge
   top/bottom crop a portrait ratio would force on those. */
.store-card-cover{position:relative;display:block;aspect-ratio:3/4;overflow:hidden;background:linear-gradient(160deg,var(--ink-raised),var(--ink-soft));}
.store-card-cover::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(to top,rgba(5,6,10,.55) 0%,transparent 35%);
}
.store-card-cover img,.store-card-noimg{width:100%;height:100%;object-fit:contain;display:block;}
.store-card-badge{position:absolute;top:12px;left:12px;z-index:1;}
.store-card-cover img.store-card-brand{
  position:absolute;top:12px;right:12px;z-index:1;width:22px;height:22px;object-fit:contain;
  opacity:.9;filter:drop-shadow(0 1px 4px rgba(0,0,0,.6));
}
.store-card-body{padding:22px 22px 24px;display:flex;flex-direction:column;gap:8px;flex:1;}
.store-card-category{margin:0;font-family:var(--font-mono);font-size:.66rem;letter-spacing:.1em;text-transform:uppercase;color:var(--accent-bright);}
.store-card-name{margin:0;font-family:var(--font-body);font-weight:650;font-size:1.08rem;line-height:1.3;letter-spacing:-.01em;}
.store-card-name a{text-decoration:none;color:var(--text);}
.store-card-name a:hover,.store-card-name a:focus-visible{color:var(--accent-bright);}
.store-card-desc{margin:0;font-size:.86rem;color:var(--graphite);line-height:1.55;}
.store-card-meta{
  margin:0 0 2px;display:flex;align-items:center;gap:5px;flex-wrap:wrap;
  font-family:var(--font-mono);font-size:.68rem;letter-spacing:.02em;color:var(--graphite-soft);
}
.store-card-meta svg{flex:none;width:12px;height:12px;margin-right:-1px;}
.store-card-footer{
  margin-top:auto;padding-top:16px;border-top:1px solid var(--line);
  display:flex;align-items:center;justify-content:space-between;gap:12px;
}
.store-card-price{margin:0;font-family:var(--font-display);font-size:1.3rem;color:var(--text);}
.store-card-price .tag-soon{font-family:var(--font-mono);font-size:.62rem;}
.store-card-cta{flex:none;}

/* ---------- mobile compact grid (≤640px) ----------
   auto-fit + a small minmax (not the desktop auto-fill/280px above, which
   only ever fits 1 column under ~600px) gives 2 cards per row down to a
   320px screen; it only drops to 1 column if the available width can't fit
   two 130px cards even after that (heavy text zoom, a folded/very narrow
   viewport) — the accessibility fallback asked for, without a second
   hardcoded breakpoint. Card internals get their own compact pass below:
   at 320px a card is ~135px wide, too narrow for the desktop 22px padding/
   1.3rem price/1.08rem title. */
@media (max-width:640px){
  .store-grid{grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:10px;}
  .store-card-body{padding:12px 12px 14px;gap:5px;}
  .store-card-category{font-size:.6rem;}
  .store-card-name{font-size:.86rem;line-height:1.28;}
  .store-card-name a{
    display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
    line-clamp:2;overflow:hidden;
  }
  /* Full description stays on the PDP; the truncated title above keeps its
     full text as the link's accessible name (line-clamp is visual-only, the
     DOM text node is untouched) so nothing here shortens what a screen
     reader or the product page shows. */
  .store-card-desc{display:none;}
  .store-card-meta{font-size:.62rem;gap:3px;}
  .store-card-meta svg{width:10px;height:10px;}
  .store-card-footer{padding-top:10px;gap:6px;flex-wrap:wrap;}
  .store-card-price{font-size:1rem;}
  .store-card-cta{padding:7px 10px;font-size:.68rem;gap:4px;}
}

/* ---------- reveal-stagger extension for card grids (#storeGrid / #relatedGrid) ----------
   theme.css:574 só define o atraso (transition-delay); falta a regra-base
   de opacidade/transform dos filhos — entra aqui, escopada ao componente de
   card, em vez de tocar theme.css (compartilhado pelo site inteiro).
   Cards 1-4 NUNCA entram (proteção de LCP — mesmos 4 cards eager-loaded em
   store.js EAGER_IMAGE_COUNT). Ver 04-motion-spec.md. */
@media (prefers-reduced-motion:no-preference){
  .store-grid.reveal-stagger > .store-card:nth-child(n+5){
    opacity:0; transform:translateY(14px);
    transition:opacity var(--cine-motion-card) var(--ease), transform var(--cine-motion-card) var(--ease);
  }
  .store-grid.reveal-stagger.in > .store-card:nth-child(n+5){ opacity:1; transform:none; }
  .store-card:nth-child(5){--i:0;} .store-card:nth-child(6){--i:1;}
  .store-card:nth-child(7){--i:2;} .store-card:nth-child(8){--i:3;}
  .store-card:nth-child(n+9){--i:4;}
}
@media (prefers-reduced-motion:reduce){
  .store-grid.reveal-stagger > .store-card{ opacity:1; transform:none; }
}

/* ---------- cinematic decorative band (hero da vitrine + CTA de fechamento da PDP) ----------
   Duas variantes de fundo (vignette | glow) + grain compartilhado, sempre
   via ::before/::after desta classe. O conteúdo real de cada banda mora num
   wrapper interno próprio (nunca filho direto marcado com .fx-spotlight) —
   um elemento só pode ter um ::before, e .fx-spotlight também usa o dele;
   ver 05-implementacao.md para o porquê dessa separação. */
.cine-band{position:relative;isolation:isolate;}
.cine-band::after{
  content:"";position:absolute;inset:0;z-index:2;pointer-events:none;
  background-image:var(--cine-grain-svg);background-size:var(--cine-grain-size);
  opacity:var(--cine-grain-opacity);mix-blend-mode:var(--cine-grain-blend);
}
.cine-band--vignette::before{
  content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background-image:var(--cine-vignette);
}
.cine-band--glow::before{
  content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background-image:var(--cine-glow-band);
}

/* ---------- mobile cover banner (vitrine, ≤640px — same breakpoint as
   .store-hero-compact in store.html) ----------
   background-image em vez de <img>/<picture>: nenhum <source media> HTML evita o
   download do <img> de fallback fora do breakpoint, mas um background-image dentro
   de @media só é buscado pelo navegador quando a media query bate — a única forma
   de garantir 0 requisição da capa em telas >640px. image-set() prioriza WebP
   (lossless, mesmo pixel da arte original) com fallback PNG. */
.store-mobile-cover{
  display:none;position:relative;width:100%;
  aspect-ratio:1860/845;border-radius:var(--radius);overflow:hidden;
  margin:10px 0 0;background-color:var(--ink-soft);
  background-repeat:no-repeat;background-position:center;background-size:contain;
  background-image:url("store-mobile-cover.png");
  background-image:image-set(url("store-mobile-cover.webp") type("image/webp"), url("store-mobile-cover.png") type("image/png"));
}
@media (max-width:640px){.store-mobile-cover{display:block;}}
/* posição em % (não px) para acompanhar o botão "24/7 Support" já desenhado na
   arte em qualquer largura — bbox medido na imagem-fonte (1860x845): pill real
   em x:1209-1807 / y:588-722px, aqui com folga extra para área de toque. */
.store-mobile-cover-support{
  position:absolute;left:63%;right:2%;top:65%;bottom:12%;border-radius:999px;
  background:none;border:0;padding:0;cursor:pointer;-webkit-tap-highlight-color:rgba(92,139,255,.25);
}
.store-mobile-cover-support:focus-visible{outline:2px solid var(--accent-bright);outline-offset:2px;}

/* ---------- filter toolbar (#storeFilters) — campos soltos, sem glass envolvendo,
   zero motion, só estética ---------- */
.cine-toolbar{
  position:sticky;top:var(--cine-toolbar-sticky-top);z-index:var(--cine-z-toolbar);
  background:var(--ink);padding-block:10px;
}
.cine-toolbar .field label{margin-bottom:1px;}
.cine-toolbar .field input, .cine-toolbar .field select{background:var(--ink-elevated);}

/* ---------- loading / error / empty states ---------- */
.store-state{padding:60px 20px;text-align:center;color:var(--graphite-soft);}
.store-state[hidden]{display:none;}
.store-spinner{width:32px;height:32px;border:3px solid var(--line-strong);border-top-color:var(--accent-bright);border-radius:50%;margin:0 auto 16px;}
@media (prefers-reduced-motion:no-preference){.store-spinner{animation:storeSpin .8s linear infinite;}}
@keyframes storeSpin{to{transform:rotate(360deg);}}

/* ---------- mobile cover banner (vitrine, <767px — ver store.html .store-hero) ----------
   background-image em vez de <img>/<picture>: nenhum <source media> HTML evita o
   download do <img> de fallback fora do breakpoint, mas um background-image dentro
   de @media só é buscado pelo navegador quando a media query bate — a única forma
   de garantir 0 requisição da capa em telas >767px. image-set() prioriza WebP
   (lossless, mesmo pixel da arte original) com fallback PNG. */
.store-mobile-cover{
  display:none;position:relative;width:100%;
  aspect-ratio:1860/845;border-radius:var(--radius);overflow:hidden;
  margin:14px 0 0;background-color:var(--ink-soft);
  background-repeat:no-repeat;background-position:center;background-size:contain;
  background-image:url("store-mobile-cover.png");
  background-image:image-set(url("store-mobile-cover.webp") type("image/webp"), url("store-mobile-cover.png") type("image/png"));
}
@media (max-width:767px){.store-mobile-cover{display:block;}}
/* posição em % (não px) para acompanhar o botão "24/7 Support" já desenhado na
   arte em qualquer largura — bbox medido na imagem-fonte (1860x845): pill real
   em x:1209-1807 / y:588-722px, aqui com folga extra para área de toque. */
.store-mobile-cover-support{position:absolute;left:63%;right:2%;top:65%;bottom:12%;border-radius:999px;-webkit-tap-highlight-color:rgba(92,139,255,.25);}
.store-mobile-cover-support:focus-visible{outline:2px solid var(--accent-bright);outline-offset:2px;}

/* ---------- support strip (repeated on vitrine + PDP) ---------- */
.store-support{text-align:center;padding:36px 20px;border-top:1px solid var(--line);margin-top:12px;}
.store-support p{color:var(--graphite);margin:0 0 16px;font-size:.94rem;}

/* ---------- breadcrumb (PDP) ---------- */
.store-breadcrumb{display:flex;flex-wrap:wrap;align-items:center;gap:6px;font-family:var(--font-mono);font-size:.72rem;color:var(--graphite-soft);padding-block:18px;}
.store-breadcrumb a{color:var(--graphite-soft);text-decoration:none;}
.store-breadcrumb a:hover{color:var(--accent-bright);}
.store-breadcrumb [aria-current="page"]{color:var(--text);}

/* ---------- notify modal success checkmark (PDP, #notifySuccess) ---------- */
.notify-success-icon{display:inline-flex;flex:none;width:18px;height:18px;color:var(--ok);opacity:0;transform:scale(.9);}
.notify-success-icon svg{width:100%;height:100%;display:block;}
.notify-success-icon svg path{stroke-dasharray:24;stroke-dashoffset:24;}
@media (prefers-reduced-motion:no-preference){
  .notify-success-icon{transition:opacity .25s var(--ease),transform .25s var(--ease);}
  .notify-success-icon svg path{transition:stroke-dashoffset .45s var(--ease) .1s;}
  #notifySuccess:not([hidden]) .notify-success-icon{opacity:1;transform:scale(1);}
  #notifySuccess:not([hidden]) .notify-success-icon svg path{stroke-dashoffset:0;}
}
/* ---------- footer collapsible sections (store.html + store-product.html only) ----------
   Desktop (≥641px): the toggle is unset back to a plain heading (no
   pointer, no chevron) and content is always shown — identical to the old
   static h4+ul, only reachable via JS in assets/footer-collapse.js. Mobile
   (≤700px, matching .footer-grid's existing single-column breakpoint):
   becomes a real disclosure, closed by default, so the 3 link columns don't
   force a long scroll before Contact/Legal are reachable. */
.footer-col-toggle{
  all:unset;display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;box-sizing:border-box;
}
.footer-col-toggle h4{margin:0;}
.footer-col-chevron{display:none;font-family:var(--font-mono);color:var(--accent-bright);font-size:.9rem;}
@media (max-width:700px){
  .footer-col-toggle{cursor:pointer;padding:14px 0;border-top:1px solid var(--line);}
  .footer-col-chevron{display:inline-block;}
  .footer-col-chevron::before{content:"+";}
  .footer-col.open .footer-col-chevron::before{content:"\2013";}
  /* theme.css's ".footer-col ul{display:flex}" is class+type (0,1,1) — more
     specific than a bare ".footer-col-body" (0,1,0) and would win regardless
     of load order, so this has to match that specificity via the same
     .footer-col ancestor to actually close the section. */
  .footer-col .footer-col-body{display:none;margin:0 0 4px;padding:0;}
  .footer-col.open .footer-col-body{display:flex;}
}

@media (prefers-reduced-motion:reduce){
  .notify-success-icon{opacity:1;transform:none;}
  .notify-success-icon svg path{stroke-dashoffset:0;}
}
