/* ==========================================================================
   COMPONENTS.CSS — componentes reutilizáveis únicos (Parte E.3)
   Regra: o mesmo botão/card/input nunca tem implementação diferente
   por secção. Todas as secções importam estas classes, nunca as recriam.
   ========================================================================== */

/* ---------- Botões (Fase 5) — 3 variantes x 6 estados ---------- */
.btn{
  font-family:var(--font-body); font-weight:var(--fw-semibold); font-size:var(--fs-button);
  padding:14px 28px; border-radius:var(--radius-btn); border:1.5px solid transparent;
  cursor:pointer; text-decoration:none; display:inline-flex; align-items:center; justify-content:center; gap:8px;
  position:relative; overflow:hidden;
  transition:transform var(--duration-fast) var(--ease-overshoot),
             background-color var(--duration-base), box-shadow var(--duration-base), opacity var(--duration-base);
  box-shadow:var(--shadow-btn);
  -webkit-tap-highlight-color:transparent;
}
/* Craftsmanship C07 — realce superior subtil, a mesma pista que os olhos
   já lêem em botões físicos polidos: luz a apanhar a aresta de cima.
   Nunca um gradiente vistoso — só o suficiente para ler "superfície". */
.btn::after{
  content:""; position:absolute; inset:0; z-index:-1; pointer-events:none; border-radius:inherit;
  background:linear-gradient(to bottom, rgba(255,255,255,.16), transparent 45%);
  opacity:.8;
}
.btn-secondary::after, .btn-on-navy.btn-secondary::after{ display:none; }
/* Craftsmanship C08 — "click confidence": a resposta ao clique é mais
   rápida que a subida ao hover, para o gesto parecer imediato e sólido. */
.btn:active{ transform:scale(.97); transition-duration:80ms; }
.btn[disabled], .btn[aria-disabled="true"]{ opacity:.4; cursor:not-allowed; pointer-events:none; }

.btn-primary{ background:var(--color-primary); color:#fff; }
.btn-primary:hover{ background:var(--color-primary-dark); transform:translateY(-2px); }

.btn-secondary{ background:transparent; color:var(--color-primary); border-color:var(--color-primary); }
.btn-secondary:hover{ background:rgba(31,32,81,.06); }

.btn-cta{ background:var(--color-accent); color:var(--color-primary); }
.btn-cta:hover{ background:var(--color-accent-dark); transform:translateY(-2px); }

.btn-on-navy.btn-secondary{ color:#fff; border-color:rgba(255,255,255,.55); }
.btn-on-navy.btn-secondary:hover{ background:rgba(255,255,255,.08); }

.btn.is-loading{ position:relative; color:transparent !important; pointer-events:none; }
.btn.is-loading::after{
  content:""; position:absolute; width:16px; height:16px; border-radius:50%;
  border:2px solid rgba(255,255,255,.5); border-top-color:#fff; animation:spin .7s linear infinite;
}
.btn-secondary.is-loading::after, .btn-cta.is-loading::after{ border-color:rgba(31,32,81,.35); border-top-color:var(--color-primary); }
@keyframes spin{ to{ transform:rotate(360deg); } }

.btn-cta.glow-pulse{ animation:glowPulse 1.2s var(--ease-standard) 1; }
@keyframes glowPulse{
  0%{ box-shadow:0 0 0 0 rgba(249,210,8,.6); }
  70%{ box-shadow:0 0 0 18px rgba(249,210,8,0); }
  100%{ box-shadow:0 0 0 0 rgba(249,210,8,0); }
}
@media (prefers-reduced-motion: reduce){ .btn-cta.glow-pulse{ animation:none; } }

/* ---------- Cards (Fase 5) ---------- */
.card{
  background:#fff; border:1px solid var(--color-border); border-radius:var(--radius-card);
  padding:var(--space-6); position:relative; overflow:hidden;
  /* camadas de sombra: contacto (nítida, curta) + elevação ambiente (difusa, larga) */
  box-shadow: var(--shadow-contact), var(--shadow-1);
  /* Nota de bug corrigido (auditoria Craftsmanship C01/C04): .card é usado
     sempre junto com .reveal (base.css). Sem opacity/transform aqui, com o
     mesmo timing do .reveal, o cartão "salta" para visível em vez de
     desvanecer — a cascata dá sempre a última regra carregada, e este
     ficheiro carrega depois de base.css. O overshoot fica reservado só
     para o :hover, nunca para o estado de repouso/entrada. */
  transition:opacity var(--duration-slow) var(--ease-standard), transform var(--duration-base) var(--ease-standard),
             box-shadow var(--duration-base) var(--ease-standard), border-color var(--duration-base) var(--ease-standard);
}
/* Feixe de luz que atravessa o cartão ao passar o rato — um único
   movimento com intenção (não decorativo gratuito): comunica "superfície
   polida", o mesmo vocabulário de luz usado no Hero e no rodapé. */
.card::before{
  content:""; position:absolute; inset:0; z-index:0; pointer-events:none;
  background:linear-gradient(115deg, transparent 40%, rgba(249,210,8,.10) 50%, transparent 60%);
  transform:translateX(-120%); transition:transform .6s var(--ease-out);
}
.card:hover::before{ transform:translateX(120%); }
.card > *{ position:relative; z-index:1; }
.card:hover, .card:focus-within{
  transform:translateY(-4px); box-shadow:var(--shadow-contact), var(--shadow-2); border-color:rgba(249,210,8,.4);
  transition:transform var(--duration-base) var(--ease-overshoot), box-shadow var(--duration-base) var(--ease-standard), border-color var(--duration-base) var(--ease-standard);
}
@media (prefers-reduced-motion: reduce){ .card::before{ transition:none; } }
/* Elevação Serviços — o ícone deixa de ser um traço solto a flutuar sobre
   fundo branco e passa a viver dentro de um "selo" com a sua própria
   superfície; o mesmo ícone (motivo do telhado, de propósito — é o motivo
   de marca, não um ícone genérico de biblioteca) ganha peso visual sem
   precisar de mudar de forma a cada cartão. */
.card-icon-badge{
  display:inline-flex; align-items:center; justify-content:center;
  width:56px; height:56px; border-radius:14px; margin-bottom:var(--space-4);
  background:var(--color-surface-alt);
  transition:background-color var(--duration-base) var(--ease-standard), transform var(--duration-base) var(--ease-standard);
}
.card:hover .card-icon-badge, .card:focus-within .card-icon-badge{
  background:rgba(249,210,8,.18); transform:rotate(-4deg) scale(1.06);
}
.card-icon{ width:24px; height:24px; margin-bottom:0; transition:transform var(--duration-base) var(--ease-standard); color:var(--color-primary); }
/* o selo já roda a si próprio — o ícone lá dentro fica quieto, para o
   gesto não ficar duplicado/exagerado (dois elementos a rodar ao mesmo
   tempo lê-se como ruído, não como polimento). */
.card:hover .card-icon, .card:focus-within .card-icon{ transform:none; }
.card h3{ margin-bottom:var(--space-2); }
.card p{ color:var(--color-text-muted); font-size:.95rem; }
.card-link{
  display:inline-flex; align-items:center; gap:6px; margin-top:var(--space-3);
  font-weight:var(--fw-semibold); font-size:.9rem; color:var(--color-primary);
  text-decoration:none; border-bottom:1.5px solid var(--color-accent); width:fit-content;
}
.card-link svg{ width:14px; height:14px; transition:transform var(--duration-fast) var(--ease-standard); }
.card-link:hover svg{ transform:translateX(3px); }
/* Cartão inteiro clicável (elevação — "mais interacção" é também maior
   alvo de clique, não só mais movimento). Padrão "stretched link": o
   .card-link fica position:static de propósito, para o seu ::after poder
   esticar-se até ao contentor .card (o ascendente posicionado mais
   próximo), em vez de ficar preso ao pequeno botão "Saber mais". Passar o
   rato em qualquer ponto do cartão continua a activar a seta do link,
   porque o overlay é o próprio ::after do .card-link. */
.card > .card-link{ position:static; }
.card-link::after{ content:""; position:absolute; inset:0; z-index:1; }

/* ---------- Campos de formulário (Fase 5 + Parte D — Refinamento Foco 3) ---------- */
.field{ margin-bottom:var(--space-6); position:relative; }
.field label{ display:block; font-size:.85rem; font-weight:var(--fw-semibold); color:var(--color-primary); margin-bottom:6px; }
.field input, .field textarea{
  width:100%; border:0; border-bottom:2px solid var(--color-border); padding:10px 2px;
  font-family:var(--font-body); font-size:1rem; background:transparent; color:var(--color-text);
  transition:border-color var(--duration-fast);
}
.field input:focus, .field textarea:focus{ outline:none; border-color:var(--color-accent); }
.field-hint{ font-size:.78rem; color:var(--color-text-muted); margin-top:4px; }
.field-error{ font-size:.8rem; color:var(--color-error); margin-top:4px; display:none; }
.field.has-error input, .field.has-error textarea{ border-color:var(--color-error); }
.field.has-error .field-error{ display:block; }

/* ---------- Motivo gráfico — duplo telhado (reutilizado em todas as secções) ---------- */
.roof-motif path{ fill:none; stroke-linecap:square; stroke-linejoin:miter; }
.roof-draw path{
  stroke-dasharray:900; stroke-dashoffset:900;
  animation:drawRoof var(--duration-hero) var(--ease-out) forwards;
}
.roof-draw path.p2{ animation-delay:150ms; }
@keyframes drawRoof{ to{ stroke-dashoffset:0; } }
@media (prefers-reduced-motion: reduce){ .roof-draw path{ animation:none; stroke-dashoffset:0; } }

/* ---------- Tabs (usados na secção Segmentos) ---------- */
.tabs-nav{ display:flex; flex-wrap:wrap; gap:var(--space-2); border-bottom:1px solid var(--color-border); margin-bottom:var(--space-8); position:relative; }
.tab-btn{
  background:none; border:0; padding:12px 4px; margin-right:var(--space-6);
  font-family:var(--font-body); font-weight:var(--fw-semibold); font-size:.95rem;
  color:var(--color-text-muted); cursor:pointer; position:relative;
}
.tab-btn[aria-selected="true"]{ color:var(--color-primary); }
#tab-indicator{ position:absolute; bottom:-1px; height:2px; background:var(--color-accent); transition:left var(--duration-base) var(--ease-standard), width var(--duration-base) var(--ease-standard); }
.tab-panel[hidden]{ display:none; }
.tab-panel-grid{ display:grid; gap:var(--space-8); }
@media(min-width:1024px){ .tab-panel-grid{ grid-template-columns:1.2fr .8fr; } }
.tab-services li{ background:var(--color-surface); border:1px solid var(--color-border); border-radius:var(--radius-btn); padding:var(--space-3) var(--space-4); font-size:.92rem; margin-bottom:var(--space-3); }

/* ---------- Empty / loading / error states (Parte D — "detalhes de acabamento") ---------- */
.form-msg{ margin-top:var(--space-4); font-size:.9rem; display:none; align-items:center; gap:10px; }
.form-msg.show{ display:flex; }
.form-msg.error{ color:var(--color-error); }
.form-msg.success{ color:#1c5e20; background:#eef8ef; border:1px solid #cfe9d1; border-radius:var(--radius-btn); padding:var(--space-4); }
.form-msg-check{ flex-shrink:0; width:22px; height:22px; }
.form-msg-check circle{ stroke:var(--color-success); stroke-width:2; fill:none; stroke-dasharray:64; stroke-dashoffset:64; animation:checkCircle .5s var(--ease-out) forwards; }
.form-msg-check path{ stroke:var(--color-success); stroke-width:2.4; fill:none; stroke-linecap:round; stroke-linejoin:round; stroke-dasharray:20; stroke-dashoffset:20; animation:checkMark .3s var(--ease-out) .45s forwards; }
@keyframes checkCircle{ to{ stroke-dashoffset:0; } }
@keyframes checkMark{ to{ stroke-dashoffset:0; } }
@media (prefers-reduced-motion: reduce){ .form-msg-check circle, .form-msg-check path{ animation:none; stroke-dashoffset:0; } }

/* ---------- Formulário Ultra Premium (Parte D — Refinamento Foco 3) ---------- */
.form-card--glass{
  position:relative; background:rgba(255,255,255,.78); overflow:hidden;
  -webkit-backdrop-filter:blur(20px); backdrop-filter:blur(20px);
  border:1px solid rgba(31,32,81,.10);
  box-shadow:var(--shadow-contact), var(--shadow-2);
}
/* Craftsmanship C07 — reflexo de vidro: uma linha de luz fininha na aresta
   de cima, a mesma leitura óptica de um painel de vidro real a apanhar
   luz ambiente. Sem isto, "glassmorphism" costuma ficar só como blur sem
   nenhuma pista física de que é vidro. */
.form-card--glass::after{
  content:""; position:absolute; top:0; left:6%; right:6%; height:1px;
  background:linear-gradient(90deg, transparent, rgba(255,255,255,.9), transparent);
  z-index:1; pointer-events:none;
}
.form-card--glass > *{ position:relative; z-index:2; }
.form-card-kicker{
  font-family:var(--font-body); font-weight:var(--fw-bold); letter-spacing:var(--tracking-kicker);
  text-transform:uppercase; font-size:var(--fs-caption); color:var(--color-primary);
  margin-bottom:var(--space-6); padding-bottom:var(--space-4); border-bottom:1px solid var(--color-border);
}

/* Floating labels — o rótulo vive dentro do campo até o utilizador focar
   ou preencher; nunca dois textos redundantes (placeholder + label) ao
   mesmo tempo, que é o erro mais comum deste padrão. */
.field--float{ position:relative; padding-top:6px; margin-bottom:var(--space-8); }
.field--float input, .field--float textarea{
  width:100%; border:0; border-bottom:1.5px solid var(--color-border); background:transparent;
  padding:14px 2px 10px; font-family:var(--font-body); font-size:1rem; color:var(--color-text);
  transition:border-color var(--duration-fast);
}
.field--float textarea{ resize:vertical; min-height:64px; }
.field--float input:focus, .field--float textarea:focus{ outline:none; }
.field--float label{
  position:absolute; left:2px; top:20px; font-size:1rem; color:var(--color-text-muted);
  font-weight:400; pointer-events:none; transform-origin:left top;
  /* Craftsmanship C04: o rótulo "assenta" com um micro-overshoot ao subir —
     o mesmo timing de um objecto físico leve, nunca um corte mecânico. */
  transition:transform .22s var(--ease-overshoot), color .18s var(--ease-out);
  max-width:calc(100% - 4px);
}
.field--float input:focus + label,
.field--float input:not(:placeholder-shown) + label,
.field--float textarea:focus + label,
.field--float textarea:not(:placeholder-shown) + label{
  transform:translateY(-16px) scale(.76); color:var(--color-primary); font-weight:600;
}
.field-underline{ position:absolute; left:0; bottom:0; height:2px; width:0; background:var(--color-accent); transition:width var(--duration-base) var(--ease-overshoot); }
.field--float input:focus ~ .field-underline, .field--float textarea:focus ~ .field-underline{ width:100%; }
.field--float.has-error input, .field--float.has-error textarea{ border-color:var(--color-error); }
.field--float.has-error label{ color:var(--color-error); }
.field--float .field-error{ display:none; font-size:.78rem; color:var(--color-error); margin-top:6px; }
.field--float.has-error .field-error{ display:block; }

/* ==========================================================================
   FOTOGRAFIA EDITORIAL — Ultra Premium Image Integration Framework
   Dois componentes reutilizáveis (Parte E.3 — nunca reimplementar por
   secção): .photo-frame para imagens contidas (cartão com moldura própria)
   e .photo-bleed para imagens de fundo full-bleed com overlay de leitura.
   Ambos partilham o mesmo vocabulário de movimento: um zoom muito lento
   e contínuo (efeito Ken Burns), nunca um zoom rápido ou chamativo — a
   imagem "respira" à mesma velocidade que os glows do Hero e do rodapé.
   ========================================================================== */
.photo-frame{
  position:relative; border-radius:var(--radius-image); overflow:hidden;
  box-shadow:var(--shadow-image); background:var(--color-surface-alt);
}
.photo-frame img{
  width:100%; height:100%; display:block; object-fit:cover; object-position:center;
  animation:photoKenBurns 24s ease-in-out infinite alternate;
}
@keyframes photoKenBurns{ from{ transform:scale(1); } to{ transform:scale(1.055); } }
@media (prefers-reduced-motion: reduce){ .photo-frame img{ animation:none; } }
/* reflexo de vidro no topo — o mesmo vocabulário de luz do form-card--glass,
   aplica-se apenas quando a moldura convive com um cartão de vidro por perto */
.photo-frame-tag{
  position:absolute; left:var(--space-4); bottom:var(--space-4); z-index:2;
  background:rgba(255,255,255,.92); backdrop-filter:blur(6px); -webkit-backdrop-filter:blur(6px);
  color:var(--color-primary); font-size:.78rem; font-weight:var(--fw-semibold);
  padding:6px 14px; border-radius:20px; box-shadow:var(--shadow-1);
}

/* .photo-bleed — imagem de fundo full-bleed (Hero, fecho de Áreas): a
   fotografia substitui/reforça o gradiente institucional, nunca o remove
   por completo — o overlay é a própria paleta da marca sobre a imagem,
   para a fotografia parecer desenhada para a Scrollup, não colada por cima. */
.photo-bleed{ position:absolute; inset:0; z-index:-1; overflow:hidden; }
.photo-bleed img{
  width:100%; height:100%; object-fit:cover; object-position:center;
  animation:photoKenBurns 28s ease-in-out infinite alternate;
}
.photo-bleed::after{
  content:""; position:absolute; inset:0;
  /* Auto-crítica (Ultra Premium Image Framework): a primeira versão usava
     .88/.72/.88 de opacidade — suficiente para ler qualquer texto, mas
     escondia quase por completo as pessoas fotografadas, violando a
     própria regra do framework ("nunca escondê-la"). Este valor base fica
     deliberadamente claro (.50/.28/.50) — a leitura de texto que precisar
     de mais contraste ganha o seu próprio overlay dirigido (ver .hero
     .photo-bleed::after e .areas-close .photo-bleed::after em sections.css),
     em vez de escurecer a fotografia inteira para todos os usos. */
  background:linear-gradient(135deg, rgba(31,32,81,.50) 0%, rgba(46,52,112,.28) 55%, rgba(31,32,81,.50) 100%);
}
@media (prefers-reduced-motion: reduce){ .photo-bleed img{ animation:none; } }
