/* ==========================================================================
   almulqi.com
   Direction: SURVEY — a measured drawing set.

   The visual language is lifted from Abdullah's own source: arena_map.py
   describes the world as boxes measured to the millimetre, with prose about
   why each number is what it is. So the site is a survey sheet. Mono is the
   DISPLAY face (CAD annotation, G-code, ROS logs are all set in mono), a
   humanist sans carries the body, and the structural device is the dimension
   callout — extension lines, tick arrows, a real measured value.

   Every dimension printed on this site is true and comes from the project it
   annotates. Nothing here is decorative numbering.
   ========================================================================== */

/* --- tokens ------------------------------------------------------------ */

:root {
  /* Drafting-sheet mineral. Deliberately greener and greyer than the
     warm-cream that light editorial pages default to. */
  --paper:      #eceee6;
  --panel:      #dfe2d8;
  --ink:        #0e110c;
  --ink-2:      #3d433a;
  /* ink-3 carries small text — labels, captions, dates. It has to clear WCAG AA
     (4.5:1) against BOTH paper and the darker panel, which is what sets it here. */
  --ink-3:      #565d51;
  --rule:       #9aa192;
  --rule-soft:  #bcc2b3;
  /* Brass — machined bronze bushing, shim stock. Warm, dry, not terracotta. */
  --accent:     #7a4b0d;
  --accent-2:   #96692a;
  --flag-purple:#6d3fb5;
  --flag-yellow:#b08319;

  --font-display: ui-monospace, "Cascadia Mono", "SF Mono", "Segoe UI Mono",
                  "Roboto Mono", Menlo, Consolas, monospace;
  --font-body:    "Segoe UI", system-ui, -apple-system, Roboto,
                  "Helvetica Neue", Arial, sans-serif;

  --measure: 62ch;
  --gutter: clamp(1.25rem, 5vw, 4rem);
  --page: 1180px;

  --step-0: 1.05rem;
  --step-1: 1.125rem;
  --step-2: clamp(1.35rem, 1.1rem + 1vw, 1.75rem);
  --step-3: clamp(1.75rem, 1.3rem + 2.2vw, 2.75rem);
  --step-4: clamp(2.4rem, 1.4rem + 4.6vw, 5rem);

  --dur: 620ms;
  --ease: cubic-bezier(.22, .61, .36, 1);
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper:      #0e100c;
    --panel:      #181b15;
    --ink:        #f1f3ea;
    --ink-2:      #c5cabb;
    --ink-3:      #99a08f;
    --rule:       #454b3f;
    --rule-soft:  #2e332a;
    --accent:     #dcab5c;
    --accent-2:   #bd8f46;
    --flag-purple:#a684e6;
    --flag-yellow:#d8ae4a;
  }
}

/* --- reset -------------------------------------------------------------- */

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img, svg, video { max-width: 100%; height: auto; display: block; }

a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--ink); }

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

h1, h2, h3, h4 { font-weight: 600; line-height: 1.12; margin: 0; letter-spacing: -0.01em; }

.visually-hidden {
  position: absolute !important; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}

.skip {
  position: absolute; left: -9999px; top: 0;
  background: var(--ink); color: var(--paper);
  padding: .75rem 1rem; z-index: 100; font-family: var(--font-display);
}
.skip:focus { left: 0; }

/* --- layout primitives -------------------------------------------------- */

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

.section { padding-block: clamp(3.5rem, 8vw, 7rem); }
.section + .section { border-top: 1px solid var(--rule-soft); }

/* Section heading: a survey sheet's field label. The rule runs to the edge
   of the column, the way a drawing's title block underlines its heading. */
.section-head {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  margin-bottom: clamp(1.75rem, 4vw, 3rem);
  border-bottom: 1px solid var(--rule);
  padding-bottom: .75rem;
}
.section-head h2 {
  font-family: var(--font-display);
  font-size: var(--step-2);
  font-weight: 500;
  letter-spacing: -0.02em;
}
.section-head .ref {
  margin-left: auto;
  font-family: var(--font-display);
  font-size: .7rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-3);
  white-space: nowrap;
}

.lede {
  font-size: var(--step-1);
  max-width: var(--measure);
  color: var(--ink);
}

/* --- the eyebrow / field label ------------------------------------------ */

.label {
  font-family: var(--font-display);
  font-size: .68rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 0;
}

/* --- SIGNATURE: the dimension callout ----------------------------------- */
/* An extension line with tick arrows and a true measured value. Used wherever
   a real figure belongs to a real thing. It is the one loud device on the
   page, so everything around it stays quiet. */

.dim {
  display: flex;
  align-items: center;
  flex-wrap: wrap;      /* long labels wrap instead of forcing a page scrollbar */
  gap: .3rem .55rem;
  margin: 0;
  font-family: var(--font-display);
  font-size: .74rem;
  letter-spacing: .04em;
  color: var(--ink);
}
.dim::before,
.dim::after {
  content: "";
  flex: 1 1 auto;
  min-width: 1.25rem;
  height: 1px;
  background: var(--rule);
  position: relative;
}
/* the tick arrows */
.dim::before { box-shadow: inset 3px 0 0 0 var(--accent); }
.dim::after  { box-shadow: inset -3px 0 0 0 var(--accent); }

.dim-value { color: var(--ink); font-variant-numeric: tabular-nums; white-space: nowrap; }
.dim-unit  { color: var(--ink-3); }

/* A stack of callouts, e.g. under a project card */
.dim-stack { display: grid; gap: .4rem; }

/* --- header ------------------------------------------------------------- */

.site-header {
  position: sticky; top: 0; z-index: 50;
  background: var(--paper);                                    /* fallback */
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--rule-soft);
}

/* the sticky header is ~3.5rem, so anchored sections must clear it */
:target, [id] { scroll-margin-top: 5rem; }
.site-header .wrap {
  display: flex; align-items: center; gap: 1rem;
  min-height: 3.5rem;
}
.wordmark {
  font-family: var(--font-display);
  font-size: .82rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink);
  display: flex; align-items: center; gap: .55rem;
}
.wordmark:hover { color: var(--accent); }
/* the axis mark: x red / y green, the triad every roboticist reads instantly */
.axis-mark { flex: none; }

.site-nav { margin-left: auto; display: flex; gap: clamp(.75rem, 2vw, 1.5rem); }
.site-nav a {
  font-family: var(--font-display);
  font-size: .74rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink-2);
  padding-block: .35rem;
  border-bottom: 1px solid transparent;
}
.site-nav a:hover, .site-nav a[aria-current="page"] {
  color: var(--ink);
  border-bottom-color: var(--accent);
}
@media (max-width: 640px) {
  .site-nav a:not(.nav-keep) { display: none; }
}

/* --- status / now ------------------------------------------------------- */

.now {
  display: grid;
  gap: 1.5rem;
  border: 1px solid var(--rule);
  border-left: 3px solid var(--accent);
  background: var(--panel);
  padding: clamp(1.25rem, 3vw, 2rem);
}
@media (min-width: 780px) {
  .now { grid-template-columns: minmax(0, 14rem) 1fr; gap: 2.5rem; }
}
.now h2 {
  font-family: var(--font-display);
  font-size: .74rem; font-weight: 500;
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--ink-3);
}
.now p { margin: 0; max-width: var(--measure); }
.now p + p { margin-top: .85rem; color: var(--ink); }
.now .role { font-size: var(--step-1); }
.now .role strong { font-weight: 600; }

.pulse {
  display: inline-block; width: .5rem; height: .5rem;
  background: var(--accent); border-radius: 50%;
  margin-right: .5rem; vertical-align: .05em;
  animation: pulse 2.6s ease-in-out infinite;
}
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }

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

.projects { display: grid; gap: 1px; background: var(--rule-soft); border: 1px solid var(--rule-soft); }

.project {
  background: var(--paper);
  padding: clamp(1.5rem, 4vw, 2.5rem);
  display: grid;
  gap: 1.5rem;
  text-decoration: none;
  color: inherit;
  transition: background var(--dur) var(--ease);
}
@media (min-width: 860px) {
  .project { grid-template-columns: minmax(0, 1fr) minmax(0, 17rem); gap: 2.5rem; align-items: start; }
}
.project:hover, .project:focus-visible { background: var(--panel); }
.project:hover .project-title { color: var(--accent); }

.project-head { display: flex; align-items: baseline; gap: .75rem; flex-wrap: wrap; }
.project-title {
  font-family: var(--font-display);
  font-size: var(--step-3);
  font-weight: 500;
  letter-spacing: -0.035em;
  transition: color var(--dur) var(--ease);
}
.project-role {
  font-family: var(--font-display);
  font-size: .7rem; letter-spacing: .14em; text-transform: uppercase;
  color: var(--accent); border: 1px solid currentColor;
  padding: .15rem .5rem;
}
.project p { margin: .9rem 0 0; max-width: var(--measure); color: var(--ink); }
.project .more, .bundle .more {
  display: inline-flex; align-items: center; gap: .5rem;
  margin-top: 1.5rem;
  font-family: var(--font-display); font-size: .76rem;
  letter-spacing: .12em; text-transform: uppercase;
  /* dim until the card is hovered or focused, so it reads as an invitation
     rather than as another line of body copy */
  color: var(--ink-3);
  transition: color var(--dur) var(--ease);
}
.project:hover .more, .project:focus-visible .more,
.bundle:hover .more, .bundle:focus-visible .more { color: var(--accent); }
.project .more::after, .bundle .more::after {
  content: ""; width: 1.5rem; height: 1px; background: currentColor;
  opacity: .55;
  transition: width var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
.project:hover .more::after, .bundle:hover .more::after { width: 3rem; opacity: 1; }

/* --- skills ------------------------------------------------------------- */

.skills { display: grid; gap: 1px; background: var(--rule-soft); border: 1px solid var(--rule-soft); }
@media (min-width: 720px) { .skills { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1020px) { .skills { grid-template-columns: repeat(3, 1fr); } }

.skill { background: var(--paper); padding: 1.5rem; }
.skill h3 {
  font-family: var(--font-display);
  font-size: .72rem; font-weight: 500;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--accent);
  padding-bottom: .6rem; margin-bottom: .85rem;
  border-bottom: 1px solid var(--rule-soft);
}
.skill ul { margin: 0; padding: 0; list-style: none; display: flex; flex-wrap: wrap; gap: .35rem .85rem; }
.skill li { font-size: .95rem; color: var(--ink); }

/* --- timeline ----------------------------------------------------------- */

.timeline { list-style: none; margin: 0; padding: 0; }
.timeline > li {
  display: grid;
  gap: .25rem 2rem;
  padding-block: 1.15rem;
  border-top: 1px solid var(--rule-soft);
}
.timeline > li:first-child { border-top: 0; padding-top: 0; }
@media (min-width: 720px) {
  .timeline > li { grid-template-columns: 11rem minmax(0, 1fr); }
}
.timeline .when {
  font-family: var(--font-display);
  font-size: .78rem; letter-spacing: .04em;
  color: var(--ink-3); font-variant-numeric: tabular-nums;
  padding-top: .15rem;
}
.timeline p { margin: 0; }
.timeline .what { font-weight: 600; }
.timeline .where { color: var(--ink); }
.timeline .note { color: var(--ink-2); font-size: .96rem; margin-top: .4rem; max-width: var(--measure); }

/* honours get the callout treatment — they are measured results */
.honours { display: grid; gap: .9rem; margin: 0; padding: 0; list-style: none; }
.honours li {
  display: grid; gap: .1rem;
  padding-left: 1rem;
  border-left: 2px solid var(--accent);
}
.honours .h-what { font-weight: 600; }
.honours .h-where { color: var(--ink-2); font-size: .96rem; }

/* --- personal ----------------------------------------------------------- */

.personal { display: grid; gap: clamp(1.5rem, 4vw, 3rem); }
@media (min-width: 900px) { .personal { grid-template-columns: 1fr 1fr; align-items: start; } }
.personal p { max-width: var(--measure); }
.personal p:first-child { margin-top: 0; }

/* --- media slots -------------------------------------------------------- */

.media { border: 1px solid var(--rule); background: var(--panel); }
.media img, .media video { width: 100%; display: block; }
.media figcaption {
  padding: .7rem .9rem;
  border-top: 1px solid var(--rule);
  font-family: var(--font-display);
  font-size: .68rem; line-height: 1.55; color: var(--ink-3);
}

/* A placeholder that holds the exact final aspect ratio, so dropping the real
   file in causes zero reflow. Delete the class, not the markup. */
.media--empty {
  display: grid; place-items: center;
  aspect-ratio: 16 / 9;
  background:
    repeating-linear-gradient(135deg,
      transparent 0 8px,
      color-mix(in srgb, var(--rule) 40%, transparent) 8px 9px);
}
.media--empty span {
  font-family: var(--font-display); font-size: .7rem;
  letter-spacing: .14em; text-transform: uppercase; color: var(--ink-3);
  background: var(--panel); padding: .4rem .7rem; border: 1px solid var(--rule);
  text-align: center;
}
.media-grid { display: grid; gap: 1rem; }
@media (min-width: 720px) { .media-grid { grid-template-columns: repeat(2, 1fr); } }

/* --- shared media primitives -------------------------------------------- */

.shot { display: block; position: relative; overflow: hidden; }
.shot img,
.shot video {
  display: block; width: 100%; height: 100%;
  object-fit: cover;
}
/* the average colour of the image sits underneath it, so a slot is never an
   empty grey rectangle and the page never reflows while loading */
.shot { background-color: var(--panel); }

.fill { position: absolute; inset: 0; }

/* --- video blocks -------------------------------------------------------- */

.clip { border: 1px solid var(--rule); background: var(--panel); }
.clip video { width: 100%; display: block; background: var(--avg, var(--panel)); }
.clip figcaption {
  padding: .7rem .9rem; border-top: 1px solid var(--rule);
  font-family: var(--font-display); font-size: .68rem;
  line-height: 1.55; color: var(--ink-3);
}
.clip-grid { display: grid; gap: 1rem; }
@media (min-width: 720px) { .clip-grid { grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); } }

/* --- case study --------------------------------------------------------- */

.case-hero { padding-block: clamp(2.5rem, 6vw, 4.5rem) clamp(2rem, 5vw, 3.5rem); }
.case-hero h1 {
  font-family: var(--font-display);
  font-size: var(--step-4);
  font-weight: 500; letter-spacing: -0.045em; line-height: .98;
  margin-block: .75rem 1.25rem;
  max-width: 18ch;
}
.case-meta {
  display: grid; gap: 1px;
  background: var(--rule-soft);
  border: 1px solid var(--rule-soft);
  margin-top: 2.5rem;
}
@media (min-width: 640px) { .case-meta { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 960px) { .case-meta { grid-template-columns: repeat(4, 1fr); } }
.case-meta div { background: var(--paper); padding: 1rem 1.15rem; }
.case-meta dt {
  font-family: var(--font-display); font-size: .66rem;
  letter-spacing: .16em; text-transform: uppercase; color: var(--ink-3);
  margin-bottom: .3rem;
}
.case-meta dd { margin: 0; font-weight: 600; }

.prose { max-width: var(--measure); }
.prose h2 {
  font-family: var(--font-display);
  font-size: var(--step-1); font-weight: 500; letter-spacing: -0.02em;
  margin-top: 2.5rem; margin-bottom: .75rem;
}
.prose h2:first-child { margin-top: 0; }
.prose p { margin: 0 0 1.1rem; }
.prose ul { margin: 0 0 1.1rem; padding-left: 1.1rem; }
.prose li { margin-bottom: .5rem; }
.prose strong { font-weight: 600; color: var(--ink); }

/* a pulled-out measured fact inside the prose */
.figure-note {
  border-left: 3px solid var(--accent);
  padding: .15rem 0 .15rem 1rem;
  margin: 1.75rem 0;
  font-family: var(--font-display);
  font-size: .9rem; line-height: 1.6;
  color: var(--ink);
}
.figure-note b { color: var(--ink); font-weight: 500; }

.case-body { display: grid; gap: clamp(2rem, 5vw, 3.5rem); }
@media (min-width: 1000px) {
  .case-body { grid-template-columns: minmax(0, 1fr) minmax(0, 20rem); align-items: start; }
  .case-aside { position: sticky; top: 5rem; }
}
.case-aside { display: grid; gap: 1.25rem; }
.spec {
  border: 1px solid var(--rule); background: var(--panel);
  padding: 1.15rem 1.25rem;
}
.spec h3 {
  font-family: var(--font-display); font-size: .68rem; font-weight: 500;
  letter-spacing: .16em; text-transform: uppercase; color: var(--ink-3);
  margin-bottom: .85rem;
}
.spec dl { margin: 0; display: grid; gap: .55rem; }
.spec .row { display: flex; align-items: baseline; gap: .6rem; }
.spec dt { font-size: .9rem; color: var(--ink); white-space: nowrap; }
.spec .fill { flex: 1 1 auto; height: 1px; background: var(--rule-soft); }
.spec dd {
  margin: 0; font-family: var(--font-display); font-size: .85rem;
  font-variant-numeric: tabular-nums; color: var(--ink); white-space: nowrap;
}

/* --- contact ------------------------------------------------------------ */

.contact-grid { display: grid; gap: clamp(1.5rem, 4vw, 3rem); }
@media (min-width: 820px) { .contact-grid { grid-template-columns: 1fr auto; align-items: start; } }

.links { display: grid; gap: 0; margin: 0; padding: 0; list-style: none; min-width: min(100%, 22rem); }
.links li { border-top: 1px solid var(--rule-soft); }
.links li:last-child { border-bottom: 1px solid var(--rule-soft); }
.links a {
  display: flex; align-items: baseline; gap: 1rem;
  padding: .95rem .25rem;
  text-decoration: none; color: var(--ink);
  font-family: var(--font-display); font-size: .9rem;
}
.links a:hover { color: var(--accent); }
.links .k {
  font-size: .66rem; letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-3); width: 5.5rem; flex: none;
}
.links a:hover .k { color: var(--accent-2); }
.links .v { word-break: break-word; }

.button {
  display: inline-flex; align-items: center; gap: .75rem;
  border: 1px solid var(--ink);
  padding: .8rem 1.25rem;
  font-family: var(--font-display); font-size: .78rem;
  letter-spacing: .12em; text-transform: uppercase;
  text-decoration: none; color: var(--ink);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.button:hover { background: var(--ink); color: var(--paper); }

/* --- footer ------------------------------------------------------------- */

.site-footer {
  border-top: 1px solid var(--rule);
  padding-block: 2rem 3rem;
  font-family: var(--font-display);
  font-size: .7rem; letter-spacing: .06em; color: var(--ink-3);
}
.site-footer .wrap { display: flex; flex-wrap: wrap; gap: .75rem 2rem; align-items: baseline; }
.site-footer a { color: var(--ink-3); }
.site-footer .rev { margin-left: auto; }

/* ==========================================================================
   MOTION — the journey
   ==========================================================================
   The page is one continuous run, not a stack of sections that fade in.

   Two signals drive everything, both written by site.js as plain numbers on
   the element itself, so all the actual animating happens in CSS on the
   compositor (transform and opacity only — no layout, no paint):

     --e   0 → 1   entry progress. 0 when the element's top touches the
                   bottom of the viewport, 1 once it has risen into place.
     --p   0 → 1   travel progress. 0 when the element first appears at the
                   bottom, 1 when it has fully left the top. Used for things
                   that should scrub continuously as you scroll.

   Nothing here is decorative-only: --p drives the robot along its planned
   path, and --e drives the dimension callouts measuring themselves out.
   ========================================================================== */

/* Without JS every element sits at its finished state. The `js` class is set
   by an inline script in <head>, before first paint, so there is no flash of
   fully-visible content collapsing into its start position. */

.reveal { opacity: 1; }

.js .reveal {
  opacity: var(--e, 0);
  transform: translate3d(0, calc((1 - var(--e, 0)) * 32px), 0);
  will-change: transform, opacity;
}

/* Content that should arrive from the side — case-study pull quotes. */
.js .reveal-x {
  opacity: var(--e, 0);
  transform: translate3d(calc((1 - var(--e, 0)) * -24px), 0, 0);
}

/* --- the dimension callout measures itself out -------------------------- */
/* The signature device animating in its own logic: the extension lines grow
   outward from the value, the way a dimension is actually taken. */

.js .dim::before,
.js .dim::after {
  transform: scaleX(var(--e, 0));
  transition: none;
}
.js .dim::before { transform-origin: right center; }
.js .dim::after  { transform-origin: left center; }

/* --- section rules draw across --------------------------------------- */

.js .section-head { border-bottom-color: transparent; position: relative; }
.js .section-head::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: -1px; height: 1px;
  background: var(--rule);
  transform: scaleX(var(--e, 0));
  transform-origin: left center;
}

/* --- the timeline draws down as you pass it ----------------------------- */

.js .timeline { position: relative; }
.js .timeline::before {
  content: "";
  position: absolute; left: -1rem; top: 0; bottom: 0; width: 2px;
  background: var(--accent);
  transform: scaleY(var(--p, 0));
  transform-origin: top center;
}
@media (max-width: 719px) { .js .timeline::before { left: -.6rem; } }

/* --- a case study reads as one descent ---------------------------------- */
/* A line draws down beside the prose as you read it. Only at the width where
   the two-column case layout exists — below that there is no margin to put it
   in without crowding the text. */

@media (min-width: 1000px) {
  .js .prose { position: relative; }
  .js .prose::before {
    content: "";
    position: absolute; left: -1.75rem; top: .4em; bottom: 0; width: 2px;
    background: var(--accent);
    transform: scaleY(var(--p, 0));
    transform-origin: top center;
  }
}

/* --- honour bars grow --------------------------------------------------- */

.js .honours li { border-left-color: transparent; position: relative; }
.js .honours li::before {
  content: "";
  position: absolute; left: 0; top: 0; bottom: 0; width: 2px;
  background: var(--accent);
  transform: scaleY(var(--e, 0));
  transform-origin: top center;
}

/* --- media drifts, for depth ------------------------------------------- */

.js .media[data-scrub] { will-change: transform; }
.js .media[data-scrub] > * {
  transform: translate3d(0, calc((var(--p, .5) - .5) * -26px), 0);
}

/* --- the arena: scroll drives the robot --------------------------------- */
/* Scrolling the hero drives the robot along its planned route, with the trail
   drawing in behind it. It never rotates, which is not a stylistic choice —
   at 419 mm wide in a 600 mm gate it physically cannot cross turned. */

.arena { --route-len: 420; }
.js .arena .route {
  stroke-dasharray: var(--route-len);
  stroke-dashoffset: calc(var(--route-len) * (1 - var(--p, 0)));
}
.bot-carrier { will-change: transform; }

/* --- the mission rail --------------------------------------------------- */
/* A fixed telemetry strip: how far through the run you are, and which
   waypoint you are at. Decorative duplicate of the nav, so hidden from
   assistive tech rather than read out twice. */

.rail { display: none; }

@media (min-width: 1180px) {
  .js .rail {
    display: block;
    position: fixed; left: 1.75rem; top: 50%; transform: translateY(-50%);
    z-index: 40;
  }
  .rail-track {
    position: relative;
    width: 2px; height: 46vh;
    background: var(--rule-soft);
    margin-left: 3px;
  }
  .rail-fill {
    position: absolute; inset: 0 auto 0 0; width: 100%;
    background: var(--accent);
    transform: scaleY(var(--scroll, 0));
    transform-origin: top center;
  }
  .rail-bot {
    position: absolute; left: 50%; top: 0;
    width: 9px; height: 9px; margin: -4px 0 0 -4px;
    background: var(--paper);
    border: 2px solid var(--accent);
    transform: translateY(calc(var(--scroll, 0) * 46vh));
  }
  .rail-stops {
    position: absolute; left: 1.15rem; top: 0; height: 100%;
    list-style: none; margin: 0; padding: 0;
  }
  .rail-stops li {
    position: absolute;
    transform: translateY(-50%);
    font-family: var(--font-display);
    font-size: .6rem; letter-spacing: .16em; text-transform: uppercase;
    white-space: nowrap;
    color: var(--ink-3);
    opacity: .45;
    transition: opacity var(--dur) var(--ease), color var(--dur) var(--ease);
  }
  .rail-stops li[data-passed] { opacity: .8; }
  .rail-stops li[data-active] { opacity: 1; color: var(--accent); }
}

/* --- the mobile progress bar -------------------------------------------- */

.progress { display: none; }
.js .progress {
  display: block;
  position: fixed; left: 0; top: 0; right: 0; height: 2px;
  background: var(--accent);
  transform: scaleX(var(--scroll, 0));
  transform-origin: left center;
  z-index: 60;
}
@media (min-width: 1180px) { .js .progress { display: none; } }

/* --- page-load orchestration -------------------------------------------- */
/* One sequence on arrival, then the page hands over to the scroll. */

.js .lift { opacity: 0; animation: lift 900ms var(--ease) forwards;
            animation-delay: var(--delay, 0ms); }
@keyframes lift {
  from { opacity: 0; transform: translate3d(0, 20px, 0); }
  to   { opacity: 1; transform: none; }
}

/* the CAD viewport drawing its geometry on arrival */
.arena .draw {
  stroke-dasharray: var(--len, 600);
  stroke-dashoffset: var(--len, 600);
  animation: draw 1500ms var(--ease) forwards;
  animation-delay: var(--delay, 0ms);
}
.arena .fade {
  opacity: 0;
  animation: fade 700ms var(--ease) forwards;
  animation-delay: var(--delay, 0ms);
}
@keyframes draw { to { stroke-dashoffset: 0; } }
@keyframes fade { to { opacity: 1; } }

/* --- reduced motion ----------------------------------------------------- */
/* Everything lands at its finished state. The robot parks at the end of its
   route and the trail is fully drawn, so no information is lost — only the
   movement is. */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .js .reveal, .js .reveal-x, .js .lift { opacity: 1; transform: none; }
  .js .dim::before, .js .dim::after,
  .js .section-head::after,
  .js .timeline::before,
  .js .honours li::before,
  .js .rail-fill { transform: none; }
  .js .media[data-scrub] > * { transform: none; }
  .js .arena .route { stroke-dasharray: none; stroke-dashoffset: 0; }
  .arena .draw { stroke-dashoffset: 0; }
  .arena .fade { opacity: 1; }
  .js .progress { display: none; }
}

@media print {
  .site-header, .site-nav, .media--empty, .rail, .progress { display: none; }
  body { background: #fff; color: #000; }
  .js .reveal, .js .reveal-x, .js .lift { opacity: 1; transform: none; }
}
