/* Tech Vision — techvision.css
   Dark premium, azul/ciano. Mobile-first. */

:root {
    --tv-bg: #05070d;
    --tv-bg-alt: #080c16;
    --tv-surface: rgba(255, 255, 255, .035);
    --tv-surface-strong: rgba(255, 255, 255, .06);
    --tv-border: rgba(94, 180, 255, .16);
    --tv-border-strong: rgba(94, 180, 255, .32);
    --tv-blue: #3b82f6;
    --tv-cyan: #22d3ee;
    --tv-violet: #6366f1;
    --tv-text: #f3f6fc;
    --tv-text-dim: #93a2bd;
    --tv-text-faint: #64748b;
    --tv-glow-cyan: 0 0 48px rgba(34, 211, 238, .22);
    --tv-glow-blue: 0 0 48px rgba(59, 130, 246, .22);
    --tv-radius: 18px;
    --tv-gap: clamp(1rem, 2.4vw, 1.75rem);
    --tv-section-pad: clamp(3.5rem, 8vw, 6.5rem);
    --tv-header-h: 68px;
    --tv-ease: cubic-bezier(.22, .61, .36, 1);
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; scroll-padding-top: calc(var(--tv-header-h) + 12px); overflow-x: hidden; }

body {
    margin: 0;
    background: var(--tv-bg);
    color: var(--tv-text);
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    line-height: 1.55;
    -webkit-font-smoothing: antialiased;
    -webkit-user-select: none;
    user-select: none;
}

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

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

h1, h2, h3, h4 { line-height: 1.2; margin: 0 0 .6em; font-weight: 800; letter-spacing: -.01em; }

p { margin: 0 0 1em; color: var(--tv-text-dim); }

.tv-container {
    width: 100%;
    max-width: 1180px;
    margin-inline: auto;
    padding-inline: clamp(1.25rem, 5vw, 2.5rem);
}

.tv-skip-link {
    position: absolute;
    left: -999px;
    top: 0;
    background: var(--tv-cyan);
    color: #041018;
    padding: .6rem 1rem;
    border-radius: 0 0 8px 0;
    z-index: 200;
}
.tv-skip-link:focus { left: 0; }

/* ── Header ── */

.tv-header {
    position: sticky;
    top: 0;
    z-index: 100;
    height: var(--tv-header-h);
    display: flex;
    align-items: center;
}

/* Isolado num elemento próprio (não no .tv-header) porque backdrop-filter/transform em um
   ancestral vira containing block de descendentes position:fixed — quebraria o drawer mobile
   (.tv-nav), que precisa ficar fixo à viewport, não ao header. */
.tv-header-backdrop {
    position: absolute;
    inset: 0;
    z-index: -1;
    background: rgba(5, 7, 13, .55);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border-bottom: 1px solid transparent;
    transition: background .3s ease, border-color .3s ease;
}
.tv-header.is-scrolled .tv-header-backdrop {
    background: rgba(5, 7, 13, .85);
    border-bottom-color: var(--tv-border);
}

.tv-header-inner { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }

.tv-brand { display: flex; align-items: center; gap: .55rem; font-weight: 800; font-size: 1.05rem; }
/* A logo tem fundo branco sólido (não transparente) — em vez de "sumir" no header escuro,
   ela ganha uma placa clara própria, com contorno/glow ciano para se integrar ao tema dark. */
.tv-brand-mark {
    width: 34px; height: 34px;
    display: grid; place-items: center;
    flex-shrink: 0;
    border-radius: 9px;
    background: #f8fafc;
    padding: 3px;
    overflow: hidden;
    box-shadow: 0 0 0 1px var(--tv-border-strong), 0 0 14px rgba(34, 211, 238, .3);
}
.tv-brand-mark img { width: 100%; height: 100%; object-fit: contain; display: block; }
.tv-brand-accent { color: var(--tv-cyan); }

.tv-nav-toggle {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 5px;
    width: 40px;
    height: 40px;
    background: none;
    border: 1px solid var(--tv-border);
    border-radius: 10px;
    cursor: pointer;
    z-index: 110;
}
.tv-nav-toggle span {
    display: block;
    width: 18px;
    height: 2px;
    margin-inline: auto;
    background: var(--tv-text);
    border-radius: 2px;
    transition: transform .25s var(--tv-ease), opacity .2s ease;
}
.tv-nav-toggle.is-open span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.tv-nav-toggle.is-open span:nth-child(2) { opacity: 0; }
.tv-nav-toggle.is-open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

.tv-nav {
    position: fixed;
    inset: var(--tv-header-h) 0 0 0;
    background: rgba(5, 8, 15, .98);
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: .25rem;
    padding: 1.5rem clamp(1.25rem, 5vw, 2.5rem) 2rem;
    clip-path: inset(0 0 0 100%);
    transition: clip-path .32s var(--tv-ease);
    overflow-y: auto;
}
.tv-nav.is-open { clip-path: inset(0 0 0 0%); }
.tv-nav a {
    padding: .85rem .25rem;
    border-bottom: 1px solid rgba(255, 255, 255, .06);
    color: var(--tv-text);
    font-weight: 600;
}
.tv-nav-cta {
    margin-top: 1rem;
    display: inline-block;
    text-align: center;
    border: 1px solid var(--tv-border-strong);
    border-radius: 12px;
    background: linear-gradient(135deg, var(--tv-blue), var(--tv-cyan));
    color: #04101c !important;
    font-weight: 700;
}
/* `.tv-nav a` tem especificidade maior que `.tv-nav-cta` sozinho (seletor com tag `a` soma um
   ponto a mais que uma classe isolada), então padding/font-size do CTA nunca eram aplicados —
   o botão sempre ficava com padding:0 herdado de `.tv-nav a`. Corrigido repetindo a classe
   (`.tv-nav-cta.tv-nav-cta`), truque que aumenta a especificidade sem depender de ancestralidade —
   funciona tanto para o CTA dentro do `.tv-nav` (mobile) quanto para a versão flutuante fora dele
   (desktop, ver `.tv-nav-cta-float` abaixo). */
.tv-nav-cta.tv-nav-cta { padding: .9rem 1.25rem; border-bottom: none; }

/* Versão flutuante do CTA (desktop): elemento irmão fora do `.tv-container`, para poder alinhar
   com a borda real da viewport na mesma distância do botão flutuante do WhatsApp — o container do
   header é centralizado com largura máxima, então qualquer coisa dentro dele nunca alcançaria essa
   margem em telas largas. Escondida no mobile (o CTA dentro do `.tv-nav` já cobre o menu ali). */
.tv-nav-cta-float { display: none; }

@media (min-width: 900px) {
    .tv-nav-toggle { display: none; }
    .tv-nav {
        position: static;
        flex-direction: row;
        align-items: center;
        background: none;
        padding: 0;
        transform: none;
        clip-path: none;
        gap: 1.75rem;
        overflow: visible;
    }
    .tv-nav a { padding: 0; border-bottom: none; font-size: .93rem; color: var(--tv-text-dim); transition: color .2s ease; }
    .tv-nav a:hover { color: var(--tv-text); }
    .tv-nav-cta {
        margin-top: 0;
        font-size: .88rem;
    }
    .tv-nav-cta.tv-nav-cta { padding: .55rem 1.4rem; }
    /* O CTA original vira um espaçador invisível (mantém o espaço reservado no fluxo do nav, para
       Início/Serviços/Produtos/Sobre/Contato não se moverem) — a versão real e clicável é a flutuante. */
    .tv-nav > .tv-nav-cta { visibility: hidden; }
    .tv-nav-cta-float {
        display: inline-block;
        position: absolute;
        top: 50%;
        right: clamp(1rem, 4vw, 1.75rem);
        transform: translateY(-50%);
    }
}

/* ── Buttons ── */

.tv-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .5rem;
    padding: .85rem 1.5rem;
    border-radius: 12px;
    font-weight: 700;
    font-size: .95rem;
    border: 1px solid transparent;
    cursor: pointer;
    transition: transform .2s var(--tv-ease), box-shadow .2s ease, border-color .2s ease, background .2s ease;
    white-space: nowrap;
}
.tv-button svg { width: 17px; height: 17px; transition: transform .2s ease; }
.tv-button--primary {
    background: linear-gradient(135deg, var(--tv-blue), var(--tv-cyan));
    color: #04101c;
    box-shadow: 0 12px 30px -12px rgba(34, 211, 238, .55);
}
.tv-button--primary:hover { transform: translateY(-2px); box-shadow: 0 16px 36px -10px rgba(34, 211, 238, .7); }
.tv-button--primary:hover svg { transform: translateX(3px); }
.tv-button--ghost {
    background: var(--tv-surface);
    border-color: var(--tv-border);
    color: var(--tv-text);
}
.tv-button--ghost:hover { border-color: var(--tv-border-strong); background: var(--tv-surface-strong); }

/* ── Hero ── */

.tv-hero { position: relative; padding-block: clamp(2.5rem, 8vw, 5rem) clamp(3rem, 8vw, 5rem); overflow: hidden; }

.tv-hero-glow {
    position: absolute;
    inset: -20% -10% auto -10%;
    height: 620px;
    background:
        radial-gradient(45% 55% at 25% 20%, rgba(59, 130, 246, .28), transparent 70%),
        radial-gradient(40% 50% at 80% 10%, rgba(34, 211, 238, .22), transparent 70%);
    pointer-events: none;
    z-index: 0;
}

.tv-hero-grid { position: relative; z-index: 1; display: grid; gap: clamp(2.5rem, 6vw, 3rem); }

.tv-badge {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    padding: .45rem .9rem;
    border-radius: 999px;
    border: 1px solid var(--tv-border-strong);
    background: var(--tv-surface);
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--tv-cyan);
    margin-bottom: 1.25rem;
}
.tv-badge-dot {
    width: 7px; height: 7px; border-radius: 50%;
    background: var(--tv-cyan);
    box-shadow: 0 0 0 0 rgba(34, 211, 238, .6);
    animation: tv-pulse 2.2s ease-in-out infinite;
}

.tv-hero-title { font-size: clamp(2.1rem, 6.5vw, 3.4rem); max-width: 18ch; }
.tv-gradient-text {
    background: linear-gradient(120deg, var(--tv-cyan), var(--tv-blue));
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}
.tv-hero-subtitle { font-size: clamp(1rem, 2.2vw, 1.15rem); max-width: 46ch; }

.tv-hero-actions { display: flex; flex-wrap: wrap; gap: .9rem; margin-top: 1.75rem; }

.tv-hero-visual { position: relative; min-height: 400px; display: flex; align-items: center; justify-content: center; }

/* ── Phone frame (mockup baseado em proporção de iPhone Pro Max, desenhado em CSS) ── */

.tv-phone {
    position: relative;
    z-index: 1;
    width: min(192px, 48vw);
    aspect-ratio: 9 / 19.5;
    border-radius: clamp(24px, 10vw, 42px);
    background: linear-gradient(160deg, #363c46, #1a1d23 45%, #08090c);
    padding: 8px;
    box-shadow:
        var(--tv-glow-cyan),
        inset 0 0 0 1px rgba(255, 255, 255, .08),
        0 40px 70px -30px rgba(0, 0, 0, .8);
    animation: tv-phone-float 6.5s ease-in-out infinite;
}

.tv-phone-island {
    position: absolute;
    top: 11px;
    left: 50%;
    transform: translateX(-50%);
    width: 36%;
    height: 16px;
    background: #05060a;
    border-radius: 999px;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    padding-right: 6px;
    z-index: 2;
}
.tv-phone-camera {
    width: 5px; height: 5px; border-radius: 50%;
    background: radial-gradient(circle at 35% 35%, #7dd3fc, #0b3a52 70%);
    box-shadow: 0 0 4px rgba(125, 211, 252, .65);
}

.tv-phone-btn {
    position: absolute;
    background: linear-gradient(180deg, #3f454e, #191c20);
    border-radius: 2px;
}
.tv-phone-btn--mute { left: -3px; top: 18%; width: 2px; height: 16px; }
.tv-phone-btn--vol-up { left: -3px; top: 26%; width: 2px; height: 30px; }
.tv-phone-btn--vol-down { left: -3px; top: 37%; width: 2px; height: 30px; }
.tv-phone-btn--side { right: -3px; top: 28%; width: 2px; height: 43px; }

.tv-phone-screen {
    position: relative;
    width: 100%;
    height: 100%;
    border-radius: clamp(18px, 8vw, 34px);
    background: linear-gradient(180deg, var(--tv-surface-strong), var(--tv-surface)), #0a0d13;
    overflow: hidden;
    padding: 1.7rem .65rem .75rem;
    display: flex;
    flex-direction: column;
}

.tv-phone-home-indicator {
    position: absolute;
    bottom: 6px;
    left: 50%;
    transform: translateX(-50%);
    width: 34%;
    height: 3px;
    border-radius: 999px;
    background: rgba(255, 255, 255, .3);
}

.tv-mockup-card-header {
    display: flex; align-items: center; gap: .35rem;
    font-size: .66rem; color: var(--tv-text-dim);
    padding-bottom: .5rem; margin-bottom: .55rem;
    border-bottom: 1px solid var(--tv-border);
}
.tv-mockup-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--tv-violet); flex-shrink: 0; }
.tv-mockup-card-header strong { color: var(--tv-text); }
.tv-mockup-menu { margin-left: auto; letter-spacing: 2px; opacity: .5; }

.tv-mockup-typing {
    display: flex;
    align-items: center;
    gap: .3rem;
    font-family: ui-monospace, 'SFMono-Regular', Menlo, Consolas, monospace;
    font-size: .58rem;
    color: var(--tv-cyan);
    background: rgba(34, 211, 238, .06);
    border: 1px solid var(--tv-border);
    border-radius: 8px;
    padding: .4rem .5rem;
    margin-bottom: .6rem;
    white-space: nowrap;
    overflow: hidden;
}
.tv-mockup-typing-prompt { opacity: .6; flex-shrink: 0; }
.tv-mockup-typing-text { overflow: hidden; text-overflow: clip; }
.tv-typing-cursor { flex-shrink: 0; animation: tv-blink 1s step-end infinite; }

.tv-mockup-core {
    display: grid; place-items: center;
    height: 77px; margin-bottom: .7rem; border-radius: 11px;
    background: radial-gradient(60% 60% at 50% 50%, rgba(34, 211, 238, .16), transparent 70%);
}
.tv-mockup-icon { color: var(--tv-cyan); filter: drop-shadow(0 0 18px rgba(34, 211, 238, .5)); }
.tv-mockup-icon svg { width: 34px; height: 34px; }

.tv-mockup-rows { display: grid; gap: .38rem; }
.tv-mockup-row {
    display: flex; align-items: center; gap: .35rem;
    font-size: .62rem; line-height: 1.3; color: var(--tv-text-dim);
    background: rgba(255, 255, 255, .025);
    border: 1px solid var(--tv-border);
    border-radius: 8px;
    padding: .4rem .48rem;
}

.tv-status-dot {
    width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0;
}
.tv-status-dot--live { background: #34d399; box-shadow: 0 0 0 3px rgba(52, 211, 153, .18); }

.tv-mockup-badge {
    position: absolute;
    z-index: 2;
    display: flex; align-items: center; gap: .5rem;
    font-size: .78rem; font-weight: 600;
    padding: .55rem .85rem;
    border-radius: 12px;
    border: 1px solid var(--tv-border-strong);
    background: rgba(8, 12, 22, .9);
    box-shadow: 0 18px 30px -16px rgba(0, 0, 0, .6);
    white-space: nowrap;
}
.tv-mockup-badge--online { top: 6%; left: -4%; }
.tv-mockup-badge--deploy { bottom: 14%; right: -6%; }
.tv-mockup-badge--app { top: 46%; left: -10%; }

/* Badges "ricos": ícone colorido + título/subtítulo + gráfico decorativo (barra ou mini bar chart) */
.tv-mockup-badge--rich {
    flex-direction: column;
    align-items: stretch;
    gap: .5rem;
    padding: .65rem .8rem .6rem;
    min-width: 150px;
    white-space: normal;
}
.tv-mockup-badge-row { display: flex; align-items: center; gap: .55rem; }

.tv-mockup-badge-icon {
    width: 28px; height: 28px;
    border-radius: 9px;
    display: grid; place-items: center;
    flex-shrink: 0;
}
.tv-mockup-badge-icon svg { width: 15px; height: 15px; color: #fff; }
.tv-mockup-badge-icon--violet { background: linear-gradient(135deg, #a78bfa, var(--tv-violet)); }
.tv-mockup-badge-icon--green { background: linear-gradient(135deg, #6ee7b7, #059669); }

.tv-mockup-badge-text { display: flex; flex-direction: column; gap: 1px; line-height: 1.25; }
.tv-mockup-badge-text strong { font-size: .78rem; color: var(--tv-text); font-weight: 700; }
.tv-mockup-badge-text small { font-size: .64rem; color: var(--tv-text-dim); font-weight: 500; }

.tv-mockup-badge-bar {
    display: block; height: 4px; border-radius: 999px;
    background: rgba(255, 255, 255, .08);
    overflow: hidden;
}
.tv-mockup-badge-bar-fill {
    display: block; height: 100%; width: 84%; border-radius: 999px;
    background: linear-gradient(90deg, var(--tv-violet), #c4b5fd);
}

.tv-mockup-badge-chart {
    display: flex; align-items: flex-end; gap: 3px;
    height: 18px;
}
.tv-mockup-badge-chart span {
    width: 4px; border-radius: 2px;
    height: var(--h, 40%);
    background: linear-gradient(180deg, #6ee7b7, #059669);
}

@media (min-width: 720px) {
    .tv-hero-grid { grid-template-columns: 1.05fr .95fr; align-items: center; }
    .tv-phone { width: 208px; }
    .tv-mockup-badge--online { left: -8%; }
    .tv-mockup-badge--deploy { right: -10%; }
    .tv-mockup-badge--app { left: -16%; }
}

/* ── Sections ── */

.tv-section { padding-block: var(--tv-section-pad); position: relative; }
.tv-section--alt { background: linear-gradient(180deg, transparent, var(--tv-bg-alt) 12%, var(--tv-bg-alt) 88%, transparent); }

.tv-section-head { max-width: 640px; margin-bottom: clamp(2.25rem, 5vw, 3.25rem); }
.tv-eyebrow {
    display: inline-flex; align-items: center; gap: .5rem;
    font-size: .75rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
    color: var(--tv-cyan); margin-bottom: .75rem;
}
.tv-eyebrow::before { content: ''; width: 8px; height: 8px; border-radius: 50%; background: var(--tv-cyan); box-shadow: 0 0 12px rgba(34, 211, 238, .8); }
.tv-section-head h2 { font-size: clamp(1.7rem, 4.5vw, 2.4rem); }
.tv-section-head p { font-size: 1.02rem; }

.tv-grid { display: grid; gap: var(--tv-gap); }
.tv-grid--2 { grid-template-columns: 1fr; }
.tv-grid--3 { grid-template-columns: 1fr; }
.tv-grid--4 { grid-template-columns: 1fr; }

@media (min-width: 640px) {
    .tv-grid--2 { grid-template-columns: repeat(2, 1fr); }
    .tv-grid--4 { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 900px) {
    .tv-grid--3 { grid-template-columns: repeat(3, 1fr); }
    .tv-grid--4 { grid-template-columns: repeat(4, 1fr); }
}

/* ── Cards ── */

.tv-card {
    padding: 1.75rem 1.5rem;
    border-radius: var(--tv-radius);
    border: 1px solid var(--tv-border);
    background: var(--tv-surface);
    transition: transform .25s var(--tv-ease), border-color .25s ease, background .25s ease, box-shadow .25s ease;
}
.tv-card h3 { font-size: 1.05rem; color: var(--tv-text); }
.tv-card p { font-size: .92rem; margin-bottom: 0; }
.tv-card-icon {
    display: inline-grid; place-items: center;
    width: 46px; height: 46px; margin-bottom: 1rem;
    border-radius: 12px;
    color: var(--tv-cyan);
    background: linear-gradient(160deg, rgba(59, 130, 246, .18), rgba(34, 211, 238, .1));
    border: 1px solid var(--tv-border-strong);
}
.tv-card-icon svg { width: 22px; height: 22px; }

.tv-card--hover:hover {
    transform: translateY(-4px);
    border-color: var(--tv-border-strong);
    background: var(--tv-surface-strong);
    box-shadow: var(--tv-glow-blue);
}

/* ── Rastro de poeira mágica — seção "Por que escolher a Tech Vision" ──
   Canvas cobrindo a seção inteira (não cada card), para o rastro nunca ser cortado nas bordas
   dos painéis. Só em dispositivos com mouse de verdade (hover:hover + pointer:fine). */
.tv-dust-canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 5;
    display: none;
}
@media (hover: hover) and (pointer: fine) {
    .tv-dust-canvas { display: block; }
}

.tv-card--compact { padding: 1.4rem 1.1rem; text-align: center; }
.tv-card--compact .tv-card-icon { margin-inline: auto; }
.tv-card--compact h3 { font-size: .95rem; margin: 0; }
.tv-card--compact p {
    margin: .75rem 0 0;
    font-size: .82rem;
    line-height: 1.55;
    color: var(--tv-text-dim);
}

.tv-values-grid { margin-top: 1.75rem; }

/* ── Portfolio cases ── */

.tv-case {
    padding: 1.85rem 1.6rem;
    border-radius: var(--tv-radius);
    border: 1px solid var(--tv-border);
    background: linear-gradient(160deg, var(--tv-surface-strong), transparent 140%);
    position: relative;
    overflow: hidden;
}
.tv-case::after {
    content: '';
    position: absolute; inset: 0;
    background: linear-gradient(120deg, transparent 20%, rgba(34, 211, 238, .08) 45%, transparent 70%);
    background-size: 220% 100%;
    background-position: 130% 0;
    pointer-events: none;
}
.tv-case:hover::after { animation: tv-shimmer 1.4s ease; }
.tv-case h3 { font-size: 1.15rem; margin-top: .6rem; }
.tv-case p { font-size: .92rem; margin-bottom: 0; }

.tv-tag {
    display: inline-block;
    font-size: .68rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
    color: #04101c;
    background: linear-gradient(135deg, var(--tv-cyan), var(--tv-blue));
    padding: .3rem .65rem;
    border-radius: 999px;
}
.tv-tag--muted {
    margin-top: 1rem;
    background: none;
    color: var(--tv-text-faint);
    border: 1px solid var(--tv-border);
}

/* ── Portfólio coverflow ──
   Carrossel 3D com arraste, autoplay e paralaxe: profundidade, rotação e desfoque crescem com a
   distância do slide ativo. O JS (wwwroot/js/coverflow.js) calcula transform/filter por slide a
   cada frame; aqui fica o visual estático, os controles e o modo estático de fallback. */

.tv-coverflow {
    position: relative;
    margin-top: 1rem;
    padding-bottom: clamp(2.5rem, 6vw, 3.5rem);
    --tv-cf-slide-w: min(560px, 84vw);
    --tv-cf-card-h: clamp(360px, 54vh, 520px);
}

.tv-coverflow-viewport {
    position: relative;
    outline: none;
    overflow: hidden;
    height: calc(var(--tv-cf-card-h) + 2rem);
    touch-action: pan-y;
}

.tv-coverflow-track {
    position: relative;
    height: 100%;
    perspective: 1200px;
}

.tv-coverflow-slide {
    position: absolute;
    top: 50%;
    left: 50%;
    width: var(--tv-cf-slide-w);
    height: var(--tv-cf-card-h);
    display: grid;
    place-items: center;
    border-radius: var(--tv-radius);
    will-change: transform, filter;
}

.tv-coverflow-card {
    position: relative;
    width: 100%;
    height: 100%;
    border-radius: inherit;
    overflow: hidden;
    border: 1px solid var(--tv-border);
    background: var(--tv-bg-alt);
    box-shadow: 0 30px 60px -30px rgba(0, 0, 0, .7);
    cursor: grab;
}
.tv-coverflow-card:active { cursor: grabbing; }

.tv-coverflow-card::before {
    content: '';
    position: absolute;
    inset: -6%;
    background: radial-gradient(120% 120% at 20% 0%, rgba(59, 130, 246, .28), transparent 55%), var(--tv-bg-alt);
    background-size: cover;
    background-position: center;
    transform: scale(1.1) translate3d(var(--tv-cf-par-bg-x, 0px), var(--tv-cf-par-bg-y, 0px), 0);
    transition: transform 700ms var(--tv-ease);
}
.tv-coverflow-card--desktop::before {
    background: radial-gradient(120% 120% at 20% 0%, rgba(167, 139, 250, .28), transparent 55%), var(--tv-bg-alt);
}
.tv-coverflow-card--web::before {
    background: radial-gradient(120% 120% at 20% 0%, rgba(34, 211, 238, .3), transparent 55%), var(--tv-bg-alt);
}
.tv-coverflow-card::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgba(5, 7, 13, .1), rgba(5, 7, 13, .35) 55%, rgba(5, 7, 13, .82));
}

.tv-coverflow-visual {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    color: var(--tv-cyan);
    opacity: .3;
    z-index: 1;
}
.tv-coverflow-visual svg { width: 34%; height: 34%; }

.tv-coverflow-head {
    position: absolute;
    inset: clamp(1.25rem, 3.4vw, 1.8rem) auto auto clamp(1.25rem, 3.4vw, 1.8rem);
    z-index: 2;
    max-width: 75%;
}
.tv-coverflow-head .tv-tag {
    margin-bottom: .7rem;
    background: rgba(255, 255, 255, .12);
    border: none;
    color: #fff;
    font-weight: 600;
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}
.tv-coverflow-head h3 { font-size: clamp(1.3rem, 2.8vw, 1.7rem); color: var(--tv-text); margin: 0; }

.tv-coverflow-desc {
    position: absolute;
    inset: auto clamp(1.25rem, 3.4vw, 1.8rem) clamp(4.8rem, 9vw, 5.6rem) clamp(1.25rem, 3.4vw, 1.8rem);
    z-index: 2;
    margin: 0;
    padding: .8rem 1rem;
    font-size: .8rem;
    line-height: 1.55;
    color: rgba(255, 255, 255, .82);
    background: rgba(255, 255, 255, .08);
    border: none;
    border-radius: 12px;
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.tv-coverflow-actions {
    position: absolute;
    inset: auto auto clamp(1.25rem, 3.4vw, 1.8rem) clamp(1.25rem, 3.4vw, 1.8rem);
    z-index: 2;
}
.tv-coverflow-actions .tv-button { padding: .6rem 1.1rem; font-size: .82rem; }

.tv-coverflow-slide[data-active="true"] .tv-coverflow-card {
    box-shadow: 0 40px 80px -30px rgba(0, 0, 0, .8), 0 0 0 1px rgba(255, 255, 255, .04) inset;
}

.tv-coverflow-controls {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    pointer-events: none;
    padding-inline: clamp(.25rem, 2vw, 1rem);
}
.tv-coverflow-arrow {
    pointer-events: auto;
    width: 42px; height: 42px;
    flex-shrink: 0;
    border-radius: 50%;
    border: 1px solid var(--tv-border-strong);
    background: rgba(8, 12, 22, .75);
    color: var(--tv-text);
    display: grid; place-items: center;
    cursor: pointer;
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    transition: background .2s ease, transform .2s ease, border-color .2s ease;
}
.tv-coverflow-arrow svg { width: 18px; height: 18px; }
.tv-coverflow-arrow:hover { background: rgba(8, 12, 22, .95); }
.tv-coverflow-arrow:active { transform: scale(.94); }

.tv-coverflow-pagination {
    display: flex;
    gap: .5rem;
    justify-content: center;
    align-items: center;
    margin-top: 1.25rem;
}
.tv-coverflow-dot {
    width: 8px; height: 8px;
    border-radius: 999px;
    border: 0;
    background: rgba(255, 255, 255, .18);
    cursor: pointer;
    transition: transform .2s ease, background .2s ease;
}
.tv-coverflow-dot[aria-selected="true"] {
    background: linear-gradient(135deg, var(--tv-cyan), var(--tv-blue));
    transform: scale(1.3);
}

.tv-coverflow-progress {
    max-width: var(--tv-cf-slide-w);
    margin: .9rem auto 0;
    height: 3px;
    border-radius: 999px;
    background: rgba(255, 255, 255, .08);
    overflow: hidden;
}
.tv-coverflow-progress-bar {
    display: block;
    height: 100%;
    width: 100%;
    transform-origin: left;
    transform: scaleX(0);
    background: linear-gradient(90deg, var(--tv-cyan), var(--tv-blue));
}

.tv-coverflow-par-1,
.tv-coverflow-par-2,
.tv-coverflow-par-3 {
    transition: transform .5s var(--tv-ease);
}

/* ── Modo estático (prefers-reduced-motion) ──
   Vira uma lista com scroll horizontal simples, sem 3D, paralaxe ou autoplay. */
.tv-coverflow.tv-coverflow--static .tv-coverflow-viewport {
    height: auto;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
}
.tv-coverflow.tv-coverflow--static .tv-coverflow-track {
    display: flex;
    gap: 1rem;
    height: auto;
    perspective: none;
    padding-inline: clamp(1.25rem, 5vw, 2.5rem);
}
.tv-coverflow.tv-coverflow--static .tv-coverflow-slide {
    position: relative;
    top: auto; left: auto;
    flex: 0 0 min(420px, 82vw);
    scroll-snap-align: center;
    transform: none !important;
    filter: none !important;
    opacity: 1 !important;
}
.tv-coverflow.tv-coverflow--static .tv-coverflow-controls,
.tv-coverflow.tv-coverflow--static .tv-coverflow-progress { display: none; }

@media (prefers-reduced-motion: reduce) {
    .tv-coverflow-par-1,
    .tv-coverflow-par-2,
    .tv-coverflow-par-3,
    .tv-coverflow-card::before {
        transition: none !important;
    }
}

/* ── About ── */

.tv-about-grid { display: grid; gap: clamp(2.5rem, 6vw, 3rem); }
.tv-lead { font-size: 1.08rem; color: var(--tv-text); }
.tv-fact-list { list-style: none; margin: 1.5rem 0 0; padding: 0; display: grid; gap: .65rem; }
.tv-fact-list li {
    position: relative; padding-left: 1.6rem; font-size: .92rem; color: var(--tv-text-dim);
}
.tv-fact-list li::before {
    content: '';
    position: absolute; left: 0; top: .45em;
    width: 9px; height: 9px; border-radius: 3px;
    background: linear-gradient(135deg, var(--tv-cyan), var(--tv-blue));
}

@media (min-width: 900px) {
    .tv-about-grid { grid-template-columns: 1.1fr .9fr; align-items: start; }
}

/* Degradê unificado por cima do grid inteiro (texto + foto) — em vez de tentar fazer o fundo da
   seção bater pixel a pixel com o fundo "atrás" da foto (nunca fica perfeito, sempre sobra uma
   linha onde as duas colunas se encontram), essa camada cobre as DUAS colunas de uma vez só, na
   metade de baixo. Fica atrás do texto (`.tv-about-text`, z-index maior) mas na frente da foto
   (`.tv-about-photo`, sem z-index próprio) — não existe mais "cor da foto" vs "cor do painel",
   é a mesma camada em cima dos dois. */
.tv-about-grid { position: relative; }
/* Sem z-index próprio: `.tv-about-photo` não deve criar seu próprio stacking context, senão os
   ícones flutuantes (`.tv-about-photo-icon`, z-index:4) ficam presos "dentro" dele e nunca
   conseguem aparecer por cima do degradê abaixo (que é irmão, não filho, do `.tv-about-photo`). */
.tv-about-photo { position: relative; }
.tv-about-text { position: relative; z-index: 2; }
/* `left/right/margin` em vez de `inset` puro: estica o degradê para 100vw (rompendo a largura do
   `.tv-container`, que tem max-width), senão ele só cobre a coluna do texto+foto e sobra uma faixa
   sem cobertura nas laterais em telas largas. `bottom` negativo (em vez de 0) estende o degradê
   além da base do grid, cobrindo também o padding inferior da seção (`--tv-section-pad`) — senão
   o degradê "para" antes da borda de baixo real do banner. Transição bem mais gradual (só fica
   sólido nos últimos ~20%) para não virar uma barra chapada. */
.tv-about-grid::after {
    content: '';
    position: absolute;
    left: 50%;
    right: 50%;
    margin-left: -50vw;
    margin-right: -50vw;
    top: 58%;
    bottom: calc(-1 * var(--tv-section-pad));
    z-index: 1;
    background: linear-gradient(180deg, transparent, var(--tv-bg-alt) 80%, var(--tv-bg-alt) 100%);
    pointer-events: none;
}
@media (min-width: 900px) {
    .tv-about-grid::after { top: 48%; }
}

/* ── Seção "Quem está por trás" — fundo imersivo ──
   O degradê cobre a seção inteira (texto + foto), num pseudo-elemento atrás do `.tv-container` —
   não fica preso numa caixa em volta da foto. Fade vertical (linear-gradient transparent→cor→
   transparent) nas bordas de cima/baixo pra não criar uma linha dura contra o fundo escuro do
   resto da página, o mesmo truque de `.tv-section--alt`, só que combinado com o glow radial. */
.tv-section--photo { position: relative; overflow: hidden; }
.tv-section--photo::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 0;
    background:
        radial-gradient(85% 95% at 72% 30%, rgba(34, 211, 238, .15), transparent 100%),
        radial-gradient(80% 90% at 85% 90%, rgba(59, 130, 246, .13), transparent 100%),
        linear-gradient(180deg, transparent, var(--tv-bg-alt) 18%, var(--tv-bg-alt) 82%, transparent);
    pointer-events: none;
}
.tv-section--photo > .tv-container { position: relative; z-index: 2; }

/* Camada de imagem de fundo (rede/plexus) — só na seção "Quem está por trás" do Sobre (a Home
   usa `.tv-circuit-canvas` pra isso ali). Elemento próprio, não pseudo-elemento: `::before` já é
   usado pelo glow radial acima e é compartilhado com a Home — mexer nele afetaria as duas
   páginas. Mask radial pra imagem se dissolver no glow por trás, sem borda de retângulo. */
.tv-section-network-bg {
    position: absolute;
    inset: -12% -8%;
    z-index: 1;
    background-image: url('/img/backgrounds/sobre-network.jpg');
    background-size: cover;
    background-position: 76% 32%;
    opacity: .55;
    -webkit-mask-image: radial-gradient(62% 78% at 76% 32%, #000 35%, transparent 82%);
    mask-image: radial-gradient(62% 78% at 76% 32%, #000 35%, transparent 82%);
    pointer-events: none;
}

/* Canvas do rastro de "linhas de circuito" — ver techvision.js. Fica entre o glow de fundo
   (z-index:0) e o conteúdo (z-index:2). O rastro por mousemove continua só em dispositivos com
   mouse de verdade (JS), mas o canvas em si fica ativo em qualquer dispositivo agora — também é
   usado para as "linhas de interferência" disparadas pelo lampejo humano↔robô (sem depender de
   mouse), então precisa existir/desenhar até no mobile. */
.tv-circuit-canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: 1;
    pointer-events: none;
    display: block;
}

/* Foto em si: sem moldura, sem caixa — a pessoa (PNG/WebP com fundo transparente) flutua direto
   sobre o degradê da seção. */
.tv-about-photo {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    max-width: 340px;
    margin-inline: auto;
}
.tv-about-photo img {
    position: relative;
    z-index: 1;
    width: 100%;
    height: auto;
    display: block;
    /* Blur/offset pequenos de propósito: a silhueta (terno) é grande e sólida, então um blur maior
       (era 40px) borra até virar um halo retangular enorme atrás da pessoa em vez de acompanhar o
       contorno — lia como um "retângulo" de cor errada atrás da foto. */
    filter: drop-shadow(0 8px 14px rgba(0, 0, 0, .35));
}

/* Degradê "imersivo" na base da foto — em vez da pessoa terminar com um corte seco embaixo
   (borda reta da imagem), a máscara vai apagando gradualmente a partir de mais ou menos onde a
   mão encontra o paletó até o fim, revelando o degradê da própria seção por trás (que já é
   azul/ciano→preto). Aplicado nas duas imagens (humano e robô) para ficar igual nos dois
   estados. */
.tv-glitch-photo-base,
.tv-glitch-photo-ghost.tv-glitch-photo-ghost {
    -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 56%, transparent 96%);
    mask-image: linear-gradient(to bottom, #000 0%, #000 56%, transparent 96%);
}

/* Foto imersiva da seção "Quem está por trás" do Sobre — mesmo espírito do fade acima, mas
   recalibrado pro `jefferson.png` (busto quase quadrado, já cortado pouco acima do quadril),
   não pra foto de corpo inteiro da Home: o fade começa bem mais tarde (72% em vez de 56%) porque
   há muito menos "sobra" vertical pra apagar. Seletor próprio (não `.tv-about-photo img`) pra não
   vazar pra dentro de `.tv-glitch-photo-base`, que tem sua própria máscara. */
.tv-about-photo--network img {
    -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 72%, transparent 97%);
    mask-image: linear-gradient(to bottom, #000 0%, #000 72%, transparent 97%);
}

/* ── Ícones de plataformas flutuando ao redor da foto (home) ──
   Mesmo espírito dos badges flutuantes do hero, ao redor do celular: cada ícone tem sua própria
   posição e uma das três animações de flutuação já existentes (`tv-float-orbit/x/diagonal`),
   com um atraso (`--tv-delay`) diferente para não ficarem todos sincronizados. */
/* Ícones em "bolha" de vidro — sem moldura/borda dura: o volume esférico vem só de gradiente
   radial (destaque de luz no canto superior-esquerdo, como reflexo) + `box-shadow` interno (aro
   claro em cima, sombra suave embaixo, simulando curvatura) + `backdrop-filter` pro efeito de
   vidro fosco. Nada de `border` — a "borda" que dá pra ver é só a transição suave do próprio
   gradiente/sombra, não uma linha. */
.tv-about-photo-icon {
    position: absolute;
    z-index: 4;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    pointer-events: none;
    background:
        radial-gradient(circle at 32% 26%, rgba(255, 255, 255, .26), rgba(255, 255, 255, 0) 45%),
        radial-gradient(circle at 72% 78%, rgba(34, 211, 238, .16), rgba(34, 211, 238, 0) 55%),
        rgba(255, 255, 255, .05);
    backdrop-filter: blur(9px) saturate(140%);
    -webkit-backdrop-filter: blur(9px) saturate(140%);
    box-shadow:
        inset 0 1px 1px rgba(255, 255, 255, .35),
        inset 0 -7px 12px -3px rgba(0, 0, 0, .28),
        0 10px 22px -10px rgba(0, 0, 0, .55);
}
.tv-about-photo-icon img {
    width: 72%;
    height: 72%;
    object-fit: contain;
    filter: drop-shadow(0 2px 3px rgba(0, 0, 0, .35));
}
.tv-about-photo-icon--apple    { top: 1%;   left: -11%; }
.tv-about-photo-icon--android  { top: 18%;  right: -13%; }
.tv-about-photo-icon--csharp   { top: 36%;  left: -14%; }
.tv-about-photo-icon--windows  { top: 54%;  right: -12%; }
.tv-about-photo-icon--cloud    { top: 71%;  left: -11%; }
.tv-about-photo-icon--web      { top: 88%;  right: -10%; }

@media (min-width: 640px) {
    .tv-about-photo-icon { width: 52px; height: 52px; }
}

/* ── Foto "humano ↔ robô" (efeito de TV antiga falhando) ──
   Alternância cronometrada por JS (ver `techvision.js`): a classe `.is-showing-robot` liga/desliga
   num roteiro fixo de segmentos (ex.: 3s humano, depois um trecho alternando em blocos de
   200-400ms, depois 3s humano de novo). Cada estado é 100% humano OU 100% robô — nunca uma
   mistura permanente — com só uma transição rápida de opacidade entre os dois. */
.tv-glitch-photo { position: relative; width: 100%; }
/* `.tv-about-photo img` (classe + tag) tem mais especificidade que `.tv-glitch-photo-ghost`
   sozinho, então `position`/`height` nunca eram aplicados — o "robô" ficava `position:relative` no
   fluxo normal, empurrado para baixo da foto humana, fora da área visível. Mesmo problema (e
   mesma solução) do CTA do nav: repetir a classe para ganhar especificidade. */
.tv-glitch-photo-ghost.tv-glitch-photo-ghost {
    position: absolute;
    inset: 0;
    z-index: 2;
    width: 100%;
    height: 100%;
    object-fit: contain;
    opacity: 0;
    pointer-events: none;
    transition: opacity 80ms ease-out;
}
.tv-glitch-photo-base { transition: opacity 80ms ease-out; }
.tv-glitch-photo.is-showing-robot .tv-glitch-photo-base { opacity: 0; }
/* Enquanto o robô está "ligado", a opacidade dele fica piscando em vez de segurar 100% firme —
   isso é o que dá a sensação de "imagem falhando" (sinal ruim), não só uma troca limpa. A
   animação roda em loop (`infinite`) e simplesmente é cortada quando a classe sai, então cada
   janela do robô (100-400ms) mostra só um pedaço do ciclo — cada vez um trecho diferente. */
.tv-glitch-photo.is-showing-robot .tv-glitch-photo-ghost {
    opacity: 1;
    animation: tv-robot-flicker 140ms steps(1, jump-end) infinite;
}
.tv-glitch-photo.is-showing-robot::after {
    animation: tv-robot-flicker-scan 170ms steps(1, jump-end) infinite;
}

@keyframes tv-robot-flicker {
    0%   { opacity: 1; }
    15%  { opacity: .25; }
    30%  { opacity: 1; }
    45%  { opacity: .15; }
    60%  { opacity: 1; }
    75%  { opacity: .35; }
    90%  { opacity: 1; }
    100% { opacity: .5; }
}
@keyframes tv-robot-flicker-scan {
    0%   { opacity: .4; }
    15%  { opacity: .1; }
    30%  { opacity: .55; }
    45%  { opacity: .08; }
    60%  { opacity: .5; }
    75%  { opacity: .12; }
    90%  { opacity: .45; }
    100% { opacity: .2; }
}

/* Sem a máscara, o `::after` é um retângulo cheio (cobre toda a caixa da foto, inclusive a área
   transparente ao redor da pessoa). `--tv-glitch-mask` é a mesma imagem (definida inline no HTML,
   por página/foto) usada como máscara alfa, então as scanlines só aparecem dentro do contorno real
   da pessoa — igual ao PNG/WebP. Acompanha a troca humano/robô com a mesma transição rápida. */
.tv-glitch-photo::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 3;
    background: repeating-linear-gradient(to bottom, rgba(224, 242, 254, .5) 0px, rgba(224, 242, 254, .5) 1px, transparent 2px, transparent 4px);
    opacity: 0;
    mix-blend-mode: overlay;
    pointer-events: none;
    transition: opacity 80ms ease-out;
    -webkit-mask-image: var(--tv-glitch-mask);
    mask-image: var(--tv-glitch-mask);
    -webkit-mask-size: contain;
    mask-size: contain;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
}

@media (prefers-reduced-motion: reduce) {
    .tv-glitch-photo-ghost.tv-glitch-photo-ghost,
    .tv-glitch-photo-base,
    .tv-glitch-photo::after {
        transition: none !important;
    }
    .tv-glitch-photo.is-showing-robot .tv-glitch-photo-ghost,
    .tv-glitch-photo.is-showing-robot::after {
        animation: none !important;
    }
}

.tv-about-photo-badge {
    position: relative;
    z-index: 2;
    margin-top: -1.5rem;
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    padding: .5rem .9rem;
    border-radius: 999px;
    border: 1px solid var(--tv-border-strong);
    background: rgba(8, 12, 22, .85);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    font-size: .78rem;
    font-weight: 700;
    color: var(--tv-text);
    white-space: nowrap;
}

@media (min-width: 900px) {
    .tv-about-photo { max-width: none; margin-inline: 0; }
}

/* Variante para foto de corpo inteiro (proporção bem mais vertical) — a home usa uma foto assim,
   diferente da meio-corpo usada em `/sobre`. Sem esse limite mesmo no desktop, a foto esticaria
   para a largura inteira da coluna e ficaria desproporcionalmente alta. */
.tv-about-photo--full { max-width: 260px; }
@media (min-width: 900px) {
    .tv-about-photo--full { max-width: 300px; margin-inline: auto; }
}

/* Foto do Sobre (headshot quase quadrado, `jefferson.png`) ganha mais presença no frame do que o
   padrão de 340px de `.tv-about-photo` — a referência usada de base tem a pessoa preenchendo
   quase toda a altura da composição, sem sobra de espaço vazio ao redor. */
.tv-about-photo--network { max-width: 300px; }
@media (min-width: 900px) {
    .tv-about-photo--network { max-width: 380px; }
}

/* `.tv-about-photo` de propósito não tem z-index próprio (ver comentário acima, perto de
   `.tv-about-grid::after`) — mas a classe `.tv-reveal`, depois de revelada, aplica
   `transform: translate(0,0)` (linha ~1633), e QUALQUER transform diferente de `none` cria um
   stacking context, mesmo sendo um no-op visual. Isso isola essa foto (e tudo dentro dela: halo,
   watermark, badge) num contexto próprio sem z-index — ou seja, nível "auto", que pinta ATRÁS do
   degradê (`z-index:1`) da seção. Resultado: o badge "Jefferson França — Fundador", que fica bem
   na parte de baixo (dentro da faixa opaca do degradê), simplesmente desaparece atrás dele. Como
   esse modificador só é usado aqui (não em `.tv-about-photo--full` da Home), dar um z-index
   explícito é seguro: agora o contexto criado pelo reveal compete no nível certo (z-index
   positivo, acima do degradê), sem precisar mexer na regra compartilhada. */
.tv-about-photo--network { position: relative; z-index: 2; }

/* Badge inferior ("Jefferson França — Fundador") ganha mais sobreposição e sombra nesta seção,
   reforçando a sensação de profundidade/3D pedida — a foto "atrás", o badge com sombra própria
   "na frente". */
.tv-about-photo-badge--elevated {
    margin-top: -2.5rem;
    box-shadow: 0 26px 46px -18px rgba(0, 0, 0, .75), var(--tv-glow-cyan);
}

/* ── CTA final ── */

.tv-cta {
    margin: 0 clamp(1rem, 4vw, 2rem) var(--tv-section-pad);
    padding: clamp(2.5rem, 7vw, 4rem) clamp(1.5rem, 6vw, 3rem);
    border-radius: 24px;
    border: 1px solid var(--tv-border-strong);
    background:
        radial-gradient(60% 120% at 15% 0%, rgba(59, 130, 246, .25), transparent 60%),
        radial-gradient(60% 120% at 85% 100%, rgba(34, 211, 238, .2), transparent 60%),
        var(--tv-bg-alt);
    text-align: center;
}
.tv-cta-inner { max-width: 680px; margin-inline: auto; }
.tv-cta h2 { font-size: clamp(1.6rem, 4.5vw, 2.2rem); }
.tv-cta-actions { justify-content: center; }

/* ── Footer ── */

.tv-footer { padding-block: 3rem 1.5rem; border-top: 1px solid var(--tv-border); }
.tv-footer-grid { display: grid; gap: 2rem; margin-bottom: 2rem; }
.tv-footer-logo {
    display: inline-block;
    background: #f8fafc;
    border-radius: 14px;
    padding: .75rem 1rem;
    box-shadow: 0 0 0 1px var(--tv-border-strong), var(--tv-glow-cyan);
}
.tv-footer-logo img { display: block; height: 34px; width: auto; }
.tv-footer-brand p { font-size: .88rem; max-width: 34ch; margin-top: .9rem; }
.tv-footer-col h4 { font-size: .82rem; text-transform: uppercase; letter-spacing: .06em; color: var(--tv-text-faint); margin-bottom: .9rem; }
.tv-footer-col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .55rem; }
.tv-footer-col a { font-size: .9rem; color: var(--tv-text-dim); transition: color .2s ease; }
.tv-footer-col a:hover { color: var(--tv-cyan); }
.tv-footer-bottom {
    display: flex; flex-wrap: wrap; gap: .5rem 1.5rem; justify-content: space-between;
    padding-top: 1.5rem; border-top: 1px solid rgba(255, 255, 255, .06);
    font-size: .8rem; color: var(--tv-text-faint);
}

@media (min-width: 720px) {
    .tv-footer-grid { grid-template-columns: 1.3fr 1fr 1fr 1fr; }
}

/* ── Cookie consent ──
   Barra ocupando quase a largura inteira da tela (com uma margem pequena nas bordas) em qualquer
   breakpoint. Em telas maiores (tablet/desktop) o conteúdo e as ações ficam lado a lado (horizontal);
   no mobile ficam empilhados. Tom de fundo propositalmente mais claro que o `--tv-bg` da página, pra
   o card se destacar em vez de se misturar com o fundo. */

.tv-cookie-consent {
    position: fixed;
    left: 1rem;
    right: 1rem;
    bottom: 1rem;
    z-index: 300;
    padding: 1.5rem clamp(1.25rem, 5vw, 2rem);
    border-radius: 20px;
    border: 1px solid var(--tv-border-strong);
    background: linear-gradient(160deg, #1c2740, #121a2b);
    box-shadow: var(--tv-glow-cyan), 0 24px 60px -20px rgba(0, 0, 0, .85);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    opacity: 0;
    transform: translateY(calc(100% + 2rem));
    transition: opacity .4s var(--tv-ease), transform .4s var(--tv-ease);
}
.tv-cookie-consent[hidden] { display: none; }
.tv-cookie-consent.is-visible { opacity: 1; transform: translateY(0); }

.tv-cookie-content { display: flex; gap: .9rem; align-items: flex-start; }
.tv-cookie-text { flex: 1; min-width: 0; }

.tv-cookie-icon {
    width: 34px; height: 34px;
    display: grid; place-items: center;
    flex-shrink: 0;
    border-radius: 10px;
    color: var(--tv-cyan);
    background: linear-gradient(160deg, rgba(59, 130, 246, .18), rgba(34, 211, 238, .1));
    border: 1px solid var(--tv-border-strong);
}
.tv-cookie-icon svg { width: 18px; height: 18px; }

.tv-cookie-consent .tv-badge { margin-bottom: .55rem; }
.tv-cookie-consent h2 { font-size: 1.05rem; margin-bottom: .4rem; color: var(--tv-text); }
.tv-cookie-consent p { font-size: .85rem; margin-bottom: .5rem; }
.tv-cookie-note { font-size: .78rem !important; color: var(--tv-text-faint) !important; margin-bottom: 0 !important; }
.tv-cookie-consent a { color: var(--tv-cyan); text-decoration: underline; text-underline-offset: 2px; }

.tv-cookie-actions { display: flex; flex-direction: column; gap: .65rem; margin-top: 1.1rem; }
.tv-cookie-actions .tv-button { width: 100%; justify-content: center; }

@media (min-width: 460px) {
    .tv-cookie-actions { flex-direction: row-reverse; }
}

@media (min-width: 720px) {
    .tv-cookie-consent {
        display: flex;
        align-items: center;
        gap: 2.5rem;
        padding-block: 1.25rem;
    }
    .tv-cookie-content { align-items: center; flex: 1; }
    .tv-cookie-consent .tv-badge,
    .tv-cookie-consent h2 { margin-bottom: .3rem; }
    .tv-cookie-consent p { margin-bottom: 0; }
    .tv-cookie-actions {
        flex-direction: row;
        margin-top: 0;
        flex-shrink: 0;
    }
    .tv-cookie-actions .tv-button { width: auto; white-space: nowrap; }
}

@media (prefers-reduced-motion: reduce) {
    .tv-cookie-consent { transition: none; }
}

/* ── Página legal (Privacidade) ── */

.tv-legal-inner { max-width: 720px; }
.tv-legal { padding-block-start: 0; }
.tv-hero--privacy {
    isolation: isolate;
    min-height: clamp(560px, 47vw, 660px);
    padding-block-end: clamp(7.75rem, 13.5vw, 11rem);
}
.tv-hero--privacy::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    background:
        linear-gradient(180deg, rgba(5, 7, 13, .86) 0%, rgba(5, 7, 13, .68) 34%, rgba(5, 7, 13, .46) 58%, rgba(5, 7, 13, .82) 100%),
        radial-gradient(72% 54% at 50% 18%, rgba(34, 211, 238, .18), transparent 70%);
}
.tv-hero--privacy .tv-hero-glow { z-index: 2; opacity: .55; }
.tv-hero--privacy .tv-container {
    position: relative;
    z-index: 3;
}
.tv-hero--privacy .tv-hero-copy {
    display: grid;
    justify-items: center;
}
.tv-hero--privacy .tv-hero-title,
.tv-hero--privacy .tv-hero-subtitle {
    text-shadow: 0 12px 34px rgba(0, 0, 0, .86), 0 0 28px rgba(5, 7, 13, .75);
}
.tv-hero--privacy .tv-hero-subtitle { color: #fff; }
.tv-privacy-hero-art {
    position: absolute;
    inset: 0;
    z-index: 0;
    margin: 0;
    overflow: hidden;
    pointer-events: none;
    background: #020814;
}
.tv-privacy-hero-art img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center 88%;
    opacity: .92;
    filter: saturate(1.08) contrast(1.08);
}
.tv-legal h1 { font-size: clamp(1.8rem, 5vw, 2.4rem); margin-bottom: .4rem; }
.tv-legal-updated { font-size: .82rem; color: var(--tv-text-faint); margin-bottom: 2rem; }
.tv-legal .tv-lead { font-size: 1.02rem; color: var(--tv-text); margin-bottom: 2rem; }
.tv-legal h2 {
    font-size: 1.1rem;
    color: var(--tv-text);
    margin-top: 2.2rem;
    margin-bottom: .6rem;
    padding-top: 1.6rem;
    border-top: 1px solid var(--tv-border);
}
.tv-legal h2:first-of-type { padding-top: 0; border-top: none; }
.tv-legal p { font-size: .94rem; line-height: 1.7; }
.tv-legal-back { margin-top: 2.5rem; }

/* ── Nav — estado ativo (páginas internas) ── */

.tv-nav a.is-active { color: var(--tv-text); }
@media (min-width: 900px) {
    .tv-nav a.is-active { color: var(--tv-cyan); position: relative; }
    .tv-nav a.is-active::after {
        content: '';
        position: absolute;
        left: 0; right: 0; bottom: -8px;
        height: 2px;
        border-radius: 999px;
        background: linear-gradient(90deg, var(--tv-cyan), var(--tv-blue));
    }
}
@media (max-width: 899px) {
    .tv-nav a.is-active { border-color: var(--tv-border-strong); color: var(--tv-cyan); }
}

/* ── Hero interno (páginas internas: serviços, portfólio, produtos, sobre, contato) ──
   Reaproveita .tv-hero/.tv-hero-glow/.tv-badge, mas numa coluna só, centralizado, sem
   o mockup/phone da home. A regra abaixo tem especificidade maior que `.tv-hero-grid`
   sozinho, então vence a coluna dupla definida em @media (min-width:720px) na home. */

.tv-hero--inner { padding-block: clamp(2.25rem, 7vw, 3.25rem) clamp(2.5rem, 6vw, 3.5rem); }
.tv-hero--inner .tv-hero-grid { grid-template-columns: 1fr; justify-items: center; text-align: center; }
.tv-hero--inner .tv-hero-copy { width: 100%; text-align: center; }
.tv-hero--inner .tv-hero-title,
.tv-hero--inner .tv-hero-subtitle { max-width: 52ch; margin-inline: auto; }
.tv-hero--inner .tv-hero-actions { justify-content: center; }

/* ── Cards — exemplos e link secundário (Serviços) ── */

.tv-card-examples { list-style: none; margin: .9rem 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: .4rem; }
.tv-card-examples li {
    font-size: .74rem;
    padding: .3rem .6rem;
    border-radius: 999px;
    background: rgba(255, 255, 255, .05);
    border: 1px solid var(--tv-border);
    color: var(--tv-text-dim);
}
.tv-card-link {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    margin-top: 1rem;
    font-size: .84rem;
    font-weight: 700;
    color: var(--tv-cyan);
}
.tv-card-link svg { width: 14px; height: 14px; transition: transform .2s ease; }
.tv-card:hover .tv-card-link svg { transform: translateX(3px); }

/* ── Etapas numeradas (Serviços "Como trabalhamos", Contato "O que acontece depois") ── */

.tv-steps { display: grid; gap: 1rem; grid-template-columns: 1fr; }
.tv-step {
    position: relative;
    padding: 1.3rem 1.2rem 1.3rem 3.7rem;
    border-radius: var(--tv-radius);
    border: 1px solid var(--tv-border);
    background: var(--tv-surface);
}
.tv-step-number {
    position: absolute;
    left: 1.1rem;
    top: 1.25rem;
    width: 28px; height: 28px;
    border-radius: 50%;
    display: grid; place-items: center;
    font-size: .8rem; font-weight: 800;
    color: #04101c;
    background: linear-gradient(135deg, var(--tv-cyan), var(--tv-blue));
    flex-shrink: 0;
}
.tv-step h3 { font-size: .98rem; margin: 0 0 .3rem; color: var(--tv-text); }
.tv-step p { font-size: .86rem; margin: 0; }

@media (min-width: 640px) { .tv-steps { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1040px) { .tv-steps { grid-template-columns: repeat(4, 1fr); } }

/* ── Case completo (Portfólio) ── */

.tv-case-full {
    border-radius: var(--tv-radius);
    border: 1px solid var(--tv-border);
    background: var(--tv-surface);
    overflow: hidden;
    transition: transform .25s var(--tv-ease), border-color .25s ease, box-shadow .25s ease;
}
.tv-case-full:hover { transform: translateY(-4px); border-color: var(--tv-border-strong); box-shadow: var(--tv-glow-blue); }
.tv-case-full-visual {
    height: 140px;
    display: grid; place-items: center;
    color: var(--tv-cyan);
    background: radial-gradient(120% 140% at 20% 0%, rgba(59, 130, 246, .28), transparent 60%), var(--tv-bg-alt);
}
.tv-case-full-visual svg { width: 30%; height: 30%; opacity: .5; }
.tv-case-full-visual--desktop { background: radial-gradient(120% 140% at 20% 0%, rgba(167, 139, 250, .28), transparent 60%), var(--tv-bg-alt); }
.tv-case-full-visual--web { background: radial-gradient(120% 140% at 20% 0%, rgba(34, 211, 238, .3), transparent 60%), var(--tv-bg-alt); }
.tv-case-full-body { padding: 1.5rem 1.4rem 1.6rem; }
.tv-case-full-tags { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; margin-bottom: .8rem; }
.tv-case-full-tags .tv-tag--muted { margin-top: 0; }
.tv-case-full h3 { font-size: 1.1rem; margin-bottom: .5rem; }
.tv-case-full p { font-size: .9rem; }
.tv-case-full-meta { display: grid; gap: .4rem; margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--tv-border); font-size: .82rem; }
.tv-case-full-meta strong { color: var(--tv-text); font-weight: 700; margin-right: .35rem; }

/* ── Bloco de destaque centralizado (Sobre "Posicionamento") ── */

.tv-callout { max-width: 760px; margin-inline: auto; padding: 2.25rem clamp(1.5rem, 5vw, 2.75rem); text-align: center; }
.tv-callout .tv-eyebrow { justify-content: center; }
.tv-callout h2 { font-size: clamp(1.5rem, 4vw, 2rem); }
.tv-callout .tv-lead { margin-bottom: 0; }

/* ── Formulário (Contato) ── */

.tv-form-wrap { max-width: 720px; margin-inline: auto; }
.tv-form { display: grid; gap: 1.1rem; margin-top: .5rem; }
.tv-form-row { display: grid; gap: 1.1rem; }
@media (min-width: 640px) { .tv-form-row { grid-template-columns: 1fr 1fr; } }
.tv-field { display: grid; gap: .45rem; }
.tv-field label { font-size: .82rem; font-weight: 700; color: var(--tv-text-dim); }
.tv-field input,
.tv-field select,
.tv-field textarea {
    width: 100%;
    padding: .8rem .95rem;
    border-radius: 12px;
    border: 1px solid var(--tv-border);
    background: var(--tv-surface);
    color: var(--tv-text);
    font: inherit;
    font-size: .92rem;
    transition: border-color .2s ease, background .2s ease;
}
.tv-field input::placeholder,
.tv-field textarea::placeholder { color: var(--tv-text-faint); }
.tv-field input:focus,
.tv-field select:focus,
.tv-field textarea:focus { outline: none; border-color: var(--tv-border-strong); background: var(--tv-surface-strong); }
.tv-field textarea { resize: vertical; min-height: 120px; }
.tv-field select {
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2393a2bd' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right .85rem center;
    background-size: 16px;
    padding-right: 2.5rem;
}
.tv-form-actions { margin-top: .3rem; }
.tv-form-note { font-size: .8rem; color: var(--tv-text-faint); margin-top: .85rem; }

/* ── Botão flutuante do WhatsApp ──
   Mesmo padrão pulsante já usado em outras landing pages da solução
   (EmbraHub.LandingPage.MVP: `.whatsapp-float-btn` + `@keyframes pulse-whatsapp`), redesenhado com
   o gradiente azul/ciano da Tech Vision em vez do dourado, e ícone SVG inline (sem imagem externa). */

.tv-whatsapp-float {
    position: fixed;
    right: clamp(1rem, 4vw, 1.75rem);
    bottom: clamp(1rem, 4vw, 1.75rem);
    z-index: 220;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    background: linear-gradient(135deg, var(--tv-blue), var(--tv-cyan));
    color: #04101c;
    box-shadow: 0 14px 32px -10px rgba(34, 211, 238, .55);
    transition: transform .2s var(--tv-ease), box-shadow .2s ease;
}
.tv-whatsapp-float:hover { transform: translateY(-3px); box-shadow: 0 18px 38px -8px rgba(34, 211, 238, .7); }
.tv-whatsapp-float svg { width: 27px; height: 27px; position: relative; z-index: 1; }
.tv-whatsapp-float-ring {
    position: absolute;
    inset: 0;
    border-radius: 50%;
    animation: tv-pulse-ring 2.4s ease-out infinite;
}

@keyframes tv-pulse-ring {
    0% { box-shadow: 0 0 0 0 rgba(34, 211, 238, .55); }
    70% { box-shadow: 0 0 0 20px rgba(34, 211, 238, 0); }
    100% { box-shadow: 0 0 0 0 rgba(34, 211, 238, 0); }
}

/* ── Error page ── */

.tv-error-inner { text-align: center; max-width: 480px; margin-inline: auto; }
.tv-error-inner .tv-button { margin-top: 1.25rem; }

/* ── Animations ── */

@keyframes tv-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(34, 211, 238, .55); }
    50% { box-shadow: 0 0 0 6px rgba(34, 211, 238, 0); }
}

/* Cada badge flutuante se move de um jeito diferente: órbita, só no eixo X, e diagonal
   (o "Deploy concluído" desliza para cima/esquerda o suficiente para passar por cima do celular). */
@keyframes tv-float-orbit {
    0% { transform: translate(0, 0); }
    25% { transform: translate(7px, -9px); }
    50% { transform: translate(0, -14px); }
    75% { transform: translate(-7px, -9px); }
    100% { transform: translate(0, 0); }
}
.tv-float-orbit { animation: tv-float-orbit 7s ease-in-out infinite; animation-delay: var(--tv-delay, 0s); }

@keyframes tv-float-x {
    0%, 100% { transform: translateX(0); }
    50% { transform: translateX(14px); }
}
.tv-float-x { animation: tv-float-x 6s ease-in-out infinite; animation-delay: var(--tv-delay, 0s); }

@keyframes tv-float-diagonal {
    0%, 100% { transform: translate(0, 0); }
    50% { transform: translate(-32px, -26px); }
}
.tv-float-diagonal { animation: tv-float-diagonal 6.8s ease-in-out infinite; animation-delay: var(--tv-delay, 0s); }

@keyframes tv-phone-float {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-12px); }
}

@keyframes tv-spin-slow {
    to { transform: rotate(360deg); }
}
.tv-spin-slow svg { animation: tv-spin-slow 14s linear infinite; }

@keyframes tv-shimmer {
    from { background-position: 130% 0; }
    to { background-position: -30% 0; }
}

@keyframes tv-blink {
    50% { opacity: 0; }
}

.tv-reveal {
    opacity: 0;
    transform: translateY(24px);
    transition: opacity .7s var(--tv-ease), transform .7s var(--tv-ease);
    transition-delay: var(--tv-delay, 0s);
}
.tv-reveal[data-tv-reveal="left"] { transform: translateX(-16px); }
.tv-reveal[data-tv-reveal="right"] { transform: translateX(16px); }
.tv-reveal.is-visible { opacity: 1; transform: translate(0, 0); }

@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    .tv-badge-dot,
    .tv-float-orbit,
    .tv-float-x,
    .tv-float-diagonal,
    .tv-phone,
    .tv-spin-slow svg,
    .tv-case::after,
    .tv-typing-cursor,
    .tv-whatsapp-float-ring {
        animation: none !important;
    }
    .tv-reveal {
        opacity: 1;
        transform: none;
        transition: none;
    }
    .tv-dust-canvas,
    .tv-circuit-canvas {
        display: none !important;
    }
}
