/* ---------------------------------------------------------------
   Adeia — base and components.

   Reads every value from tokens.css. The signatures live here: the
   gradient-clipped headline, the floating outlined frames, the sticky
   rail, and the bento grid.
   --------------------------------------------------------------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  /* Smooth by default, for anchor jumps and for anyone whose browser
     never runs motion.js. */
  scroll-behavior: smooth;
}

/* But not once the inertia loop is driving. The two compound: every
   scrollTo starts its own browser animation while rAF issues the next
   one, and the page runs away past its target. The class is added by
   motion.js only after it takes over. */
html.has-inertia {
  scroll-behavior: auto;
}

body {
  margin: 0;
  background: var(--black);
  color: var(--paper);
  font-family: var(--sans);
  font-size: var(--t-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

img,
svg,
canvas {
  display: block;
  max-width: 100%;
}

a {
  color: inherit;
}

:focus-visible {
  outline: 2px solid var(--warm);
  outline-offset: 3px;
  border-radius: 3px;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.wrap {
  width: 100%;
  max-width: 80rem;
  margin: 0 auto;
  padding-inline: var(--gutter);
}

/* ---------- type ---------- */

h1,
h2,
h3 {
  font-weight: 500;
  letter-spacing: var(--tracking-display);
  line-height: 1;
  margin: 0;
  text-wrap: balance;
}

.display {
  font-size: var(--t-display);
}
.h1 {
  font-size: var(--t-h1);
}
.h2 {
  font-size: var(--t-h2);
}
.h3 {
  font-size: var(--t-h3);
  letter-spacing: var(--tracking-tight);
  line-height: 1.25;
}

p {
  margin: 0;
}

.lede {
  font-size: clamp(1rem, 0.95rem + 0.45vw, 1.25rem);
  color: var(--muted);
  max-width: var(--measure);
  line-height: 1.6;
  letter-spacing: -0.005em;
}

.body {
  color: var(--muted);
  max-width: var(--measure);
}

.mono {
  font-family: var(--mono);
  font-variant-ligatures: none;
  letter-spacing: -0.01em;
}

/* A value the machine used. */
.val {
  font-family: var(--mono);
  font-size: 0.92em;
  color: var(--cold);
  font-variant-ligatures: none;
}

/* ---------- the accent phrase ----------
   This used to be the gradient clipped to the glyphs, tracking the
   cursor through --sweep-x. It was the single loudest thing on the page
   saying the page was generated: a gradient headline is the one ornament
   every template of the last two years shipped with, and the dark ground
   was never the problem — this was.

   It is one colour now. The phrase it wraps is the phrase that matters
   in that headline, and it is amber because that is the colour this
   system uses for a person, which is what every one of those headlines
   is actually about. --person on --black is 9.2:1.
   --------------------------------------------------------------- */

.sweep {
  color: var(--person);
}

/* ---------- buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.875rem 1.75rem;
  border: 0;
  border-radius: 999px;
  background: var(--paper);
  color: var(--black);
  font-family: var(--sans);
  font-size: var(--t-small);
  font-weight: 500;
  letter-spacing: -0.01em;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  transition:
    background var(--quick) var(--ease-cursor),
    transform var(--quick) var(--ease-cursor),
    box-shadow var(--mid-dur) var(--ease-cursor);
}

.btn:hover {
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--warm) 50%, transparent),
    0 8px 40px -8px color-mix(in srgb, var(--warm) 55%, transparent);
}

.btn--ghost {
  background: transparent;
  color: var(--paper);
  border: 1px solid var(--hair-lit);
}

.btn--ghost:hover {
  border-color: color-mix(in srgb, var(--warm) 55%, transparent);
  background: color-mix(in srgb, var(--warm) 8%, transparent);
}

/* ---------- section scaffolding ---------- */

.section {
  padding-block: var(--section-y);
  position: relative;
}

.section-head {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 1.5rem;
}

.section-head .h1,
.section-head .h2 {
  max-width: 20ch;
}

/* A small gradient-bordered label above a section. */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4375rem 0.9375rem;
  border-radius: 999px;
  font-family: var(--mono);
  font-size: var(--t-micro);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  background: var(--raised);
  border: 1px solid var(--hair);
}

.eyebrow::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 2px;
  background: var(--warm);
}

.eyebrow--machine::before {
  background: var(--cold);
}

/* ---------- cards ---------- */

.grid {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  margin-top: clamp(2.5rem, 6vh, 4.5rem);
}

.card {
  position: relative;
  padding: 1.75rem;
  border: 1px solid var(--hair);
  border-radius: var(--radius);
  background: var(--near);
  overflow: hidden;
  transition:
    border-color var(--quick) var(--ease-cursor),
    background var(--quick) var(--ease-cursor);
}

/* Cursor-tracked wash. --mx/--my come from cursor.js. */
.card::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(
    20rem circle at var(--mx, 50%) var(--my, 50%),
    color-mix(in srgb, var(--warm) 10%, transparent),
    transparent 62%
  );
  opacity: 0;
  transition: opacity var(--mid-dur) var(--ease-cursor);
  pointer-events: none;
}

.card:hover {
  border-color: var(--hair-lit);
}

.card:hover::before {
  opacity: 1;
}

.card--machine::before {
  background: radial-gradient(
    20rem circle at var(--mx, 50%) var(--my, 50%),
    color-mix(in srgb, var(--cold) 10%, transparent),
    transparent 62%
  );
}

.card__label {
  font-family: var(--mono);
  font-size: var(--t-micro);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--faint);
  margin-bottom: 1rem;
}

.card__title {
  margin-bottom: 0.625rem;
}

.card__body {
  color: var(--muted);
  font-size: var(--t-small);
  line-height: 1.65;
}

/* ---------- reveal ---------- */

/* Hidden only under .has-motion, which reveal.js adds after it has
   confirmed Motion loaded and motion is wanted. A missing script, a
   blocked bundle or prefers-reduced-motion all leave this selector
   unmatched and the page simply finished — which is the one property
   worth more than the entrance itself.

   .is-in is kept because scenes.js and the canvas engines still set it
   on their own schedule. */
.has-motion [data-reveal]:not(.is-in) {
  opacity: 0;
}

/* ---------- the caret ----------
   Sits after the last character typed. On the element rather than a
   node in the flow, so it cannot end up inside the accent span or
   disturb the line it is on. */

[data-typing]::after {
  content: "";
  display: inline-block;
  width: 0.06em;
  height: 0.78em;
  margin-left: 0.06em;
  vertical-align: baseline;
  background: var(--person);
  animation: caret-blink 1s steps(2) infinite;
}

@keyframes caret-blink {
  50% {
    opacity: 0;
  }
}

/* A heading being typed must not reflow the page under the reader, so
   typing.js pins its finished height first. This stops the pin from
   fighting a heading that wraps differently at a new width. */
[data-typing] {
  min-height: 0;
}
