/* =============================================================================
   RAYASA — Page sections
   Composition and one-off layout for the landing page and inner pages.
   ========================================================================== */

/* -----------------------------------------------------------------------------
   Ambient background: a faint engineering grid plus two colour washes. Fixed so
   it reads as depth behind the page rather than as a texture that scrolls with
   it. `pointer-events: none` keeps it out of the way of everything.
   -------------------------------------------------------------------------- */
.backdrop {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    radial-gradient(60rem 40rem at 78% -10%, rgb(0 83 154 / 22%), transparent 60%),
    radial-gradient(45rem 35rem at 8% 12%, rgb(34 211 238 / 8%), transparent 62%);
}

.grid-lines {
  position: absolute;
  inset: 0;
  background-size: 34px 34px;
  background-image:
    linear-gradient(to right, rgb(30 133 230 / 4%) 1px, transparent 1px),
    linear-gradient(to bottom, rgb(30 133 230 / 4%) 1px, transparent 1px);
  mask-image: radial-gradient(ellipse 90% 60% at 50% 40%, #000 30%, transparent 100%);
  -webkit-mask-image: radial-gradient(ellipse 90% 60% at 50% 40%, #000 30%, transparent 100%);
}

.page {
  position: relative;
  z-index: 1;
}

/* -----------------------------------------------------------------------------
   Hero
   -------------------------------------------------------------------------- */
.hero {
  position: relative;
  display: flex;
  align-items: center;
  min-block-size: min(46rem, 100svh);
  padding-block: calc(var(--header-h) + var(--space-12)) var(--space-16);
  overflow: hidden;
}

.hero__media {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.hero__video {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  opacity: 0.42;
  transition: opacity 1.2s var(--ease-out);
}

/* Once the clip has played its useful stretch the JS parks it and drops it back
   so the copy on top keeps its contrast. */
.hero__video.is-parked {
  opacity: 0.2;
}

.hero__scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to top, var(--bg) 4%, rgb(4 6 10 / 72%) 45%, rgb(4 6 10 / 35%) 100%),
    radial-gradient(ellipse at 50% 45%, rgb(1 32 60 / 30%), transparent 70%);
}

.hero__inner {
  position: relative;
  z-index: 1;
  display: grid;
  gap: var(--space-12);
  align-items: center;
}

/* Grid children refuse to shrink below their min-content width by default, and
   the terminal's unbreakable command strings are wide. */
.hero__inner > * {
  min-inline-size: 0;
}

@media (min-width: 64rem) {
  .hero__inner {
    grid-template-columns: 1fr 1fr;
    gap: var(--space-16);
  }
}

.hero__copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-6);
}

.hero h1 {
  font-size: var(--text-5xl);
  font-weight: 900;
  letter-spacing: -0.015em;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  padding-block-start: var(--space-2);
}

/* Proof strip under the fold-line. */
.proof {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-4) var(--space-8);
  inline-size: 100%;
  margin-block-start: var(--space-6);
  padding-block-start: var(--space-6);
  border-block-start: 1px solid var(--line);
}

@media (min-width: 30rem) {
  .proof {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.proof__value {
  display: block;
  font-size: var(--text-2xl);
  font-weight: 900;
  color: var(--text);
  line-height: 1.15;
  font-variant-numeric: tabular-nums;
}

.proof__label {
  display: block;
  font-size: var(--text-2xs);
  color: var(--text-muted);
  line-height: 1.5;
}

/* -----------------------------------------------------------------------------
   Floating agent launcher

   Bottom-left on this RTL page — the inline-end corner, which is where a
   floating assistant is expected to live in either direction.

   It stays out of the way until the hero has scrolled past: a fixed widget of
   this size sitting over the hero would cover either the terminal or the proof
   figures at common laptop widths, and the hero already has a call to action.
   The hidden state is scoped to `.js` so a scriptless visitor still gets the
   button.
   -------------------------------------------------------------------------- */
.agent-launcher {
  position: fixed;
  inset-block-end: var(--space-6);
  inset-inline-end: var(--space-6);
  z-index: 55;
  transition:
    opacity var(--dur-slow) var(--ease-out),
    transform var(--dur-slow) var(--ease-out),
    visibility var(--dur-slow) var(--ease-out);
}

.js .agent-launcher:not(.is-ready) {
  opacity: 0;
  visibility: hidden;
  transform: translateY(1.5rem);
  pointer-events: none;
}

@media (max-width: 47.99rem) {
  .agent-launcher {
    inset-block-end: var(--space-4);
    inset-inline-end: var(--space-4);
  }
}

.agent-launcher__btn {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  inline-size: 4.75rem;
  block-size: 10.5rem;
  padding: var(--space-2);
  background: var(--surface-glass);
  border: 1px solid var(--line-brand);
  border-radius: var(--r-xl);
  overflow: hidden;
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow: var(--shadow-md);
  transition:
    border-color var(--dur-base) var(--ease-out),
    box-shadow var(--dur-base) var(--ease-out),
    transform var(--dur-base) var(--ease-out);
}

@media (max-width: 47.99rem) {
  .agent-launcher__btn {
    inline-size: 3.75rem;
    block-size: 8rem;
  }
}

.agent-launcher__btn:hover,
.agent-launcher__btn:focus-visible {
  border-color: var(--line-accent);
  box-shadow: var(--shadow-md), var(--glow-accent);
  transform: translateY(-4px);
}

.agent-launcher__meta {
  inline-size: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-inline: var(--space-1);
  font-family: var(--font-mono);
  font-size: 0.5rem;
  color: var(--text-dim);
  direction: ltr;
  unicode-bidi: isolate;
  transition: color var(--dur-base) var(--ease-out);
}

.agent-launcher__btn:hover .agent-launcher__meta {
  color: var(--accent-400);
}

.agent-launcher__dot {
  inline-size: 0.3125rem;
  block-size: 0.3125rem;
  border-radius: var(--r-full);
  background: var(--brand-400);
  box-shadow: 0 0 6px currentcolor;
  transition: background-color var(--dur-base) var(--ease-out);
}

.agent-launcher__btn:hover .agent-launcher__dot {
  background: var(--accent-400);
}

.agent-launcher__art {
  position: relative;
  inline-size: 100%;
  flex: 1;
  margin-block: var(--space-1);
}

.agent-launcher__art img {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  object-fit: contain;
  transition:
    opacity var(--dur-base) var(--ease-out),
    filter var(--dur-base) var(--ease-out);
}

.agent-launcher__art .is-active {
  opacity: 0;
}

.agent-launcher__btn:hover .agent-launcher__art .is-idle,
.agent-launcher__btn:focus-visible .agent-launcher__art .is-idle {
  opacity: 0;
}

.agent-launcher__btn:hover .agent-launcher__art .is-active,
.agent-launcher__btn:focus-visible .agent-launcher__art .is-active {
  opacity: 1;
  filter: drop-shadow(0 0 12px rgb(34 211 238 / 75%));
}

.agent-launcher__label {
  inline-size: 100%;
  padding-block-start: var(--space-1);
  border-block-start: 1px solid var(--line);
  text-align: center;
  font-size: 0.5625rem;
  font-weight: 800;
  color: var(--brand-300);
  transition: color var(--dur-base) var(--ease-out);
}

.agent-launcher__btn:hover .agent-launcher__label {
  color: var(--accent-300);
}

/* Scan line sweeping the housing. */
.agent-launcher__scan {
  position: absolute;
  inset-inline: 0;
  block-size: 45%;
  background: linear-gradient(to bottom, transparent, rgb(34 211 238 / 26%), transparent);
  opacity: 0;
  pointer-events: none;
}

.agent-launcher__btn:hover .agent-launcher__scan {
  animation: scan-sweep 2.2s var(--ease-in-out) infinite;
}

@keyframes scan-sweep {
  0% {
    inset-block-start: -50%;
    opacity: 0;
  }

  50% {
    opacity: 1;
  }

  100% {
    inset-block-start: 120%;
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .agent-launcher__btn:hover .agent-launcher__scan {
    animation: none;
  }
}

/* Hover flag. Hidden on touch, where there is no hover to reveal it. */
.agent-launcher__flag {
  position: absolute;
  inset-inline-start: calc(100% + var(--space-3));
  inset-block-start: 50%;
  display: none;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  background: var(--surface-glass);
  border: 1px solid var(--line-accent);
  border-radius: var(--r-md);
  white-space: nowrap;
  font-family: var(--font-mono);
  font-size: 0.5625rem;
  font-weight: 700;
  color: var(--accent-300);
  direction: ltr;
  unicode-bidi: isolate;
  opacity: 0;
  transform: translateY(-50%) translateX(-0.4rem);
  transition:
    opacity var(--dur-base) var(--ease-out),
    transform var(--dur-base) var(--ease-out);
  pointer-events: none;
}

@media (hover: hover) and (min-width: 48rem) {
  .agent-launcher__flag {
    display: flex;
  }

  .agent-launcher:hover .agent-launcher__flag,
  .agent-launcher:focus-within .agent-launcher__flag {
    opacity: 1;
    transform: translateY(-50%);
  }
}

/* -----------------------------------------------------------------------------
   Bento grid — engineering pillars
   -------------------------------------------------------------------------- */
.bento {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: 1fr;
}

@media (min-width: 48rem) {
  .bento {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .bento__item--wide {
    grid-column: span 2;
  }
}

/* -----------------------------------------------------------------------------
   Products

   Two columns rather than four: each card carries a description and a list of
   capabilities, and four across squeezes both into slivers on anything short of
   a very wide screen.
   -------------------------------------------------------------------------- */
.product-grid {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: 1fr;
}

@media (min-width: 48rem) {
  .product-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* -----------------------------------------------------------------------------
   Architecture simulator
   -------------------------------------------------------------------------- */
.sim {
  position: relative;
  padding: var(--space-6);
  background: rgb(7 11 19 / 92%);
  border: 1px solid var(--line-brand);
  border-radius: var(--r-3xl);
  overflow: hidden;
  box-shadow: 0 0 70px -30px rgb(0 105 196 / 60%);
}

@media (min-width: 48rem) {
  .sim {
    padding: var(--space-10);
  }
}

.sim__head {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  padding-block-end: var(--space-8);
  margin-block-end: var(--space-8);
  border-block-end: 1px solid var(--line);
}

@media (min-width: 64rem) {
  .sim__head {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-10);
  }
}

.sim__stage {
  position: relative;
  z-index: 1;
  padding: var(--space-4);
  background: rgb(0 0 0 / 45%);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  overflow: hidden;
}

@media (min-width: 40rem) {
  .sim__stage {
    padding: var(--space-6);
  }
}

/* The topology drawing scrolls sideways on narrow screens instead of shrinking
   its labels into illegibility. */
.sim__canvas {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  min-inline-size: 0;
}

/* Latin labels inside the topology must not be reordered by the RTL page. */
.sim__canvas svg {
  direction: ltr;
  inline-size: 100%;
  min-inline-size: 44rem;
  block-size: auto;
}

.sim__node rect,
.sim__node circle {
  transition: stroke var(--dur-slow) var(--ease-out), fill var(--dur-slow) var(--ease-out);
}

.sim__node text {
  font-family: var(--font-sans);
}

.sim__node .sim__node-sub {
  font-family: var(--font-mono);
}

/* Packets travelling the wires. Pure SVG/CSS: no per-frame JS. */
.sim__packet {
  animation: packet-travel 2.6s linear infinite;
}

@keyframes packet-travel {
  from {
    stroke-dashoffset: 44;
  }

  to {
    stroke-dashoffset: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .sim__packet {
    animation: none;
  }
}

.sim__metrics {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: var(--space-4);
  margin-block-start: var(--space-6);
  padding-block-start: var(--space-6);
  border-block-start: 1px solid var(--line);
}

.sim__note {
  margin-block-start: var(--space-4);
  font-size: var(--text-2xs);
  color: var(--text-dim);
}

/* -----------------------------------------------------------------------------
   Process
   -------------------------------------------------------------------------- */
.process {
  display: grid;
  gap: var(--space-5);
  counter-reset: step;
}

@media (min-width: 48rem) {
  .process {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 72rem) {
  .process {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.process__step {
  position: relative;
  padding: var(--space-6);
  background: var(--surface-1);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  counter-increment: step;
  transition: border-color var(--dur-base) var(--ease-out);
}

.process__step:hover {
  border-color: var(--line-brand);
}

.process__step::before {
  content: '0' counter(step);
  display: block;
  margin-block-end: var(--space-4);
  font-family: var(--font-mono);
  font-size: var(--text-2xl);
  font-weight: 700;
  color: var(--brand-600);
  direction: ltr;
}

.process__step h3 {
  font-size: var(--text-base);
  margin-block-end: var(--space-2);
}

.process__step p {
  font-size: var(--text-xs);
  color: var(--text-muted);
}

/* -----------------------------------------------------------------------------
   Value cards
   -------------------------------------------------------------------------- */
.value-grid {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
}

/* -----------------------------------------------------------------------------
   Stack
   -------------------------------------------------------------------------- */
.stack-groups {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
}

.stack-group {
  padding: var(--space-6);
  background: var(--surface-1);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
}

.stack-group h3 {
  font-size: var(--text-sm);
  color: var(--brand-300);
  letter-spacing: var(--tracking-wide);
  margin-block-end: var(--space-4);
}

.stack-group ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

/* -----------------------------------------------------------------------------
   Contact
   -------------------------------------------------------------------------- */
.contact {
  display: grid;
  gap: var(--space-10);
  align-items: start;
}

.contact > * {
  min-inline-size: 0;
}

@media (min-width: 64rem) {
  .contact {
    grid-template-columns: 0.85fr 1.15fr;
    gap: var(--space-16);
  }
}

@media (min-width: 40rem) {
  .contact__row {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-5);
  }
}

.contact__status {
  display: none;
  padding: var(--space-4);
  border-radius: var(--r-md);
  font-size: var(--text-xs);
  line-height: var(--leading-normal);
}

.contact__status.is-shown {
  display: block;
}

.contact__status--ok {
  background: rgb(52 211 153 / 10%);
  border: 1px solid rgb(52 211 153 / 32%);
  color: var(--ok-400);
}

.contact__status--error {
  background: rgb(248 113 113 / 10%);
  border: 1px solid rgb(248 113 113 / 32%);
  color: var(--danger-400);
}

.contact__channels {
  display: grid;
  gap: var(--space-4);
}

.channel {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  padding: var(--space-5);
  background: var(--surface-1);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  transition: border-color var(--dur-base) var(--ease-out);
}

.channel:hover {
  border-color: var(--line-brand);
}

.channel__label {
  display: block;
  font-size: var(--text-2xs);
  color: var(--text-dim);
}

.channel__value {
  display: block;
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--text);
}

/* -----------------------------------------------------------------------------
   FAQ — <details> so it works without a line of JavaScript.
   -------------------------------------------------------------------------- */
.faq {
  display: grid;
  gap: var(--space-3);
  max-inline-size: 52rem;
}

.faq__item {
  background: var(--surface-1);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  overflow: hidden;
  transition: border-color var(--dur-base) var(--ease-out);
}

.faq__item[open] {
  border-color: var(--line-brand);
}

.faq__item summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-5) var(--space-6);
  cursor: pointer;
  list-style: none;
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--text);
}

.faq__item summary::-webkit-details-marker {
  display: none;
}

.faq__sign {
  flex: none;
  inline-size: 1.5rem;
  block-size: 1.5rem;
  display: grid;
  place-items: center;
  border-radius: var(--r-full);
  border: 1px solid var(--line-strong);
  color: var(--brand-300);
  font-family: var(--font-mono);
  line-height: 1;
  transition: transform var(--dur-base) var(--ease-out);
}

.faq__item[open] .faq__sign {
  transform: rotate(45deg);
}

.faq__answer {
  padding: 0 var(--space-6) var(--space-6);
  font-size: var(--text-sm);
  color: var(--text-muted);
}

/* -----------------------------------------------------------------------------
   Closing CTA
   -------------------------------------------------------------------------- */
.cta {
  position: relative;
  padding: var(--space-12) var(--space-6);
  text-align: center;
  background:
    linear-gradient(120deg, rgb(1 32 60 / 55%), rgb(7 11 19 / 90%) 45%, rgb(1 32 60 / 55%));
  border: 1px solid var(--line-accent);
  border-radius: var(--r-3xl);
  overflow: hidden;
  box-shadow: 0 0 90px -40px rgb(34 211 238 / 45%);
}

@media (min-width: 48rem) {
  .cta {
    padding: var(--space-16) var(--space-12);
  }
}

.cta__inner {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-5);
  max-inline-size: 44rem;
  margin-inline: auto;
}

.cta__inner .lede {
  text-align: center;
}

/* -----------------------------------------------------------------------------
   Footer
   -------------------------------------------------------------------------- */

/* No top margin: the last section already ends on a full --section-gap of
   padding, and stacking a second one leaves a visible hole above the footer. */
.site-footer {
  position: relative;
  padding-block: var(--space-16) var(--space-10);
  background: var(--bg);
  border-block-start: 1px solid var(--line-brand);
  overflow: hidden;
}

.site-footer__ghost {
  position: absolute;
  inset-block-start: 55%;
  inset-inline: 0;
  text-align: center;
  font-family: var(--font-mono);
  font-size: 17vw;
  font-weight: 800;
  letter-spacing: var(--tracking-wider);
  color: var(--brand-600);
  opacity: 0.045;
  line-height: 1;
  transform: translateY(-50%);
  pointer-events: none;
  user-select: none;
  direction: ltr;
}

.site-footer__inner {
  position: relative;
  z-index: 1;
  display: grid;
  gap: var(--space-12);
}

.status-bar {
  display: grid;
  gap: var(--space-6);
  align-items: center;
  padding: var(--space-6);
  background: var(--surface-1);
  border: 1px solid var(--line);
  border-radius: var(--r-2xl);
}

@media (min-width: 64rem) {
  .status-bar {
    grid-template-columns: 1fr 1fr;
    gap: var(--space-10);
    padding: var(--space-6) var(--space-8);
  }
}

.newsletter {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

@media (min-width: 30rem) {
  .newsletter {
    flex-direction: row;

    /*
      Standing room for the validation message, kept whether or not there is
      one. The error lives inside .field, so on a single row its arrival grew
      the field, and the button — a flex item stretching to the tallest sibling
      — grew with it from one line to two. Reserving the space costs a little
      air under the form and buys a layout that never moves.

      Enough for one line, which every message here is. A wrapped one spills
      into the footer's own gap rather than pushing anything — the button, in
      particular, never changes size again.
    */
    padding-block-end: var(--space-7);
  }

  .newsletter .input {
    flex: 1;
  }

  .newsletter .field {
    position: relative;
  }

  .newsletter .field__error {
    position: absolute;
    inset-block-start: calc(100% + var(--space-1));
    inset-inline: 0;
  }

  /*
    Wide enough for "در حال ارسال…", the label the button wears while the
    request is in flight. Sized for its widest state so it has only one size:
    the input beside it is flex:1, so a button that grows mid-submit drags the
    field narrower and the whole row lurches at the exact moment the visitor is
    waiting to see whether anything worked.
  */
  .newsletter .btn {
    min-inline-size: 8.5rem;
  }
}

.footer-cols {
  display: grid;
  gap: var(--space-10);
  grid-template-columns: 1fr;
}

@media (min-width: 40rem) {
  .footer-cols {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 64rem) {
  .footer-cols {
    grid-template-columns: 1.6fr 1fr 1fr 1.2fr;
    gap: var(--space-12);
  }
}

.footer-col h2 {
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--brand-300);
  letter-spacing: var(--tracking-wide);
  margin-block-end: var(--space-4);
}

/* Scoped to its own class: a bare `.footer-col ul` also caught the chip rows,
   overriding .cluster's flex layout and reinstating list markers. */
.footer-list {
  display: grid;
  gap: var(--space-3);
  font-size: var(--text-xs);
  color: var(--text-muted);
}

.footer-col a {
  transition: color var(--dur-base) var(--ease-out);
}

.footer-col a:hover {
  color: var(--accent-300);
}

.footer-legal {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding-block-start: var(--space-8);
  border-block-start: 1px solid var(--line);
  font-size: var(--text-xs);
  color: var(--text-dim);
}

@media (min-width: 56rem) {
  .footer-legal {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }
}

.footer-legal__links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
  color: var(--text-muted);
}

/* -----------------------------------------------------------------------------
   Inner pages (legal, 404)
   -------------------------------------------------------------------------- */
.prose {
  max-inline-size: 46rem;
  font-size: var(--text-sm);
  color: var(--text-muted);
}

.prose h2 {
  font-size: var(--text-xl);
  margin-block: var(--space-10) var(--space-4);
}

.prose h2:first-child {
  margin-block-start: 0;
}

.prose p + p,
.prose ul {
  margin-block-start: var(--space-4);
}

.prose ul {
  padding-inline-start: var(--space-5);
  display: grid;
  gap: var(--space-2);
}

.prose li::marker {
  color: var(--brand-400);
}

.prose a {
  color: var(--accent-300);
  text-decoration: underline;
  text-underline-offset: 0.25em;
}

.page-hero {
  padding-block: calc(var(--header-h) + var(--space-16)) var(--space-10);
}

.error-page {
  display: grid;
  place-items: center;
  min-block-size: 100svh;
  text-align: center;
  padding: calc(var(--header-h) + var(--space-12)) var(--shell-pad) var(--space-16);
}

.error-page__code {
  font-family: var(--font-mono);
  font-size: clamp(5rem, 18vw, 11rem);
  font-weight: 800;
  line-height: 1;
  color: transparent;
  background: linear-gradient(180deg, var(--brand-400), transparent 92%);
  -webkit-background-clip: text;
  background-clip: text;
  direction: ltr;
}

/* -----------------------------------------------------------------------------
   About — the film opens the page, then the page carries on

   This used to be a single screen composed like a business card, on the
   argument that the site already says what Rayasa builds at length. That
   argument was half right: the card said who it is, and then stopped before
   saying anything a prospective client could weigh. The reveal is still the
   arrival — it is the one moment on the site that is purely brand — but it now
   opens a page with sections under it rather than being the whole of it.

   What survived the change, because it was never about the card: the film is
   shown at its own size and never above it, it is masked into the page rather
   than framed, and every beat of the arrival degrades to the finished mark.
   -------------------------------------------------------------------------- */
.aboutpage {
  /*
    The glow behind the film is deliberately wider than the film, so on a narrow
    screen it reaches past the viewport and gives the page a sideways scroll of
    thirty-odd pixels. `clip` rather than `hidden`: it trims the bleed without
    turning this into a scroll container. The gradient is soft enough at the rim
    that the cut is invisible.
  */
  overflow-x: clip;
}

/* -----------------------------------------------------------------------------
   The opening screen
   -------------------------------------------------------------------------- */
/*
  The spacing here is a budget, not a preference.

  Every rem this block spends on padding, gaps and copy is a rem the film does
  not get, because the film is sized from the height that is left over. The
  first version spent 568px of a 900px window on everything-but-the-film and
  left the reveal at 590px wide — a third of the viewport for the one thing on
  the page that is meant to be looked at. Trimming the padding, closing the gaps
  by one step and dropping a redundant eyebrow bought 126px, and every one of
  those pixels went into the film's width at 16/9.

  So: before loosening anything below, look at what it costs the film.
*/
.aboutpage__intro {
  display: grid;
  justify-items: center;
  align-content: center;
  gap: var(--space-4);
  min-block-size: 100dvh;
  text-align: center;

  /* `.site-header` is fixed, so nothing below it reserves its space by itself. */
  padding-block: calc(var(--header-h) + var(--space-6)) var(--space-8);
}

.aboutpage__intro > * {
  inline-size: 100%;
}

/* -----------------------------------------------------------------------------
   The film

   Shown at its own size and never above it. The footage is 1280×720, and
   blowing that up is what made an earlier version both soft and jerky: past
   1:1 the compositor resamples every frame, and 720p stretched across a desktop
   looks exactly as cheap as it is. Downscaling costs nothing and stays sharp.
   -------------------------------------------------------------------------- */
.brandfilm {
  position: relative;
  display: grid;
  margin: 0 auto;

  /*
    80rem is the footage's own 1280px, so the film is never enlarged — and the
    `.shell` this sits in caps it below that anyway. Under both, the height left
    over governs, because a 16:9 film sized only to its column is the one
    element tall enough to push the name and the actions off a laptop screen,
    which is exactly where they must not be on an opening screen.

    The 27.5rem is everything else in this block — header clearance, the name,
    the role, the lead, the buttons, the continue link, the gaps and the padding
    below. It is measured in a browser rather than added up from the tokens: an
    early attempt summed the scales to 33rem and left the opening block 38px
    taller than the window, because a line of Persian at the loose leading this
    site uses is not the height its font-size suggests.

    It was 35.5rem until the film was judged too small at it, which is the
    number to watch: this term is subtraction, so every rem of padding or copy
    the block above spends comes straight out of the film's width at 16/9.
    Buying 8rem back — tighter padding, gaps closed one step, a redundant
    eyebrow removed — took the reveal from 590px to 818px on a 1440×900 laptop,
    roughly double the area, without moving the buttons below the fold.
    Measured at 1920×1080, 1440×900, 1366×768 and 1280×720: the opening block
    lands within 7px of the viewport in all four.

    The 32rem floor stops a short window shrinking the film to a thumbnail.
    Below roughly 720px of viewport height it wins and the block runs a few
    dozen pixels past the fold, which is the right way round — the film is why
    anyone is on this screen, and the continue link already says the page goes
    on. Narrower than about 1000px the column governs first, and on a phone it
    is the only thing that does.
  */
  inline-size: min(80rem, 100%, max(32rem, calc((100dvh - 27.5rem) * 16 / 9)));
}

/*
  The pool of light the mark sits in. Sized larger than the film and blurred, so
  what reads is a glow behind the footage rather than a lit rectangle — the
  difference between something resting on the page and something pasted onto it.
*/
.brandfilm::before {
  content: '';
  position: absolute;
  inset: -14% -10%;
  z-index: 0;
  background:
    radial-gradient(closest-side, rgb(0 83 154 / 30%), transparent 72%),
    radial-gradient(closest-side, rgb(30 133 230 / 14%), transparent 55%);
  filter: blur(34px);
  pointer-events: none;
}

.brandfilm__frame {
  position: relative;
  z-index: 1;
  aspect-ratio: 16 / 9;
}

/*
  No border, no radius, no card, and no overlay: the footage is dissolved into
  the page by a mask, so the mark simply appears rather than being shown inside
  something.

  The stops are arithmetic, not taste. Radial-gradient radii are fractions of
  the box, so with a radius of 0.72 the box's own edge sits at 0.5/0.72 = 69%
  along the gradient and its corners at 98% — meaning a transparent stop at 69%
  is the point where the mask is guaranteed to have finished before the video
  runs out. An earlier version faded from 48% to 88% of a 0.74 radius, which put
  the box edge at 68% of a gradient that was still half opaque there: a rim of
  rgb(29,29,29) against a rgb(4,6,10) page, which is exactly the visible border
  it was supposed to prevent.

  The opaque stop is set from the mark, so it moves when the mark does. The
  current reveal settles at ±33% of the frame height, or 33/72 = 46% along this
  gradient; 48% clears it with margin. It was 42% for the previous footage,
  whose mark only reached ±26% — leaving it there would have cut the new mark's
  lower edge into the fade.
*/
.brandfilm__video {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  mask-image: radial-gradient(ellipse 72% 72% at 50% 50%, #000 48%, transparent 69%);
  -webkit-mask-image: radial-gradient(ellipse 72% 72% at 50% 50%, #000 48%, transparent 69%);
}

/* -----------------------------------------------------------------------------
   Identity
   -------------------------------------------------------------------------- */
.aboutpage__id {
  display: grid;
  gap: var(--space-3);
}

.aboutpage__name {
  margin: 0;
  font-size: var(--text-4xl);
  font-weight: 900;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--text);
}

.aboutpage__role {
  margin: 0;
  font-size: var(--text-sm);
  letter-spacing: var(--tracking-wide);
  color: var(--brand-300);
}

.aboutpage__lead {
  /* Its own measure: a line of prose does not want the film's width. */
  max-inline-size: 40rem;
  margin: 0 auto;
  font-size: var(--text-base);
  line-height: var(--leading-loose);
  color: var(--text-muted);
  text-wrap: balance;
}

.aboutpage__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  justify-content: center;
}

/*
  The continue link.

  An opening screen that fills the window with a film has one failure mode: the
  visitor does not know there is anything under it. This is an ordinary anchor
  to the first section, so it works with the script gone and lands on a real id
  rather than scrolling by hand.
*/
.aboutpage__more {
  display: grid;
  justify-items: center;
  gap: var(--space-1);
  font-size: var(--text-2xs);
  letter-spacing: var(--tracking-wider);
  color: var(--text-dim);
  text-decoration: none;
  transition: color var(--dur-base) var(--ease-out);
}

.aboutpage__more:hover {
  color: var(--text-soft);
}

.aboutpage__more-rule {
  inline-size: 1px;
  block-size: var(--space-5);
  background: linear-gradient(180deg, var(--line-strong), transparent);
}

/* The step number on a principle card — decoration, so it is hidden from AT. */
.aboutpage__index {
  margin: 0 0 var(--space-4);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wider);
  color: var(--brand-400);
}

/* -----------------------------------------------------------------------------
   Contact facts
   -------------------------------------------------------------------------- */
.aboutpage__facts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-8);
  justify-content: center;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--text-sm);
}

.aboutpage__facts a {
  color: var(--text-soft);
  text-decoration: none;
  border-block-end: 1px solid var(--line-strong);
  padding-block-end: 2px;
  transition:
    color var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out);
}

.aboutpage__facts a:hover {
  color: var(--text);
  border-color: var(--brand-400);
}

.aboutpage__facts span {
  color: var(--text-dim);
}

/* -----------------------------------------------------------------------------
   Arrival

   Three beats, in order: the film alone in the middle of the window, then the
   film rising to its place, then the page resolving around it. Each waits for
   the one before rather than overlapping, so the page assembles instead of
   fading in all at once.

   The film is only ever *translated* — never scaled, never masked mid-flight.
   A transform that moves is one composited property; a transform that resizes
   makes the compositor resample every frame of the video underneath it, which
   is what made an earlier fullscreen version stutter.

   `[data-intro]` is set by the blocking guard, and the guard ships on the about
   page only — which is what makes it safe for the selectors below to name the
   site header and footer without scoping them to this page some other way.

   Every state below is set by the script. Without it the page is just the page.
   -------------------------------------------------------------------------- */

/*
  Beat zero: nothing. Set by the blocking guard before the first paint, so the
  page never shows its own ending while it waits for the sequence to start. The
  header, the sections and the footer are held too — an opening beat that leaves
  a navigation bar and a copyright line on screen is not an opening beat.
*/
[data-intro='pending'] .brandfilm,
[data-intro='pending'] .aboutpage__intro > *,
[data-intro='pending'] .site-header,
[data-intro='pending'] .aboutpage > .section,
[data-intro='pending'] .site-footer {
  opacity: 0;
}

/* Beat one: the film is centred by an inline transform the script measures. */
[data-intro='solo'] .aboutpage__intro > *:not(.brandfilm),
[data-intro='rising'] .aboutpage__intro > *:not(.brandfilm),
[data-intro='solo'] .site-header,
[data-intro='rising'] .site-header,
[data-intro='solo'] .aboutpage > .section,
[data-intro='rising'] .aboutpage > .section,
[data-intro='solo'] .site-footer,
[data-intro='rising'] .site-footer {
  opacity: 0;
  transform: translateY(0.75rem);
}

[data-intro='solo'] .brandfilm,
[data-intro='rising'] .brandfilm {
  /* Promoted for the move only, so the layer is not held for the page's life. */
  will-change: transform;
}

/* The film arrives on a fade rather than appearing between two frames. */
[data-intro='solo'] .brandfilm {
  opacity: 1;
  transition: opacity 600ms var(--ease-out);
}

/* Beat two: clearing the inline transform is what animates it home. */
[data-intro='rising'] .brandfilm {
  transition: transform 900ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* Beat three. */
[data-intro='done'] .aboutpage__intro > *:not(.brandfilm),
[data-intro='done'] .site-header,
[data-intro='done'] .aboutpage > .section,
[data-intro='done'] .site-footer {
  opacity: 1;
  transform: none;
  transition:
    opacity 700ms var(--ease-out),
    transform 700ms var(--ease-out);
}

[data-intro='done'] .aboutpage__intro > *:nth-child(2) { transition-delay: 40ms; }
[data-intro='done'] .aboutpage__intro > *:nth-child(3) { transition-delay: 100ms; }
[data-intro='done'] .aboutpage__intro > *:nth-child(4) { transition-delay: 150ms; }
[data-intro='done'] .aboutpage__intro > *:nth-child(5) { transition-delay: 200ms; }

/* Nothing scrolls while the film has the window to itself. */
[data-intro='solo'] { overflow: hidden; }

/* --- Skip ---------------------------------------------------------------- */

.film-skip {
  position: fixed;
  z-index: 60;
  inset-block-end: var(--space-8);
  inset-inline: 0;
  inline-size: fit-content;
  margin-inline: auto;
  padding: var(--space-2) var(--space-5);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-full);
  background: rgb(4 6 10 / 55%);
  backdrop-filter: blur(8px);
  font: inherit;
  font-size: var(--text-2xs);
  color: var(--text-soft);
  cursor: pointer;
  transition:
    color var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out);
}

.film-skip:hover {
  border-color: var(--brand-400);
  color: var(--text);
}

/*
  The sequence is decoration over content that is already there. A visitor who
  has asked for less movement gets the page, immediately, with nothing to skip.
*/
@media (prefers-reduced-motion: reduce) {
  [data-intro] .brandfilm,
  [data-intro] .aboutpage__intro > *:not(.brandfilm),
  [data-intro] .site-header,
  [data-intro] .aboutpage > .section,
  [data-intro] .site-footer {
    opacity: 1;
    transform: none;
    transition: none;
  }
}
