/* ==========================================================================
   kit.css  -  the shared motion and shape layer for the spec sites.

   Canonical copy lives in demos/_kit/. Each build gets its own copy at
   css/kit.css and loads it BEFORE css/site.css, so a site can override any of
   this without fighting specificity. Change it HERE and re-stamp.

   This file owns motion and shape only. It sets no color, no typeface and no
   page layout: those belong to each build's own site.css, because the whole
   point is that four car sites share a motion vocabulary and still do not look
   like each other.

   It expects two things from the build:
     1. <script>document.documentElement.className+=" js"</script> in the head,
        which is already the house pattern. Everything that starts hidden is
        hidden only under .js, so with scripting off the page is fully readable
        rather than blank.
     2. --ease, --wrap and --gutter defined in the build's :root.
   ========================================================================== */

:root{
  --ease-out:cubic-bezier(.16,1,.3,1);
  --ease-spring:cubic-bezier(.34,1.56,.64,1);
  --marq-time:40s;
}

/* ==========================================================================
   1. REVEAL
   ========================================================================== */

.js [data-reveal]{
  opacity:0;
  transform:translateY(22px);
  transition:opacity .75s var(--ease,var(--ease-out)),
             transform .75s var(--ease,var(--ease-out));
  transition-delay:var(--d,0ms);
}
.js [data-reveal].in{opacity:1;transform:none}

/* rows: top to bottom, one after the next.
   The delay lives on each child as --d, written by motion.js. */
.js [data-rows]>*{
  opacity:0;
  transform:translateY(26px);
  transition:opacity .7s var(--ease,var(--ease-out)) var(--d,0ms),
             transform .7s var(--ease,var(--ease-out)) var(--d,0ms);
}
.js [data-rows].in>*{opacity:1;transform:none}

/* columns: left to right, one box at a time.
   The card body fades, but the card's BACKGROUND wipes across from the left
   underneath it, which is what gives the row its direction. Anything that
   wants the wipe carries .wipe and provides its own --wipe color. */
.js [data-cols]>*{
  opacity:0;
  transform:translateY(20px);
  transition:opacity .6s var(--ease,var(--ease-out)) var(--d,0ms),
             transform .6s var(--ease,var(--ease-out)) var(--d,0ms);
}
.js [data-cols].in>*{opacity:1;transform:none}

.wipe{position:relative;isolation:isolate}
.wipe::before{
  content:"";position:absolute;inset:0;z-index:-1;
  background:var(--wipe,rgba(0,0,0,.06));
  border-radius:inherit;
  transform:scaleX(0);transform-origin:left center;
  transition:transform .62s var(--ease,var(--ease-out)) var(--d,0ms);
}
.js [data-cols].in>.wipe::before,
.js [data-reveal].in.wipe::before{transform:scaleX(1)}
html:not(.js) .wipe::before{transform:scaleX(1)}

/* ==========================================================================
   2. HERO LINE REVEAL
   Words rise from behind a mask. .ln is the mask, its child is the mover.
   ========================================================================== */

.ln{display:block;overflow:hidden;padding-bottom:.06em;margin-bottom:-.06em}
.js [data-split] .w{
  display:inline-block;
  transform:translateY(105%);
  opacity:0;
  transition:transform .95s var(--ease,var(--ease-out)) var(--d,0ms),
             opacity .7s linear var(--d,0ms);
}
.js [data-split].ready .w{transform:translateY(0);opacity:1}

/* ==========================================================================
   3. MARQUEE  -  right to left, seamless, edge-faded.

   The track is duplicated by motion.js and this moves the pair -50%, so the
   copy lands exactly where the original began and the seam is invisible.
   --marq-time is computed from the real width so speed, not duration, is what
   is held constant between a strip of four logos and a strip of fourteen.
   ========================================================================== */

.marq{
  display:flex;
  overflow:hidden;
  gap:var(--marq-gap,clamp(34px,5vw,72px));
  /* the fade has to be wide enough that a logo is properly gone before the
     edge, or it reads as a clipped logo rather than a continuous strip */
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
          mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
}
.marq__track{
  display:flex;align-items:center;flex:0 0 auto;
  gap:var(--marq-gap,clamp(34px,5vw,72px));
  padding-right:var(--marq-gap,clamp(34px,5vw,72px));
}
.marq.running .marq__track{animation:marq var(--marq-time) linear infinite}
.marq:hover .marq__track{animation-play-state:paused}
@keyframes marq{to{transform:translateX(-100%)}}

/* A logo in the strip. Sized by height so marks of different aspect ratios sit
   on one optical line, and given a generous min-width so a tall narrow mark
   does not crowd its neighbors. */
.marq__logo{
  flex:0 0 auto;
  display:flex;align-items:center;justify-content:center;
  height:var(--logo-h,34px);
  opacity:.72;
  transition:opacity .35s var(--ease,var(--ease-out)),
             filter .35s var(--ease,var(--ease-out));
}
.marq__logo svg,.marq__logo img{
  height:100%;width:auto;max-width:none;display:block;
  fill:currentColor;
}
.marq:hover .marq__logo{opacity:.45}
.marq .marq__logo:hover{opacity:1}

/* ==========================================================================
   4. MAGNETIC CTA
   The transform is written by motion.js. Everything else, including the whole
   touch and no-JS experience, is here.
   ========================================================================== */

[data-magnet-stage]{position:relative}

.mag{
  position:relative;display:inline-flex;align-items:center;justify-content:center;
  gap:.6em;
  border:0;cursor:pointer;text-decoration:none;
  border-radius:999px;
  isolation:isolate;
  will-change:transform;
}
.mag .mag__l{
  position:relative;z-index:2;display:inline-flex;align-items:center;gap:.55em;
  transition:transform .1s linear;
}
/* the fill grows from the center on hover rather than changing color, so the
   button reads as a physical thing being pressed */
.mag::after{
  content:"";position:absolute;inset:0;z-index:1;
  border-radius:inherit;
  background:var(--mag-hover,rgba(255,255,255,.16));
  transform:scale(0);
  transition:transform .45s var(--ease,var(--ease-out));
}
.mag:hover::after,.mag:focus-visible::after{transform:scale(1)}
.mag:active{transform:scale(.97)}

/* A round CTA, the shape the reference car sites use. Kept square via aspect
   ratio so it stays a circle at every width. */
.mag--disc{
  aspect-ratio:1;
  width:var(--disc,clamp(112px,13vw,168px));
  text-align:center;line-height:1.2;
  padding:0;
}

/* ==========================================================================
   5. SHAPE  -  the rounded, curvy vocabulary the car references use.
   ========================================================================== */

/* The big soft curve that lifts one band up into the one above it. This is the
   shape from the atomic-age reference: a very wide, very shallow ellipse, not
   a border-radius on a box. Put it on a section and give it --curve-fill in
   the color of the section ABOVE. */
/* These sit flush to the edges rather than overhanging. An earlier version bled
   them to -8% either side to flatten the arc, which looked identical and cost a
   115px horizontal overflow on the body: invisible on screen under
   overflow-x:clip, but full-page screenshots capture body.scrollWidth and every
   render came out with a white band down the right. At full-bleed width the
   ellipse is already shallow enough, so there is nothing to buy back.
   Clipping them locally is not an option: overflow:hidden on these sections
   would kill position:sticky in the columns inside them. */
.curve-top{position:relative}
.curve-top::before{
  content:"";position:absolute;left:0;right:0;top:-1px;
  height:clamp(46px,7vw,110px);
  background:var(--curve-fill,#fff);
  border-radius:0 0 50% 50% / 0 0 100% 100%;
  pointer-events:none;
}
/* and the same shape hanging off the bottom of a band */
.curve-bottom{position:relative}
.curve-bottom::after{
  content:"";position:absolute;left:0;right:0;bottom:-1px;
  height:clamp(46px,7vw,110px);
  background:var(--curve-fill,#fff);
  border-radius:50% 50% 0 0 / 100% 100% 0 0;
  pointer-events:none;
}

/* Asymmetric big-radius panels. One corner is enormous, the rest are normal:
   the move the atomic-age page makes, and what keeps a rounded card from
   reading as a generic rounded card. */
.pane{border-radius:var(--r,28px);overflow:hidden}
.pane--sw{border-radius:var(--r,28px) var(--r,28px) var(--r,28px) var(--big,110px)}
.pane--se{border-radius:var(--r,28px) var(--r,28px) var(--big,110px) var(--r,28px)}
.pane--nw{border-radius:var(--big,110px) var(--r,28px) var(--r,28px) var(--r,28px)}

/* ==========================================================================
   6. BIG ICON BLOCK  -  grayswan.ai's arrangement: a large stroked icon, a
   small letterspaced eyebrow under it, then the heading. The icon is big
   enough to read as a drawing rather than as a bullet.
   ========================================================================== */

.bigicon{
  display:block;
  width:var(--icon,clamp(44px,5vw,62px));
  height:var(--icon,clamp(44px,5vw,62px));
  margin-bottom:clamp(14px,1.8vw,22px);
  color:var(--icon-color,currentColor);
}
.bigicon svg{width:100%;height:100%;display:block;
  fill:none;stroke:currentColor;stroke-width:1.4;
  stroke-linecap:round;stroke-linejoin:round}

/* ==========================================================================
   7. REDUCED MOTION
   Everything lands in its finished state. Nothing is left hidden, nothing
   animates, and the marquee simply stops as a static row of logos.
   ========================================================================== */

@media (prefers-reduced-motion: reduce){
  .js [data-reveal],
  .js [data-rows]>*,
  .js [data-cols]>*,
  .js [data-split] .w{
    opacity:1!important;transform:none!important;transition:none!important;
  }
  .wipe::before{transform:scaleX(1)!important;transition:none!important}
  .marq.running .marq__track{animation:none}
  .marq{-webkit-mask-image:none;mask-image:none;flex-wrap:wrap}
  .mag::after{transition:none}
  *,*::before,*::after{animation-duration:.001ms!important;
    animation-iteration-count:1!important;transition-duration:.001ms!important}
}

/* ==========================================================================
   8. THE PREMIUM LAYER
   Added 2 Sep 2026 for the three high-end rebuilds: 2 Guys From Sweden,
   AE German and Bon Voyage. Those three sell to people spending real money on
   a Volvo, a Porsche or a collision repair, and the first builds were honest
   but plain. This is the vocabulary that lifts them.

   Glass is used SPARINGLY and only over something worth seeing through: a
   photograph, a gradient, a colored band. Over flat paper a blurred panel is
   just a grey box with extra cost, so every .glass here sits on top of an
   image or a colored ground.
   ========================================================================== */

/* --------------------------------------------------------------- glass
   backdrop-filter over a photograph. The inset hairline on the top edge is
   what sells it as a physical pane rather than a translucent rectangle. */
.glass{
  position:relative;
  background:var(--glass-bg,rgba(255,255,255,.09));
  border:1px solid var(--glass-line,rgba(255,255,255,.18));
  border-radius:var(--r,24px);
  -webkit-backdrop-filter:blur(var(--glass-blur,18px)) saturate(1.5);
          backdrop-filter:blur(var(--glass-blur,18px)) saturate(1.5);
  box-shadow:
    inset 0 1px 0 var(--glass-top,rgba(255,255,255,.28)),
    0 24px 60px -28px rgba(0,0,0,.6);
}
/* Firefox before 103 and anything else without backdrop-filter gets a solid
   panel instead of a transparent one, which is legible rather than clever. */
@supports not ((-webkit-backdrop-filter:blur(1px)) or (backdrop-filter:blur(1px))){
  .glass{background:var(--glass-solid,rgba(20,20,22,.86))}
}
.glass--light{
  --glass-bg:rgba(255,255,255,.62);
  --glass-line:rgba(255,255,255,.75);
  --glass-top:rgba(255,255,255,.9);
  --glass-solid:rgba(255,255,255,.94);
  box-shadow:
    inset 0 1px 0 var(--glass-top),
    0 22px 50px -30px rgba(0,0,0,.28);
}

/* ---------------------------------------------------------------- sheen
   A specular band that crosses the surface on hover. Skinned to the element's
   own radius, so it works on a card, a button or a photograph. */
.sheen{position:relative;overflow:hidden;isolation:isolate}
.sheen::after{
  content:"";position:absolute;inset:0;z-index:3;pointer-events:none;
  background:linear-gradient(105deg,transparent 38%,
    var(--sheen,rgba(255,255,255,.22)) 47%,transparent 58%);
  transform:translateX(-120%);
  transition:transform .9s var(--ease,var(--ease-out));
}
.sheen:hover::after{transform:translateX(120%)}

/* ----------------------------------------------------------------- spot
   A soft light behind a dark band, so the section has a centre of gravity
   instead of reading as a flat rectangle of colour. */
.spot{position:relative;isolation:isolate}
.spot::before{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:radial-gradient(60% 70% at var(--spot-x,26%) var(--spot-y,22%),
    var(--spot-c,rgba(255,255,255,.14)) 0,transparent 68%);
}

/* --------------------------------------------------------------- hairline
   A 1px rule that fades out at both ends. Reads as considered where a solid
   border reads as a box. */
.hair{border:0;height:1px;margin:0;
  background:linear-gradient(90deg,transparent,var(--hair,rgba(255,255,255,.22)) 18%,
    var(--hair,rgba(255,255,255,.22)) 82%,transparent)}

/* ------------------------------------------------------- premium marquee
   Same mechanics as .marq, but the marks sit in their own glass pills. Used
   for marque strips where the logos are the argument. */
.marq__pill{
  flex:0 0 auto;display:flex;align-items:center;justify-content:center;
  gap:.7em;
  padding:var(--pill-y,14px) var(--pill-x,26px);
  border-radius:999px;
  background:var(--pill-bg,rgba(255,255,255,.07));
  border:1px solid var(--pill-line,rgba(255,255,255,.16));
  -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);
  transition:background .35s var(--ease,var(--ease-out)),
             border-color .35s var(--ease,var(--ease-out)),
             transform .35s var(--ease,var(--ease-out));
}
.marq__pill svg,.marq__pill img{
  height:var(--pill-h,26px);width:auto;display:block;flex:0 0 auto}
.marq__pill b{font-weight:600;white-space:nowrap;letter-spacing:.02em}
.marq:hover .marq__pill{opacity:.5}
.marq .marq__pill:hover{opacity:1;transform:translateY(-2px);
  background:var(--pill-bg-h,rgba(255,255,255,.14))}

@media (prefers-reduced-motion: reduce){
  .sheen::after{display:none}
  .marq .marq__pill:hover{transform:none}
}
