/* "U is you" entrance (owner decision, October 13, 2026), grown in the owner's
   nature direction the same day. Growth rings spread from the person, mycelium
   creeps in from the edges, six sense roots approach the open U counter
   with a drop of sap running ahead, the exact Sora U reveals first, R S L Y rise
   in order, followed by "Six senses. One interface." and the human-to-technology flow. The mark then flies to the header. Colours are
   brand tokens; times are the --es-entry-* clock in brand/tokens.css, which the
   JS phase machine in site/entry-experience.js matches. */

#entry-experience[hidden] {
  display: none !important;
}

#entry-experience {
  position: fixed;
  inset: 0;
  z-index: 150;
  isolation: isolate;
  overflow: hidden;
  /* The ground lives on the stage so the stage can clear while the mark is
     still flying to the header. */
  background: transparent;
  color: var(--es-ink);
  color-scheme: dark;
}

.entry-stage {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: var(--es-ground);
  transition: opacity calc(var(--es-entry-fade-seconds, 0.9) * 1s) ease-in;
}

/* Loam: soft low-frequency clouds in the brand teal, strongest at the edges
   and clear in the middle, like moss on a forest floor at night. */
.entry-substrate {
  position: absolute;
  inset: 0;
  background: var(--es-pore);
  mask-image:
    var(--es-entry-loam),
    radial-gradient(ellipse 70% 62% at 50% 48%, transparent 18%, black 82%);
  mask-size:
    var(--es-entry-loam-tile, 480px) var(--es-entry-loam-tile, 480px),
    100% 100%;
  mask-composite: intersect;
  opacity: 0;
  animation: entry-substrate-in
    calc(var(--es-entry-substrate-duration, 0.6) * 1s) ease-out
    calc(var(--es-entry-substrate-delay, 0) * 1s) both;
  --entry-substrate-to: var(--es-entry-loam-ink, 0.08);
}

@keyframes entry-substrate-in {
  from {
    opacity: 0;
  }
  to {
    opacity: var(--entry-substrate-to, 1);
  }
}

/* Grain over the whole board, at a whisper. */
.entry-stage::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--es-entry-grain) 0 0 / 160px 160px;
  mix-blend-mode: overlay;
  opacity: var(--es-entry-grain-ink, 0.07);
  pointer-events: none;
}

/* Light comes from the letters: a soft teal glow behind the mark that breathes
   once the mark has landed. */
.entry-glow {
  position: absolute;
  inset: 0;
  background: radial-gradient(
    ellipse 42% 30% at 50% 46%,
    var(--es-glow-soft),
    transparent 70%
  );
  opacity: 0;
  animation:
    entry-substrate-in calc(var(--es-entry-u-duration, 0.65) * 1s) ease-out
      calc(var(--es-entry-u-delay, 0.7) * 1s) both,
    entry-breathe 3.2s ease-in-out
      calc(var(--es-entry-assembly-seconds, 2.8) * 1s) infinite;
}

@keyframes entry-breathe {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.62;
  }
}

/* The ground the script lays out for the measured stage. */
.entry-board {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}

/* Growth rings: a year at a time, outward from the person. */
.entry-ring {
  fill: none;
  stroke: var(--es-pore);
  stroke-width: 1;
  stroke-linejoin: round;
  stroke-opacity: calc(var(--es-entry-ring-ink, 0.1) * var(--entry-fade, 1));
  opacity: 0;
  animation: entry-ring-in calc(var(--es-entry-ring-duration, 0.5) * 1s)
    ease-out
    calc(
      (
          var(--es-entry-ring-delay, 0.05) + var(--es-entry-ring-step, 0.022) *
            var(--entry-index, 0)
        ) *
        1s
    )
    both;
}
.entry-ring--late {
  stroke-width: 1.6;
  stroke-opacity: calc(var(--es-entry-late-ink, 0.16) * var(--entry-fade, 1));
}

@keyframes entry-ring-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* Once the mark has landed, a slow wave of light runs out through the rings
   from the person, a year at a time, as if the ground were breathing. */
.entry-ring {
  animation:
    entry-ring-in calc(var(--es-entry-ring-duration, 0.5) * 1s) ease-out
      calc(
        (
            var(--es-entry-ring-delay, 0.05) +
              var(--es-entry-ring-step, 0.022) * var(--entry-index, 0)
          ) *
          1s
      )
      both,
    entry-ring-wave calc(var(--es-entry-wave-seconds, 3.6) * 1s) ease-in-out
      calc(
        (var(--es-entry-assembly-seconds, 2.8) + 0.06 * var(--entry-index, 0)) *
          1s
      )
      infinite;
}
@keyframes entry-ring-wave {
  0%,
  100% {
    stroke-width: 1;
  }
  18% {
    stroke-width: 2.2;
  }
  40% {
    stroke-width: 1;
  }
}

/* Motes: spores of light in the six sense colours drift up and fade. */
.entry-mote {
  fill: var(--entry-sense, var(--es-pore));
  opacity: 0;
  transform-box: fill-box;
  animation: entry-mote-drift calc(var(--entry-mote-period, 7) * 1s) ease-in-out
    calc((var(--es-entry-route-delay, 0.3) + var(--entry-mote-delay, 0)) * 1s)
    infinite;
}
@keyframes entry-mote-drift {
  0% {
    opacity: 0;
    translate: 0 0;
  }
  25% {
    opacity: var(--es-entry-mote-ink, 0.55);
  }
  70% {
    opacity: calc(var(--es-entry-mote-ink, 0.55) * 0.6);
  }
  100% {
    opacity: 0;
    translate: var(--entry-mote-dx, 0) var(--entry-mote-dy, -80px);
  }
}

/* Mycelium: hyphae creep in from the margins, branch, and end in spores. */
.entry-hypha-line {
  fill: none;
  stroke: var(--es-pore);
  stroke-width: 0.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-opacity: var(--es-entry-hypha-ink, 0.14);
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: entry-grow calc(var(--es-entry-hypha-duration, 0.9) * 1s) ease-out
    calc(
      (
          var(--es-entry-hypha-delay, 0) + var(--es-entry-hypha-step, 0.3) *
            var(--entry-index, 0)
        ) *
        1s
    )
    both;
}
.entry-spore {
  fill: var(--es-pore);
  fill-opacity: calc(var(--es-entry-hypha-ink, 0.14) * 2);
  opacity: 0;
  animation: entry-substrate-in 0.3s ease-out
    calc(
      (
          var(--es-entry-hypha-delay, 0) + var(--es-entry-hypha-step, 0.3) *
            var(--entry-index, 0) + var(--es-entry-hypha-duration, 0.9)
        ) *
        1s
    )
    both;
}

/* Six sense roots: a dim bed, the root growing in from the edge with its
   rootlets, and a drop of sap that runs ahead of it into the U. Each in its
   product hue. */
.entry-route {
  --entry-sense: var(--es-pore);
  --entry-route-at: calc(
    (
        var(--es-entry-route-delay, 0.3) + var(--es-entry-route-step, 0.07) *
          var(--entry-index, 0)
      ) *
      1s
  );
}
.entry-route--voice {
  --entry-sense: var(--es-hear);
}
.entry-route--motion {
  --entry-sense: var(--es-move);
}
.entry-route--smell {
  --entry-sense: var(--es-smell);
}
.entry-route--taste {
  --entry-sense: var(--es-taste);
}
.entry-route--sight {
  --entry-sense: var(--es-view);
}
.entry-route--touch {
  --entry-sense: var(--es-touch);
}
.entry-route :is(.entry-route-bed, .entry-route-line, .entry-route-pulse) {
  fill: none;
  stroke: var(--entry-sense);
  stroke-linecap: round;
  stroke-linejoin: round;
}
.entry-route-bed {
  stroke-width: 3;
  stroke-opacity: 0.08;
}
/* Nothing marks the way ahead: the bed grows with its root. */
.entry-route-bed,
.entry-route-line {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: entry-grow calc(var(--es-entry-route-duration, 0.8) * 1s)
    cubic-bezier(0.55, 0, 0.25, 1) var(--entry-route-at) both;
}
.entry-route-line {
  stroke-width: 1.4;
  stroke-opacity: var(--es-entry-route-rest-ink, 0.42);
}
/* A rootlet sprouts once the root has grown past it. */
.entry-rootlet {
  fill: none;
  stroke: var(--entry-sense);
  stroke-width: 0.9;
  stroke-linecap: round;
  stroke-opacity: calc(var(--es-entry-route-rest-ink, 0.42) * 0.8);
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: entry-grow calc(var(--es-entry-rootlet-duration, 0.3) * 1s)
    ease-out
    calc(
      var(--entry-route-at) + var(--es-entry-route-duration, 0.8) *
        var(--entry-at, 0.5) * 1s
    )
    both;
}
.entry-route-pulse {
  stroke-width: 2.4;
  stroke-dasharray: 0.07 1;
  stroke-dashoffset: 0.07;
  opacity: 0;
  filter: drop-shadow(0 0 3px var(--entry-sense));
  animation: entry-pulse-run calc(var(--es-entry-route-duration, 0.8) * 1s)
    cubic-bezier(0.55, 0, 0.25, 1) var(--entry-route-at) both;
}
.entry-route-pad {
  fill: var(--entry-sense);
  opacity: 0;
  animation: entry-substrate-in 0.2s ease-out var(--entry-route-at) both;
}
.entry-route-label {
  fill: var(--es-ink);
  paint-order: stroke;
  stroke: var(--es-ground);
  stroke-width: 2px;
  stroke-linejoin: round;
  font: 600 var(--es-entry-label-size, 0.8125rem) / 1 var(--es-font-data);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0;
  animation: entry-substrate-in 0.3s ease-out var(--entry-route-at) both;
}

@keyframes entry-grow {
  from {
    stroke-dashoffset: 1;
  }
  to {
    stroke-dashoffset: 0;
  }
}

/* The sap travels the whole root, arriving as the root completes, then the
   person it fed answers. */
@keyframes entry-pulse-run {
  0% {
    stroke-dashoffset: 0.07;
    opacity: 1;
  }
  92% {
    opacity: 1;
  }
  100% {
    stroke-dashoffset: -0.95;
    opacity: 0;
  }
}

/* The lockup: the mark, the tagline and the motto, centred. */
.entry-lockup {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--es-entry-lockup-gap, 1.5rem);
  padding: max(4.5rem, env(safe-area-inset-top)) var(--es-space-4)
    max(2rem, env(safe-area-inset-bottom));
  z-index: 1;
  text-align: center;
}

.entry-wordmark {
  position: relative;
  flex: 0 0 auto;
  width: var(--es-entry-wordmark-width, clamp(13rem, 64vw, 34rem));
  max-width: calc(100vw - 2 * var(--es-space-4));
  aspect-ratio: var(--es-brand-wordmark-ratio);
  transform-origin: center;
}
.entry-mark {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}

/* The source font outlines are filled once, without an outline or bevel. */
.entry-letter {
  fill: currentColor;
  stroke: none;
  color: var(--es-ink);
}

/* Reveal the unmodified U outline, then introduce the other letters. */
.entry-u {
  opacity: 0;
  animation: entry-u-draw calc(var(--es-entry-u-duration, 0.65) * 1s)
    cubic-bezier(0.6, 0, 0.2, 1) calc(var(--es-entry-u-delay, 0.7) * 1s) both;
}

@keyframes entry-u-draw {
  from {
    opacity: 0;
    clip-path: inset(0 0 100% 0) fill-box;
  }
  to {
    opacity: 1;
    clip-path: inset(0) fill-box;
  }
}

/* R, S, L, Y rise 8px and fade in, 90ms apart. */
.entry-rise {
  opacity: 0;
  animation: entry-letter-rise calc(var(--es-entry-letter-duration, 0.42) * 1s)
    cubic-bezier(0.22, 0.7, 0.3, 1)
    calc(
      (
          var(--es-entry-letter-delay, 1.25) +
            var(--es-entry-letter-step, 0.09) * var(--entry-index, 0)
        ) *
        1s
    )
    both;
}

@keyframes entry-letter-rise {
  from {
    opacity: 0;
    translate: 0 var(--es-entry-rise, 8px);
  }
  to {
    opacity: 1;
    translate: 0 0;
  }
}

/* Open capture brackets draw around the ordinary U. */
.entry-trace-line {
  fill: none;
  stroke: var(--es-pore);
  stroke-width: var(--entry-capture-stroke);
  stroke-linecap: square;
  stroke-linejoin: miter;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
}
.entry-trace {
  --entry-trace-at: calc(
    (
        var(--es-entry-trace-delay, 1.35) + var(--es-entry-trace-step, 0.09) *
          var(--entry-index, 0)
      ) *
      1s
  );
}
.entry-trace .entry-trace-line {
  animation: entry-trace-light calc(var(--es-entry-trace-duration, 0.36) * 1s)
    ease-out var(--entry-trace-at) both;
}

@keyframes entry-trace-light {
  from {
    stroke-dashoffset: 1;
  }
  to {
    stroke-dashoffset: 0;
  }
}

/* The two actual channel brackets arrive first; no extra person/sensor dot.
   The existing person-first score now lights the interface's entry channels. */
.entry-trace.entry-channel .entry-trace-line {
  animation: entry-channel-in calc(var(--es-entry-you-duration, 0.5) * 1s)
    ease-out calc(var(--es-entry-you-delay, 0.15) * 1s) both;
}
@keyframes entry-channel-in {
  from {
    opacity: 0;
    stroke-dashoffset: 1;
  }
  to {
    opacity: 1;
    stroke-dashoffset: 0;
  }
}

/* A specular sweep across the letters once they are all in. */
.entry-gleam {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    105deg,
    transparent 40%,
    color-mix(in oklab, var(--es-pearl) 55%, transparent) 50%,
    transparent 60%
  );
  background-size: 280% 100%;
  background-position: 150% 0;
  /* The sweep lights the letters only, never the navy around them. */
  mask: url("../brand/ursly-wordmark-on-dark.svg") center / contain no-repeat;
  mix-blend-mode: soft-light;
  opacity: 0;
  animation: entry-gleam-sweep calc(var(--es-entry-gleam-duration, 0.7) * 1s)
    cubic-bezier(0.22, 0.7, 0.3, 1) calc(var(--es-entry-gleam-delay, 1.9) * 1s)
    both;
  pointer-events: none;
}

@keyframes entry-gleam-sweep {
  0% {
    opacity: 0;
    background-position: 150% 0;
  }
  30% {
    opacity: 1;
  }
  100% {
    opacity: 0;
    background-position: -50% 0;
  }
}

/* State the interface promise before showing the six individual channels. */
.entry-tagline {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.15em 0.5em;
  max-width: 40rem;
  margin: 0;
  font: 600 var(--es-entry-line-size, clamp(1.15rem, 2.6vw, 1.75rem)) / 1.25
    var(--es-font-display);
  letter-spacing: -0.02em;
  color: var(--es-ink);
}
.entry-line {
  display: inline-block;
  opacity: 0;
  animation: entry-line-in calc(var(--es-entry-line-duration, 0.45) * 1s)
    cubic-bezier(0.22, 0.7, 0.3, 1)
    calc(
      (
          var(--es-entry-line-delay, 1.95) + var(--es-entry-line-step, 0.2) *
            var(--entry-index, 0)
        ) *
        1s
    )
    both;
}
.entry-line-lead {
  font-style: normal;
  color: var(--es-pore);
}

@keyframes entry-line-in {
  from {
    opacity: 0;
    translate: 0 0.35em;
  }
  to {
    opacity: 1;
    translate: 0 0;
  }
}

.entry-motto {
  position: relative;
  margin: var(--es-entry-flow-room, 0.75rem) 0 0;
  font: 500 var(--es-entry-motto-size, clamp(0.8125rem, 1.6vw, 1rem)) / 1.4
    var(--es-font-data);
  letter-spacing: 0.04em;
  color: var(--es-ink);
  opacity: 0;
  animation: entry-substrate-in 0.5s ease-out
    calc(
      (var(--es-entry-line-delay, 1.95) + var(--es-entry-line-step, 0.2) * 2) *
        1s
    )
    both;
}

@media (max-width: 480px) {
  .entry-tagline {
    flex-direction: column;
    align-items: center;
  }
}

/* Keep three approach lanes above the frame in short landscape.
   The mark keeps its real aspect ratio; the copy retains its ordinary size. */
@media (max-height: 520px) and (min-width: 481px) {
  .entry-lockup {
    padding-block: 7rem 1rem;
    gap: 0.5rem;
  }
  /* The flow projects 2rem above the motto: reserve it after the compact gap. */
  .entry-motto {
    margin-top: var(--es-entry-flow-room-landscape, 1.75rem);
  }
  /* Keep the upper-right channel legend clear of the 44px exit target. */
  .entry-route--taste :is(.entry-sense-glyph, .entry-route-label) {
    translate: calc(-1 * var(--es-entry-exit-label-clearance, 4rem)) 0;
  }
  .entry-wordmark {
    width: min(
      var(--es-entry-wordmark-width, clamp(13rem, 64vw, 34rem)),
      calc(max(1px, 100svh - 13rem) * var(--es-brand-wordmark-ratio))
    );
  }
}

/* Skip introduction holds focus at load: its ring shows from the first frame
   (WCAG 2.4.7), not only after a Tab press. */
.entry-exit {
  appearance: none;
  position: absolute;
  right: max(1rem, env(safe-area-inset-right));
  top: max(1rem, env(safe-area-inset-top));
  width: 2.75rem;
  height: 2.75rem;
  display: grid;
  place-items: center;
  border: 1px solid var(--es-line);
  border-radius: 50%;
  padding: 0;
  background: color-mix(in oklab, var(--es-surface) 70%, transparent);
  color: var(--es-ink);
  cursor: pointer;
  opacity: 0.8;
  transition: opacity var(--es-dur-ui, 240ms) ease;
  z-index: 2;
}
.entry-exit:hover {
  opacity: 1;
}
.entry-exit:focus-visible,
#entry-experience[data-keyboard="true"] .entry-exit:focus-visible {
  outline: 2px solid var(--es-pore);
  outline-offset: 0.2rem;
}
.entry-cross {
  font: 300 1.5rem/1 var(--es-font-body);
}

body.entry-open
  :is(
    #overview,
    #telemetry,
    .es-telemetry,
    .wordmark,
    .brand-subtitle,
    .sequence-status
  ) {
  visibility: hidden !important;
  pointer-events: none;
}

/* Leaving: the board clears, the words go, and the mark flies to the header
   mark it becomes. Without a measured header the mark fades with the rest. */
#entry-experience[data-phase="leaving"] {
  pointer-events: none;
}
#entry-experience[data-phase="leaving"] .entry-stage {
  opacity: 0;
}
#entry-experience[data-phase="leaving"] :is(.entry-tagline, .entry-motto) {
  opacity: 0;
  transition: opacity calc(var(--es-entry-fade-seconds, 0.9) * 0.4s) ease-in;
}
#entry-experience[data-phase="leaving"] .entry-exit {
  opacity: 0;
}
#entry-experience[data-phase="leaving"] .entry-wordmark {
  opacity: 0;
  transition: opacity calc(var(--es-entry-fade-seconds, 0.9) * 1s) ease-in;
}
#entry-experience[data-phase="leaving"][data-handoff="true"] .entry-wordmark {
  opacity: 1;
  translate: var(--es-entry-handoff-x, 0) var(--es-entry-handoff-y, 0);
  scale: var(--es-entry-handoff-scale, 1);
  transition:
    translate calc(var(--es-entry-fade-seconds, 0.9) * 1s)
      cubic-bezier(0.65, 0, 0.25, 1),
    scale calc(var(--es-entry-fade-seconds, 0.9) * 1s)
      cubic-bezier(0.65, 0, 0.25, 1);
}
#entry-experience[data-phase="leaving"][data-handoff="true"] .entry-gleam {
  opacity: 0;
  transition: opacity calc(var(--es-entry-fade-seconds, 0.9) * 0.5s) ease-in;
}

/* Reduced motion: the settled frame, then a brief fade. */
@media (prefers-reduced-motion: reduce) {
  .entry-stage {
    transition: opacity calc(var(--es-entry-reduced-fade-seconds, 0.18) * 1s)
      ease;
  }
  #entry-experience[data-phase="leaving"] .entry-wordmark {
    transition: opacity calc(var(--es-entry-reduced-fade-seconds, 0.18) * 1s)
      ease;
  }
  .entry-glow,
  .entry-ring,
  .entry-spore,
  .entry-route-pad,
  .entry-route-label,
  .entry-u,
  .entry-rise,
  .entry-line,
  .entry-motto {
    animation: none;
    opacity: 1;
    translate: none;
    scale: none;
  }
  .entry-substrate {
    animation: none;
    opacity: var(--entry-substrate-to);
  }
  .entry-u,
  .entry-route-bed,
  .entry-route-line,
  .entry-rootlet,
  .entry-hypha-line,
  .entry-trace .entry-trace-line {
    animation: none;
    stroke-dashoffset: 0;
    clip-path: none;
  }
  .entry-route-pulse,
  .entry-gleam,
  .entry-mote {
    animation: none;
    opacity: 0;
  }
}

/* Earth → human senses → a shared technology network. */
.entry-earth {
  fill: none;
  stroke: var(--es-pore);
  stroke-width: 1;
  opacity: 0.18;
  transform-origin: center;
  animation: entry-earth-rise 2.2s ease-out both;
}
.entry-earth-meridian {
  stroke-opacity: 0.6;
}
.entry-earth-latitude {
  stroke-opacity: 0.4;
}
.entry-tech-channel {
  fill: none;
  stroke: var(--es-pore);
  opacity: 0.28;
}
.entry-tech-channel polyline {
  stroke-width: 1;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: entry-grow 1.2s ease-out calc(1s + var(--entry-index) * 0.12s) both;
}
.entry-tech-channel rect {
  fill: var(--es-pore);
  stroke: none;
  animation: entry-tech-node 1s ease-out calc(1.8s + var(--entry-index) * 0.12s)
    both;
}
.entry-sense-glyph {
  fill: none;
  stroke: var(--entry-sense);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.entry-sense-motion {
  transform-origin: 12px 12px;
  animation: entry-sense-reveal 0.6s ease-out var(--entry-route-at) both;
}
.entry-sense-glyph--voice .entry-sense-motion {
  animation-name: entry-sense-wave;
}
.entry-sense-glyph--motion .entry-sense-motion {
  animation-name: entry-sense-step;
}
.entry-sense-glyph--smell .entry-sense-motion {
  animation-name: entry-sense-rise;
}
.entry-sense-glyph--taste .entry-sense-motion {
  animation-name: entry-sense-reveal;
}
.entry-sense-glyph--sight .entry-sense-motion {
  animation-name: entry-sense-open;
}
.entry-sense-glyph--touch .entry-sense-motion {
  animation-name: entry-sense-touch;
}
@keyframes entry-earth-rise {
  from {
    opacity: 0;
    transform: translateY(24px);
  }
  to {
    opacity: 0.18;
    transform: translateY(0);
  }
}
@keyframes entry-tech-node {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
@keyframes entry-sense-reveal {
  from {
    opacity: 0;
    transform: scale(0.65);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}
@keyframes entry-sense-wave {
  0% {
    opacity: 0;
    transform: scaleX(0.4);
  }
  60% {
    opacity: 1;
    transform: scaleX(1.2);
  }
  100% {
    transform: scaleX(1);
  }
}
@keyframes entry-sense-step {
  from {
    opacity: 0;
    transform: translateX(-10px) rotate(-15deg);
  }
  to {
    opacity: 1;
    transform: translateX(0) rotate(0);
  }
}
@keyframes entry-sense-rise {
  from {
    opacity: 0;
    transform: translateY(12px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
@keyframes entry-sense-open {
  from {
    opacity: 0;
    transform: scaleY(0.1);
  }
  to {
    opacity: 1;
    transform: scaleY(1);
  }
}
@keyframes entry-sense-touch {
  0% {
    opacity: 0;
    transform: scale(1.3);
  }
  70% {
    opacity: 1;
    transform: scale(0.9);
  }
  100% {
    transform: scale(1);
  }
}
@media (prefers-reduced-motion: reduce) {
  .entry-earth,
  .entry-tech-channel polyline,
  .entry-tech-channel rect,
  .entry-sense-glyph .entry-sense-motion {
    animation: none;
    stroke-dashoffset: 0;
  }
}
.entry-earth-outline {
  stroke-width: 1.8;
  stroke-opacity: 0.95;
}

/* A compact, directional bridge: human input → the exact U → technology.
   This illustrates the intended interface, not a validated sensing path. */
.entry-interface-flow {
  position: absolute;
  width: min(15rem, 78vw);
  height: 1.75rem;
  left: 50%;
  top: -2rem;
  transform: translateX(-50%);
  pointer-events: none;
  overflow: visible;
  fill: none;
  stroke: var(--es-pore);
  stroke-width: 1.3;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.entry-interface-u {
  fill: var(--es-ink);
  stroke: none;
}
.entry-interface-arrow {
  opacity: var(--es-entry-flow-ink, 0.8);
}
.entry-interface-pulse {
  fill: var(--es-ink);
  stroke: none;
  opacity: 0;
  animation: entry-interface-send calc(var(--es-entry-flow-duration, 0.42) * 1s)
    ease-in-out
    calc(
      (var(--es-entry-line-delay, 1.95) + 0.55 + var(--entry-index) * 0.4) * 1s
    )
    both;
}
@keyframes entry-interface-send {
  0% {
    transform: translateX(0);
    opacity: 0;
  }
  15%,
  85% {
    opacity: 1;
  }
  100% {
    transform: translateX(69px);
    opacity: 0;
  }
}
@media (prefers-reduced-motion: reduce) {
  .entry-interface-pulse {
    animation: none;
    opacity: 0;
  }
}
