/* ==========================================================================
   Ganesha - theme.css (shared by index.html and features.html)

   Cinematic dark: rounded image panels framed on a near-black page, glass
   pill navigation, big pale-gradient headlines, glass cards, dot-grid
   sections. Every image is generated locally (tools/make_images.py) and
   every font is self-hosted. No external request anywhere in this file.

   Typeface: Manrope, (c) 2019 The Manrope Project Authors, SIL OFL 1.1 -
   see assets/fonts/LICENSE-OFL-Manrope.txt
   ========================================================================== */

@font-face{
  font-family:"Manrope";
  src:url("../fonts/Manrope-Variable-Latin.woff2") format("woff2-variations"),
      url("../fonts/Manrope-Variable-Latin.woff2") format("woff2");
  font-weight:200 800;font-style:normal;font-display:swap;
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

:root{
  --page:#0E0E0E;          /* the frame around the panels */
  --panel:#15110F;
  --fg:#F5F3EE;
  --muted:rgba(245,243,238,.72);   /* ~9:1 on the page */
  --faint:rgba(245,243,238,.52);   /* ~5:1 on the page */
  --line:rgba(255,255,255,.10);
  --line-2:rgba(255,255,255,.18);

  /* Headline gradients */
  --grad:linear-gradient(95deg,#F7F2C4 0%,#DDEACB 30%,#BFD9CF 62%,#EEF3F1 100%);
  --grad-warm:linear-gradient(95deg,#EBCFC2 0%,#D9B2A0 55%,#F2E0D5 100%);
  --grad-steel:linear-gradient(180deg,#FFFFFF 10%,#BDB8B5 100%);

  --frame:clamp(8px,1.1vw,20px);
  --r-panel:clamp(20px,2vw,30px);
  --font:"Manrope","Segoe UI",system-ui,-apple-system,"Helvetica Neue",Arial,sans-serif;
  --ease:cubic-bezier(.22,.61,.36,1);
}

*,*::before,*::after{box-sizing:border-box;}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;}
body{margin:0;background:var(--page);color:var(--fg);font-family:var(--font);
  font-size:1rem;line-height:1.6;-webkit-font-smoothing:antialiased;overflow-x:hidden;}
h1,h2,h3,p,ul,ol,dl,dd,figure{margin:0;}
/* Balanced lines: on phones the big headings otherwise leave one word alone on
   the last line ("site.", "soon.", "product,"). Ignored by older browsers. */
h1,h2,h3,dt,.hero__line{text-wrap:balance;}
/* Chrome only balances up to 6 lines; the statement runs to 8 on phones, so it
   uses pretty, which exists to stop a last word sitting alone. */
.statement__text{text-wrap:pretty;}
ul,ol{padding:0;list-style:none;}
a{color:inherit;text-decoration:none;}
svg{display:block;}
img{max-width:100%;display:block;}
:focus-visible{outline:2px solid #fff;outline-offset:3px;border-radius:8px;}
.visually-hidden{position:absolute!important;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;}
.skip{position:absolute;left:-9999px;top:8px;z-index:100;background:#fff;color:#000;padding:8px 12px;border-radius:8px;}
.skip:focus{left:16px;}
:target{scroll-margin-top:24px;}

/* --- Shared pieces --------------------------------------------------------- */

.grad-text,.warm-text,.steel-text{-webkit-background-clip:text;background-clip:text;
  color:transparent;-webkit-text-fill-color:transparent;}
.grad-text{background-image:var(--grad);}
.warm-text{background-image:var(--grad-warm);}
.steel-text{background-image:var(--grad-steel);}

.eyebrow{font-size:.8125rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--faint);}

.glass{
  background:rgba(255,255,255,.07);
  -webkit-backdrop-filter:blur(18px) saturate(140%);backdrop-filter:blur(18px) saturate(140%);
  border:1px solid rgba(255,255,255,.2);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.16),0 10px 30px rgba(0,0,0,.18);
}

.panel{position:relative;isolation:isolate;overflow:hidden;margin:var(--frame);
  border-radius:var(--r-panel);background:var(--panel);}
.panel__bg{position:absolute;inset:0;z-index:-1;background-size:cover;background-position:center;}

.dots{background-image:radial-gradient(rgba(255,255,255,.1) 1px,transparent 1.4px);background-size:22px 22px;}

/* Frosted cards (replaced the dot pattern on cards, 2026-09-17). Backdrop blur
   has nothing to frost on a flat near-black page, so every section holding
   frosted cards also gets .glow: soft colour fields behind the cards, drawn
   from the headline palette. */
.glow{position:relative;isolation:isolate;overflow:hidden;}
.glow::before{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;filter:blur(90px);opacity:.55;
  background:
    radial-gradient(28% 34% at 18% 30%,rgba(242,161,94,.38),transparent 70%),
    radial-gradient(26% 32% at 82% 22%,rgba(191,217,207,.45),transparent 70%),
    radial-gradient(30% 30% at 55% 78%,rgba(181,94,46,.5),transparent 70%),
    radial-gradient(22% 26% at 90% 85%,rgba(92,118,144,.45),transparent 70%);}
.frost{
  background:linear-gradient(160deg,rgba(255,255,255,.075) 0%,rgba(255,255,255,.025) 45%,rgba(255,255,255,.04) 100%),rgba(18,15,13,.45);
  -webkit-backdrop-filter:blur(28px) saturate(140%);backdrop-filter:blur(28px) saturate(140%);
  border-color:rgba(255,255,255,.13);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 24px 60px -30px rgba(0,0,0,.6);}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .frost{background:rgba(32,27,24,.92);}
}

.wrap{max-width:1400px;margin:0 auto;}
.section{padding:clamp(80px,9vw,150px) clamp(20px,5vw,72px);}
.section__head{text-align:center;margin:0 auto clamp(40px,5vw,72px);max-width:56rem;}
.h2{font-size:clamp(2.125rem,4.6vw,4.25rem);font-weight:650;line-height:1.05;letter-spacing:-.045em;}
.lead{margin-top:16px;font-size:clamp(1.0625rem,1.3vw,1.25rem);color:var(--faint);text-wrap:balance;}

.brand{display:inline-flex;align-items:center;gap:10px;font-size:1.375rem;font-weight:650;letter-spacing:-.035em;color:#fff;}
.brand__mark{width:30px;height:27px;flex:none;}

/* Buttons */
.btn-white,.btn-dark,.cta{display:inline-flex;align-items:center;justify-content:center;gap:8px;
  border-radius:999px;font-family:inherit;font-weight:600;white-space:nowrap;cursor:pointer;
  transition:transform 220ms var(--ease),background-color 200ms,border-color 200ms;}
.btn-white{background:#fff;color:#111;border:0;padding:12px 22px;font-size:.9375rem;}
.btn-white:hover{background:#ECE9E4;}
.btn-dark,.cta{background:rgba(22,15,12,.72);color:#fff;border:1px solid rgba(255,255,255,.24);
  padding:16px 32px;font-size:1.0625rem;
  -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);}
.btn-dark:hover,.cta:hover{background:rgba(22,15,12,.9);border-color:rgba(255,255,255,.45);}
.btn-white:active,.btn-dark:active,.cta:active{transform:scale(.98);}

/* Card icons (replaced the lit orbs, 2026-09-18): a line glyph in the
   headline gradient inside a small glass tile, framed by detection-box corner
   marks. The glyphs and the gradient live in each page's SVG sprite. */
.ico{flex:none;display:grid;place-items:center;width:52px;height:52px;border-radius:15px;
  background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.2);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.12),0 8px 20px -10px rgba(0,0,0,.5);
  -webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px);}
.ico svg{width:100%;height:100%;overflow:visible;fill:none;stroke:url(#ico-grad);stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round;}
.ico .ico__frame{stroke:rgba(245,243,238,.45);stroke-width:1.3;}
.ico__glyph{transform:scale(1.12);transform-origin:22px 22px;}

/* =============================== NAV ==================================== */

.nav{position:relative;z-index:40;display:flex;flex-wrap:wrap;justify-content:space-between;align-items:flex-start;
  gap:10px;padding:clamp(10px,1.2vw,20px);}
.nav__pill{display:flex;align-items:center;flex-wrap:wrap;gap:6px 10px;border-radius:26px;padding:10px 14px 10px 20px;}
.nav__left{width:100%;}
.nav__right{width:100%;justify-content:space-between;padding:6px 6px 6px 18px;}
.nav__links{display:flex;flex-wrap:wrap;align-items:center;gap:2px;width:100%;margin-left:-12px;}
.nav__links > a{display:inline-flex;align-items:center;gap:6px;padding:8px 12px;border-radius:999px;
  font-size:1rem;font-weight:500;color:rgba(255,255,255,.86);cursor:pointer;transition:color 150ms,background-color 150ms;}
.nav__links > a:hover{color:#fff;background:rgba(255,255,255,.08);}
.nav__links a[aria-current="page"]{color:#fff;}
.nav__contact{font-size:.8125rem;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:rgba(255,255,255,.82);padding:8px 4px;}
.nav__contact:hover{color:#fff;}

/* Hamburger (2026-09-19). Below 1000px, with JS, the left pill is just the
   brand and a menu button; the links, Contact and the briefing button drop
   down in a panel over the hero. Without JS the links wrap in the pill as
   before, and the menu-only items stay hidden. */
.nav__toggle,.nav__links > .nav__menu-only{display:none;}
@media (max-width:999px){
  .js .nav__right{display:none;}
  .js .nav__left{position:relative;flex-wrap:nowrap;justify-content:space-between;padding:8px 8px 8px 18px;}
  .js .nav__toggle{display:grid;place-items:center;flex:none;width:44px;height:44px;border-radius:50%;cursor:pointer;
    color:#fff;background:rgba(255,255,255,.1);border:1px solid rgba(255,255,255,.22);}
  .js .nav__toggle:hover{background:rgba(255,255,255,.16);}
  .js .nav__left .brand{min-height:44px;}
  .nav__bars{position:relative;width:18px;height:12px;}
  .nav__bars i{position:absolute;left:0;width:100%;height:1.8px;border-radius:2px;background:currentColor;
    transition:transform 180ms ease-out,opacity 120ms,top 180ms ease-out;}
  .nav__bars i:nth-child(1){top:0;}
  .nav__bars i:nth-child(2){top:5.1px;}
  .nav__bars i:nth-child(3){top:10.2px;}
  .nav.is-open .nav__bars i:nth-child(1){top:5.1px;transform:rotate(45deg);}
  .nav.is-open .nav__bars i:nth-child(2){opacity:0;}
  .nav.is-open .nav__bars i:nth-child(3){top:5.1px;transform:rotate(-45deg);}
  .js .nav__links{display:none;position:absolute;left:0;right:0;top:calc(100% + 8px);margin:0;width:auto;
    flex-direction:column;align-items:stretch;gap:0;padding:8px;border-radius:22px;
    background:rgba(24,20,18,.97);border:1px solid rgba(255,255,255,.14);box-shadow:0 24px 60px rgba(0,0,0,.55);}
  .js .nav.is-open .nav__links{display:flex;}
  .js .nav__links{max-height:calc(100svh - 96px);overflow-y:auto;overscroll-behavior:contain;}
  .js .nav__links > a{padding:14px 14px;font-size:1.0625rem;border-radius:14px;}
  .js .nav__links > a + a{border-top:1px solid rgba(255,255,255,.07);}
  .js .nav__links a[aria-current="page"]{background:rgba(255,255,255,.07);}
  .js .nav__links > .nav__menu-only{display:flex;}
  .js .nav__links > .nav__cta{justify-content:center;margin-top:8px;border-top:0;color:#111;background:#fff;border-radius:999px;font-weight:600;}
  .js .nav__links > .nav__cta:hover{background:#f1efe9;}
}
/* Phones held sideways are 320-430px tall: the one-column menu (448px) ran off
   the bottom. Two columns of links with the button across both fits. */
@media (max-width:999px) and (max-height:520px){
  .js .nav.is-open .nav__links{display:grid;grid-template-columns:1fr 1fr;column-gap:6px;}
  .js .nav__links > a{padding:11px 14px;}
  .js .nav__links > a + a{border-top:0;}
  .js .nav__links > .nav__cta{grid-column:1 / -1;}
}

/* Phones and tablets: one compact pill. The right pill's two links both go to
   the coming-soon notice (#contact), which the hero button already reaches, so
   it only shows from 640px; this keeps the hero's on-premise line above an
   800px fold.
   The hero overrides are prefixed with .hero on purpose: the base hero rules
   come later in this file, so at equal specificity they silently won and none
   of these phone sizes applied (found 2026-09-17). */
@media (max-width:999px){
  .nav__left{padding:8px 10px 8px 16px;gap:2px 8px;}
  .nav__links{margin-left:-10px;}
  .nav__links > a{padding:6px 10px;font-size:.9375rem;}
  .hero .hero__content{padding-top:28px;padding-bottom:48px;}
  .hero .pill{margin-bottom:20px;}
}
@media (max-width:639px){
  .nav__right{display:none;}
  /* top-aligned, not centred: centring in a full-height hero pushed the
     standing line down however small the type got */
  .hero .hero__content{justify-content:flex-start;padding-top:12px;}
  /* Tall phones left a wide empty band below the standing line, because the
     content was pinned to the top of a full-height hero. From 700px of height
     there is room to sit it in the middle; shorter screens keep the top
     alignment, which is why it was pinned in the first place (2026-09-20). */
  @media (min-height:700px){
    .hero .hero__content{justify-content:center;padding-top:20px;padding-bottom:36px;}
  }
  .hero .pill{margin-bottom:16px;}
  /* "One understanding." is one long word: at a flat 2.5rem it broke into
   "One" + "understanding." below 412px, leaving a word alone on its own
   line. Scaling with the viewport keeps each hero line whole (2026-09-20). */
.hero .hero__title{font-size:min(2.5rem,8.6vw);margin-bottom:calc(16px - .14em);}
  .hero .hero__sub{font-size:1rem;line-height:1.5;margin-bottom:20px;}
  .hero .btn-dark{padding:14px 26px;font-size:1rem;}
  .hero .hero__standing{margin-top:14px;}
}

/* The nav stays in normal flow at every width. It used to be absolutely placed
   from 1000px, and on short laptop screens (1280x720, 1366x768, 1536x730 ...)
   the hero copy's top padding was smaller than the nav, so the "New" pill slid
   underneath it. In flow, the hero copy centres in the space below the nav. */
@media (min-width:1000px){
  .nav{flex-wrap:nowrap;}
  .nav__pill{border-radius:999px;flex-wrap:nowrap;}
  .nav__left{width:auto;padding:12px 26px 12px 34px;gap:clamp(40px,8vw,160px);}
  .nav__right{width:auto;gap:22px;padding:8px 8px 8px 22px;}
  .nav__links{width:auto;margin-left:0;flex-wrap:nowrap;}
}
/* Narrow laptops: at 8vw the brand-to-links gap pushed the two pills to within
   ~10px of each other at 1024px, and into each other at 1000px. */
@media (min-width:1000px) and (max-width:1199px){
  .nav__left{gap:28px;padding-left:26px;}
  .nav__right{gap:16px;}
}

/* =============================== HERO =================================== */

.hero{min-height:calc(100svh - 2 * var(--frame));display:flex;flex-direction:column;}
.hero .panel__bg{
  background-image:
    linear-gradient(180deg,rgba(8,8,8,.18) 0%,rgba(8,8,8,0) 30%,rgba(8,8,8,.12) 60%,rgba(10,9,8,.7) 100%),
    url("../img/hero.jpg");
  transform-origin:50% 30%;
}
.hero__content{flex:1;position:relative;z-index:2;display:flex;flex-direction:column;align-items:center;justify-content:center;
  text-align:center;padding:clamp(24px,5vh,90px) 20px clamp(56px,10vh,130px);will-change:transform,opacity;}

/* One pill, on the homepage only: it names the product that ships and links to
   its page. The "New" badge and the feature list it carried were dropped on
   2026-09-20 — the hero should say what the company sells, not which rule
   shipped last — and the features page lost its pill altogether. It stays on
   one line at every width; below 520px it sets smaller. */
.pill{display:inline-flex;align-items:center;gap:10px;padding:8px 16px;border-radius:999px;margin-bottom:28px;
  max-width:100%;font-size:.875rem;font-weight:500;color:rgba(255,255,255,.88);}
.pill__text{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.pill__arrow{flex:none;width:14px;height:14px;margin-left:-2px;opacity:.75;}
a.pill:hover .pill__arrow{opacity:1;}
@media (max-width:519px){
  .pill{gap:8px;padding:7px 14px;font-size:.8125rem;}
}
a.pill:hover{background:rgba(255,255,255,.12);}

/* Gradient headings are painted inside their own box (background-clip:text),
   and these line-heights are tighter than the font's descenders, so a final
   "g" or "p" was sliced off — seen on "One understanding." (2026-09-20).
   Each gets painted room at the bottom, taken back out of the margin below,
   so nothing on the page moves. */
.hero__title{font-size:clamp(2.75rem,min(8.2vw,15vh),8.5rem);font-weight:500;line-height:1.02;letter-spacing:-.04em;
  padding-bottom:.14em;margin-bottom:calc(clamp(20px,2.4vw,34px) - .14em);
  filter:drop-shadow(0 4px 40px rgba(0,0,0,.18));}
.hero__line{display:block;}
.hero__sub{font-size:clamp(1.0625rem,1.35vw,1.3125rem);line-height:1.55;color:rgba(255,255,255,.92);
  max-width:44rem;margin-bottom:30px;text-shadow:0 1px 18px rgba(0,0,0,.35);text-wrap:balance;}
.br-md{display:none;}
@media (min-width:1100px){.br-md{display:inline;}}
.hero__standing{margin-top:22px;font-size:.875rem;color:rgba(255,255,255,.72);max-width:34rem;}

/* ============================= STATEMENT ================================ */

.statement{position:relative;overflow:hidden;min-height:92vh;display:grid;place-items:center;align-content:center;
  gap:clamp(16px,3vh,32px);padding:clamp(40px,10vh,150px) clamp(20px,5vw,72px);}
.statement::before{content:"";position:absolute;inset:0;z-index:-1;
  background-image:radial-gradient(rgba(255,255,255,.13) 1px,transparent 1.4px);background-size:24px 24px;
  -webkit-mask-image:radial-gradient(55% 60% at 50% 30%,#000 0%,rgba(0,0,0,.35) 55%,rgba(0,0,0,.1) 100%);
          mask-image:radial-gradient(55% 60% at 50% 30%,#000 0%,rgba(0,0,0,.35) 55%,rgba(0,0,0,.1) 100%);}
.statement{isolation:isolate;}
.statement__inner{position:relative;max-width:70rem;text-align:center;display:flex;flex-direction:column;align-items:center;gap:28px;}
.statement__text{font-size:clamp(1.75rem,min(4.2vw,6.2vh),4rem);font-weight:500;line-height:1.14;letter-spacing:-.035em;
  max-width:19em;padding-bottom:.1em;margin-bottom:-.1em;}
.statement__text.is-split{background:none;-webkit-text-fill-color:currentColor;color:var(--fg);}
.statement__text .w{display:inline-block;margin-right:.26em;transition:opacity 120ms linear;}

/* The glowing ring: the brand mark held in a lit lens */
.ring{position:absolute;width:clamp(120px,15vw,290px);aspect-ratio:1;border-radius:50%;
  display:grid;place-items:center;pointer-events:none;}
.ring::before,.ring::after{content:"";position:absolute;border-radius:50%;border:1px solid rgba(255,255,255,.07);}
.ring::before{inset:0;}
.ring::after{inset:13%;border-color:rgba(255,255,255,.1);}
.ring__core{position:relative;width:52%;aspect-ratio:1;border-radius:50%;display:grid;place-items:center;
  background:radial-gradient(circle at 50% 45%,#1c1c1c,#0d0d0d 70%);
  box-shadow:0 0 0 1.5px rgba(255,255,255,.75),0 0 26px 4px rgba(255,255,255,.35),inset 0 0 26px rgba(255,255,255,.12);}
.ring__core svg{width:36%;height:36%;color:rgba(255,255,255,.35);}
/* In flow, centred above the eyebrow. It used to float top-right, where it sat
   on the statement text at every width from 1100px to 1920px. */
.statement .ring{position:relative;width:clamp(96px,min(11vw,19vh),210px);}

/* ========================= SHOWCASE PANEL =============================== */

.showcase{padding:clamp(56px,7vw,120px) clamp(20px,6vw,104px) clamp(24px,4vw,72px);}
.showcase .panel__bg{background-image:
  linear-gradient(100deg,rgba(9,8,7,.94) 0%,rgba(9,8,7,.55) 45%,rgba(9,8,7,.12) 100%),
  linear-gradient(0deg,rgba(9,8,7,.55),rgba(9,8,7,0) 40%),
  url("../img/panel.jpg");}
.showcase__head{max-width:64rem;margin-bottom:clamp(64px,10vw,170px);}
.showcase__h{font-size:clamp(2rem,4.3vw,4.125rem);font-weight:500;line-height:1.08;letter-spacing:-.04em;
  padding-bottom:.1em;margin:18px 0 calc(22px - .1em);}
.showcase__h span{display:block;}
.showcase__p{font-size:clamp(1rem,1.25vw,1.1875rem);line-height:1.6;color:rgba(255,255,255,.74);max-width:38rem;}

.cards{display:grid;gap:clamp(12px,1.5vw,24px);grid-template-columns:1fr;}
@media (min-width:640px){.cards{grid-template-columns:repeat(2,1fr);}}
@media (min-width:1100px){.cards{grid-template-columns:repeat(3,1fr);}
  .cards--4{grid-template-columns:repeat(4,1fr);}}

.card{position:relative;display:flex;flex-direction:column;padding:26px 26px 30px;border-radius:24px;min-height:250px;
  background:linear-gradient(180deg,rgba(48,36,29,.5) 0%,rgba(14,12,11,.72) 100%);
  border:1px solid rgba(255,255,255,.09);
  -webkit-backdrop-filter:blur(18px) saturate(130%);backdrop-filter:blur(18px) saturate(130%);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.07);
  transition:transform 280ms var(--ease),border-color 280ms,background-color 280ms;}
a.card:hover{transform:translateY(-4px);border-color:rgba(255,255,255,.24);}
.card__arrow{position:absolute;top:24px;right:24px;width:22px;height:22px;color:rgba(255,255,255,.72);
  transition:transform 280ms var(--ease),color 200ms;}
a.card:hover .card__arrow{transform:translate(3px,-3px);color:#fff;}
.card__step{position:absolute;top:26px;right:26px;font-size:.8125rem;font-weight:600;color:var(--faint);}
.card h3{margin-top:36px;font-size:1.5rem;font-weight:500;letter-spacing:-.02em;line-height:1.2;}
.card p{margin-top:10px;font-size:1rem;line-height:1.5;color:rgba(255,255,255,.7);}

/* ============================ TILE CARDS ================================ */

.tiles{display:grid;gap:clamp(16px,1.8vw,28px);}
/* Three across only from 1200px: at 960-1199px each column was ~290px, which
   clipped the card illustrations and squeezed the paragraphs into slivers.
   Between 760 and 1199px each card lays its text beside its illustration. */
@media (min-width:1200px){.tiles--3{grid-template-columns:repeat(3,1fr);}}
@media (min-width:760px) and (max-width:1199px){
  .tiles--3 .tile-card{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);grid-template-rows:auto auto 1fr;
    column-gap:clamp(28px,4vw,48px);row-gap:14px;align-items:start;}
  .tiles--3 .tile-card > :not(.tile-card__visual){grid-column:1;}
  .tiles--3 .tile-card__visual{grid-column:2;grid-row:1 / span 3;align-self:center;padding-top:0;margin-top:0;}
}
@media (min-width:760px){.tiles--2{grid-template-columns:repeat(2,1fr);}}

/* min-width:0 - grid items default to their min-content width, and the
   nowrap labels inside the card visuals widened a 360px phone to 386px. */
.tiles > *,.cards > *,.specs > *{min-width:0;}
.tile-card{position:relative;display:flex;flex-direction:column;gap:14px;min-width:0;
  padding:clamp(28px,3.2vw,60px) clamp(24px,3vw,60px);border-radius:28px;
  border:1px solid rgba(255,255,255,.12);background-color:rgba(255,255,255,.012);}
.tile-card h3{font-size:clamp(1.5rem,2.3vw,2.375rem);font-weight:500;line-height:1.18;letter-spacing:-.025em;}
.tile-card p{font-size:1.0625rem;line-height:1.65;color:var(--muted);}
.tile-card__visual{margin-top:auto;padding-top:clamp(28px,3.4vw,56px);}

/* ============================== FEATURES ================================ */

/* Product view: the Ganesha dashboard, drawn */
.dash-stage{position:relative;max-width:1180px;margin:0 auto;}
.dash-stage::before{content:"";position:absolute;inset:8% -4% -6%;z-index:-1;border-radius:40px;filter:blur(60px);opacity:.55;
  background:url("../img/panel.jpg") center/cover;}
.dash{position:relative;border-radius:22px;overflow:hidden;
  background:rgba(14,13,12,.92);border:1px solid rgba(255,255,255,.14);
  box-shadow:0 40px 120px rgba(0,0,0,.6),inset 0 1px 0 rgba(255,255,255,.08);
  font-size:clamp(6px,.9vw,12.5px);color:hsl(0 0% 88%);}
.dash__bar{display:flex;align-items:center;gap:1.4em;padding:.9em 1.4em;border-bottom:1px solid rgba(255,255,255,.08);}
.dash__brand{display:inline-flex;align-items:center;gap:.6em;font-weight:600;color:#fff;margin-right:1em;}
.dash__brand svg{width:1.5em;height:1.5em;color:#fff;}
.dash__tab{padding:.35em .9em;border-radius:999px;color:hsl(0 0% 60%);}
.dash__tab--on{background:rgba(255,255,255,.1);color:#fff;}
.dash__live{margin-left:auto;display:inline-flex;align-items:center;gap:.5em;color:#fff;}
.dash__live i{width:.6em;height:.6em;border-radius:50%;background:#F2A15E;box-shadow:0 0 .8em #F2A15E;}
.dash__body{display:grid;grid-template-columns:11em 1fr 17em;min-height:0;}
.dash__rail{padding:1em .8em;border-right:1px solid rgba(255,255,255,.08);display:grid;gap:.4em;align-content:start;}
.dash__rail li{padding:.6em .7em;border-radius:.7em;display:grid;gap:.1em;}
.dash__rail b{font-weight:600;color:hsl(0 0% 85%);}
.dash__rail span{color:hsl(0 0% 52%);}
.dash__rail .is-on{background:rgba(255,255,255,.08);}
.dash__rail .is-on b{color:#fff;}
.dash__main{padding:1em;display:grid;gap:1em;}
.dash__feed{width:100%;height:auto;aspect-ratio:16/9;border-radius:.8em;}
.dash__stats{display:grid;grid-template-columns:repeat(4,1fr);gap:.8em;}
.dash__stats div{background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.08);border-radius:.8em;padding:.7em .9em;}
.dash__stats dt{color:hsl(0 0% 58%);}
.dash__stats dd{font-size:1.6em;font-weight:600;color:#fff;letter-spacing:-.02em;}
.dash__side{padding:1em 1.2em;border-left:1px solid rgba(255,255,255,.08);display:grid;gap:.8em;align-content:start;}
.dash__h{font-weight:600;color:hsl(0 0% 72%);}
.dash__alerts{display:grid;gap:.6em;}
.dash__alerts li{display:grid;grid-template-columns:1fr auto;gap:.1em .8em;padding:.7em .8em;
  border-radius:.8em;background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.08);}
.dash__alerts b{font-weight:600;color:#fff;}
.dash__alerts span{grid-column:1;color:hsl(0 0% 56%);}
.dash__alerts time{grid-column:2;grid-row:1;color:hsl(0 0% 56%);}
.dash__alerts .is-hot{border-color:rgba(242,161,94,.55);background:rgba(242,161,94,.1);}
.dash__heat{display:grid;grid-template-columns:repeat(6,1fr);gap:.25em;}
.dash__heat i{aspect-ratio:1;border-radius:.25em;background:rgba(242,161,94,calc(.06 + var(--h) * .9));}
@media (max-width:640px){
  .dash{font-size:9px;}
  .dash__body{grid-template-columns:1fr;}
  .dash__rail,.dash__side{display:none;}
  .dash__tab:not(.dash__tab--on){display:none;}
  .dash__stats{grid-template-columns:repeat(2,1fr);}
}
.dash-caption{margin:28px auto 0;text-align:center;color:var(--faint);max-width:40rem;}

/* Views: four tabbed dashboards (traffic, people, heatmaps, search). Without
   JS the tabs are hidden and all four views stack, so nothing is lost. */
.views{display:none;}
.js .views{display:flex;flex-wrap:wrap;justify-content:center;gap:8px;margin:0 auto clamp(20px,2.4vw,32px);
  padding:6px;width:fit-content;max-width:100%;border-radius:999px;
  background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.12);}
.views__tab{font:inherit;font-size:1rem;font-weight:600;color:rgba(255,255,255,.72);background:transparent;border:0;
  padding:10px 22px;border-radius:999px;cursor:pointer;transition:color 150ms,background-color 150ms;
  display:inline-flex;align-items:center;justify-content:center;gap:8px;}
/* Tab glyphs follow the text colour, not the gradient: the selected tab is
   white, and the cream gradient would vanish on it. */
.views__ico{width:18px;height:18px;flex:none;fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;}
.views__tab:hover{color:#fff;background:rgba(255,255,255,.07);}
.views__tab[aria-selected="true"]{background:#fff;color:#111;}
.dash__view + .dash__view{margin-top:24px;}
.js .dash__view + .dash__view{margin-top:0;}
.dash__view:focus-visible{outline-offset:6px;border-radius:24px;}
.dash__live--off{color:hsl(0 0% 70%);}

.dash__meter{display:grid;grid-template-columns:repeat(4,1fr);gap:.3em;}
.dash__meter li{text-align:center;padding:.45em 0;font-size:.85em;min-width:0;border-radius:.5em;background:rgba(255,255,255,.05);color:hsl(0 0% 58%);}
.dash__meter .is-on{background:rgba(242,161,94,.22);color:#fff;font-weight:600;}
.dash__plate{display:grid;gap:.2em;padding:.7em .8em;border-radius:.8em;background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.08);
  font-weight:700;letter-spacing:.06em;color:#fff;}
.dash__plate span{font-weight:400;letter-spacing:0;color:hsl(0 0% 56%);}
.dash__attrs{display:grid;grid-template-columns:1fr 1fr;gap:.4em;}
.dash__attrs div{padding:.5em .7em;border-radius:.6em;background:rgba(255,255,255,.05);}
.dash__attrs dt{color:hsl(0 0% 56%);}
.dash__attrs dd{color:#fff;font-weight:600;}
.dash__note{color:hsl(0 0% 60%);line-height:1.5;}
.dash__chips{display:flex;flex-wrap:wrap;gap:.4em;}
.dash__chips li{padding:.35em .9em;border-radius:999px;border:1px solid rgba(255,255,255,.14);color:hsl(0 0% 64%);}
.dash__chips .is-on{background:rgba(255,255,255,.12);color:#fff;border-color:rgba(255,255,255,.3);}
.dash__query{display:flex;align-items:center;gap:.8em;padding:1em 1.3em;border-radius:999px;font-size:1.25em;color:#fff;
  background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.18);}
.dash__query svg{width:1.2em;height:1.2em;flex:none;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;}
.dash__results{display:grid;grid-template-columns:repeat(3,1fr);gap:.8em;}
.dash__results li{border-radius:.8em;overflow:hidden;background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.08);}
.dash__results svg{width:100%;height:auto;aspect-ratio:16/10;}
.dash__results span{display:grid;padding:.4em .7em;color:hsl(0 0% 56%);}
.dash__results b{font-weight:600;color:#fff;}
.dash__journey{display:grid;gap:.35em;}
.dash__journey li{display:flex;justify-content:space-between;gap:.6em;padding:.55em .8em;border-radius:.6em;
  background:rgba(255,255,255,.05);border-left:2px solid #F2A15E;}
.dash__journey b{font-weight:600;color:#fff;}
.dash__journey time{color:hsl(0 0% 56%);}
.dash__journey .is-gap{background:transparent;border:1px dashed rgba(255,255,255,.2);}
.dash__journey .is-gap b{color:hsl(0 0% 60%);font-weight:500;}
@media (max-width:640px){
  .js .views{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));width:100%;gap:4px;padding:4px;}
  .views__tab{padding:9px 2px;font-size:.875rem;}
  /* four tabs share a phone's width; the words fit, the glyphs would not */
  .views__ico{display:none;}
  .dash__results{grid-template-columns:repeat(2,1fr);}
  .dash__query{font-size:1.1em;}
}

/* Catalogue */
.catalog .tiles{gap:clamp(16px,1.6vw,24px);}
/* The six groups hold 3 to 6 items. Equal cards left empty space under the
   short ones, and packed columns left the bottoms staggered. So the long
   groups get wider instead of taller: "Vehicles and plates" (6 items) spans two
   columns with its items in two inner columns, and "Alerts and integration" is
   a full-width band. Every row then holds cards of about the same height.
     3 columns: Detection | Vehicles (x2)  /  People | Movement | Search  /  Alerts (x3)
     2 columns: Detection | People  /  Vehicles (x2)  /  Movement | Search  /  Alerts (x2)
   The 2-column layout uses dense packing to pull People up beside Detection. */
@media (min-width:760px){
  .catalog .tiles{grid-template-columns:repeat(2,minmax(0,1fr));grid-auto-flow:row dense;}
  .catalog .group--wide,.catalog .group--band{grid-column:1 / -1;}
  .catalog .group--wide .group__list,.catalog .group--band .group__list{
    grid-template-columns:repeat(2,minmax(0,1fr));column-gap:clamp(24px,3vw,48px);}
}
@media (min-width:1180px){
  .catalog .tiles{grid-template-columns:repeat(3,minmax(0,1fr));grid-auto-flow:row;}
  .catalog .group--wide{grid-column:span 2;}
  .catalog .group--band .group__list{grid-template-columns:repeat(4,minmax(0,1fr));}
}
.group{scroll-margin-top:24px;padding:clamp(26px,2.6vw,40px);}
.group__head{display:flex;align-items:center;gap:14px;}
.group__head .ico{width:44px;height:44px;border-radius:13px;}
.group__head h3{font-size:1.375rem;}
.group__list{display:grid;gap:16px;margin-top:10px;}
.group__list li{display:grid;gap:3px;align-content:start;padding-top:16px;border-top:1px solid var(--line);}
.group__list b{display:flex;flex-wrap:wrap;align-items:center;gap:4px 8px;text-wrap:balance;font-weight:600;font-size:1.0625rem;line-height:1.35;color:#fff;}
.group__list b .tag{margin-left:0;}
.group__list span{font-size:.9375rem;line-height:1.55;color:var(--muted);}
.tag{display:inline-block;margin-left:6px;padding:1px 9px;border-radius:999px;vertical-align:.12em;
  font-style:normal;font-size:.75rem;font-weight:600;color:#F7F2C4;background:rgba(247,242,196,.12);border:1px solid rgba(247,242,196,.25);}
.tag--soft{color:#EBCFC2;background:rgba(235,207,194,.1);border-color:rgba(235,207,194,.25);}


/* ============================== FINALE ================================== */

.finale{margin-bottom:0;border-bottom-left-radius:0;border-bottom-right-radius:0;
  padding:clamp(90px,11vw,170px) clamp(20px,5vw,72px) clamp(200px,20vw,280px);text-align:center;}
.finale .panel__bg{background-image:
  linear-gradient(180deg,rgba(12,9,9,.1),rgba(12,9,9,0) 40%,rgba(18,14,14,.3) 80%,#120E0E 100%),
  url("../img/closing.jpg");background-position:center 30%;}
.finale__h{font-size:clamp(3rem,9.4vw,9.5rem);font-weight:500;line-height:1;letter-spacing:-.05em;}
.finale__p{margin:22px auto 0;max-width:40rem;font-size:clamp(1.0625rem,1.3vw,1.25rem);color:rgba(255,255,255,.8);}
.finale .btn-dark{margin-top:34px;}

/* The footer is a glass card lifted over the bottom of the finale image.
   Since 2026-09-19 the card is closed on all four sides with the same inset
   below as at the sides; it used to run open-ended into the page edge and
   looked cut off, especially on phones. */
.foot{position:relative;z-index:2;margin:calc(-1 * clamp(150px,15vw,210px)) var(--frame) var(--frame);
  padding:0 clamp(12px,3vw,52px) clamp(12px,3vw,52px);
  border-radius:0 0 var(--r-panel) var(--r-panel);
  background:linear-gradient(180deg,transparent 0,transparent clamp(150px,15vw,210px),#120E0E clamp(150px,15vw,210px));}
.foot__card{border-radius:28px;border:1px solid rgba(255,255,255,.12);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.08),0 30px 60px -30px rgba(0,0,0,.7);
  background:linear-gradient(180deg,rgba(64,44,40,.42),rgba(18,14,14,.55) 60%,rgba(22,17,16,.92));
  -webkit-backdrop-filter:blur(22px) saturate(120%);backdrop-filter:blur(22px) saturate(120%);
  padding:clamp(32px,4vw,64px) clamp(22px,4vw,60px) clamp(26px,3vw,40px);}
.foot__grid{display:grid;gap:36px;}
/* Below 1100px: the brand and Contact span the full width, with Site and
   Features side by side between them (a single stacked column made the phone
   footer 15 links tall). Four columns from 1100px: at 900-1099px four columns
   were narrow enough to break the email address mid-word. */
@media (max-width:1099px){
  .foot__grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:32px 24px;}
  .foot__grid > :first-child,.foot__grid > :last-child{grid-column:1 / -1;}
}
@media (max-width:599px){
  .foot__grid a,.foot__grid p,.foot .foot__grid .link-off{font-size:1rem;}
  .foot ul{gap:2px;}
}
@media (min-width:1100px){.foot__grid{grid-template-columns:1.6fr 1fr 1fr 1.2fr;gap:40px;}}
.foot__grid .foot__brand{font-size:clamp(2.25rem,4vw,3.75rem);font-weight:500;letter-spacing:-.04em;line-height:1.05;
  display:inline-block;padding-bottom:.12em;margin-bottom:-.12em;}
.foot__blurb{margin-top:20px;font-size:1.0625rem;line-height:1.55;color:rgba(255,255,255,.8);max-width:26rem;}
.foot h2{font-size:.8125rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--faint);margin:10px 0 18px;}
.foot ul{display:grid;gap:4px;}
.foot ul a,.foot ul .link-off{display:inline-block;padding:4px 0;}
.foot__grid a,.foot__grid p{font-size:1.0625rem;font-weight:500;color:rgba(255,255,255,.9);overflow-wrap:anywhere;}
.foot__grid a:hover{color:#fff;text-decoration:underline;text-underline-offset:4px;}
.foot__grid a[aria-current]{color:#fff;}
.foot__legal-row{margin-top:clamp(36px,5vw,72px);padding-top:clamp(18px,2vw,24px);border-top:1px solid rgba(255,255,255,.1);
  display:flex;flex-wrap:wrap;justify-content:space-between;gap:12px 28px;
  font-size:.9375rem;color:rgba(255,255,255,.72);}
.foot__legal-row a:hover{color:#fff;}
/* Not-yet-live destinations (privacy page, real contact email): plain text,
   styled like the text around it, so nothing leads to a 404 or a dead inbox.
   Turn them back into <a> once the page or address exists. */
.link-off{cursor:default;}
/* Hyphenated words kept whole: no line break after the hyphen. */
.nw{white-space:nowrap;}
.foot__grid .link-off{font-size:1.0625rem;font-weight:500;color:rgba(255,255,255,.9);overflow-wrap:anywhere;}
.soon__p .link-off{color:#fff;font-weight:600;overflow-wrap:anywhere;}

/* ============================= MOTION =================================== */

/* One orchestrated load: the hero image settles, then the copy rises in. */
.js .hero .panel__bg{animation:settle 2.2s var(--ease) both;}
@keyframes settle{from{transform:scale(1.09);filter:brightness(.7);}to{transform:none;filter:none;}}
.js .enter{opacity:0;animation:enter .8s var(--ease) both;}
.js .enter--1{--y:10px;animation-delay:.25s;}
.js .enter--2{--y:24px;animation-delay:.35s;}
.js .enter--3{--y:20px;animation-delay:.5s;}
.js .enter--4{--y:20px;animation-delay:.6s;}
@keyframes enter{from{opacity:0;translate:0 var(--y,20px);}to{opacity:1;translate:0 0;}}

@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto;}
  .js .hero .panel__bg{animation:none;}
  .js .enter{animation:none;opacity:1;}
  .card,.card__arrow,.btn-white,.btn-dark,.cta{transition:none;}
  a.card:hover{transform:none;}
}
