/* ═══════════════════════════════════════════════════════════════
   ANGELX — black & white · dotmax / retro-fantasy / high-tech
   The page is INVERTED on the vertical: it begins at the bottom
   (#entrance) and is read upward to the summit (#finale, doc top).
   ═══════════════════════════════════════════════════════════════ */

:root{
  --bg:#050506;
  --bg-2:#0a0a0d;
  --ink:#f4f4f7;
  --dim:#a2a2ac;
  --faint:#5b5b66;
  --line:#26262d;
  --line-2:#3a3a44;
  --font-fantasy:'Cinzel','Times New Roman',Georgia,serif;
  --font-dos:'VT323','Courier New',ui-monospace,monospace;
  --font-mono:ui-monospace,'Cascadia Mono',Menlo,Consolas,'Courier New',monospace;
  /* one knob for every picture on the page: monochrome, then the #tone curve
     from index.html pushes the contrast at both ends */
  --media-filter:grayscale(1) url(#tone);
}

*{box-sizing:border-box}
html{scroll-behavior:smooth;color-scheme:dark}
html,body{margin:0;padding:0;background:var(--bg);color:var(--ink)}
body{font-family:var(--font-mono);font-size:16px;line-height:1.65;overflow-x:hidden;overscroll-behavior-y:none}
a{color:inherit}
::selection{background:#fff;color:#000}

/* ─── atmosphere overlays ─────────────────────────────────────── */
.dotfield{position:fixed;inset:0;z-index:0;pointer-events:none;
  background-image:radial-gradient(circle,rgba(255,255,255,.055) 1px,transparent 1.4px);
  background-size:22px 22px}
.vignette{position:fixed;inset:0;z-index:2;pointer-events:none;
  background:radial-gradient(ellipse at 50% 42%,transparent 55%,rgba(0,0,0,.5) 100%)}
.scanlines{position:fixed;inset:0;z-index:3;pointer-events:none;opacity:.45;
  background:repeating-linear-gradient(to bottom,rgba(0,0,0,0) 0 2px,rgba(0,0,0,.22) 2px 3px)}

/* ─── guiding star (fixed at the top, leads the ascent) ───────── */
#star-guide{position:fixed;top:14px;left:50%;transform:translateX(-50%);z-index:3;
  opacity:0;pointer-events:none;transition:opacity 1.2s ease}
#star-guide .star{width:26px;height:26px;display:block;fill:#fff;
  filter:drop-shadow(0 0 6px rgba(255,255,255,.9)) drop-shadow(0 0 20px rgba(255,255,255,.55));
  animation:bob 3.2s ease-in-out infinite}
@keyframes bob{50%{transform:translateY(4px)}}

/* ─── ascent HUD ──────────────────────────────────────────────── */
.hud{position:fixed;left:18px;bottom:16px;z-index:6;font-family:var(--font-dos);
  color:var(--dim);font-size:20px;letter-spacing:.06em;pointer-events:none;
  display:flex;flex-direction:column;align-items:flex-start;gap:8px}
/* the ascent readout arrives with the climb; the install chip is there from the start */
.hud-ascent{opacity:0;transition:opacity .9s ease}
body.ascended .hud-ascent{opacity:1}
.hud-row{display:flex;gap:10px;align-items:baseline}
.hud-pct{color:var(--ink)}
.hud-bar{width:180px;height:9px;border:1px solid var(--line-2);margin:4px 0 6px;padding:1px}
.hud-bar i{display:block;height:100%;width:0%;background:repeating-linear-gradient(90deg,#fff 0 3px,transparent 3px 6px)}
.repo-link{display:flex;align-items:center;gap:8px;max-width:min(560px,84vw);
  background:rgba(0,0,0,.76);border:1px solid var(--line-2);color:var(--dim);
  font-family:var(--font-dos);font-size:16px;letter-spacing:.04em;padding:6px 10px;
  text-decoration:none;pointer-events:auto}
.repo-link code{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-family:var(--font-dos)}
.repo-link:hover{color:#fff;border-color:#fff}
.icon{width:16px;height:16px;flex:none;display:block;fill:none;stroke:currentColor;
  stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.icon-github{fill:currentColor;stroke:none}
.icon-check{display:none}
.copied .icon-copy{display:none}
.copied .icon-check{display:block}

/* ─── one-command install at the summit ───────────────────────── */
.install{margin:26px auto 0;max-width:min(760px,100%);border:1px solid var(--line-2);
  background:rgba(0,0,0,.55);padding:14px 16px;text-align:left}
.install-label{font-family:var(--font-dos);color:var(--faint);font-size:15px;
  letter-spacing:.14em;margin:0 0 10px;text-align:center}
/* command centred on the block, copy button pinned to the edge so it cannot
   push the text off-centre */
.install-row{position:relative;display:flex;align-items:center;justify-content:center}
.install-cmd{flex:0 1 auto;font-family:var(--font-dos);font-size:17px;color:var(--ink);
  white-space:nowrap;overflow-x:auto;text-align:center;padding:0 48px}
.copy-btn{position:absolute;right:0;top:50%;transform:translateY(-50%);
  display:grid;place-items:center;background:none;border:1px solid var(--line-2);
  color:var(--dim);padding:7px;cursor:pointer}
.copy-btn:hover,.copy-btn.copied{color:#000;background:#fff;border-color:#fff}


/* ─── sections (document order = reverse reading order) ───────── */
main{position:relative;z-index:2}
section{position:relative;min-height:100vh;padding:14vh 24px;
  display:flex;align-items:center;justify-content:center}
section:not(#entrance){border-bottom:1px dashed var(--line)}
/* centred page: with the numbered labels gone, every section reads from the
   middle. #entrance is its own hero and the install box keeps its command
   left-aligned, so both opt out. */
section:not(#entrance) .wrap{text-align:center}
section:not(#entrance) .lede{margin-left:auto;margin-right:auto}   /* keeps its 68ch measure */
.wrap{width:min(980px,100%)}

.noscript-note{position:fixed;top:14px;left:50%;transform:translateX(-50%);z-index:9;
  font-family:var(--font-dos);color:var(--ink);background:#000;border:1px solid var(--line-2);
  padding:8px 16px;font-size:20px}

h2.title{font-family:var(--font-fantasy);font-weight:700;letter-spacing:.04em;
  font-size:clamp(30px,4.6vw,52px);margin:0 0 18px}
.display{font-family:var(--font-fantasy);font-weight:900;line-height:1.12;letter-spacing:.03em;
  font-size:clamp(34px,6vw,64px);margin:6px 0 14px;transition:text-shadow 1.2s ease,color 1.2s ease}
.display.blackletter{font-family:'BlackletterDS','UnifrakturMaguntia','Old English Text MT',Palatino,serif;
  font-weight:400;letter-spacing:.01em;font-size:clamp(44px,8vw,88px);
  color:#fff;-webkit-text-fill-color:#fff;paint-order:stroke fill}
.lede{color:var(--dim);max-width:68ch;font-size:16.5px;margin:0 0 14px}
.lede.centered{margin-inline:auto;text-align:center}
.rule{margin:34px auto;text-align:center;color:var(--faint);font-family:var(--font-dos);
  letter-spacing:1.2em;font-size:15px;padding-left:1.2em}
.fineprint{font-family:var(--font-dos);color:var(--dim);font-size:18px;margin-top:26px;letter-spacing:.08em}
.fineprint a{color:var(--ink);text-decoration:underline dotted;text-underline-offset:3px;
  text-decoration-color:var(--faint);transition:color .25s ease,text-decoration-color .25s ease}
.fineprint a:hover,.fineprint a:focus-visible{color:#fff;text-decoration-color:#fff}

/* reveal-on-scroll: content arrives from ABOVE (we are ascending) */
.reveal{opacity:0;transform:translateY(-36px);
  transition:opacity .95s ease,transform .95s cubic-bezier(.18,.7,.2,1)}
.reveal.in-view{opacity:1;transform:none}

/* ─── intro: spec plate ───────────────────────────────────────── */
dl.plate{margin:30px 0 0;font-family:var(--font-dos);font-size:21px;max-width:560px}
.plate .row{display:flex;align-items:baseline;gap:10px;padding:5px 0}
.plate dt{color:var(--dim);white-space:nowrap}
.plate .leader{flex:1;border-bottom:2px dotted var(--faint);transform:translateY(-4px);min-width:24px}
.plate dd{margin:0;color:var(--ink);white-space:nowrap}

/* ─── the twelve tenets ───────────────────────────────────────── */
ol.tenets{list-style:none;margin:26px auto 0;padding:0;counter-reset:tenet;max-width:780px}
ol.tenets li{counter-increment:tenet;display:grid;
  grid-template-columns:86px minmax(0,1fr) 86px;gap:18px;
  padding:20px 10px;border-top:1px dotted var(--line-2)}
ol.tenets li:last-child{border-bottom:1px dotted var(--line-2)}
.tenet-num{font-family:var(--font-dos);font-size:42px;color:var(--faint);line-height:1;
  transition:color .3s ease,text-shadow .3s ease}
.tenet-num::before{content:counter(tenet,decimal-leading-zero)}
ol.tenets li:hover .tenet-num{color:var(--ink);text-shadow:0 0 14px rgba(255,255,255,.6)}
.tenet-body h3{font-family:var(--font-fantasy);font-size:19px;letter-spacing:.08em;margin:0 0 6px;font-weight:700}
.tenet-body p{margin:0;color:var(--dim);font-size:15.5px}

/* ─── figures / gallery / charts ──────────────────────────────── */
.fig-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:26px;margin-top:30px}
/* the benchmarks door: centred under the four plates, which leaves it beside
   the lion plate that sits bottom-left of this section */
.bench-cta{text-align:center;margin:38px 0 0;position:relative;z-index:2}
/* the door to the measured results: a touch louder than a ghost link */
.bench-cta .ghost-link{padding:12px 26px;font-size:21px;color:var(--ink);
  border-color:var(--line-2);background:rgba(5,5,6,.55)}
.bench-cta .ghost-link:hover{color:#000;background:#fff;border-color:#fff}
figure{margin:0}
figure svg.art{width:100%;height:auto;display:block;background:var(--bg-2);border:1px solid var(--line)}
/* one size for every plate: a fixed 3:2 window, the artwork centred and cropped
   to fit — the capture sizes differ, the tiles do not */
figure img.art{width:100%;aspect-ratio:3/2;height:auto;object-fit:cover;object-position:center top;
  display:block;background:var(--bg-2);border:1px solid var(--line)}
/* Square live capture: preserve the full harness frame at every screen size. */
video.teaser{width:80%;aspect-ratio:1/1;height:auto;display:block;margin:30px auto 0;
  background:var(--bg-2);border:1px solid var(--line);object-fit:contain}

/* ─── section backdrop: the lion behind the field-imagery frame ──────
   A black-and-white photograph whose creature sits in the RIGHT edge and the
   BOTTOM of the plate: right-anchored and bottom-anchored, so cover crops only
   empty sky. The generous bottom padding is the point — it is the band the
   lion looks out of, below the plates and clear of his face. Screen blending lets its black dissolve into
   the page's black, and the scrim is heavier on the left — over the type
   column — and lifts toward the lion, so the creature stays bright. */
section.has-backdrop{padding-bottom:34vh}     /* the band under the plates: his face stays clear */
section.has-backdrop > .wrap{position:relative;z-index:2}
section.has-backdrop figure,section.has-backdrop .fig-grid{position:relative;z-index:2}
img.section-backdrop{position:absolute;inset:0;z-index:0;width:100%;height:100%;
  object-fit:cover;object-position:right bottom;mix-blend-mode:screen;
  /* the plate composes its lion right-of-frame: the crop keeps him in shot at
     every width, and the mirror lands him — face turned inward — bottom-left */
  transform:scaleX(-1);transform-origin:center;
  pointer-events:none;user-select:none}
section.has-backdrop::before{content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(to bottom,rgba(5,5,6,.72) 0 44%,rgba(5,5,6,.16))}
@media (max-width:760px){
  section.has-backdrop{padding-bottom:26vh}
  .fig-grid{grid-template-columns:minmax(0,1fr)}
}

/* narrow: the command scrolls, so the copy button must sit in flow beside it
   rather than floating over text that can slide underneath */
@media (max-width:640px){
  .install-row{justify-content:flex-start}
  .install-cmd{flex:1;text-align:left;padding:0 8px}
  .copy-btn{position:static;transform:none;flex:none}
}

/* ─── pictures: photographs, plates and the teaser loop all resolve to the
   page's own black and white. The dot-matrix canvases are drawn in white on
   transparent already, so they are left alone. ── */
img,video{filter:var(--media-filter)}

/* ─── finale / summit ─────────────────────────────────────────── */
#finale{text-align:center}
/* the app's mountain scene: one canvas pixel per dot, scaled up crisp */
#mountain{display:block;width:min(600px,84vw);aspect-ratio:200/80;height:auto;
  image-rendering:pixelated;background:transparent;margin:0 auto 30px}
#finale.crowned .display{color:#fff;text-shadow:0 0 18px rgba(255,255,255,.55),0 0 60px rgba(255,255,255,.25)}
/* the outline cut is the face itself; keep it bright white at all times,
   with a soft glow only once the summit is crowned */
#finale .display.blackletter{color:#fff;-webkit-text-stroke:1px #fff;opacity:1;
  text-shadow:0 0 16px rgba(255,255,255,.30)}
#finale.crowned .display.blackletter{opacity:1;text-shadow:0 0 22px rgba(255,255,255,.35),0 0 70px rgba(255,255,255,.18)}
.ghost-link{background:none;border:1px solid var(--line-2);color:var(--dim);
  font-family:var(--font-dos);font-size:20px;letter-spacing:.1em;padding:10px 22px;
  cursor:pointer;transition:all .3s ease}
.ghost-link:hover{color:#000;background:#fff;border-color:#fff}


/* ─── what it is built from: two centred rows of small white line icons ── */
.stack-strip{display:flex;flex-direction:column;gap:14px;margin:26px auto 0;max-width:620px}
.stack-row{display:flex;flex-wrap:wrap;justify-content:center;gap:14px 18px}
.stack-item{display:flex;flex-direction:column;align-items:center;gap:6px;min-width:50px;
  color:var(--ink);opacity:.72;transition:opacity .25s ease}
.stack-item:hover{opacity:1}
.stack-item .ico{width:26px;height:26px;fill:none;stroke:currentColor;stroke-width:1.4;
  stroke-linecap:round;stroke-linejoin:round}
.stack-item span{font-family:var(--font-dos);font-size:16px;line-height:1;
  letter-spacing:.06em;color:var(--dim);white-space:nowrap}
.stack-item:hover span{color:var(--ink)}

/* ─── THE ENTRANCE (bottom of the document = the beginning) ───── */
#entrance{height:100vh;height:100svh;min-height:100svh;padding:0 24px;cursor:pointer;border-bottom:none}
.stage{display:flex;flex-direction:column;align-items:center;gap:3.5vh;margin:auto;
  transition:opacity .9s ease,transform .9s ease;position:relative}
.stage::before{content:"";position:absolute;inset:-18% -30%;z-index:-1;pointer-events:none;
  /* the faint lift behind the stage, faded out wide so it never reads as a patch
     on the letters: nothing here is drawn on the mark itself */
  background:radial-gradient(ellipse at 50% 45%,rgba(255,255,255,.045),transparent 72%)}

.axcalibur-wrap,.logo-wrap{opacity:0;animation:rise 1.7s cubic-bezier(.16,.84,.28,1) .55s forwards}


/* 01 · the points — the plate style, carried over */
.intro-points{margin:30px auto 0;font-family:var(--font-dos);font-size:21px;max-width:760px}
.intro-points .row{display:flex;align-items:baseline;gap:10px;padding:5px 0}
.intro-points dt{color:var(--dim);white-space:nowrap}
.intro-points .leader{flex:1;border-bottom:2px dotted var(--faint);transform:translateY(-4px);min-width:24px}
.intro-points dd{margin:0;color:var(--ink)}

/* ─── the mark: the angelX chrome wordmark ─────────────────────── */
.logo-wrap{z-index:2;display:flex;flex-direction:column;align-items:center;margin:0}
h1.logo{margin:0;line-height:1}
/* the wordmark keeps its chrome tint — the one deliberate break from the page's
   monochrome, so the mark reads as polished metal instead of flat white. It
   still takes the #tone curve, so its contrast matches every other picture. */
h1.logo img{display:block;width:min(510px,64vw);aspect-ratio:1429/331;height:auto;
  filter:url(#tone)}
.logo-sub{font-family:var(--font-dos);font-size:clamp(15px,2.2vw,22px);color:var(--faint);
  letter-spacing:.42em;text-transform:uppercase;margin:0;padding-left:.42em}

/* ─── the axcalibur rises; the mark waits beneath it ───────────── */
.axcalibur-wrap{z-index:1;display:flex;flex-direction:column;align-items:center}
.axcalibur-wrap .logo-wrap{margin-top:2.34%}
/* the real intro: one canvas pixel per dot, scaled up crisp */
#excalibur{display:block;width:min(900px,calc(1.765*min(510px,64vw)));aspect-ratio:1032/576;height:auto;
  image-rendering:pixelated;background:transparent;
  /* the water's own depth, plus the transparent rows the atlas carries: drop the
     animation by a share of its own height so the swell meets the letter tops
     with no gap. A transform, so the mark's layout never moves. */
  transform:translateY(9%)}
@keyframes rise{60%{opacity:1}100%{opacity:1;transform:translateY(0) scale(1)}}

/* ...pick it up — DOS prompt, bottom right */
.pick{position:absolute;right:4.5vw;bottom:6vh;background:none;border:none;cursor:pointer;
  color:var(--dim);font-family:var(--font-dos);font-size:clamp(22px,3vw,34px);
  letter-spacing:.04em;padding:8px 10px;opacity:0;
  animation:appear .8s ease 2.7s forwards,invite 2.8s ease-in-out 4.2s infinite}
.pick:hover{color:#fff;text-shadow:0 0 12px rgba(255,255,255,.7)}
.pick .cursor{display:inline-block;width:.55em;height:1em;background:currentColor;
  margin-left:.18em;vertical-align:-.12em;animation:blink 1.1s steps(1) infinite}
@keyframes blink{50%{opacity:0}}
@keyframes appear{to{opacity:1}}
@keyframes invite{50%{color:var(--ink)}}

/* rising dust motes */
.motes{position:absolute;inset:0;pointer-events:none;overflow:hidden}
.mote{position:absolute;width:3px;height:3px;border-radius:50%;background:#fff;opacity:0;
  animation:drift 10s linear infinite}
@keyframes drift{0%{transform:translateY(30px);opacity:0}10%{opacity:.5}
  90%{opacity:.15}100%{transform:translateY(-46vh);opacity:0}}

/* gate lifts once the star rises */
#entrance.lifted{cursor:default}
#entrance.lifted .motes{opacity:0;transition:opacity 1s ease}


/* the tiny star ping at the sword tip (before the ascent) */
.tip-ping{position:fixed;z-index:5;width:18px;height:18px;margin:-9px 0 0 -9px;
  pointer-events:none;fill:#fff;
  filter:drop-shadow(0 0 6px #fff) drop-shadow(0 0 16px rgba(255,255,255,.8));
  animation:ping 3.4s ease-in-out infinite}
@keyframes ping{0%{opacity:0;transform:scale(.25)}12%{opacity:1;transform:scale(1)}
  26%{opacity:.85;transform:scale(.8)}38%{opacity:.95;transform:scale(1.05)}
  55%{opacity:0;transform:scale(.35)}100%{opacity:0;transform:scale(.25)}}

/* the light streak the star rides during the ascent — a scroll-linked beam */
.light-streak{position:fixed;z-index:1;left:50%;width:7px;pointer-events:none;
  top:6vh;height:88vh;transform:translateX(-50%) scaleY(var(--p,0));
  transform-origin:50% 100%;border-radius:3px;
  background:linear-gradient(to top,rgba(255,255,255,0) 0%,
    rgba(255,255,255,.10) 18%,rgba(255,255,255,.32) 55%,rgba(255,255,255,.85) 92%,#fff 100%);
  filter:drop-shadow(0 0 8px rgba(255,255,255,.65));
  transition:transform .18s linear,opacity .5s ease}
body:not(.ascended) .light-streak{opacity:0}

/* the star that rises from behind the sword tip */
.rising-star{position:fixed;z-index:7;width:64px;height:64px;margin:-32px 0 0 -32px;pointer-events:none}
.rising-star svg{width:100%;height:100%;fill:#fff;
  filter:drop-shadow(0 0 8px #fff) drop-shadow(0 0 26px rgba(255,255,255,.85))}
.rising-star::after{content:"";position:absolute;left:50%;top:60%;width:2px;height:34vh;
  background:linear-gradient(to bottom,rgba(255,255,255,.85),transparent);transform:translateX(-50%)}
.rising-star.rise{animation:soar 1.5s cubic-bezier(.4,0,.8,.6) forwards}
@keyframes soar{to{transform:translateY(-135vh)}}

/* ─── small screens ───────────────────────────────────────────── */
@media (max-width:640px){
  section{padding:12vh 18px}
  ol.tenets li{grid-template-columns:56px 1fr;gap:12px}
  .tenet-num{font-size:32px}
  .hud{left:12px;bottom:12px;font-size:17px}
  .hud-bar{width:130px}
  .repo-link{font-size:14px;max-width:88vw}
  .pick{right:5vw;bottom:4vh}
}

/* ─── reduced motion ──────────────────────────────────────────── */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important}
  .reveal{opacity:1;transform:none}
  .axcalibur-wrap,.pick{opacity:1;transform:none}
}

/* the number gutter shifts the copy 52px right of the axis; at narrow widths the
   mirrored gutter costs more than it buys, so the number stacks above instead */
@media (max-width:760px){
  ol.tenets li{grid-template-columns:1fr;gap:6px;justify-items:center}
  .tenet-num{font-size:32px}
}

/* Blackletter DS (Derek Vogelpohl, dafont) — hero display face */
@font-face{font-family:'BlackletterDS';src:url('../assets/fonts/BlackletterDS.ttf') format('truetype');font-weight:400;font-display:swap}
