/* Spotify Wrapped — digital longread
   Design units: 1u = 1px of the 1440 Figma frame (scales with the viewport). */
:root {
  --ink: #0A0A0B; --ink-2: #141416; --white: #F3F3F0; --silver: #C9CCD1; --steel: #8A8F98;
  --ultra: #1ED760; --ultra-l: #1ED760;
  --u: calc(100vw / 1440);
  --ease-out: cubic-bezier(.16, 1, .3, 1);
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html { background: var(--ink); scrollbar-width: none; }
html::-webkit-scrollbar { display: none; }
body { background: var(--ink); color: var(--white); font-family: 'Onest', system-ui, sans-serif; -webkit-font-smoothing: antialiased; overflow-x: hidden; }
::selection { background: var(--ultra); color: var(--ink); }

/* ---------- layers ---------- */
#gl { position: fixed; inset: 0; width: 100vw; height: 100vh; z-index: 1; display: block; }
#track { position: relative; width: 1px; pointer-events: none; }
#chapters { position: fixed; inset: 0; z-index: 2; pointer-events: none; }
.ch .stage { position: fixed; inset: 0; overflow: hidden; visibility: hidden; contain: layout paint; }
.ch .stage.on { visibility: visible; }
.inner { position: relative; height: calc(var(--h) * var(--u)); will-change: transform; }

/* ---------- absolute Figma layout ---------- */
.it { position: absolute; left: calc(var(--x) * var(--u)); top: calc(var(--y) * var(--u)); }
.t { font-size: calc(var(--z) * var(--u)); line-height: var(--lh); letter-spacing: var(--ls); white-space: pre; font-feature-settings: 'tnum' 1, 'lnum' 1; }
.t.wrap { width: calc(var(--w) * var(--u)); white-space: pre-line; }
.fU { font-family: 'Unbounded', sans-serif; }
.fO { font-family: 'Onest', sans-serif; }
.up { text-transform: uppercase; }
.shape { width: calc(var(--w) * var(--u)); height: max(1px, calc(var(--h) * var(--u))); }
.shape.dot { border-radius: 50%; }
.shape.vbar { transform-origin: 50% 100%; transform: scaleY(var(--k, 0)); transition: transform 1.1s var(--ease-out); }
.shape.hbar { transform-origin: 0 50%; transform: scaleX(var(--k, 0)); transition: transform 1.2s var(--ease-out); }
.shape.hair { transform-origin: 0 50%; transform: scaleX(var(--k, 0)); transition: transform 1.4s var(--ease-out); }
.outline { width: calc(var(--w) * var(--u)); height: calc(var(--w) * var(--u) * 0.1665); overflow: visible; font-family: 'Unbounded', sans-serif; font-weight: 300; }
.outline text { animation: dash 9s linear infinite; }
@keyframes dash { to { stroke-dashoffset: -280; } }

/* 3D anchors: the WebGL object is drawn exactly into this box; the poster is the no-WebGL fallback */
.a3d { width: calc(var(--w) * var(--u)); height: calc(var(--h) * var(--u)); }
.a3d .poster { width: 100%; height: 100%; object-fit: contain; display: block; transition: opacity .6s; }
body.gl .a3d .poster { opacity: 0; }
.bulk { width: calc(var(--w) * var(--u)); height: calc(var(--h) * var(--u)); }
.bulk canvas { width: 100%; height: 100%; display: block; }

/* 06 — network + shared 9:16 frames */
.link { width: calc(var(--w) * var(--u)); height: 0; border-top: 1px dashed rgba(243, 243, 240, .5); transform-origin: 0 0; transform: rotate(var(--r)) scaleX(var(--k, 0)); }
.share { left: calc(var(--cx) * var(--u)); top: calc(var(--cy) * var(--u)); width: calc(var(--w) * var(--u)); height: calc(var(--h) * var(--u)); overflow: hidden;
  transform: translate(-50%, -50%) translate(var(--dx, 0px), var(--dy, 0px)) rotate(calc(var(--rot) * var(--e, 1))) scale(calc(.35 + .65 * var(--e, 1))); opacity: var(--e, 1); }
.share .share-img { width: calc(var(--w) * var(--u)); height: calc(var(--h) * var(--u)); object-fit: cover; }

/* 04 — story card */
.card { width: calc(var(--w) * var(--u)); height: calc(var(--h) * var(--u)); overflow: hidden; box-shadow: inset 0 0 0 1px rgba(243, 243, 240, .15); }
.card-bar { position: absolute; right: calc(80 * var(--u)); top: calc(40 * var(--u)); width: calc(6 * var(--u)); height: calc(410 * var(--u)); background: var(--ultra); transform-origin: 50% 100%; transform: scaleY(var(--k, 0)); transition: transform 1.4s var(--ease-out) .3s; }
.card.in .card-bar { --k: 1; }

/* 05 — sticky states */
.states { position: absolute; inset: 0; pointer-events: none; }
.stage:not(.on) .state { visibility: hidden !important; }   /* a chapter that left the screen takes its last Wrapped screen with it */
.state { position: absolute; left: 0; width: 100%; top: calc(50vh - 440 * var(--u)); height: calc(880 * var(--u)); visibility: hidden; }

/* ---------- the personal episode: a real Wrapped screenshot, the Spotify player, the reader's own track ---------- */
.box { width: calc(var(--w) * var(--u)); height: calc(var(--h) * var(--u)); }
.slot { border: 1.5px dashed rgba(243, 243, 240, .35); border-radius: calc(18 * var(--u)); background: var(--ink-2); display: flex; align-items: center; justify-content: center; overflow: hidden; }
.slot span { font-family: 'Onest', sans-serif; font-size: max(10px, calc(15 * var(--u))); line-height: 1.4; color: var(--steel); white-space: pre-line; padding: 12%; }
.slot img { width: 100%; height: 100%; object-fit: cover; display: block; }
.slot.shot { border: 1px solid rgba(243, 243, 240, .18); }
.embed { border-radius: calc(12 * var(--u)); background: #282828; overflow: hidden; pointer-events: auto; display: flex; align-items: center; }
.embed-host, .embed iframe { width: 100%; height: 100%; border: 0; }
.embed-wait { font-family: 'Onest', sans-serif; font-size: max(12px, calc(18 * var(--u))); color: #b3b3b3; padding: 0 6%; }
.field { pointer-events: auto; background: var(--ink-2); border: 1px solid rgba(243, 243, 240, .25); border-radius: calc(10 * var(--u)); color: var(--white);
  font: 400 max(14px, calc(20 * var(--u)))/1.4 'Onest', sans-serif; padding: calc(18 * var(--u)) calc(20 * var(--u)); resize: none; outline: none; }
.field:focus { border-color: var(--ultra-l); }
.field::placeholder { color: var(--steel); }
.btn { pointer-events: auto; background: var(--ultra); color: var(--ink); border: 0; border-radius: 999px; cursor: pointer;
  font: 500 max(11px, calc(15 * var(--u)))/1 'Unbounded', sans-serif; letter-spacing: .04em; text-transform: uppercase; }
.btn:hover { background: #3be477; }

.veil { filter: blur(7px); opacity: .55; transition: filter .7s var(--ease-out), opacity .7s; pointer-events: auto; cursor: pointer; user-select: none; }
.veil.open { filter: none; opacity: 1; cursor: auto; user-select: auto; }
.cue { pointer-events: auto; cursor: pointer; text-decoration: underline; text-underline-offset: .25em; transition: opacity .4s; }
.cue.gone { opacity: 0 !important; pointer-events: none; }
.btn.ghost { background: transparent; color: var(--ultra); box-shadow: inset 0 0 0 1.5px var(--ultra); }
.btn.ghost:hover { background: rgba(30, 215, 96, .1); }

.rcard { --k: 1; --p: calc(var(--k) * var(--u)); pointer-events: auto; position: relative; display: flex; flex-direction: column; padding: calc(28 * var(--p)) calc(24 * var(--p)) calc(26 * var(--p)); border-radius: calc(4 * var(--p)); overflow: hidden;
  background: radial-gradient(circle at 50% 23%, rgba(30, 215, 96, .16), transparent 50%), #0c0c0e; box-shadow: inset 0 0 0 1px rgba(243, 243, 240, .12); }
.rcard.on { background: radial-gradient(circle at 50% 23%, rgba(30, 215, 96, .4), rgba(30, 215, 96, .08) 40%, transparent 62%), #0c0c0e; }
.rc-label { font: 500 calc(9 * var(--p))/1.2 'Unbounded', sans-serif; letter-spacing: .06em; text-transform: uppercase; color: var(--white); }
.rc-disc { width: calc(120 * var(--p)); aspect-ratio: 1; flex: none; margin: calc(25 * var(--p)) auto 0; border-radius: 50%; position: relative;
  background: repeating-radial-gradient(circle, #17171a 0 1px, #0e0e10 1px 3px); box-shadow: 0 calc(14 * var(--p)) calc(30 * var(--p)) rgba(0, 0, 0, .6), inset 0 0 0 1px rgba(243, 243, 240, .1); }
.rc-disc::before { content: ''; position: absolute; inset: 0; border-radius: 50%; background: conic-gradient(from 200deg, transparent 0 20%, rgba(243, 243, 240, .14) 26%, transparent 32% 70%, rgba(243, 243, 240, .08) 76%, transparent 82%); }
.rc-disc i { position: absolute; inset: 35%; border-radius: 50%; background: radial-gradient(circle, #0c0c0e 0 10%, #3a3d42 11% 100%); transition: background .6s; }
.rcard.on .rc-disc { animation: rcspin 8s linear infinite; }
.rcard.on .rc-disc i { background: radial-gradient(circle, #0c0c0e 0 10%, var(--ultra) 11% 100%); }
@keyframes rcspin { to { transform: rotate(360deg); } }
.rc-track { margin-top: calc(30 * var(--p)); flex: none; font: 700 calc(26 * var(--p))/1.1 'Unbounded', sans-serif; letter-spacing: -.02em; color: rgba(243, 243, 240, .35); overflow-wrap: anywhere; hyphens: auto; }
.rcard.on .rc-track { color: var(--white); }
.rc-by { margin-top: calc(6 * var(--p)); flex: none; font: 400 calc(15 * var(--p))/1.3 'Onest', sans-serif; color: var(--steel); overflow-wrap: anywhere; }
.rcard.on .rc-by { color: var(--silver); }
.rc-why { margin-top: calc(16 * var(--p)); padding-top: calc(14 * var(--p)); border-top: 1px solid rgba(243, 243, 240, .14); flex: 1; min-height: 0; font: 400 calc(14 * var(--p))/1.45 'Onest', sans-serif; color: var(--steel); overflow-wrap: anywhere; overflow: hidden; }
.rcard.on .rc-why { color: var(--white); }
.btn:disabled { opacity: .35; cursor: default; }

/* ---------- reveals (calm: short travel, slow fade) ---------- */
.rv { opacity: 0; transform: translate3d(0, calc(12 * var(--u)), 0); transition: opacity 1.4s var(--ease-out), transform 1.4s var(--ease-out); }
.rv.in { opacity: 1; transform: none; }
.title.rv, .title.rv.in { opacity: 1; transform: none; }
.title .ln { display: block; overflow: hidden; padding-bottom: .08em; margin-bottom: -.08em; }
.title .ln > span { display: inline-block; transform: translate3d(0, 110%, 0); transition: transform 1.3s var(--ease-out); }
.title.in .ln > span { transform: none; }
.title .ln:nth-child(2) > span { transition-delay: .09s; }
.title .ln:nth-child(3) > span { transition-delay: .18s; }
.title .ln:nth-child(4) > span { transition-delay: .27s; }
.state .rv { transition-duration: .7s, .9s; }

/* ---------- chrome ---------- */
body.gl { cursor: grab; }
body.dragging { cursor: grabbing; }
#loader { position: fixed; inset: 0; z-index: 50; background: var(--ink); display: flex; flex-direction: column; justify-content: flex-end; padding: calc(48 * var(--u)); gap: 16px; transition: opacity .9s var(--ease-out), visibility .9s; }
#loader.done { opacity: 0; visibility: hidden; }
.ld-row { display: flex; justify-content: space-between; align-items: baseline; font-family: 'Unbounded', sans-serif; text-transform: uppercase; }
.ld-label { font-size: max(11px, calc(13 * var(--u))); letter-spacing: .08em; color: var(--steel); }
.ld-num { font-size: max(48px, calc(160 * var(--u))); font-weight: 200; letter-spacing: -.06em; line-height: .8; color: var(--white); font-feature-settings: 'tnum' 1; }
.ld-bar { height: 2px; background: rgba(243, 243, 240, .12); }
.ld-bar i { display: block; height: 100%; width: 0; background: var(--ultra); transition: width .3s; }
#hud { position: fixed; z-index: 10; left: calc(48 * var(--u)); bottom: max(20px, calc(32 * var(--u))); font-family: 'Unbounded', sans-serif; font-size: 11px; letter-spacing: .12em; color: var(--steel); pointer-events: none; opacity: 0; transition: opacity .6s; mix-blend-mode: difference; }
body.ready #hud { opacity: 1; }
.hud-num { color: var(--white); }
#grain { position: fixed; inset: -50%; z-index: 20; pointer-events: none; opacity: .055;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: grain 1.2s steps(6) infinite; }
@keyframes grain { 0%{transform:translate(0,0)} 20%{transform:translate(-3%,2%)} 40%{transform:translate(2%,-4%)} 60%{transform:translate(-4%,-2%)} 80%{transform:translate(3%,3%)} 100%{transform:translate(0,0)} }

/* ---------- no WebGL / reduced motion: a calm, fully readable page ---------- */
body.static #chapters, body.static .ch .stage { position: relative; inset: auto; visibility: visible; }
body.static .ch .stage { height: auto; }
body.static #track, body.static #gl { display: none; }
body.static .rv, body.static .title .ln > span { opacity: 1; transform: none; transition: none; }
body.static .shape { --k: 1; transition: none; }
body.static .link, body.static .share { --k: 1; --e: 1; }
body.static .states { position: relative; }
body.static .state { position: relative; top: auto; visibility: visible; }
body.static #chapters { pointer-events: auto; }

.mt { display: none; }

/* ---------- narrow screens: the Figma 414 (phone) and 768 (tablet) frames ---------- */
@media (max-width: 600px) {
  html:not(.desk) { --mu: calc(100vw / 414); }
  html:not(.desk) .inner { height: calc(var(--mih) * var(--mu)); }
  html:not(.desk) .mh { display: none !important; }
  html:not(.desk) .m { left: calc(var(--mx) * var(--mu)); top: calc(var(--my) * var(--mu)); }
  html:not(.desk) .m.t { font-size: max(7px, calc(var(--mf) * var(--mu))); }
  html:not(.desk) .m.t:not(.mw) { width: auto !important; white-space: pre; }
  html:not(.desk) .m.t.mw { width: calc(var(--mw) * var(--mu)) !important; white-space: pre-line; }
  html:not(.desk) .m.shape, html:not(.desk) .m.a3d, html:not(.desk) .m.bulk { width: calc(var(--mw) * var(--mu)); height: max(1px, calc(var(--mh) * var(--mu))); }
  html:not(.desk) .m.outline { width: calc(var(--mw) * var(--mu)); height: calc(var(--mw) * var(--mu) * .1665); }
  html:not(.desk) .m.box { width: calc(var(--mw) * var(--mu)); height: calc(var(--mh) * var(--mu)); }
  html:not(.desk) .m.field { font-size: max(14px, calc(14 * var(--mu))); padding: calc(12 * var(--mu)) calc(14 * var(--mu)); }
  html:not(.desk) .m.btn { font-size: calc(12 * var(--mu)); }
  html:not(.desk) .m.slot span { font-size: calc(10 * var(--mu)); }
  html:not(.desk) .m.embed .embed-wait { font-size: calc(12 * var(--mu)); }
  html:not(.desk) .m.rcard { --u: var(--mu); --k: 1; }
  html:not(.desk) .m.card { --u: calc(var(--mu) * var(--mk)); }
  html:not(.desk) .link { left: calc(var(--mlx) * var(--mu)); top: calc(var(--mly) * var(--mu)); width: calc(var(--w) * var(--mu) * 0.5); }
  html:not(.desk) .share { --u: calc(var(--mu) * 0.5); left: calc(var(--mlx) * var(--mu)); top: calc(var(--mly) * var(--mu)); }
  html:not(.desk) .state { top: calc(50vh - var(--msh) * var(--mu) / 2); height: calc(var(--msh) * var(--mu)); }
  html:not(.desk) .dt { display: none; }
  html:not(.desk) .mt { display: inline; }
  html:not(.desk) #loader { padding: 24px; }
  html:not(.desk) #hud { left: 20px; }
}
@media (min-width: 601px) and (max-width: 1024px) {
  html:not(.desk) { --qu: calc(100vw / 768); }
  html:not(.desk) .inner { height: calc(var(--qih) * var(--qu)); }
  html:not(.desk) .qh { display: none !important; }
  html:not(.desk) .q { left: calc(var(--qx) * var(--qu)); top: calc(var(--qy) * var(--qu)); }
  html:not(.desk) .q.t { font-size: max(7px, calc(var(--qf) * var(--qu))); }
  html:not(.desk) .q.t:not(.qw) { width: auto !important; white-space: pre; }
  html:not(.desk) .q.t.qw { width: calc(var(--qw) * var(--qu)) !important; white-space: pre-line; }
  html:not(.desk) .q.shape, html:not(.desk) .q.a3d, html:not(.desk) .q.bulk { width: calc(var(--qw) * var(--qu)); height: max(1px, calc(var(--qh) * var(--qu))); }
  html:not(.desk) .q.outline { width: calc(var(--qw) * var(--qu)); height: calc(var(--qw) * var(--qu) * .1665); }
  html:not(.desk) .q.box { width: calc(var(--qw) * var(--qu)); height: calc(var(--qh) * var(--qu)); }
  html:not(.desk) .q.field { font-size: max(14px, calc(21.0 * var(--qu))); padding: calc(18.0 * var(--qu)) calc(21.0 * var(--qu)); }
  html:not(.desk) .q.btn { font-size: calc(18.0 * var(--qu)); }
  html:not(.desk) .q.slot span { font-size: calc(15.0 * var(--qu)); }
  html:not(.desk) .q.embed .embed-wait { font-size: calc(18.0 * var(--qu)); }
  html:not(.desk) .q.rcard { --u: var(--qu); --k: 1; }
  html:not(.desk) .q.card { --u: calc(var(--qu) * var(--qk)); }
  html:not(.desk) .link { left: calc(var(--qlx) * var(--qu)); top: calc(var(--qly) * var(--qu)); width: calc(var(--w) * var(--qu) * 0.75); }
  html:not(.desk) .share { --u: calc(var(--qu) * 0.75); left: calc(var(--qlx) * var(--qu)); top: calc(var(--qly) * var(--qu)); }
  html:not(.desk) .state { top: calc(50vh - var(--qsh) * var(--qu) / 2); height: calc(var(--qsh) * var(--qu)); }
  html:not(.desk) .dt { display: none; }
  html:not(.desk) .mt { display: inline; }
  html:not(.desk) #loader { padding: 24px; }
  html:not(.desk) #hud { left: 40px; }
}
@media (prefers-reduced-motion: reduce) { #grain { animation: none; } }
