/* ============================================================================
   XARQ — sections, in page order
   ========================================================================== */

/* ================================================================= preloader
   It exists for one reason: the hero render and the webfonts arrive a few
   hundred ms apart, and without a cover the page visibly reflows twice.

   It dismisses itself in CSS, and that is the important part. main.js adding
   .is-done is only the fast path — if the module never runs at all (scripting
   disabled, a blocked or unreachable CDN, an old browser that chokes on import
   maps) nothing would ever add that class, and a full-screen opaque cover would
   sit over a page that is otherwise perfectly readable. The animation below
   guarantees the cover leaves on its own, whatever happens to the JavaScript. */
.preload {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: grid;
  place-items: center;
  gap: var(--sp-5);
  background: var(--bg);
  transition: opacity 620ms var(--ease-out), visibility 620ms;
  animation: preload-timeout 700ms var(--ease-out) 3.4s forwards;
}
.preload.is-done {
  /* The class wins: cancel the timed fallback so the two cannot fight. */
  animation: none;
  opacity: 0;
  visibility: hidden;
}
.preload__mark {
  width: 72px;
  animation: float-y 3s var(--ease-in-out) infinite alternate;
}
.preload__bar {
  width: min(220px, 50vw);
  height: 2px;
  border-radius: 2px;
  background: var(--line);
  overflow: hidden;
}
.preload__bar i {
  display: block;
  height: 100%;
  width: 100%;
  background: var(--grad-brand);
  transform: scaleX(0);
  transform-origin: 0 50%;
  animation: load-bar 1.6s var(--ease-out) forwards;
}

/* ====================================================================== hero */
.hero {
  position: relative;
  z-index: var(--z-content);
  min-height: 100svh;
  display: grid;
  /* minmax(0, 1fr), not the default `auto`: an auto track grows to its
     content's min-content width, so one unbreakable element anywhere inside the
     hero would widen the whole page rather than overflowing its own box. */
  grid-template-columns: minmax(0, 1fr);
  align-items: center;
  padding-block: clamp(7rem, 5rem + 7vw, 10rem) clamp(3rem, 2rem + 3vw, 5rem);
}

.hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(2rem, 1rem + 3vw, 4rem);
  align-items: center;
}
@media (min-width: 960px) {
  .hero__grid {
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.8fr);
  }
}

.hero__inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(1.3rem, 0.9rem + 1.3vw, 2.1rem);
  max-width: 48rem;
}

/* Only the badge shrinks to its own width. Doing this with justify-items on
   the grid would give every child max-content sizing, and the paragraphs and
   the button row would then refuse to wrap on a phone. */
.hero__inner > .badge {
  justify-self: start;
}

.hero__title {
  font-size: clamp(2.8rem, 1.5rem + 5vw, 6.4rem);
  font-weight: 600;
  line-height: 0.96;
  letter-spacing: -0.045em;
}

/* Each line is a clipping window; reveal.js slides the inner span up out of it.
   The overflow has to be on a block-level wrapper — on an inline element the
   clip box is the line box and descenders get shaved. */
.line {
  display: block;
  overflow: hidden;
  padding-bottom: 0.1em;
  margin-bottom: -0.1em;
}
.line > span {
  display: block;
  will-change: transform;
}

.hero__copy {
  display: grid;
  gap: 0.7rem;
}
.hero__sub {
  font-size: var(--t-lg);
  color: var(--text);
  max-width: 46ch;
}
.hero__sub--muted {
  color: var(--text-2);
  font-size: var(--t-base);
}

.hero__cta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.8rem;
  align-items: center;
}

/* Below the two-column breakpoint the hero render would push the buttons and
   the motto below the fold, so it steps aside rather than stacking. */
.hero__visual {
  display: none;
  place-items: center;
}
@media (min-width: 960px) {
  .hero__visual {
    display: grid;
  }
}

/* "We build. We improve. We keep moving forward." as a three-beat row. */
.hero__motto {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr));
  gap: 0;
  margin-top: clamp(2.5rem, 1.5rem + 3vw, 4.5rem);
  border-top: 1px solid var(--line);
}
.hero__motto li {
  display: flex;
  align-items: baseline;
  gap: 0.9rem;
  padding: 1.2rem 1.2rem 0 0;
  font-family: var(--font-display);
  font-size: var(--t-xl);
  font-weight: 500;
  letter-spacing: -0.02em;
}
.hero__motto li span {
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.18em;
  color: var(--accent);
}

.hero__scroll {
  position: absolute;
  left: 50%;
  bottom: clamp(1rem, 2vh, 2.2rem);
  transform: translateX(-50%);
  display: grid;
  justify-items: center;
  gap: 0.6rem;
  color: var(--faint);
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
}
.hero__scroll i {
  display: block;
  width: 1px;
  height: 42px;
  background: linear-gradient(var(--accent), transparent);
  animation: scroll-hint 2.2s var(--ease-in-out) infinite;
}
/* The hint needs a viewport with room to spare beneath the content. */
@media (max-height: 760px), (max-width: 640px) {
  .hero__scroll {
    display: none;
  }
}

/* A badge that is also a link. */
.badge--link {
  transition: border-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.badge--link svg {
  width: 13px;
  height: 13px;
  transition: transform var(--dur) var(--ease-spring);
}
.badge--link:hover {
  border-color: var(--accent-line);
  color: var(--text);
}
.badge--link:hover svg {
  transform: translateX(3px);
}

/* =================================================================== section
   The larger section headline used throughout, with room for a serif accent. */
.section__title em.serif,
.contact__title em.serif {
  line-height: 1;
}

/* ====================================================================== flow
   WHAT WE DO — the pinned section.

   Mechanics, in one place:
     .flow__track   three screens tall; it is what the visitor scrolls through
     .flow__stage   position:sticky, one screen tall; it is what they see
   scroll-scenes.js reads progress through the track (0 → 1) and toggles
   .is-active / .is-past on the panels, renders and tabs, and writes --p for the
   lifecycle rail. Nothing here is pinned by JavaScript — sticky does the
   holding, which is why it cannot drift out of sync with Lenis.

   The panels share one grid cell rather than being absolutely positioned, so
   the cell is always as tall as the tallest panel and nothing below it has to
   guess a height. */
.flow {
  position: relative;
  z-index: var(--z-content);
  padding-top: var(--section-y);
}

.flow__intro {
  display: grid;
  gap: var(--sp-4);
  max-width: 54rem;
}

.flow__track {
  position: relative;
  /* One screen per panel, plus a short dwell so the last one gets a full read
     before the page moves on. */
  height: 340svh;
}

.flow__stage {
  position: sticky;
  top: 0;
  height: 100svh;
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  gap: clamp(1rem, 0.6rem + 1.4vw, 2rem);
  padding-top: clamp(5rem, 4rem + 2vw, 6.5rem);
  padding-bottom: clamp(1.4rem, 1rem + 1.5vw, 2.6rem);
  overflow: hidden;
  --p: 0;
}

.flow__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr);
  gap: clamp(1rem, 0.5rem + 2vw, 3rem);
  align-items: center;
  min-height: 0;
}
@media (min-width: 960px) {
  .flow__grid {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
    grid-template-rows: minmax(0, 1fr);
  }
}

.flow__copy {
  display: grid;
  gap: clamp(1rem, 0.6rem + 1.6vw, 2.2rem);
  align-content: center;
}

/* ------------------------------------------------------------ step tabs */
.flow__tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
}
.flow__tabs li {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.42rem 0.85rem;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  font-family: var(--font-mono);
  font-size: 0.64rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--faint);
  transition: color 400ms var(--ease-out), border-color 400ms var(--ease-out),
    background-color 400ms var(--ease-out);
}
.flow__tabs li span {
  color: var(--accent);
  opacity: 0.8;
}
.flow__tabs li.is-active {
  color: var(--text);
  border-color: var(--accent-line);
  background: var(--accent-soft);
}

/* --------------------------------------------------------------- panels */
.flow__panels {
  display: grid;
}
.flow__panel {
  grid-area: 1 / 1;
  display: grid;
  gap: var(--sp-4);
  align-content: start;
  opacity: 0;
  transform: translate3d(0, 34px, 0);
  filter: blur(10px);
  pointer-events: none;
  transition: opacity 600ms var(--ease-out), transform 900ms var(--ease-out), filter 600ms var(--ease-out);
}
/* Direction-aware: a panel you have scrolled past leaves upward, the next one
   arrives from below — so scrolling back reverses the motion instead of
   replaying it. */
.flow__panel.is-past {
  transform: translate3d(0, -34px, 0);
}
.flow__panel.is-active {
  opacity: 1;
  transform: none;
  filter: none;
  pointer-events: auto;
}

.flow__num {
  font-family: var(--font-display);
  font-size: clamp(3.6rem, 1.8rem + 6.5vw, 8rem);
  font-weight: 600;
  line-height: 0.8;
  letter-spacing: -0.06em;
  background: var(--grad-brand);
  background-clip: text;
  -webkit-background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.flow__panel h3 {
  font-size: var(--t-3xl);
}
.flow__panel p {
  font-size: var(--t-lg);
  color: var(--text-2);
  max-width: 40ch;
}
.flow__panel .card__meta {
  margin-top: 0;
}

/* --------------------------------------------------------------- renders */
.flow__art {
  position: relative;
  display: grid;
  place-items: center;
  min-height: 0;
  height: 100%;
}
.flow__art .art {
  grid-area: 1 / 1;
  /* Bound by the stage height as well as the column width, so the render can
     never push the lifecycle rail off a short laptop screen. */
  width: min(100%, 460px, 52svh);
  opacity: 0;
  transform: scale(0.8) rotate(-12deg);
  transition: opacity 700ms var(--ease-out), transform 1100ms var(--ease-out);
}
.flow__art .art.is-past {
  transform: scale(0.88) rotate(12deg) translate3d(0, -6%, 0);
}
.flow__art .art.is-active {
  opacity: 1;
  transform: none;
}
@media (max-width: 959px) {
  .flow__art .art {
    width: min(78%, 34svh);
  }
}

/* ------------------------------------------------------- lifecycle rail */
.flow__life {
  display: grid;
  gap: 0.8rem;
}
.flow__rail {
  height: 2px;
  border-radius: 2px;
  background: var(--line);
  overflow: hidden;
}
.flow__rail i {
  display: block;
  height: 100%;
  background: var(--grad-brand);
  transform: scaleX(var(--p));
  transform-origin: 0 50%;
}
.flow__life ol {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
}
.flow__life li {
  font-family: var(--font-mono);
  font-size: clamp(0.52rem, 0.46rem + 0.2vw, 0.66rem);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--faint);
  text-align: center;
  transition: color 400ms var(--ease-out);
}
.flow__life li:first-child {
  text-align: left;
}
.flow__life li:last-child {
  text-align: right;
}
.flow__life li.is-on {
  color: var(--text);
}

/* ------------------------------------------------------ static fallback
   No JS, or a visitor who asked for reduced motion: the track collapses, the
   stage stops sticking, and all three panels are simply listed. Nothing is
   hidden behind a scroll interaction that will never run. */
html.no-js .flow__track,
.flow.is-static .flow__track {
  height: auto;
}
html.no-js .flow__stage,
.flow.is-static .flow__stage {
  position: relative;
  height: auto;
  padding-top: var(--sp-7);
  --p: 1;
}
html.no-js .flow__panels,
.flow.is-static .flow__panels {
  gap: var(--sp-7);
}
html.no-js .flow__panel,
.flow.is-static .flow__panel {
  grid-area: auto;
  opacity: 1;
  transform: none;
  filter: none;
}
html.no-js .flow__tabs,
.flow.is-static .flow__tabs {
  display: none;
}
/* The renders share one grid cell while the section is stepping. Once it is
   static they have to be given their own rows, or all three sit on top of one
   another in a single pile. */
html.no-js .flow__art,
.flow.is-static .flow__art {
  gap: var(--sp-8);
  align-content: center;
}
html.no-js .flow__art .art,
.flow.is-static .flow__art .art {
  grid-area: auto;
  opacity: 1;
  transform: none;
}
html.no-js .flow__life li,
.flow.is-static .flow__life li {
  color: var(--text-2);
}
@media (prefers-reduced-motion: reduce) {
  .flow__track {
    height: auto;
  }
  .flow__stage {
    position: relative;
    height: auto;
    padding-top: var(--sp-7);
    --p: 1;
  }
  .flow__panels {
    gap: var(--sp-7);
  }
  .flow__panel {
    grid-area: auto;
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
  }
  .flow__tabs {
    display: none;
  }
  .flow__art {
    gap: var(--sp-8);
    align-content: center;
  }
  .flow__art .art {
    grid-area: auto;
    opacity: 1 !important;
    transform: none !important;
  }
}

/* ====================================================================== art
   One component for all four illustration slots — the hero object and the
   three renders in the pinned section.

   The bloom is CSS and the render is a background-image on top of it. Using a
   background rather than an <img> is the whole trick: a background-image whose
   file does not exist paints nothing at all, while a broken <img> paints the
   browser's broken-image icon in the middle of the section.

   These images are decorative (their containers are aria-hidden, and the
   meaning is in the text beside them), which is what makes a background the
   correct choice here rather than a shortcut.

   Sizes and prompts for the renders are in ASSET_PROMPTS.md. */
.art {
  position: relative;
  width: min(94%, 440px);
  aspect-ratio: 1;
  display: grid;
  place-items: center;
}

/* The bloom. Sits behind the render and picks up the travelling --accent, so
   each step's artwork is lit in that step's colour. */
.art::before {
  content: '';
  position: absolute;
  inset: 12%;
  border-radius: 50%;
  background: radial-gradient(
    circle at 42% 38%,
    color-mix(in oklab, var(--accent) 46%, transparent),
    color-mix(in oklab, var(--violet) 20%, transparent) 46%,
    transparent 70%
  );
  filter: blur(56px);
  opacity: 0.75;
  animation: float-y 9s var(--ease-in-out) infinite alternate;
}

.art__obj {
  position: relative;
  width: 100%;
  height: 100%;
  background-position: center;
  background-repeat: no-repeat;
  background-size: contain;
  /* Renders arrive with their own baked lighting; the page only adds the
     contact shadow that grounds the object against the section behind it. */
  filter: drop-shadow(0 26px 42px rgba(0, 0, 0, 0.45));
  animation: float-y 7s var(--ease-in-out) infinite alternate;
  will-change: transform;
}

:root[data-theme='light'] .art__obj {
  filter: drop-shadow(0 24px 40px rgba(16, 24, 40, 0.18));
}

/* ------------------------------------------------------- the four renders
   One line each. This is the only place a render's path appears, so swapping
   artwork is a one-line change. Sizes and prompts: ASSET_PROMPTS.md */
.art--hero .art__obj { background-image: url('/assets/art/hero-object.webp'); }
.art--ideas .art__obj { background-image: url('/assets/art/ideas-orb.webp'); }
.art--build .art__obj { background-image: url('/assets/art/build-stack.webp'); }
.art--digital .art__obj { background-image: url('/assets/art/live-core.webp'); }

.art--hero {
  width: min(100%, 500px);
}
.art--hero .art__obj {
  animation-duration: 9s;
}

/* ===================================================================== apps
   GetHired, as a feature panel. */
.case {
  position: relative;
  border-radius: var(--r-xl);
  border: 1px solid var(--glass-line);
  background: linear-gradient(150deg, var(--surface-2), var(--surface));
  overflow: hidden;
  box-shadow: var(--shadow-lg);
}
.case__inner {
  display: grid;
  gap: clamp(2rem, 1rem + 4vw, 4rem);
  padding: clamp(1.6rem, 1rem + 3vw, 3.6rem);
  align-items: center;
}
@media (min-width: 960px) {
  .case__inner {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
  }
}

.case__glow {
  position: absolute;
  top: -30%;
  right: -10%;
  width: 60%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle, color-mix(in oklab, var(--accent) 34%, transparent), transparent 66%);
  filter: blur(70px);
  pointer-events: none;
}

.case__copy {
  position: relative;
  display: grid;
  gap: var(--sp-4);
}
.case__copy > p {
  font-size: var(--t-base);
  color: var(--text);
  max-width: 54ch;
}
.case__copy > p.case__muted {
  color: var(--text-2);
}

.case__name {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  flex-wrap: wrap;
  font-size: var(--t-3xl);
}

.case__live {
  font-family: var(--font-mono);
  font-size: 0.6rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: #22c55e;
  border: 1px solid color-mix(in oklab, #22c55e 40%, transparent);
  background: color-mix(in oklab, #22c55e 12%, transparent);
  border-radius: var(--r-pill);
  padding: 0.28rem 0.65rem;
}

/* Matched as a child of .case__copy, not on its own: `.case__copy > p` is a
   class *and* a type selector, so a bare .case__tag loses to it and the
   tagline silently renders at body size. */
.case__copy > .case__tag {
  font-family: var(--font-display);
  font-size: var(--t-2xl);
  font-weight: 500;
  line-height: 1.1;
  letter-spacing: -0.03em;
  margin-bottom: var(--sp-2);
}

/* The two sides of the marketplace, as a pair. */
.audience {
  display: grid;
  gap: 0.8rem;
  grid-template-columns: repeat(auto-fit, minmax(min(230px, 100%), 1fr));
  margin-top: var(--sp-2);
}
.audience__card {
  display: grid;
  gap: 0.45rem;
  padding: 1.1rem 1.2rem;
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: color-mix(in oklab, var(--surface-2) 80%, transparent);
  transition: border-color var(--dur) var(--ease-out), transform var(--dur) var(--ease-out);
}
.audience__card:hover {
  border-color: var(--accent-line);
  transform: translateY(-2px);
}
.audience__card b {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--font-display);
  font-size: var(--t-lg);
  font-weight: 500;
}
.audience__card svg {
  width: 20px;
  height: 20px;
  color: var(--accent);
  flex-shrink: 0;
}
.audience__card p {
  font-size: var(--t-sm);
  color: var(--text-2);
}

.case__foot {
  display: flex;
  flex-wrap: wrap;
  gap: 1.2rem 1.6rem;
  align-items: center;
  justify-content: space-between;
  padding-top: var(--sp-5);
  margin-top: var(--sp-2);
  border-top: 1px solid var(--line);
}

/* "Simple. Local. Practical." — one word per step of the brand ramp. */
.trio {
  display: flex;
  flex-wrap: wrap;
  gap: 0.2rem 0.7rem;
  font-family: var(--font-serif);
  font-style: italic;
  font-size: var(--t-xl);
}
.trio li:nth-child(1) { color: var(--violet); }
.trio li:nth-child(2) { color: var(--blue-lt); }
.trio li:nth-child(3) { color: var(--cyan); }

/* "More from Xarq" — honest about what exists and what does not yet. */
.next {
  display: grid;
  gap: 0.6rem;
  justify-items: start;
  margin-top: clamp(1rem, 0.6rem + 1.4vw, 1.6rem);
  padding: clamp(1.4rem, 1rem + 1.5vw, 2.2rem);
  border-radius: var(--r-lg);
  border: 1px dashed var(--line-strong);
  background: color-mix(in oklab, var(--surface) 50%, transparent);
  color: var(--text-2);
  transition: border-color var(--dur) var(--ease-out);
}
.next:hover {
  border-color: var(--accent-line);
}
.next__tag {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--font-mono);
  font-size: 0.64rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}
.next__tag i {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  animation: pulse-dot 2.4s var(--ease-out) infinite;
}
.next__title {
  font-family: var(--font-display);
  font-size: var(--t-xl);
  font-weight: 500;
  color: var(--text);
}

/* ---------------------------------------------------------- device mockup
   A CSS phone, not a screenshot: it is theme-aware, sharp at any DPR, weighs
   nothing, and never goes stale when the real app changes. Swap in real
   screenshots later by replacing .phone__screen's children with an <img>. */
.devices {
  position: relative;
  display: grid;
  place-items: center;
  min-height: 420px;
  perspective: 1400px;
}

.phone {
  position: relative;
  width: min(252px, 62vw);
  aspect-ratio: 9 / 19;
  border-radius: 34px;
  padding: 8px;
  background: linear-gradient(160deg, #2a2f3d, #0b0d14 60%);
  box-shadow: var(--shadow-lg), 0 0 0 1px rgba(255, 255, 255, 0.08) inset;
  transform: rotateY(-16deg) rotateX(6deg) rotateZ(-2deg);
  transform-style: preserve-3d;
  will-change: transform;
  transition: transform 700ms var(--ease-out);
}
.phone--back {
  position: absolute;
  left: 50%;
  top: 50%;
  width: min(214px, 54vw);
  transform: translate(-76%, -54%) rotateY(-22deg) rotateX(7deg) rotateZ(-6deg) scale(0.88);
  opacity: 0.55;
  filter: blur(0.4px);
  z-index: -1;
}
@media (max-width: 560px) {
  .phone--back {
    display: none;
  }
}

.phone__screen {
  position: relative;
  height: 100%;
  border-radius: 27px;
  overflow: hidden;
  background: var(--bg-deep);
  display: grid;
  grid-template-rows: auto 1fr auto;
  gap: 0.5rem;
  padding: 1.4rem 0.75rem 0.7rem;
  font-size: 0.62rem;
}
.phone__notch {
  position: absolute;
  top: 8px;
  left: 50%;
  transform: translateX(-50%);
  width: 42%;
  height: 16px;
  border-radius: 0 0 12px 12px;
  background: #0b0d14;
  z-index: 2;
}

.ui-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  color: #edf0f7;
  font-weight: 600;
  font-size: 0.68rem;
  padding-inline: 0.25rem;
}
.ui-head em {
  font-style: normal;
  font-family: var(--font-mono);
  font-size: 0.52rem;
  color: #22c55e;
}

.ui-body {
  display: grid;
  gap: 0.42rem;
  align-content: start;
}

.ui-card {
  border-radius: 10px;
  padding: 0.5rem 0.55rem;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.08);
  display: flex;
  align-items: center;
  gap: 0.45rem;
  color: #cfd5e4;
}
.ui-card i {
  width: 20px;
  height: 20px;
  border-radius: 6px;
  background: var(--grad-brand);
  flex-shrink: 0;
}
.ui-card b {
  font-size: 0.6rem;
  font-weight: 600;
  color: #fff;
  display: block;
}
.ui-card s {
  text-decoration: none;
  font-size: 0.52rem;
  color: #8b93a8;
  display: block;
}
.ui-card u {
  text-decoration: none;
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 0.55rem;
  color: var(--cyan-lt);
}

.ui-qr {
  margin: 0.2rem auto;
  width: 78px;
  height: 78px;
  border-radius: 8px;
  background: #fff;
  padding: 6px;
  display: grid;
  grid-template: repeat(5, 1fr) / repeat(5, 1fr);
  gap: 2px;
}
.ui-qr span {
  background: #05060b;
  border-radius: 1px;
}
.ui-qr span.o {
  background: transparent;
}

.ui-cta {
  border-radius: 10px;
  padding: 0.5rem;
  text-align: center;
  font-weight: 700;
  font-size: 0.62rem;
  color: #fff;
  background: var(--grad-brand);
}


/* ===================================================================== bento
   WHY XARQ — three reasons, one tall and two stacked. An asymmetric grid reads
   as designed; three equal columns read as a template. Each card carries a
   small CSS illustration of its own idea — no images, nothing to load. */
.bento {
  display: grid;
  gap: clamp(0.9rem, 0.6rem + 1vw, 1.4rem);
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 900px) {
  .bento {
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
    grid-template-rows: auto auto;
  }
  .bento > :first-child {
    grid-row: span 2;
  }
}

.bento .tilt,
.bento__card {
  height: 100%;
}
.bento__card {
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
}
.bento__text {
  display: grid;
  gap: 0.6rem;
  margin-top: auto;
}
.bento__text p {
  font-size: var(--t-base);
  max-width: 46ch;
}

.bento__vis {
  position: relative;
  height: clamp(150px, 8vw + 110px, 210px);
  border-radius: var(--r-md);
  overflow: hidden;
  background: radial-gradient(
      circle at 50% 55%,
      color-mix(in oklab, var(--accent) 16%, transparent),
      transparent 70%
    ),
    color-mix(in oklab, var(--surface-2) 60%, transparent);
  border: 1px solid var(--line);
}
.bento__card--tall .bento__vis {
  flex: 1;
  min-height: clamp(220px, 16vw + 140px, 340px);
  /* flex:1 lets it grow to match the two stacked cards beside it — without a
     cap that is ~700px of empty orbit and the heading falls off the screen. */
  max-height: 440px;
}

/* ------------------------------------------ 01 Built for People: orbits
   People in orbit around a single, simple core. */
.vis-orbit {
  display: grid;
  place-items: center;
}
.vis-orbit__core {
  position: absolute;
  width: 58px;
  height: 58px;
  border-radius: 50%;
  background: var(--grad-brand);
  box-shadow: 0 0 60px color-mix(in oklab, var(--azure) 70%, transparent);
  animation: float-y 5s var(--ease-in-out) infinite alternate;
}
.vis-orbit__ring {
  position: absolute;
  border-radius: 50%;
  border: 1px solid var(--line-strong);
  animation: spin-slow 28s linear infinite;
}
.vis-orbit__ring:nth-child(1) { width: 130px; height: 130px; }
.vis-orbit__ring:nth-child(2) { width: 220px; height: 220px; animation-duration: 40s; animation-direction: reverse; }
.vis-orbit__ring:nth-child(3) { width: 310px; height: 310px; animation-duration: 56s; border-style: dashed; }
.vis-orbit__ring i {
  position: absolute;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--surface);
  border: 2px solid var(--violet);
  box-shadow: 0 0 16px color-mix(in oklab, var(--violet) 60%, transparent);
}
.vis-orbit__ring i:nth-child(1) { top: -7px; left: calc(50% - 7px); }
.vis-orbit__ring i:nth-child(2) { bottom: -7px; left: calc(50% - 7px); border-color: var(--cyan); box-shadow: 0 0 16px color-mix(in oklab, var(--cyan) 60%, transparent); }
.vis-orbit__ring:nth-child(2) i:nth-child(1) { top: calc(50% - 7px); left: -7px; border-color: var(--blue-lt); }
.vis-orbit__ring:nth-child(2) i:nth-child(2) { top: calc(50% - 7px); left: auto; right: -7px; bottom: auto; }
.vis-orbit__ring:nth-child(3) i:nth-child(1) { top: 14%; left: 12%; border-color: var(--cyan); }

/* ----------------------------------- 02 Ideas Into Products: sketch → app
   A dashed outline on the left becomes a solid, lit product on the right. */
.vis-idea {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(0.8rem, 0.4rem + 1.4vw, 1.6rem);
}
.vis-idea__sketch,
.vis-idea__product {
  width: 74px;
  height: 108px;
  border-radius: 16px;
}
.vis-idea__sketch {
  border: 2px dashed var(--line-strong);
  position: relative;
}
.vis-idea__sketch::before,
.vis-idea__sketch::after {
  content: '';
  position: absolute;
  left: 14px;
  right: 14px;
  height: 2px;
  border-radius: 2px;
  background: var(--line-strong);
}
.vis-idea__sketch::before { top: 30px; }
.vis-idea__sketch::after { top: 44px; right: 30px; }
.vis-idea__arrow {
  width: 44px;
  height: 2px;
  background: linear-gradient(90deg, var(--line-strong), var(--accent));
  position: relative;
}
.vis-idea__arrow::after {
  content: '';
  position: absolute;
  right: -1px;
  top: -4px;
  width: 10px;
  height: 10px;
  border-top: 2px solid var(--accent);
  border-right: 2px solid var(--accent);
  transform: rotate(45deg);
}
.vis-idea__product {
  position: relative;
  display: grid;
  align-content: start;
  gap: 7px;
  padding: 18px 12px;
  background: var(--grad-brand);
  box-shadow: 0 18px 40px -14px color-mix(in oklab, var(--azure) 80%, transparent);
  animation: float-y 4.5s var(--ease-in-out) infinite alternate;
}
.vis-idea__product i {
  display: block;
  height: 8px;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.85);
}
.vis-idea__product i:nth-child(2) { width: 70%; background: rgba(255, 255, 255, 0.55); }
.vis-idea__product i:nth-child(3) { margin-top: 26px; height: 16px; border-radius: 6px; background: rgba(255, 255, 255, 0.95); }

/* ---------------------------------------- 03 Designed to Grow: rising bars */
.vis-grow {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: clamp(8px, 1vw, 12px);
  padding: 1.4rem 1.6rem 0;
}
.vis-grow i {
  flex: 1;
  max-width: 34px;
  height: var(--h);
  border-radius: 8px 8px 0 0;
  background: linear-gradient(to top, color-mix(in oklab, var(--violet) 70%, transparent), var(--cyan));
  transform-origin: 50% 100%;
  transform: scaleY(0.12);
  transition: transform 1100ms var(--ease-out);
}
.vis-grow i:nth-child(1) { transition-delay: 0ms; }
.vis-grow i:nth-child(2) { transition-delay: 90ms; }
.vis-grow i:nth-child(3) { transition-delay: 180ms; }
.vis-grow i:nth-child(4) { transition-delay: 270ms; }
.vis-grow i:nth-child(5) { transition-delay: 360ms; }
.vis-grow i:nth-child(6) { transition-delay: 450ms; }
/* The bars grow when the grid is revealed — the reveal class is already on
   the parent, so no extra observer is needed. */
.bento.is-in .vis-grow i,
html.no-js .vis-grow i {
  transform: none;
}

/* ==================================================================== mantra
   OUR APPROACH — the second pinned section. Three lines fill with the brand
   gradient in turn as the track is scrolled.

   Only --p (0 → 1) is written from JavaScript. Each line derives its own
   progress from it in CSS:  --lp = clamp(0, p·3.3 − i·1.05, 1)  — so the lines
   overlap slightly rather than waiting for each other, which is what makes the
   fill feel like one continuous gesture instead of three separate events.

   The fill is two backgrounds clipped to the text: the brand gradient, sized
   to --lp of the width, over a flat faint base. As --lp grows the gradient
   sweeps left to right through the letters. */
.mantra {
  position: relative;
  z-index: var(--z-content);
}
.mantra__track {
  position: relative;
  height: 320svh;
}
.mantra__stage {
  position: sticky;
  top: 0;
  height: 100svh;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: clamp(1.3rem, 0.8rem + 1.6vw, 2.4rem);
  padding-inline: var(--gutter);
  text-align: center;
  --p: 0;
}

.mantra__lines {
  display: grid;
  gap: 0.02em;
  font-size: clamp(2.7rem, 0.9rem + 8vw, 9rem);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.05em;
}
.mantra__line {
  --lp: clamp(0, calc(var(--p) * 3.3 - var(--i) * 1.05), 1);
  display: block;
  background: linear-gradient(100deg, var(--violet), var(--azure) 50%, var(--cyan)) 0 0 /
      calc(var(--lp) * 100%) 100% no-repeat,
    linear-gradient(var(--line-strong), var(--line-strong));
  background-clip: text;
  -webkit-background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  transform: translate3d(0, calc((1 - var(--lp)) * 22px), 0);
  padding-bottom: 0.06em;
}
/* The serif word inherits the clip — it must not paint a colour of its own. */
.mantra__line .serif {
  font-weight: 400;
  -webkit-text-fill-color: transparent;
}

.mantra__note {
  --np: clamp(0, calc(var(--p) * 4 - 3), 1);
  max-width: 34ch;
  font-size: var(--t-xl);
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: -0.02em;
  color: var(--text-2);
  opacity: var(--np);
  transform: translate3d(0, calc((1 - var(--np)) * 18px), 0);
}

.mantra__after {
  display: grid;
  gap: clamp(2rem, 1.4rem + 2vw, 3.5rem);
  padding-block: clamp(1rem, 0.5rem + 2vw, 3rem) var(--section-y);
}
.mantra__lead {
  font-family: var(--font-display);
  font-size: var(--t-2xl);
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: -0.03em;
  max-width: 30ch;
}
.mantra__steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));
  gap: 0;
  border-top: 1px solid var(--line);
}
.mantra__steps > div {
  display: grid;
  gap: 0.4rem;
  padding: 1.4rem 1.4rem 0 0;
}
.mantra__steps span {
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.18em;
  color: var(--accent);
}
.mantra__steps b {
  font-family: var(--font-display);
  font-size: var(--t-lg);
  font-weight: 500;
}
.mantra__steps p {
  color: var(--text-2);
  font-size: var(--t-sm);
}
.mantra__close {
  font-family: var(--font-display);
  font-size: var(--t-3xl);
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: -0.04em;
  max-width: 22ch;
}

/* No JS or reduced motion: fully filled, not pinned. */
html.no-js .mantra__track,
.mantra.is-static .mantra__track {
  height: auto;
}
html.no-js .mantra__stage,
.mantra.is-static .mantra__stage {
  position: relative;
  height: auto;
  padding-block: var(--section-y) var(--sp-7);
  --p: 1;
}
@media (prefers-reduced-motion: reduce) {
  .mantra__track {
    height: auto;
  }
  .mantra__stage {
    position: relative;
    height: auto;
    padding-block: var(--section-y) var(--sp-7);
    --p: 1;
  }
}

/* ===================================================================== about */
/* The statement lights up word by word as it crosses the viewport. js/
   scroll-scenes.js splits it into .w spans carrying --i, and writes --p on the
   paragraph; a word is fully lit once p·n has passed its index. Without JS the
   words are never split, so the sentence is simply there at full strength. */
.about__statement {
  margin-top: var(--sp-5);
  font-family: var(--font-display);
  font-size: clamp(2rem, 0.9rem + 3.6vw, 4.4rem);
  font-weight: 500;
  line-height: 1.08;
  letter-spacing: -0.04em;
  max-width: 24ch;
  --p: 0;
}
.about__statement .w {
  opacity: clamp(0.14, calc(var(--p) * var(--n) - var(--i)), 1);
  transition: opacity 180ms linear;
}
.about__statement .serif {
  font-weight: 400;
}

.about__grid {
  display: grid;
  gap: clamp(1.4rem, 1rem + 2vw, 3rem);
  margin-top: clamp(2.5rem, 1.6rem + 3vw, 4.5rem);
  padding-top: clamp(2rem, 1.4rem + 2vw, 3rem);
  border-top: 1px solid var(--line);
}
@media (min-width: 900px) {
  .about__grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: start;
  }
}

.about__goal {
  display: grid;
  gap: 0.9rem;
  margin: 0;
}
.about__goal p {
  font-family: var(--font-display);
  font-size: var(--t-2xl);
  font-weight: 500;
  line-height: 1.15;
  letter-spacing: -0.03em;
}

.about__text {
  display: grid;
  gap: var(--sp-5);
}
.about__text > p {
  font-size: var(--t-lg);
  color: var(--text-2);
}

.today {
  display: grid;
  gap: 0.5rem;
  padding: 1.2rem 1.3rem;
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: color-mix(in oklab, var(--surface-2) 70%, transparent);
}
.today__tag {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--font-mono);
  font-size: 0.64rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}
.today__tag .badge__dot {
  margin-left: 0;
}
.today p {
  font-size: var(--t-base);
}
.today a {
  color: var(--accent);
  border-bottom: 1px solid var(--accent-line);
  transition: border-color var(--dur-fast) var(--ease-out);
}
.today a:hover {
  border-color: var(--accent);
}

/* =================================================================== contact
   The closing headline is larger than a section title: it is the last thing
   the page says. */
.contact__title {
  margin-top: 1rem;
  font-size: var(--t-4xl);
  font-weight: 600;
  line-height: 0.98;
  letter-spacing: -0.045em;
}

/* ==================================================================== footer */
.footer__line {
  margin-top: 1rem;
  font-family: var(--font-display);
  font-size: var(--t-lg);
  font-weight: 500;
  letter-spacing: -0.01em;
}

/* =================================================================== contact */
.contact {
  position: relative;
  border-radius: var(--r-xl);
  border: 1px solid var(--glass-line);
  background: linear-gradient(150deg, var(--surface-2), var(--surface));
  padding: clamp(1.6rem, 1rem + 3vw, 4rem);
  overflow: hidden;
  box-shadow: var(--shadow-lg);
}
.contact__grid {
  display: grid;
  gap: clamp(2rem, 1rem + 3vw, 4rem);
  position: relative;
}
@media (min-width: 880px) {
  .contact__grid {
    grid-template-columns: 1fr 1fr;
  }
}
.contact__form {
  display: grid;
  gap: var(--sp-4);
}
.contact__row {
  display: grid;
  gap: var(--sp-4);
}
@media (min-width: 520px) {
  .contact__row {
    grid-template-columns: 1fr 1fr;
  }
}

.contact__direct {
  display: grid;
  gap: 0.9rem;
  margin-top: var(--sp-5);
}
.contact__direct a {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  padding: 0.9rem 1.1rem;
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--surface-2);
  font-size: var(--t-sm);
  transition: border-color var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out),
    background-color var(--dur-fast) var(--ease-out);
}
.contact__direct a:hover {
  border-color: var(--accent-line);
  transform: translateX(4px);
}
.contact__direct svg {
  width: 18px;
  height: 18px;
  color: var(--accent);
  flex-shrink: 0;
}
.contact__direct span {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  color: var(--faint);
}

.form__note {
  font-size: var(--t-xs);
  color: var(--faint);
}
.form__status {
  font-size: var(--t-xs);
  padding: 0.7rem 1rem;
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--surface-2);
  transition: all var(--dur) var(--ease-out);
}
.form__status--ok {
  color: #34d399;
  border-color: rgba(52, 211, 153, 0.25);
  background: rgba(52, 211, 153, 0.06);
}
.form__status--err {
  color: #f87171;
  border-color: rgba(248, 113, 113, 0.25);
  background: rgba(248, 113, 113, 0.06);
}
@keyframes spin {
  to { transform: rotate(360deg); }
}

/* ====================================================================== FAQ */
.faq {
  display: grid;
  gap: clamp(2rem, 1rem + 3vw, 4rem);
}
@media (min-width: 900px) {
  .faq {
    grid-template-columns: 0.8fr 1.2fr;
    align-items: start;
  }
}

/* ================================================================== noscript */
.noscript {
  position: relative;
  z-index: var(--z-content);
  margin: var(--sp-5) auto;
  max-width: var(--maxw);
  padding: var(--sp-4) var(--sp-5);
  border-radius: var(--r-md);
  border: 1px solid var(--line-strong);
  background: var(--surface-2);
  font-size: var(--t-sm);
  color: var(--text-2);
}
