/* WebNest - rebrand test site.
   White only, monochrome. Contained left-aligned content column; photographs
   live inside cards at their native 4:3, never stretched full-bleed.
   No decorative gradients, no glows, no scroll reveals.
   The only gradient is the hero legibility scrim. */

@import url("https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&display=swap");

:root{
  --ground:#FFFFFF;
  /* One tinted band colour, used by every alternating section including the
     hero. Three near-identical greys read as a mistake, not a rhythm. */
  --grey:#F4F4F6;
  --ink:#171A20;
  --ink-soft:#5C5F66;
  --rule:#DCDCE2;
  --rule-strong:#B9B9C4;   /* diagram strokes, darker than a hairline */
  /* Accent. Lives in exactly four places: primary button fill, link hover,
     focus ring, and the diagram nodes. Never on headings, backgrounds,
     borders or icons. */
  --brand:#3A20C8;
  --brand-dark:#2C18A0;
  --ink-violet:#191428;   /* near-black carrying the accent's hue */

  --pad:clamp(1.25rem,4vw,3.5rem);
  --gap:clamp(2.75rem,5vw,4.25rem);
  --wrap:92rem;
  --measure:46rem;

  /* One radius for every control. Mixing a 100px pill with a 4px field read
     as two different design languages. */
  --r-control:4px;

  --font:"DM Sans","Helvetica Neue",Helvetica,Arial,"Liberation Sans",sans-serif;
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;background:var(--ground)}
body{
  margin:0;
  background:var(--ground);
  color:var(--ink);
  font-family:var(--font);
  font-size:1.0625rem;
  line-height:1.62;
  -webkit-font-smoothing:antialiased;
}
/* height:auto is required - the width/height HTML attributes map to the CSS
   height property as presentational hints, which makes the box definite and
   silently defeats aspect-ratio on the cards. */
img{display:block;max-width:100%;height:auto}
a{color:inherit;text-decoration:none}
ul,ol,dl,dd{margin:0;padding:0;list-style:none}
:focus-visible{outline:2px solid var(--brand);outline-offset:3px;border-radius:2px}

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

.wrap{max-width:var(--wrap);margin-inline:auto}
.measure{max-width:var(--measure)}

/* ---------- type ---------- */
.h2{font-size:clamp(1.65rem,3vw,2.35rem);font-weight:700;line-height:1.14;letter-spacing:-0.028em;margin:0;text-wrap:balance}
.lede{font-size:clamp(1.0625rem,1.35vw,1.1875rem);line-height:1.55;color:var(--ink-soft);margin:.9rem 0 0}
.body{margin:1.1rem 0 0;color:var(--ink-soft)}

/* ---------- nav ---------- */
.nav{
  position:sticky;top:0;z-index:30;
  display:grid;grid-template-columns:1fr auto 1fr;align-items:center;
  gap:1.5rem;height:76px;padding-inline:var(--pad);
  background:rgba(255,255,255,.9);
  backdrop-filter:saturate(1.4) blur(12px);
  border-bottom:1px solid var(--rule);
}
.nav__logo{justify-self:start}
.nav__logo img{height:46px;width:auto}
.nav__mid{justify-self:center}
.nav__links{display:flex;gap:.25rem}
.nav__links a,.nav__pill{
  display:inline-flex;align-items:center;
  font:inherit;font-size:.9375rem;font-weight:700;color:var(--ink);
  padding:.42rem .8rem;border-radius:var(--r-control);
  background:transparent;border:0;cursor:pointer;white-space:nowrap;
  transition:background-color .18s ease,color .18s ease;
}
.nav__links a:hover,.nav__pill:hover{background:rgba(23,26,32,.07)}
.nav__util{justify-self:end;display:flex;align-items:center;gap:.4rem}
/* Mobile menu button. Hidden on desktop, where the links sit inline. */
.nav__burger{
  display:none;width:38px;height:38px;padding:0;cursor:pointer;
  background:transparent;border:0;border-radius:var(--r-control);
  flex-direction:column;align-items:center;justify-content:center;gap:4px;
}
.nav__burger:hover{background:rgba(23,26,32,.07)}
.nav__burger span{display:block;width:17px;height:1.5px;background:var(--ink);transition:transform .2s ease,opacity .2s ease}
.nav.is-open .nav__burger span:nth-child(1){transform:translateY(5.5px) rotate(45deg)}
.nav.is-open .nav__burger span:nth-child(2){opacity:0}
.nav.is-open .nav__burger span:nth-child(3){transform:translateY(-5.5px) rotate(-45deg)}

.nav__pill--cta{background:var(--ink-violet);color:#fff}
.nav__pill--cta:hover{background:var(--brand);color:#fff}

/* ---------- hero ---------- */
.hero{position:relative;background:var(--grey);padding:calc(var(--gap) * 1.15) var(--pad)}
.hero::before{
  content:"";position:absolute;inset:0;pointer-events:none;z-index:0;
  background:
    radial-gradient(60% 78% at 78% 24%, rgba(255,255,255,.96) 0%, rgba(255,255,255,.78) 28%, rgba(255,255,255,0) 62%),
    linear-gradient(90deg, rgba(247,247,244,.98) 0%, rgba(247,247,244,.97) 32%, rgba(247,247,244,.82) 48%, rgba(247,247,244,.24) 64%, rgba(247,247,244,0) 78%);
}
.hero__inner{position:relative;z-index:1}
.hero__inner{display:grid;grid-template-columns:minmax(0,56%) minmax(0,44%);gap:clamp(2rem,5vw,4.5rem);align-items:center;min-height:clamp(30rem,70vh,44rem)}
.hero__copy{display:flex;flex-direction:column;align-items:flex-start;position:relative;z-index:2;max-width:42rem;transform:translateY(-126px)}
.hero__title{font-size:clamp(2.1rem,4.4vw,3.5rem);font-weight:700;line-height:1.03;letter-spacing:-0.035em;margin:0;max-width:28ch;text-wrap:balance}
.hero__lede{font-size:clamp(1.0625rem,1.5vw,1.25rem);line-height:1.5;color:var(--ink-soft);margin:1.25rem 0 0;max-width:32rem}
.hero .btns{margin-top:2rem}
.hero__visual{
  position:absolute;top:-4%;right:-8vw;
  bottom:-6%;width:76vw;max-width:none;pointer-events:none;z-index:1;
  transform:scale(1.2);transform-origin:right bottom;
  mask-image:
    linear-gradient(90deg, transparent 0%, rgba(0,0,0,.7) 18%, #000 34%, #000 94%, transparent 100%),
    linear-gradient(180deg, transparent 0%, #000 10%, #000 92%, transparent 100%);
  mask-composite:intersect;
  -webkit-mask-image:
    linear-gradient(90deg, transparent 0%, rgba(0,0,0,.7) 18%, #000 34%, #000 94%, transparent 100%),
    linear-gradient(180deg, transparent 0%, #000 10%, #000 92%, transparent 100%);
  -webkit-mask-composite:source-in;
}
.hero__image{display:block;width:100%;height:100%;object-fit:cover;object-position:54% 56%}
.hero__chip-engraving{
  position:absolute;left:32.9%;top:79%;width:2.25%;aspect-ratio:1;
  transform-origin:center;
  transform:translate(-50%,-50%) matrix(1,-.52,.92,.7,0,0);
  pointer-events:none;
}
.hero__chip-mark{position:absolute;inset:0;display:block;width:100%;height:100%}
.hero__chip-mark--shade{
  opacity:.55;filter:brightness(.76) blur(.18px);
  mix-blend-mode:multiply;transform:translate(.7px,.7px);
}
.hero__chip-mark--light{
  opacity:.6;filter:brightness(1.08) blur(.12px);
  mix-blend-mode:screen;transform:translate(-.7px,-.7px);
}
/* ---------- terminal ---------- */
.term{
  border-radius:8px;overflow:hidden;background:#14161A;
  box-shadow:0 28px 64px rgba(23,26,32,.20), 0 3px 10px rgba(23,26,32,.10),
             inset 0 1px 0 rgba(255,255,255,.06);
  backface-visibility:hidden;
}
.term__bar{
  display:flex;gap:8px;align-items:center;height:34px;padding:0 14px;
  background:#1E2127;border-bottom:1px solid #262A31;
}
.term__dot{width:11px;height:11px;border-radius:50%;flex:0 0 auto}
.term__dot:nth-child(1){background:#FF5F57}
.term__dot:nth-child(2){background:#FEBC2E}
.term__dot:nth-child(3){background:#28C840}
/* Top-right corner of the terminal itself, not tucked inside the title bar. */
.term{position:relative}
.term__mark{
  position:absolute;top:52px;right:22px;z-index:1;
  height:30px;width:auto;opacity:.72;
}
.term__body{
  padding:1.7rem 1.9rem 1.9rem;
  /* Real mono faces first, then the ones that actually exist on Linux. The
     previous stack resolved to a generic fallback and rendered soft. */
  font-family:"JetBrains Mono","Fira Code","SF Mono",Menlo,Consolas,
              "DejaVu Sans Mono","Liberation Mono",ui-monospace,monospace;
  font-size:1rem;line-height:1.7;color:#EAEDF2;
  -webkit-font-smoothing:antialiased;
  font-variant-ligatures:none;
}
.term__cmd{margin:0 0 1.1rem;color:#fff}
.term__prompt{color:#6E737D}
.term__out{display:flex;flex-direction:column;gap:.55rem;margin:0;padding:0;list-style:none}
.term__line{display:grid;grid-template-columns:1.1rem minmax(0,1fr) auto;gap:.75rem;align-items:baseline}
.term__ok{color:#5FD08A}
.term__note{color:#9AA0AA;font-size:.875rem;text-align:right}
.term__warn{color:#E0A93B}
.term__line--warn span:nth-child(2){color:#E0A93B}
.term__sum{margin:1rem 0 0;padding-top:.9rem;border-top:1px solid #262A31;color:#868C96;font-size:.8125rem}
.term__live{
  width:7px;height:7px;border-radius:50%;background:#5FD08A;
  justify-self:center;align-self:center;
}
.term__line--live{margin:.9rem 0 0;padding-top:1rem;border-top:1px solid #262A31}
.term__cursor{margin:1.1rem 0 0;color:#787D87}

.hero--term .term{margin-right:calc(var(--pad) * -0.55)}

/* The command types itself, then each line lands in turn. Once, slowly.
   clip-path rather than width, so it works at any string length - the
   Portuguese and English commands differ. */
.term__cmd [data-i18n]{
  display:inline-block;
  max-width:100%;              /* inline-block will not wrap without this */
  clip-path:inset(0 100% 0 0);
  animation:term-type 1.05s steps(22,end) .35s forwards;
}
@keyframes term-type{to{clip-path:inset(0 0 0 0)}}

.hero--term .term__line{opacity:0;animation:term-in .01s linear forwards}
.hero--term .term__out .term__line:nth-child(1){animation-delay:1.55s}
.hero--term .term__out .term__line:nth-child(2){animation-delay:1.78s}
.hero--term .term__out .term__line:nth-child(3){animation-delay:2.01s}
.hero--term .term__out .term__line:nth-child(4){animation-delay:2.30s}
.hero--term .term__out .term__line:nth-child(5){animation-delay:2.53s}
.hero--term .term__out .term__line:nth-child(6){animation-delay:2.76s}
.hero--term .term__line--live{animation-delay:3.10s}
@keyframes term-in{to{opacity:1}}

/* A blinking cursor is what a terminal does - an affordance, not decoration. */
.term__cursor{animation:term-blink 1.1s steps(1,end) 3.4s infinite}
@keyframes term-blink{0%,50%{opacity:1}50.01%,100%{opacity:.15}}



/* ---------- assistant ---------- */
.asst__launch{
  position:fixed;right:1.25rem;bottom:1.25rem;z-index:50;
  display:flex;align-items:center;gap:.7rem;
  padding:.75rem 1.15rem .75rem .85rem;
  font:inherit;text-align:left;cursor:pointer;
  background:var(--ink-violet);color:#fff;
  border:0;border-radius:var(--r-control);
  box-shadow:0 12px 30px rgba(25,20,40,.30);
  transition:background-color .18s ease,transform .18s ease;
}
.asst__launch:hover{background:#221B36;transform:translateY(-1px)}
.asst__launch-mark{display:flex;width:26px;height:26px;flex:0 0 auto}
.asst__launch-mark img{width:100%;height:auto;opacity:.9}
.asst__launch-title{font-size:.875rem;font-weight:700}

.asst__backdrop{position:fixed;inset:0;z-index:49;border:0;background:rgba(23,26,32,.38);cursor:pointer}
/* Page is pinned while the sheet is open, so it cannot scroll behind it. */
body.asst-open{position:fixed;left:0;right:0;width:100%;overflow:hidden}
.asst__backdrop[hidden]{display:none}

.asst__panel{
  position:fixed;right:1.25rem;bottom:1.25rem;z-index:51;
  /* Sized from the viewport, so it stays usable on a laptop and uses the room
     available on a large monitor. A definite height rather than a cap: without
     it the panel only ever grows to fit its content and stays short on a big
     screen. The thread takes the slack. */
  width:clamp(20rem,26vw,27rem);
  max-width:calc(100vw - 2.5rem);
  height:clamp(21rem,58svh,42rem);
  max-height:calc(100svh - 6.5rem);
  display:flex;flex-direction:column;
  overflow:hidden;
  background:var(--ground);border:1px solid var(--rule);border-radius:var(--r-control);
  box-shadow:0 24px 60px rgba(23,26,32,.22);
}
.asst__panel[hidden]{display:none}

/* Dark header, so the panel reads as part of the same family as the terminal
   rather than a generic support widget. */
.asst__grab{display:none}
.asst__top{position:relative}
.asst__top{
  flex:0 0 auto;
  display:flex;align-items:center;gap:.7rem;
  padding:.8rem 1rem .8rem 1.05rem;
  background:var(--ink-violet);color:#fff;
}
.asst__mark{width:22px;height:auto;flex:0 0 auto;opacity:.92}
.asst__title{margin:0;font-size:.9375rem;font-weight:700;letter-spacing:-0.015em}
.asst__close{
  margin-left:auto;flex:0 0 auto;
  display:inline-flex;align-items:center;justify-content:center;
  width:30px;height:30px;padding:0;cursor:pointer;
  background:transparent;border:0;border-radius:var(--r-control);
  color:rgba(255,255,255,.62);
  transition:background-color .16s ease,color .16s ease;
}
.asst__close:hover{background:rgba(255,255,255,.12);color:#fff}
.asst__lead{flex:0 0 auto;margin:0;padding:1rem 1.05rem 0;font-size:.8125rem;color:var(--ink-soft)}
/* The thread takes the slack so the form sits at the bottom of the panel, and
   messages stack up from just above it. margin-top:auto on the first message
   rather than justify-content:flex-end, which clips the top of an overflowing
   flex column in several browsers. */
.asst__thread{flex:1 1 auto;min-height:0;display:flex;flex-direction:column;gap:.6rem;overflow-y:auto;padding:1rem 1.05rem 0}
.asst__thread>:first-child{margin-top:auto}
.asst__msg{padding:.6rem .8rem;border-radius:var(--r-control);font-size:.875rem;line-height:1.5}
.asst__msg--user{background:var(--grey);color:var(--ink);align-self:flex-end;max-width:85%}
.asst__msg--bot{background:var(--ground);border:1px solid var(--rule);color:var(--ink-soft)}
.asst__thinking{display:flex;align-items:center;gap:.28rem;min-width:3.2rem;min-height:1.15rem}
.asst__thinking span{width:.42rem;height:.42rem;border-radius:50%;background:var(--brand);animation:asst-pulse 1.05s ease-in-out infinite}
.asst__thinking span:nth-child(2){animation-delay:.14s}.asst__thinking span:nth-child(3){animation-delay:.28s}
@keyframes asst-pulse{0%,60%,100%{opacity:.3;transform:translateY(0)}30%{opacity:1;transform:translateY(-.18rem)}}
.asst__form{flex:0 0 auto;display:flex;flex-direction:column;gap:.5rem;padding:1rem 1.05rem 1.1rem}
/* Composer follows the convention the messaging apps set: one line to start,
   growing to about five, then scrolling internally, with a send arrow that
   only takes the accent colour once there is something to send. */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.asst__composer{
  display:flex;align-items:flex-end;gap:.5rem;
  padding:.4rem .4rem .4rem .75rem;
  border:1px solid var(--rule);border-radius:10px;background:var(--ground);
  transition:border-color .16s ease;
}
.asst__composer:focus-within{border-color:var(--ink)}
.asst__input{
  flex:1 1 auto;min-width:0;
  font:inherit;font-size:1rem;line-height:1.5;color:var(--ink);
  background:transparent;border:0;outline:none;resize:none;
  padding:.45rem 0;max-height:7.5rem;overflow-y:auto;
}
.asst__send{
  flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;
  width:34px;height:34px;padding:0;cursor:pointer;
  border:0;border-radius:8px;
  background:var(--grey);color:var(--ink-soft);
  transition:background-color .16s ease,color .16s ease;
}
.asst__send:enabled{background:var(--brand);color:#fff}
.asst__send:enabled:hover{background:var(--brand-dark)}
.asst__send:disabled{cursor:default}
.asst__meta{margin:0;font-size:.6875rem;color:var(--ink-soft)}
.asst__status{margin:0;font-size:.75rem;color:var(--ink-soft)}

/* Something to tap in an empty conversation, rather than a blank panel. */
.asst__suggest{display:flex;flex-wrap:wrap;gap:.4rem;padding:0 1.05rem}
.asst__suggest[hidden]{display:none}
.asst__chip{
  font:inherit;font-size:.8125rem;cursor:pointer;text-align:left;
  padding:.45rem .75rem;
  background:var(--grey);color:var(--ink);
  border:1px solid var(--rule);border-radius:999px;
  transition:border-color .16s ease,background-color .16s ease;
}
.asst__chip:hover{border-color:var(--ink);background:var(--ground)}
.asst__status[data-state="error"]{color:#B23A28}

@media (max-width:620px){
  /* 16px minimum on the field, otherwise iOS zooms the whole page on focus */
  .asst__input{font-size:16px}
  /* A proper sheet: tall enough to read as one, with a grabber and a slide-up.
     A content-height strip floating mid-screen is what looked unfinished. */
  .asst__panel{
    left:0;right:0;bottom:0;width:100%;max-width:none;
    padding-bottom:env(safe-area-inset-bottom,0px);
    height:auto;min-height:52dvh;max-height:88dvh;
    border-radius:16px 16px 0 0;border-left:0;border-right:0;border-bottom:0;
    animation:sheet-up .28s cubic-bezier(.22,.61,.36,1);
  }
  @keyframes sheet-up{from{transform:translateY(12%);opacity:.6}to{transform:none;opacity:1}}
  /* On the header, not on a white strip above it - that seam was the one
     place the sheet showed its construction. */
  .asst__top{padding-top:1.25rem;border-radius:16px 16px 0 0}
  .asst__grab{
    display:block;position:absolute;top:.5rem;left:50%;transform:translateX(-50%);
    width:36px;height:4px;border-radius:99px;
    background:rgba(255,255,255,.32);
  }
  .asst__thread{flex:1 1 auto;max-height:none}
  .asst__suggest{padding-bottom:.25rem}
  .asst__launch{right:.9rem;bottom:calc(.9rem + env(safe-area-inset-bottom,0px));padding:.7rem 1.05rem .7rem .8rem}
  .asst__launch-mark{width:22px;height:22px}
  .asst__launch-title{font-size:.8125rem}
}

/* ---------- sections ---------- */
.section{padding:var(--gap) var(--pad)}
/* anchor targets land below the sticky nav with breathing room above */
section[id]{scroll-margin-top:clamp(5rem,11vh,8rem)}
.section--grey{background:var(--grey)}
.section__head{margin-bottom:clamp(1.75rem,3vw,2.5rem)}

/* ---------- buttons ---------- */
.btns{display:flex;flex-wrap:wrap;gap:.75rem}
.btn{
  display:inline-flex;align-items:center;justify-content:center;
  min-height:44px;padding:.65rem 1.6rem;
  font:inherit;font-size:.9375rem;font-weight:700;
  border:1px solid transparent;border-radius:var(--r-control);cursor:pointer;
  transition:background-color .18s ease,border-color .18s ease,color .18s ease;
}
/* At rest the buttons sit in the same near-black family as the CTA band and
   the launcher, so the darks resolve instead of competing. The accent arrives
   on hover, which is also where it does the most work. */
.btn--solid{background:var(--ink-violet);color:#fff}
.btn--solid:hover{background:var(--brand)}
.btn--ghost{background:#fff;color:var(--ink);border-color:var(--ink)}
.btn--ghost:hover{background:var(--ink);color:#fff}
.btn--invert{background:#fff;color:var(--ink-violet)}
.btn--invert:hover{background:#EDEDF0;color:var(--brand)}
.btn--outline{background:transparent;color:#fff;border-color:rgba(255,255,255,.45)}
.btn--outline:hover{border-color:#fff}

/* ---------- area cards ----------
   The photograph is framed inside a flat panel and the text sits below it on
   solid colour. Text never touches the image, so contrast holds whatever the
   photo contains - no per-image tuning, no overlay to dim. WCAG advises against
   text over images for exactly this reason. */
.cards{display:grid;grid-template-columns:repeat(6,1fr);gap:clamp(1rem,1.6vw,1.4rem)}
.cards>.card:nth-child(-n+3){grid-column:span 2}
.cards>.card:nth-child(n+4){grid-column:span 3}

/* Light frame rather than dark: five dark panels in a row sat too heavy in a
   white page, and the photographs read better against paper than against ink. */
.card{
  display:flex;flex-direction:column;
  background:var(--ground);
  border:1px solid var(--rule);
  border-radius:6px;padding:.65rem;
  transition:transform .22s ease, box-shadow .22s ease, border-color .22s ease;
}
.card:hover{transform:translateY(-2px);border-color:var(--ink-violet);box-shadow:0 14px 30px rgba(23,26,32,.10)}
.card:focus-visible{outline:2px solid var(--brand);outline-offset:3px}
.card__media{position:relative;overflow:hidden;border-radius:3px}
.card__img{width:100%;aspect-ratio:4/3;object-fit:cover;background:var(--grey);display:block}
.card__body{padding:1rem .55rem .5rem;display:flex;flex-direction:column;gap:.45rem}
.card__title{margin:0;color:var(--ink);font-size:1.125rem;font-weight:700;letter-spacing:-0.018em}
.card__copy{margin:0;color:var(--ink-soft);font-size:.9375rem;line-height:1.55}

/* ---------- area cards: desktop ----------
   Above 620px the frame is dropped and the layout returns to the mosaic, with
   the text over the photograph and revealed on hover. The framed card is a
   phone treatment only: there is no hover there, and a paragraph over an image
   is unreadable at that size. */
@media (min-width:621px){
  .cards{grid-template-columns:repeat(12,1fr)}
  .cards>.card:nth-child(1){grid-column:span 5}
  .cards>.card:nth-child(2){grid-column:span 7}
  .cards>.card:nth-child(n+3){grid-column:span 4}
  .cards>.card:nth-child(1) .card__media{aspect-ratio:1.060}
  .cards>.card:nth-child(2) .card__media{aspect-ratio:1.500}
  .cards>.card:nth-child(n+3) .card__media{aspect-ratio:1.217}

  .card{background:none;border:0;border-radius:0;padding:0;position:relative}
  .card:hover{transform:none;box-shadow:none;border-color:transparent}
  .card__media{border-radius:2px}
  .card__img{aspect-ratio:auto;height:100%;transition:transform .5s cubic-bezier(.22,.61,.36,1)}
  .card:hover .card__img,.card:focus-visible .card__img{transform:scale(1.04)}

  /* gradient on the media itself: no extra element in the markup */
  .card__media::after{
    content:"";position:absolute;inset:0;pointer-events:none;
    background:linear-gradient(to top,
      rgba(14,16,20,.86) 0%, rgba(14,16,20,.5) 22%, rgba(14,16,20,0) 46%);
    transition:background .28s ease;
  }
  .card:hover .card__media::after,.card:focus-visible .card__media::after{
    background:linear-gradient(to top,
      rgba(14,16,20,.94) 0%, rgba(14,16,20,.82) 30%,
      rgba(14,16,20,.35) 55%, rgba(14,16,20,0) 72%);
  }
  .card--top .card__media::after{
    background:linear-gradient(to bottom,
      rgba(14,16,20,.86) 0%, rgba(14,16,20,.5) 22%, rgba(14,16,20,0) 46%);
  }
  .card--top:hover .card__media::after,.card--top:focus-visible .card__media::after{
    background:linear-gradient(to bottom,
      rgba(14,16,20,.94) 0%, rgba(14,16,20,.82) 30%,
      rgba(14,16,20,.35) 55%, rgba(14,16,20,0) 72%);
  }

  .card__body{
    position:absolute;left:0;right:0;bottom:0;z-index:1;
    padding:1.5rem 1.6rem;max-width:min(92%,42ch);
    display:flex;flex-direction:column;gap:.55rem;
  }
  .card--top .card__body{top:0;bottom:auto}
  .card__title{order:2;color:#fff;font-size:clamp(1.15rem,1.35vw,1.4rem);text-shadow:0 1px 12px rgba(0,0,0,.28)}
  .card--top .card__title{order:1}
  .card__copy{
    order:1;color:rgba(255,255,255,.9);
    opacity:0;transform:translateY(6px);
    transition:opacity .28s ease, transform .28s ease;
  }
  .card--top .card__copy{order:2}
  .card:hover .card__copy,.card:focus-visible .card__copy{opacity:1;transform:none}
}

/* ---------- carousel controls ----------
   A scroll carousel gives no sign that it scrolls. Arrows say so, and give a
   target for anyone who would rather tap than swipe. */
.rail-nav{display:none}
@media (max-width:620px){
  .rail-nav{
    display:flex;align-items:center;justify-content:flex-end;gap:.5rem;
    margin-top:.9rem;
  }
  .rail-nav__btn{
    display:inline-flex;align-items:center;justify-content:center;
    width:40px;height:40px;padding:0;cursor:pointer;
    background:var(--ground);color:var(--ink);
    border:1px solid var(--rule);border-radius:var(--r-control);
  }
  .rail-nav__btn:disabled{opacity:.35;cursor:default}
  .rail-nav__count{
    margin-right:auto;font-size:.8125rem;color:var(--ink-soft);
    font-variant-numeric:tabular-nums;
  }
}

/* ---------- technology marks ----------
   The only colour on the page, and it belongs to the brands themselves. */
/* No box and no hover state: these are labels, not controls. A bordered
   rounded rectangle reads as a button and invites a click that does nothing. */
.marquee{
  display:flex;overflow:hidden;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 5%,#000 95%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 5%,#000 95%,transparent);
}
.marquee__track{
  display:flex;gap:3rem;flex:0 0 auto;padding-right:3rem;
  animation:marquee 38s linear infinite;
}
.marquee:hover .marquee__track{animation-play-state:paused}
@keyframes marquee{from{transform:translateX(0)}to{transform:translateX(-100%)}}
.mark{display:flex;align-items:center;gap:.65rem;white-space:nowrap}
.mark img{width:26px;height:26px;flex:0 0 auto}
.mark span{font-size:.9375rem;font-weight:400;color:var(--ink-soft);letter-spacing:0}

/* ---------- process ----------
   A horizontal rail with a node per stage. The sequence is the graphic - no
   icons, because a picture per step says nothing the number does not. The rail
   fills as the section scrolls in, once. */
.steps{
  position:relative;
  display:grid;grid-template-columns:repeat(5,1fr);
  gap:clamp(1rem,2vw,2rem);
  padding-top:2.25rem;
}
/* the track, and the accent that runs along it */
.steps::before,.steps::after{
  content:"";position:absolute;top:6px;height:1px;
  left:calc(10% - 0px);right:calc(10% - 0px);
}
.steps::before{background:var(--rule)}
.steps::after{
  /* The gradient fades the last few percent, so the growing edge is soft
     rather than a hard cut. It scales with the line, so the softness stays
     proportional the whole way across. */
  background:linear-gradient(90deg,var(--brand) 0%,var(--brand) 88%,rgba(58,32,200,0) 100%);
  transform:scaleX(0);transform-origin:left center;
  transition:transform 2.4s linear;
}
.steps.is-on::after{transform:scaleX(1)}

.step{position:relative;display:flex;flex-direction:column;gap:.3rem}
.step__node{
  position:absolute;top:-2.25rem;left:calc(50% - 6.5px);
  width:13px;height:13px;border-radius:50%;
  background:var(--grey);border:1.5px solid var(--rule);
  transition:background-color .35s ease,border-color .35s ease,transform .35s ease,box-shadow .35s ease;
}
.steps.is-on .step__node{
  background:var(--brand);border-color:var(--brand);
  /* A soft halo, not a glow: a wide low-alpha ring plus a small blurred
     shadow, so a lit node sits on the page instead of floating over it. */
  box-shadow:0 0 0 5px rgba(58,32,200,.10), 0 2px 6px rgba(58,32,200,.22);
}
.steps .step:nth-child(1) .step__node{transition-delay:.15s}
.steps .step:nth-child(2) .step__node{transition-delay:.72s}
.steps .step:nth-child(3) .step__node{transition-delay:1.29s}
.steps .step:nth-child(4) .step__node{transition-delay:1.86s}
.steps .step:nth-child(5) .step__node{transition-delay:2.43s}
.steps.is-on .step--last .step__node{
  background:#2FA968;border-color:#2FA968;transform:scale(1.15);
  box-shadow:0 0 0 5px rgba(47,169,104,.12), 0 2px 6px rgba(47,169,104,.24);
}
.step__n{font-size:.8125rem;color:var(--ink-soft);font-variant-numeric:tabular-nums}
.step__t{font-size:1.0625rem;font-weight:700;letter-spacing:-0.012em;margin:0}
.step__d{font-size:.9rem;line-height:1.5;color:var(--ink-soft);margin:.15rem 0 0}
.step__n{font-size:.875rem;color:var(--ink-soft);font-variant-numeric:tabular-nums}
.step__t{font-size:1.0625rem;font-weight:700;letter-spacing:-0.012em;margin:0}
.step__d{font-size:.9rem;line-height:1.5;color:var(--ink-soft);margin:.25rem 0 0}

/* ---------- deliverables ---------- */
.delivers{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(1rem,1.75vw,1.25rem)}
.deliver{
  border:1px solid var(--rule);border-radius:var(--r-control);
  padding:1.35rem 1.5rem;background:var(--ground);
}
.section--grey .deliver{background:var(--ground)}
.deliver__t{font-size:1rem;font-weight:700;letter-spacing:-0.012em;margin:0}
.deliver__d{font-size:.9375rem;color:var(--ink-soft);margin:.4rem 0 0}

/* ---------- news ---------- */
/* Cards with one clear hierarchy - meta, title, cue - and the whole card as
   the link, so the target is card-sized rather than a two-word "Read". */
.news{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(1rem,1.5vw,1.25rem)}
.news__item{display:flex}
.news__box{
  display:flex;flex-direction:column;flex:1 1 auto;
  padding:1.25rem 1.35rem 1.35rem;
  background:var(--ground);
  border:1px solid var(--rule);border-radius:var(--r-control);
  transition:border-color .18s ease,box-shadow .18s ease,transform .18s ease;
}
.news__box:hover{
  border-color:var(--ink-violet);
  box-shadow:0 10px 26px rgba(23,26,32,.09);
  transform:translateY(-2px);
}
.news__meta{display:flex;gap:.6rem;font-size:.75rem;color:var(--ink-soft);font-variant-numeric:tabular-nums}
.news__title{font-size:1rem;font-weight:700;line-height:1.35;letter-spacing:-0.012em;margin:.55rem 0 0}
.news__link{margin-top:auto;padding-top:1rem;font-size:.875rem;color:var(--ink-soft)}
.news__box:hover .news__link{color:var(--brand)}

/* ---------- feed page ---------- */
.feed{display:flex;flex-direction:column}
.feed .news__item{display:block}
.feed .news__box{
  display:grid;grid-template-columns:9rem minmax(0,1fr) auto;
  gap:1.5rem;align-items:baseline;
  padding:1.15rem 1rem;margin:0 -1rem;
  background:transparent;border:0;border-top:1px solid var(--rule);border-radius:0;
  transform:none;
}
.feed .news__item:last-child .news__box{border-bottom:1px solid var(--rule)}
.feed .news__box:hover{background:var(--ground);box-shadow:none;transform:none;border-color:var(--rule)}
.feed .news__title{margin:0}
.feed .news__link{margin:0;padding:0;white-space:nowrap}
.feed__empty{font-size:.9375rem;color:var(--ink-soft);margin:0}
.news__all{margin:1.75rem 0 0}
.news__all a{font-size:.9375rem;font-weight:700;border-bottom:1px solid var(--rule)}
.news__all a:hover{border-color:var(--brand)}

@media (max-width:760px){
  .feed .news__item{grid-template-columns:1fr;gap:.35rem}
}

/* ---------- CTA band ---------- */
.cta{background:var(--ink-violet);color:#fff;padding:clamp(3rem,6vw,4.5rem) var(--pad);text-align:center}
.cta__inner{display:flex;flex-direction:column;align-items:center;text-align:center;gap:1.75rem}
.cta__title{color:#fff}
.cta__copy{color:rgba(255,255,255,.82);margin:.9rem auto 0;max-width:38rem}

/* ---------- contact ---------- */
.contact{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:clamp(2.5rem,5vw,4.5rem);align-items:start}
.facts{margin-top:2rem;display:flex;flex-direction:column;gap:1.1rem}
.fact{border-top:1px solid var(--rule);padding-top:.75rem}
.fact dt{font-size:.8125rem;color:var(--ink-soft)}
.fact dd{font-size:1rem;margin:.2rem 0 0}
.fact a{border-bottom:1px solid var(--rule)}
.fact a:hover{border-color:var(--brand)}
.form{display:flex;flex-direction:column;gap:1rem}
.contact-status{margin:0;padding:.8rem 1rem;border-radius:.4rem;font-size:.9rem}.contact-status[data-state="success"]{color:#174d2d;background:#dff3e6;border:1px solid #73bd8b}.contact-status[data-state="error"]{color:#7d241b;background:#fde5e1;border:1px solid #df8b80}
.field{display:flex;flex-direction:column;gap:.35rem}
.field label{font-size:.8125rem;color:var(--ink-soft)}
.field input,.field textarea{
  font:inherit;font-size:.9375rem;color:var(--ink);background:var(--ground);
  border:1px solid var(--rule);border-radius:var(--r-control);padding:.7rem .85rem;width:100%;
}
.field input:focus,.field textarea:focus{border-color:var(--ink);outline:none}
.field textarea{min-height:7rem;resize:vertical}
.field-row{display:grid;grid-template-columns:1fr 1fr;gap:1rem}
.form__send{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:1rem;margin-top:.3rem}
.form__send .note{text-align:right;max-width:20rem}
.note{font-size:.8125rem;color:var(--ink-soft);margin:0}
.note a{border-bottom:1px solid var(--rule)}
.note a:hover{border-color:var(--brand)}

/* ---------- legal pages ---------- */
.legal__head{padding-bottom:clamp(1.5rem,3vw,2.25rem)}
.legal__kicker{font-size:.8125rem;color:var(--ink-soft);margin:0 0 .9rem}
.legal__title{font-size:clamp(1.9rem,4vw,3rem);font-weight:700;line-height:1.06;letter-spacing:-0.032em;margin:0}
.legal__updated{font-size:.8125rem;color:var(--ink-soft);margin:1.5rem 0 0;padding-top:1.1rem;border-top:1px solid var(--rule)}
.legal{display:flex;flex-direction:column;gap:clamp(1.75rem,3vw,2.5rem)}
.legal__item{display:flex;flex-direction:column;gap:.65rem}
.legal__h{
  display:grid;grid-template-columns:2.75rem 1fr;gap:.5rem;align-items:baseline;
  font-size:1.0625rem;font-weight:700;letter-spacing:-0.012em;margin:0;
}
.legal__n{font-size:.8125rem;color:var(--ink-soft);font-variant-numeric:tabular-nums}
.legal__item p{margin:0 0 0 3.25rem;font-size:.9375rem;line-height:1.65;color:var(--ink-soft);}
.legal__item p + p{margin-top:.75rem}
.legal__item a{color:var(--ink);border-bottom:1px solid var(--rule)}
.legal__item a:hover{border-color:var(--brand)}

@media (max-width:620px){
  .legal__h{grid-template-columns:1fr;gap:.15rem}
  .legal__item p{margin-left:0}
}

/* ---------- footer ----------
   Shape taken from the live site: mark, one nav row, one legal row, copyright.
   Centred and compact rather than four columns. */
.foot{
  background:var(--ground);
  border-top:1px solid var(--rule);
  padding:clamp(1.5rem,2.5vw,2rem) var(--pad)
    calc(clamp(1.5rem,2.5vw,2rem) + env(safe-area-inset-bottom,0px));
}
/* One row: mark and nav on the left, legal and copyright pushed right. */
.foot__inner{display:flex;flex-wrap:wrap;align-items:center;gap:.75rem 2.25rem}
.foot__logo{display:block;flex:0 0 auto}
.foot__logo img{height:28px;width:auto}
.foot__nav{display:flex;flex-wrap:wrap;gap:.4rem 1.6rem}
.foot__nav a{font-size:.9375rem;color:var(--ink)}
.foot__nav a:hover{color:var(--ink-soft)}
.foot__legal{display:flex;flex-wrap:wrap;align-items:center;gap:.4rem 1.5rem;margin-left:auto}
.foot__legal a,.foot__copy{font-size:.8125rem;color:var(--ink-soft)}
.foot__legal a:hover{color:var(--ink)}

/* Placed after the desktop footer rules on purpose: media queries add no
   specificity, so an override written earlier in the file simply loses. */
@media (max-width:620px){
  .foot__inner{flex-direction:column;align-items:center;text-align:center;gap:1rem}
  .foot__nav,.foot__legal{justify-content:center;margin-left:0;margin-right:0}
}

@media (max-width:1000px){
  .cards{grid-template-columns:repeat(2,1fr)}
  .cards>.card:nth-child(n) .card__media{aspect-ratio:4/3}
  .delivers{grid-template-columns:repeat(2,1fr)}
  .news{grid-template-columns:repeat(2,1fr)}
}
@media (max-width:860px){
  .nav{grid-template-columns:auto 1fr;height:60px}
  .nav__burger{display:flex}
  /* No positioning at all: the bar itself grows and the links occupy a second
     grid row. Absolute and fixed both failed here - an absolutely-positioned
     grid item is contained by its grid area, and .nav's backdrop-filter creates
     a containing block that traps fixed descendants too. */
  .nav{height:auto;min-height:60px;padding-block:0}
  .nav__logo{grid-row:1;grid-column:1}
  .nav__util{grid-row:1;grid-column:2}
  .nav__mid{
    grid-row:2;grid-column:1 / -1;
    /* the base rule centres this item, which shrink-wraps it - that, not the
       positioning, is why the panel kept coming out narrow */
    justify-self:stretch;
    display:none;
    margin:0 calc(var(--pad) * -1);
    padding:.25rem var(--pad) .75rem;
    border-top:1px solid var(--rule);
  }
  .nav.is-open .nav__mid{display:block}
  .nav.is-open{padding-bottom:0}
  .nav__links{flex-direction:column;gap:0}
  .nav__links a{display:block;padding:.7rem .2rem;font-size:1rem;border-bottom:1px solid var(--rule)}
  .nav__links li:last-child a{border-bottom:0}
  .nav__logo img{height:38px}
  .contact{grid-template-columns:1fr}
  .hero__inner{grid-template-columns:1fr;gap:2.5rem;min-height:auto}
  .hero__copy{align-items:flex-start;text-align:left;max-width:42rem;transform:translateY(-60px)}
  .hero__title{max-width:28ch}
  .hero__lede{margin-inline:0}
  .hero .btns{width:auto;max-width:none;margin-inline:0}
  .hero__visual{
    top:-1%;right:-13vw;
    bottom:-4%;width:80vw;max-width:none;
    transform:scale(1.16)
  }
  .hero__image{object-position:58% 54%}
  .hero__chip-engraving{left:32.9%;top:78.3%}
  /* caret for the typed headline */
  .hero__title.is-typing::after{
    content:"";display:inline-block;width:.06em;height:.85em;
    margin-left:.06em;vertical-align:-0.08em;background:var(--ink);
    animation:caret 1s steps(1,end) infinite;
  }
  @keyframes caret{0%,50%{opacity:1}50.01%,100%{opacity:0}}
  .hero__diagram{max-width:32rem}
  .stack{grid-template-columns:1fr}
  .hero__scrim{background:linear-gradient(180deg, rgba(255,255,255,.92) 0%, rgba(255,255,255,.8) 55%, rgba(255,255,255,.55) 100%)}
}
@media (max-width:620px){
  .hero{
    padding-top:calc(var(--gap) * 1.05);
    padding-bottom:calc(var(--gap) * .95);
  }
  .hero::before{
    background:
      radial-gradient(58% 56% at 80% 12%, rgba(255,255,255,.96) 0%, rgba(255,255,255,.74) 24%, rgba(255,255,255,0) 58%),
      linear-gradient(180deg, rgba(247,247,244,.98) 0%, rgba(244,243,238,.94) 62%, rgba(240,238,232,.94) 100%);
  }
  .hero__inner{gap:2rem}
  .hero__copy{max-width:none;transform:none}
  .hero__title{max-width:none}
  .hero__lede{max-width:28rem}
  .hero__visual{
    position:relative;top:auto;right:auto;bottom:auto;width:100%;
    margin-top:.75rem;aspect-ratio:1672 / 941;
    mask-image:
      linear-gradient(180deg, transparent 0%, rgba(0,0,0,.84) 14%, #000 30%, #000 88%, transparent 100%),
      linear-gradient(90deg, transparent 0%, #000 8%, #000 92%, transparent 100%);
    -webkit-mask-image:
      linear-gradient(180deg, transparent 0%, rgba(0,0,0,.84) 14%, #000 30%, #000 88%, transparent 100%),
      linear-gradient(90deg, transparent 0%, #000 8%, #000 92%, transparent 100%);
  }
  .hero__image{object-fit:cover;object-position:54% 48%}
  .hero__chip-engraving{display:none}
  /* Carousel: one framed card at a time, snapping. Full-bleed so the
     neighbours peek in and it reads as scrollable without a scrollbar. */
  .cards{
    display:flex;gap:.75rem;
    overflow-x:auto;overscroll-behavior-x:contain;
    scroll-snap-type:x mandatory;
    scroll-padding-inline:var(--pad);
    margin-inline:calc(var(--pad) * -1);
    /* Leading space as padding, trailing space as a real flex item. WebKit
       leaves padding-inline-end out of the scrollable overflow, so a padded
       track can never scroll its last card fully into view on iOS. A spacer
       is content, and content always scrolls. */
    padding-inline-start:var(--pad);
    padding-inline-end:0;
    scrollbar-width:none;
  }
  .cards::after{content:"";flex:0 0 var(--pad);align-self:stretch}
  .cards::-webkit-scrollbar{display:none}
  .cards>.card:nth-child(n){grid-column:auto;flex:0 0 86%;scroll-snap-align:start}
  .cards>.card:last-child{scroll-snap-align:end}
  .card__body{padding:.9rem .5rem .4rem}
  .card__title{font-size:1.0625rem}
  .card:hover{transform:none;box-shadow:none}

  .news{
    display:flex;gap:.75rem;
    overflow-x:auto;overscroll-behavior-x:contain;
    scroll-snap-type:x mandatory;
    scroll-padding-inline:var(--pad);
    margin-inline:calc(var(--pad) * -1);
    padding-inline-start:var(--pad);
    padding-inline-end:0;
    scrollbar-width:none;
  }
  .news::after{content:"";flex:0 0 var(--pad);align-self:stretch}
  .news::-webkit-scrollbar{display:none}
  .news__item{flex:0 0 80%;scroll-snap-align:start}
  .news__item:last-child{scroll-snap-align:end}
  .steps{grid-template-columns:1fr;gap:1.5rem;padding-top:0;padding-left:1.5rem}
  /* --rail-h is measured in JS: the distance between the first and last node,
     so the line ends on the green marker rather than running past it */
  .steps::before,.steps::after{
    top:0;bottom:auto;left:5px;right:auto;width:1px;
    height:var(--rail-h,100%);
  }
  .steps::after{transform:scaleY(0);transform-origin:top center}
  .steps.is-on::after{transform:scaleY(1)}
  .step__node{top:.4rem;left:-1.5rem}
  .delivers{grid-template-columns:1fr}
  .field-row{grid-template-columns:1fr}
  .form__send{flex-direction:column;align-items:stretch}
  .form__send .note{text-align:left;max-width:none}
  .btns{flex-direction:column;align-items:stretch}
  .btn{width:100%}
}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  .steps::after{transition:none}
  .step__node{transition:none;transition-delay:0s !important}
  .hero--term .term__line{opacity:1;animation:none}
  .term__cmd [data-i18n]{clip-path:none;animation:none}
  .term__cursor{animation:none}
  .marquee{display:block;-webkit-mask-image:none;mask-image:none}
  .marquee__track{animation:none;flex-wrap:wrap;gap:1.75rem 2.5rem;padding-right:0}
  .marquee__track[aria-hidden="true"]{display:none}
  *{transition-duration:.01ms !important}
}
