/* ============================================================
   Neovixta — visión artificial
   Design adapted from the chosen light blue-grey layout.
   Plain CSS, no build step, no external requests: the font stack
   is the OS one on purpose (nothing fetched from a CDN, which
   also keeps Google Fonts' GDPR problem out of the picture).
   ============================================================ */
:root{
  --bg:#f3f5f7; --ink:#111820; --muted:#69747f; --line:#cfd5db;
  --panel:#e6eaee; --accent:#5da9e9; --dark:#18212b;
  --max:1180px; --radius:22px;
  /* this design is deliberately light-only; stop browsers auto-darkening it */
  color-scheme: light;
}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.01ms!important;transition-duration:.01ms!important}
}
body{margin:0;background:var(--bg);color:var(--ink);
  font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;
  line-height:1.5;-webkit-font-smoothing:antialiased}
a{color:inherit;text-decoration:none}
:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:4px}
.wrap{width:min(calc(100% - 40px),var(--max));margin:auto}

.skip{position:absolute;left:-9999px;background:var(--ink);color:#f5f8fb;
  padding:.6rem 1rem;z-index:100;font-weight:700}
.skip:focus{left:0;top:0}

/* ---- nav ---- */
/* Scoped to the direct child of .wrap on purpose: the footer's legal links are
   also a <nav>, and a bare `nav` selector gave them an 82px bar of their own. */
.wrap > nav{height:96px;display:flex;align-items:center;gap:30px;border-bottom:1px solid var(--line)}
.navlinks{margin-left:auto}
.logo{font-weight:800;letter-spacing:-.04em;font-size:22px;display:inline-flex;align-items:baseline;gap:9px}
.logo span{color:#71808c}
.logo img{height:32px;width:auto;display:block;flex:none}
.navlinks{display:flex;gap:34px;font-size:16px;color:#53606c;margin-left:auto}
.navlinks a:hover{color:var(--ink)}
.navcta{padding:12px 20px;border:1px solid #7c8995;border-radius:999px;font-weight:700;font-size:15px;color:var(--ink)}
/* language toggle — plain links, no JS, so each language stays crawlable */
.lang{display:flex;align-items:center;gap:5px;margin-left:auto;
  font:800 13px ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:.08em}
.lang a{color:#95a0aa;padding:5px 9px;border-radius:999px;
  display:inline-flex;align-items:center;gap:7px}
/* The flags carry white, so a hairline ring keeps them from bleeding into the
   light page. The inactive one dims with its label. */
.lang img{width:20px;height:14px;border-radius:2px;display:block;
  box-shadow:0 0 0 1px rgba(17,24,32,.14)}
.lang a:not(.on) img{opacity:.5}
.lang a:hover{color:var(--ink)}
/* Selected state has to read on the label as well as the flag: ink text on a
   pill, so the flag and its code are highlighted as one unit. */
.lang a.on{color:var(--ink);background:#e1e7ed;box-shadow:inset 0 0 0 1px #d0d8e0}
/* Direct child only: the "/" separator. A bare `.lang span` also caught the
   EN/ES label spans inside the links and overrode their selected colour. */
.lang > span{color:#bcc4cb}
.navcta:hover{background:var(--ink);color:#f5f8fb}

/* ---- hero (404 page) ---- */
.hero{padding:105px 0 95px;display:grid;grid-template-columns:1.25fr .75fr;gap:70px;align-items:end}
.eyebrow{font-size:12px;text-transform:uppercase;letter-spacing:.14em;font-weight:800;color:#64717d;margin-bottom:22px}
h1{font-size:clamp(46px,6.1vw,80px);line-height:.95;letter-spacing:-.07em;margin:0;max-width:900px}
h1 em{font-style:normal;color:#71766d}
.hero-copy{font-size:18px;max-width:440px;color:#586570;margin:30px 0 8px}
.hero-actions{display:flex;gap:12px;margin-top:28px;flex-wrap:wrap}
.btn{display:inline-flex;align-items:center;justify-content:center;padding:14px 19px;border-radius:999px;font-weight:750;border:1px solid #7c8995}
.btn.primary{background:var(--ink);color:#f5f8fb}
.btn.primary:hover{filter:brightness(1.25)}
.btn.secondary{background:transparent}
.btn.secondary:hover{background:var(--panel)}

.signal{height:180px;border-radius:var(--radius);background:linear-gradient(145deg,#18212b,#26333f);position:relative;overflow:hidden;display:flex;align-items:center;justify-content:center}
.signal:before,.signal:after{content:"";position:absolute;border:1px solid #5e655b;opacity:.65}
.signal:before{inset:25px;border-radius:15px}
.signal:after{width:58%;height:58%;border-color:var(--accent);border-radius:12px}
.cross{position:absolute;width:18px;height:18px;border-left:1px solid var(--accent);border-top:1px solid var(--accent);top:40px;left:42px}
.cross.r{left:auto;right:42px;transform:rotate(90deg)}
.cross.b{top:auto;bottom:40px;transform:rotate(-90deg)}
.cross.br{top:auto;left:auto;right:42px;bottom:40px;transform:rotate(180deg)}
.signal-label{z-index:1;color:#e4ebf2;font:700 11px ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:.12em;text-transform:uppercase}

/* ---- intro (home) ---- */
.intro{padding:100px 0 92px}
.intro h1{margin:0}
.intro-copy{font-size:20px;max-width:640px;color:#586570;margin:30px 0 0}
.intro-cols{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-top:62px}
.intro-col{background:linear-gradient(145deg,#e8edf1,#dde3e8);border-radius:var(--radius);padding:30px 32px 32px}
.intro-col h2{font-size:26px;letter-spacing:-.04em;line-height:1.15;font-weight:700;
  color:var(--ink);margin:0 0 12px;max-width:none}
.intro-col ul{list-style:none;margin:0;padding:0}
/* grid, not flex: the dot sits in its own column so the sub text lines up under
   the label instead of wrapping around the bullet. */
.intro-col li{display:grid;grid-template-columns:auto 1fr;gap:3px 14px;
  padding:17px 0;border-bottom:1px solid #cdd5db}
.intro-col li:last-child{border-bottom:0;padding-bottom:0}
.intro-col li:before{content:"";width:9px;height:9px;border-radius:50%;
  border:2px solid var(--accent);margin-top:9px}
.intro-col li b{font-size:20px;letter-spacing:-.03em;font-weight:700}
.intro-col li span{grid-column:2;color:#5f6b76;font-size:15.5px;line-height:1.45}

/* ---- sections ---- */
section{padding:95px 0;border-top:1px solid var(--line)}
.section-head{margin-bottom:45px}
h2{font-size:clamp(35px,4.7vw,62px);line-height:.98;letter-spacing:-.06em;margin:0;max-width:850px}
.lead{font-size:19px;color:#5f6b76;max-width:680px;margin:22px 0 0}

/* Two columns, not the template's three: there are four capabilities now, and
   four in a 3-up grid leaves one stranded on its own row. 2x2 also picks up the
   rhythm of the intro panels directly above. */
/* Subgrid, so the three bands of a card - marker, title, body - line up across
   the row. The template's space-between started every card's body copy at a
   different height (cards in a row are as tall as the tallest); a plain
   two-line floor on the heading fixed that but left a gap under every one-line
   title. Subgrid sizes the title band to the tallest heading in that row and no
   more, which is the actual requirement. Row gap is 0 so the bands are not
   pushed apart inside each card - the 14px between card rows is put back as a
   margin below. */
.grid{display:grid;grid-template-columns:repeat(2,1fr);column-gap:14px;row-gap:0}
.card{grid-row:span 3;display:grid;grid-template-rows:subgrid;
  background:linear-gradient(145deg,#e8edf1,#dde3e8);padding:30px 34px 34px;
  border-radius:var(--radius)}
/* assumes the 2-column desktop grid: everything from the third card on starts a
   new row and needs the gutter the parent no longer supplies */
.card:nth-child(n+3){margin-top:14px}
/* Scoped to .card: the process steps use .num too, with their own type. */
.card .num{display:block;font:700 12px ui-monospace,SFMono-Regular,Menlo,monospace;
  color:#77828d;letter-spacing:.1em;padding-bottom:15px;margin-bottom:22px;
  border-bottom:1px solid #ccd4db}
/* The two-line floor is what finishes the alignment job: without it a one-line
   heading pulls its paragraph up and the body text sits high in that card.
   2.2em == two lines at line-height 1.1, so it scales with the clamp. */
.card h3{font-size:clamp(25px,2.2vw,32px);line-height:1.1;letter-spacing:-.045em;
  margin:0 0 14px}
/* Fallback for anything without subgrid: reserve two lines so the body copy
   still starts level. 2.2em == two lines at line-height 1.1. */
@supports not (grid-template-rows: subgrid){
  .card h3{min-height:2.2em}
}
.card p{color:#5f6b76;font-size:16px;margin:0;max-width:470px}

/* ---- demos ---- */
/* Base layout: one column, all three the same width. This is what ships without
   JS, and what the markup means on its own. 960px keeps the invoice text legible. */
.demo{display:grid;grid-template-columns:1fr;gap:14px;max-width:960px;margin-inline:auto}

/* Rotary stage. main.js adds .rotary, so everything below is enhancement - the
   stacked column above is the fallback. One clip centred at --cw, the other two
   scaled back and tucked behind it; the stage is exactly one card tall, which is
   the whole point: the section drops from ~1500px to ~500px. */
.demo.rotary{--cw:min(720px,60vw);display:block;position:relative;max-width:none;
  height:calc(var(--cw) * .5625 + 46px);overflow:hidden;
  /* the side cards run past the container; without this they end in a hard
     vertical slice at the gutter instead of receding */
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 9%,#000 91%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 9%,#000 91%,transparent)}
.demo.rotary .video-card{position:absolute;top:0;left:50%;width:var(--cw);
  margin-left:calc(var(--cw) / -2);
  transition:transform .5s cubic-bezier(.4,0,.2,1),opacity .5s}
.demo.rotary .video-card[data-pos="c"]{transform:none;opacity:1;z-index:3}
.demo.rotary .video-card[data-pos="l"],
.demo.rotary .video-card[data-pos="r"]{opacity:.58;z-index:2;cursor:pointer}
.demo.rotary .video-card[data-pos="l"]{transform:translateX(-62%) scale(.76)}
.demo.rotary .video-card[data-pos="r"]{transform:translateX(62%) scale(.76)}
.demo.rotary .video-card[data-pos="l"]:hover,
.demo.rotary .video-card[data-pos="r"]:hover{opacity:.74}

.demo-nav{display:flex;align-items:center;justify-content:center;gap:20px;margin-top:30px}
.demo-arrow{width:42px;height:42px;padding:0;border:1px solid var(--line);background:transparent;
  border-radius:999px;color:#4d5964;cursor:pointer;
  display:flex;align-items:center;justify-content:center}
.demo-arrow:hover{background:var(--panel);color:var(--ink);border-color:#9aa5b0}
.demo-dots{display:flex;align-items:center;gap:10px}
.demo-nav .demo-dots button{width:10px;height:10px;padding:0;border-radius:50%;
  border:1px solid #b0bac3;background:transparent;cursor:pointer}
.demo-nav .demo-dots button[aria-current="true"]{background:var(--accent);border-color:var(--accent)}
.demo-nav .demo-dots button:hover{border-color:#6d7883}
.video-card{background:linear-gradient(145deg,#18212b,#26333f);border-radius:var(--radius);overflow:hidden;color:#f5f8fb}
/* 16/9, not the template's 16/10: these clips are 1280x720 and `cover` would
   crop the sides, taking the corner watermark with them. */
/* height:auto is required - the width/height HTML attributes map to a
   presentational height:720px, which would otherwise beat aspect-ratio and
   leave object-fit:cover zooming hard into the frame. */
.video-card video{width:100%;height:auto;aspect-ratio:16/9;display:block;background:#10120f;object-fit:cover}
/* The title sits above the clip, so the padding is weighted the other way:
   less below, where the video meets it. Kept tight - it is a label on a card,
   not a section heading, and every pixel here is one the clip does not get.
   The 46px in the rotary stage's height calc is this bar; change one, change
   the other. */
.video-info{padding:12px 24px 11px}
.video-info h3{margin:0;font-size:19px;letter-spacing:-.03em;line-height:1.2}

/* ---- process ----
   One panel, not four bare columns. This was the only section on the page with
   no surface at all - hairlines and text between a six-card grid and the dark
   contact block - so it read as an afterthought. It is also not a *set* of
   things like the solutions grid above; it is a sequence, so the design says
   sequence: one enclosure divided into stages, each stage capped by a rail
   segment that gains colour as the work progresses, ending solid accent on
   Deployment. The oversized ghost numeral gives the section the weight the
   hairline version never had. */
.process{background:linear-gradient(145deg,#e8edf1,#dde3e8);border-radius:var(--radius);
  display:grid;grid-template-columns:repeat(4,1fr);overflow:hidden}
.step{position:relative;padding:34px 28px 34px;border-left:1px solid #ccd4db}
.step:first-child{border-left:0}
/* rail segment per step, not one absolute line across the panel: this way the
   progression survives every breakpoint, including the single-column phone
   layout where the steps stack. */
.step:before{content:"";position:absolute;top:0;left:0;right:0;height:4px;background:var(--accent)}
.step .num{display:block;font:800 44px/1 ui-monospace,SFMono-Regular,Menlo,monospace;
  letter-spacing:-.05em;color:var(--accent);margin:0 0 16px}
/* The numeral carries the same opacity as its own rail segment, so each number
   renders in exactly the colour of the line above it - one accent, four
   strengths, tying the marker to the stage it belongs to. */
.step:nth-child(1):before,.step:nth-child(1) .num{opacity:.42}
.step:nth-child(2):before,.step:nth-child(2) .num{opacity:.61}
.step:nth-child(3):before,.step:nth-child(3) .num{opacity:.8}
.step:nth-child(4):before,.step:nth-child(4) .num{opacity:1}
.step strong{display:block;font-size:21px;margin:0 0 9px;letter-spacing:-.035em}
.step p{font-size:15px;color:#5f6b76;margin:0}

/* ---- contact + footer ---- */
.contact{background:linear-gradient(145deg,#18212b,#26333f);color:#f5f8fb;border-radius:30px;padding:58px;display:grid;grid-template-columns:1.2fr .8fr;gap:50px;align-items:end}
.contact .eyebrow{color:#9ba9b5}
.contact h2{max-width:700px}
.contact p{color:#b5c0ca;max-width:480px}
.contact .btn.primary{background:var(--accent);color:#111820;border-color:var(--accent);
  padding:21px 38px;font-size:19px}
.contact .btn.primary:hover{filter:brightness(1.08)}
/* The panel bottom-aligns its columns; the button opts out and centres itself
   in its own cell, both axes. */
.contact .hero-actions{margin:0;justify-content:center;align-self:center}
footer{padding:30px 0 45px;color:#687580;font-size:13px;display:flex;justify-content:space-between;gap:20px;
  border-top:1px solid var(--line)}
.footer-legal{display:flex;align-items:center;gap:22px}
.footer-legal a:hover{color:var(--ink)}

/* ---- legal pages ---- */
.legal{padding:70px 0 90px;border-top:0;max-width:760px}
.legal h1{font-size:clamp(38px,4.6vw,58px);margin:0 0 10px}
.legal .updated{font:700 12px ui-monospace,SFMono-Regular,Menlo,monospace;
  text-transform:uppercase;letter-spacing:.12em;color:#7a8590;margin:0 0 42px}
.legal h2{font-size:23px;letter-spacing:-.03em;margin:44px 0 12px;max-width:none}
.legal p,.legal li{color:#4d5964;font-size:17px;margin:0 0 14px}
.legal ul{padding-left:20px;margin:0 0 14px}
.legal li{margin:0 0 7px}
.legal a{color:#2f6ea8;text-decoration:underline}
.legal dl{margin:0 0 14px;display:grid;grid-template-columns:190px 1fr;gap:9px 20px}
.legal dt{font-weight:700;color:var(--ink)}
.legal dd{margin:0;color:#4d5964}
.legal code{font:600 15px ui-monospace,SFMono-Regular,Menlo,monospace;background:#e3e8ec;
  padding:1px 6px;border-radius:5px}

@media(max-width:850px){
  .navlinks{display:none}
  .lang{margin-left:auto}
  .hero,.contact,.intro-cols{grid-template-columns:1fr}
  .hero,.intro{padding:75px 0}
  .intro-cols{margin-top:40px}
  .legal dl{grid-template-columns:1fr;gap:2px 0}
  .legal dt{margin-top:10px}
  /* No room to peek at 850px: the side cards drop out and the arrows and dots
     do the navigating. */
  .demo.rotary{--cw:min(88vw,600px)}
  .demo.rotary .video-card[data-pos="l"],
  .demo.rotary .video-card[data-pos="r"]{opacity:0;pointer-events:none;transform:scale(.9)}
  /* one column: nothing left to align against, so the cards go back to being
     ordinary blocks and each supplies its own gutter */
  .grid{grid-template-columns:1fr;row-gap:14px}
  .card{grid-row:auto;display:block}
  .card:nth-child(n+3){margin-top:0}
  .card h3{min-height:0}
  .process{grid-template-columns:1fr 1fr}
  .step:nth-child(3),.step:nth-child(4){border-top:1px solid #ccd4db}
  .step:nth-child(3){border-left:0}
  .contact{padding:35px 28px}
}
@media(max-width:520px){
  .wrap{width:min(calc(100% - 28px),var(--max))}
  /* The header grew at desktop; on a phone the wordmark, the language toggle
     and the CTA are competing for ~330px, so everything gives a little and the
     CTA is pinned to one line - it wrapped to two and burst the bar otherwise. */
  .wrap > nav{height:76px;gap:14px}
  .logo img{height:26px}
  .navcta{padding:9px 13px;font-size:13px;white-space:nowrap}
  /* Flags only. The bar is tight enough at 360px that flags *and* labels push
     the CTA off the edge; the flags alone are narrower than the labels were, so
     this buys space rather than costing it. The labels stay in the DOM,
     clipped, so the toggle keeps its accessible name. */
  .lang{gap:4px}
  .lang a{gap:0;padding:7px 8px}
  .lang a > span{position:absolute;width:1px;height:1px;overflow:hidden;
    clip-path:inset(50%);white-space:nowrap}
  .lang img{width:22px;height:15px}
  .hero h1,.intro h1{font-size:50px}
  .process{grid-template-columns:1fr}
  .step{border-left:0;border-top:1px solid #ccd4db;padding:28px 24px}
  .step:first-child{border-top:0}
  .step .num{font-size:36px;margin-bottom:12px}
  section{padding:70px 0}
  .contact{border-radius:22px}
  footer{display:block}
  .footer-legal{margin-top:10px;flex-wrap:wrap;gap:16px}
}
/* Small phones: wordmark, two flags and the CTA still have to share one line.
   Verified down to 320px. */
@media(max-width:385px){
  .wrap > nav{gap:8px}
  .logo img{height:20px}
  .lang{gap:2px}
  .lang > span{display:none}          /* the "/" earns nothing between two flags */
  .lang a{padding:6px 6px}
  .lang img{width:20px;height:14px}
  .navcta{padding:8px 10px;font-size:11.5px}
}
