/* Outsentia brand graphics: markup lives in each component's preview, motion lives here.
   Variables come from tokens.css (--accent, --surface, --hairline, --canvas, --ink, --ink-soft, --band). */
:root { --color-accent: var(--accent); --color-surface: var(--surface); --color-hairline: var(--hairline); --color-canvas: var(--canvas); --color-ink: var(--ink); --color-ink-soft: var(--ink-soft); --font-display: "Outfit", system-ui, sans-serif; --font-body: "Manrope", system-ui, sans-serif; }
.plate { border-radius: 4px; }
.label { font-family: var(--font-body); font-weight: 600; font-size: 0.75rem; letter-spacing: 0.16em; text-transform: uppercase; }
/* the few utility classes the exported markup carries */
.font-display { font-family: var(--font-display); }
.flex { display: flex; } .items-start { align-items: flex-start; } .justify-between { justify-content: space-between; } .gap-4 { gap: 16px; }
.mt-1 { margin-top: 4px; } .mt-1\.5 { margin-top: 6px; } .font-body { font-family: var(--font-body); } .font-normal { font-weight: 400; } .mt-2 { margin-top: 8px; } .mt-3 { margin-top: 12px; }
.text-xl { font-size: 20px; line-height: 1.3; } .text-3xl { font-size: 30px; }
.text-\[13px\] { font-size: 13px; } .text-\[14px\] { font-size: 14px; }
.font-bold { font-weight: 700; } .leading-tight { line-height: 1.15; } .tabular-nums { font-variant-numeric: tabular-nums; }
.text-white { color: #ffffff; } .text-white\/70 { color: rgb(255 255 255 / 0.7); } .text-white\/80 { color: rgb(255 255 255 / 0.8); }
.text-ink { color: var(--ink); } .text-ink-soft { color: var(--ink-soft); } .text-accent { color: var(--accent); }
.mx-auto { margin-inline: auto; } .aspect-square { aspect-ratio: 1; } .w-full { width: 100%; } .h-full { height: 100%; } .h-auto { height: auto; } .max-w-\[460px\] { max-width: 460px; }
.aspect-\[4\/3\] { aspect-ratio: 4 / 3; } .items-center { align-items: center; } .overflow-hidden { overflow: hidden; } .p-6 { padding: 24px; }
.border { border-width: 1px; border-style: solid; } .border-hairline { border-color: var(--hairline); } .bg-surface { background: var(--surface); }
.vstack__card p { margin: 0; } .vstack__plate p { margin: 0; }
@media (prefers-reduced-motion: reduce) { .flow-dot { display: none; } }

/* ------------------------------------------------------- vendor stack --
   Six invoices spread up the panel on a purple plate, far enough apart that every card
   shows both its lines. Once the panel is in view the sequence runs on a nine-second
   cycle: a beat at rest, the cards drop top first into the plate, the plate grows to the
   panel's full height and holds (its text stays centred as it grows), then shrinks back
   as the pile returns. Per-card delays shift the phase. */
.vstack {
  position: relative;
  width: 100%; /* auto margins alone would shrink a box whose children are all absolute */
  max-width: 440px;
  height: 100%;
  min-height: 660px;
  margin-inline: auto;
}
.vstack__plate {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 150px;
  padding: 28px;
  background: var(--color-accent);
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.vstack__cards {
  position: absolute;
  inset: 0;
  list-style: none;
  margin: 0;
  padding: 0;
}
.vstack__card {
  position: absolute;
  left: calc(8px + var(--i) * 7px);
  right: calc(8px + (5 - var(--i)) * 7px);
  bottom: calc(165px + var(--i) * 78px);
  padding: 12px 16px;
  background: var(--color-surface);
  border: 1px solid var(--color-hairline);
  transform: rotate(calc((var(--i) - 2.5) * 0.7deg));
  transform-origin: 50% 100%;
}
/* one 9s cycle; percentages are shared, per-card animation-delay shifts the phase */
@keyframes vstack-cycle {
  0%, 10% { transform: translate3d(0, 0, 0) rotate(calc((var(--i) - 2.5) * 0.7deg)); opacity: 1; }
  16% { transform: translate3d(0, calc(165px + var(--i) * 78px - 70px), 0) rotate(0deg) scale(0.96); opacity: 1; }
  19%, 74% { transform: translate3d(0, calc(165px + var(--i) * 78px - 50px), 0) scale(0.9); opacity: 0; }
  80%, 100% { transform: translate3d(0, 0, 0) rotate(calc((var(--i) - 2.5) * 0.7deg)); opacity: 1; }
}
@keyframes vstack-plate-cycle {
  0%, 30% { height: 150px; }
  33% { height: 142px; }
  42%, 70% { height: 100%; }
  78%, 100% { height: 150px; }
}
.vstack .vstack__card {
  animation: vstack-cycle 9s cubic-bezier(0.4, 0, 0.2, 1) infinite;
  animation-delay: calc((5 - var(--i)) * 220ms);
}
.vstack .vstack__plate {
  animation: vstack-plate-cycle 9s cubic-bezier(0.2, 0.7, 0.2, 1) infinite;
}
@media (max-width: 480px) {
  .vstack { min-height: 590px; }
  .vstack__card { bottom: calc(150px + var(--i) * 68px); padding: 10px 14px; }
  @keyframes vstack-cycle {
    0%, 10% { transform: none; opacity: 1; }
    16% { transform: translate3d(0, calc(150px + var(--i) * 68px - 60px), 0) scale(0.96); opacity: 1; }
    19%, 74% { transform: translate3d(0, calc(150px + var(--i) * 68px - 40px), 0) scale(0.9); opacity: 0; }
    80%, 100% { transform: none; opacity: 1; }
  }
}
@media (prefers-reduced-motion: reduce) {
  .vstack .vstack__card { animation: none; opacity: 1; }
  .vstack .vstack__plate { animation: none; }
}


/* --------------------------------------------------------------- atom --
   Orbits turn around the nucleus; each <g> sets its own duration and direction. */
@keyframes atom-turn {
  to { transform: rotate(360deg); }
}
.atom__orbit {
  transform-origin: 230px 230px;
  transform-box: view-box;
  animation-name: atom-turn;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
}
@media (prefers-reduced-motion: reduce) {
  .atom__orbit { animation: none; }
}


/* ------------------------------------------------------- mark breathe --
   The square swells a touch every eight seconds. Inside it, the six globe pieces
   push outward from the centre together, then click back one by one, counterclockwise from the upper left. */
.mark { display: block; overflow: visible; }
@keyframes mark-breathe {
  0%, 100% { transform: scale(1); }
  45% { transform: scale(1.04); }
  60% { transform: scale(0.99); }
  75% { transform: scale(1); }
}
/* All six pieces push out together (30% to 38% of the cycle), hold, then click
   back one at a time counterclockwise from the upper left: upper left, lower left,
   bottom, lower right, upper right, top. Each piece has its own keyframes so the push-out stays
   simultaneous while only the return is staggered (400ms apart). */
@keyframes mark-click-0 {
  0%, 30% { transform: scale(1); }
  38%, 44% { transform: scale(1.2); }
  48% { transform: scale(0.96); }
  50%, 100% { transform: scale(1); }
}
@keyframes mark-click-1 {
  0%, 30% { transform: scale(1); }
  38%, 49% { transform: scale(1.2); }
  53% { transform: scale(0.96); }
  55%, 100% { transform: scale(1); }
}
@keyframes mark-click-2 {
  0%, 30% { transform: scale(1); }
  38%, 54% { transform: scale(1.2); }
  58% { transform: scale(0.96); }
  60%, 100% { transform: scale(1); }
}
@keyframes mark-click-3 {
  0%, 30% { transform: scale(1); }
  38%, 59% { transform: scale(1.2); }
  63% { transform: scale(0.96); }
  65%, 100% { transform: scale(1); }
}
@keyframes mark-click-4 {
  0%, 30% { transform: scale(1); }
  38%, 64% { transform: scale(1.2); }
  68% { transform: scale(0.96); }
  70%, 100% { transform: scale(1); }
}
@keyframes mark-click-5 {
  0%, 30% { transform: scale(1); }
  38%, 69% { transform: scale(1.2); }
  73% { transform: scale(0.96); }
  75%, 100% { transform: scale(1); }
}
.mark-breathe {
  animation: mark-breathe 8s cubic-bezier(0.4, 0, 0.2, 1) infinite;
  animation-delay: 2s;
  will-change: transform;
}
.mark__piece {
  transform-box: view-box;
  transform-origin: 87.5px 86.5px;
  animation: mark-click-0 8s cubic-bezier(0.3, 0.9, 0.3, 1) infinite;
  animation-delay: 2s;
  will-change: transform;
}
/* return order, counterclockwise from the upper left: upper left, lower left, bottom,
   lower right, upper right, top. Paths sit top, upper right, lower right, bottom,
   lower left, upper left, so the mapping runs backwards. */
.mark__piece:nth-of-type(2) { animation-name: mark-click-5; } /* top */
.mark__piece:nth-of-type(3) { animation-name: mark-click-4; } /* upper right */
.mark__piece:nth-of-type(4) { animation-name: mark-click-3; } /* lower right */
.mark__piece:nth-of-type(5) { animation-name: mark-click-2; } /* bottom */
.mark__piece:nth-of-type(6) { animation-name: mark-click-1; } /* lower left */
.mark__piece:nth-of-type(7) { animation-name: mark-click-0; } /* upper left */
@media (prefers-reduced-motion: reduce) {
  .mark-breathe, .mark__piece { animation: none; }
}


/* ------------------------------------------------------ dotted backdrop --
   One of the eight dotted illustrations as a section background: large, faint, to one
   side, dissolving at every edge. A radial mask does the fading, so a section shorter
   than the artwork never shows a hard cut. The section that holds it needs
   position:relative, isolation:isolate and overflow:hidden. Desktop only: on phones the
   copy stacks across the full width and the dots would sit behind the text.
   --w sets the width (height follows at 0.9), --a the opacity. */
.dotbd {
  --w: 760px;
  --a: 0.55;
  --dotbd-mask: radial-gradient(ellipse at center, #000 0%, #000 42%, rgba(0, 0, 0, 0.6) 62%, transparent 82%);
  position: absolute;
  z-index: -10;
  top: 50%;
  width: var(--w);
  height: calc(var(--w) * 0.9);
  opacity: var(--a);
  transform: translateY(-50%);
  pointer-events: none;
  -webkit-mask-image: var(--dotbd-mask);
  mask-image: var(--dotbd-mask);
}
.dotbd--right { right: -3%; }
.dotbd--left { left: -3%; }
.dotbd > img,
.dotbd > svg {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 100%;
  transform: translate(-50%, -50%);
}
@media (max-width: 1023px) { .dotbd { display: none; } }


/* ------------------------------------------------------ dotted fingerprint --
   Each dot of the dotted fingerprint rises in turn; delays run clockwise around the
   print, so one pulse travels round the finger every eight seconds. Each dot carries its
   own --o (its resting opacity) and --d (its delay), set from its angle about the centre. */
@keyframes fp-raise {
  0%, 100% { transform: scale(1); opacity: var(--o); }
  3% { transform: scale(2.6); opacity: 1; }
  10% { transform: scale(1); opacity: var(--o); }
}
.fp-dot {
  opacity: var(--o);
  transform-box: fill-box;
  transform-origin: center;
  animation: fp-raise 8s linear infinite;
  animation-delay: var(--d);
}
@media (prefers-reduced-motion: reduce) { .fp-dot { animation: none; } }


/* -------------------------------------------------------- dotted building --
   Six floors, ground floor first: each slides right and settles back in its own slot of
   the cycle; the roof and the base stay put. 1.1s per floor plus a 1.4s rest at the top.
   Each floor group carries --i, its storey number counting up from the ground. */
.bl { display: block; overflow: visible; }
.bl-floor {
  animation: bl-floor 8s cubic-bezier(0.4, 0, 0.2, 1) infinite;
  animation-delay: calc(var(--i) * 1.1s);
  will-change: transform;
}
@keyframes bl-floor {
  0% { transform: translateX(0); }
  6% { transform: translateX(46px); }
  13.75% { transform: translateX(0); }
  100% { transform: translateX(0); }
}
@media (prefers-reduced-motion: reduce) { .bl-floor { animation: none; } }
