/* ============================================================
   THE ARTIST'S OWN PAGE — Steam's profile, in this site's hand.

   The arrangement is Steam's: a header band, a narrow right column of
   status and counts, a wide left column of showcases, the thread last.
   The hand is the site's: All campaigns' rounded panels and toolbar pill
   (grid.css), the campaign page's avatar, pills, meter and comments
   (campaign.css), and nothing but --ground, --ink, --soft and --rule for
   colour, so light and dark both come for free.
   ============================================================ */

.sp{--gut:clamp(2rem, 4vw, 6rem); --panel:color-mix(in srgb, var(--ink) 4.5%, var(--ground))}
.sp [hidden]{display:none}

/* ============================================================
   THE HEADER BAND

   Steam lays the profile's background image under the band. Here it is the
   artist's own first photograph, taken out of focus and faded into the
   ground, so the band carries their colour without a single hardcoded one
   and the type over it stays legible in light and in dark.
   ============================================================ */
.sp-head{position:relative; isolation:isolate; overflow:hidden; margin-bottom:var(--s5)}
/* THE LIVING BACKGROUND. One layer per photograph (up to five), all blurred,
   only one lit at a time; the lit one fades in over 2.4s and creeps larger
   over 9s, so the band is never quite still. The whole stack of layers is
   moved against the cursor by profile.js — the inset leaves the room. */
/* the blurred layers get a frame of their own that crops them: Safari let
   them spill over the bar and the page once the menu floated (22 Sept 2026) */
.sp-head_clip{position:absolute; inset:0; z-index:-2; overflow:hidden; clip-path:inset(0)}
.sp-head_bg{position:absolute; inset:-14%; will-change:transform}
.sp-head_bg i{
  position:absolute; inset:0; background:center / cover no-repeat;
  filter:blur(3.6rem) saturate(1.25); opacity:0; transform:scale(1.08);
  transition:opacity 2.4s var(--easing), transform 9s linear;
}
.sp-head_bg i.is-on{opacity:.55; transform:scale(1.18)}
.sp-head::after{
  content:""; position:absolute; inset:0; z-index:-1;
  background:linear-gradient(to bottom,
    color-mix(in srgb, var(--ground) 35%, transparent) 0%,
    color-mix(in srgb, var(--ground) 72%, transparent) 60%,
    var(--ground) 100%);
}
.sp-head_in{
  max-width:148rem; margin:0 auto;
  padding:clamp(4rem, 8vh, 9rem) var(--gut) clamp(3rem, 6vh, 6rem);
  display:grid; grid-template-columns:auto minmax(0, 1fr) auto;
  gap:clamp(2rem, 3vw, 4rem); align-items:start;
}
.sp-avatar{width:clamp(9rem, 11vw, 16.4rem); height:clamp(9rem, 11vw, 16.4rem)}
.sp-name{
  margin:0; font-family:var(--face); font-weight:700;
  
  /* a step down (client, 12 September 2026): at 6.4rem the name outweighed
     the picture beside it and the line under it; 5.2rem still leads */
  font-size:clamp(2.8rem, 3.6vw, 5.2rem); line-height:.94; letter-spacing:-0.02em;
  text-transform:uppercase; text-wrap:balance;
}
.sp-tags{margin-top:1.2rem}
.sp-summary{
  margin:2rem 0 0; max-width:52ch;
  font-family:var(--face-ui); font-size:1.7rem; line-height:1.5; letter-spacing:-0.01em;
  text-wrap:pretty;
}

/* the primary action and the More menu, top right like Steam's */
.sp-acts{
  position:relative; display:flex; flex-wrap:wrap; justify-content:flex-end;
  align-items:center; gap:1rem; max-width:40rem;
}
.sp-say{flex-basis:100%; margin:0; text-align:right; min-height:1.6rem}
.sp-more{position:relative}
/* the toolbar pill from All campaigns, grown to sit beside a full button */
.sp-more_btn{padding:1.6rem 2rem; font-size:1.2rem}
.sp-more_btn i.sp-caret{
  /* class AND element: grid.css's `.cg-tool i{height:1.3rem}` is both, and
     at one class this lost its height, stretched tall and thin, and the
     rotated corner read as a tick instead of a chevron */
  width:.7rem; height:.7rem; border-right:1.5px solid currentColor; border-bottom:1.5px solid currentColor;
  transform:translateY(-.2rem) rotate(45deg); transition:transform var(--speed) var(--easing);
}
.sp-more_btn[aria-expanded="true"] .sp-caret{transform:translateY(.2rem) rotate(-135deg)}
.sp-menu{
  position:absolute; right:0; top:calc(100% + .8rem); z-index:200; min-width:20rem;
  padding:.6rem; border-radius:1.6rem; background:var(--ground);
  border:1px solid color-mix(in srgb, var(--ink) 14%, var(--ground));
  box-shadow:0 2rem 5rem -2rem color-mix(in srgb, var(--ink) 40%, transparent);
}
.sp-menu button{
  display:block; width:100%; padding:1.2rem 1.4rem; border:0; border-radius:1rem;
  background:none; color:var(--ink); text-align:left; cursor:pointer;
  font-family:var(--face-ui); font-size:1.4rem; font-weight:500;
}
.sp-menu button:hover,.sp-menu button:focus-visible{
  background:color-mix(in srgb, var(--ink) 8%, var(--ground)); outline:none;
}

/* ============================================================
   THE TWO COLUMNS — showcases wide on the left, the glance on the right
   ============================================================ */
.sp-cols{
  max-width:148rem; margin:0 auto; padding:0 var(--gut);
  display:grid; grid-template-columns:minmax(0, 1fr) 32rem;
  grid-template-areas:"main side";
  gap:clamp(2.4rem, 3vw, 4rem); align-items:start;
}
.sp-main{grid-area:main; display:grid; gap:var(--s4); min-width:0}
.sp-side{grid-area:side; position:sticky; top:var(--s4); display:grid; gap:var(--s4)}

/* ---- a showcase: the Cash App card ---- */
/* NO PANEL FILL — see the note on .lp-panel in leo.css. */
.sp-show{
  padding:clamp(2rem, 2.6vw, 3.2rem) 0; scroll-margin-top:var(--s4);
}
.sp-h{
  margin:0 0 var(--s4); display:flex; align-items:baseline; gap:1rem;
  font-family:var(--face-ui); font-weight:700; font-size:1.2rem; line-height:1;
  letter-spacing:.14em; text-transform:uppercase; color:var(--soft);
}
.sp-h em{font-style:normal; color:var(--ink); font-variant-numeric:tabular-nums}

/* ---- the photographs: one large, and a strip of the rest that scrolls ----

   THE STRIP SHOWS THREE AND SCROLLS THROUGH THE REST (client, 12 September
   2026). Steam counts what does not fit into a "+ 3" that goes somewhere
   else; here nothing goes anywhere until a photograph is chosen. The
   column holds up to nineteen and snaps a whole tile at a time. No fade
   (client, 13 September 2026): the top of the next row shows under the
   last full one instead, which says there is more without fogging a photo. Only a click on a photograph
   opens anything, and what it opens is the stack. */
.sp-shots{
  /* PORTRAIT, BECAUSE A PHONE SHOOTS PORTRAIT (client, 13 September 2026).
     Most of what artists upload is a 3:4 photograph from an iPhone; the old
     wide frame (2:1, a 2fr + 1fr split) showed 57% of such a photo's height
     in the big tile and 36% in the small ones — heads and tops cut off.
     Now the frame is 3:2 and splits in two equal halves: the big photograph
     on the left, a two-column strip on the right. With a 1.2rem gap both
     halves' tiles come out at 3:4, so a portrait shows whole; a landscape
     photograph gives up a little of its sides instead. */
  display:grid; grid-template-columns:minmax(0, 1fr) minmax(0, 1fr);
  grid-template-rows:minmax(0, 1fr); gap:1.2rem;
  aspect-ratio:3 / 2;
}
.sp-strip{
  position:relative; display:grid; gap:1.2rem; min-height:0;
  /* ONE TO A LINE (client, 22 September 2026): not two side by side, but
     one photograph per row, the width of the column, scrolling down */
  grid-template-columns:minmax(0, 1fr);
  grid-auto-rows:calc((100% - 2.4rem) / 2.2);   /* two rows, and the top of the third */
  overflow-y:auto; overscroll-behavior:contain;
  scroll-snap-type:y mandatory; scrollbar-width:none;
  border-radius:1.8rem;
}
.sp-strip::-webkit-scrollbar{display:none}
.sp-strip > .sp-shot{scroll-snap-align:start}
.sp-shot{
  position:relative; display:block; width:100%; height:100%; min-height:0;
  padding:0; border:0; overflow:hidden; border-radius:1.8rem;
  background:color-mix(in srgb, var(--ink) 8%, var(--ground));
  color:var(--ink); font:inherit; cursor:pointer; -webkit-appearance:none; appearance:none;
  /* ALL CAMPAIGNS' HIDDEN STATE, scale .55 and nothing to see, until the
     showcase comes into view — then each tile comes up on its own delay */
  opacity:0; transform:scale(.55);
  transition:opacity var(--speed-slow) var(--power3-out), transform var(--speed-slow) var(--power3-out);
}
.sp-shots.is-shown .sp-shot{opacity:1; transform:none; transition-delay:var(--d, 0s)}
.sp-shot img{
  position:absolute; inset:0; display:block; width:100%; height:100%; object-fit:cover;
  -webkit-user-drag:none; transition:transform var(--speed) var(--easing);
}
.sp-shot:hover img{transform:scale(1.04)}
.sp-shot:focus-visible{outline:2px solid var(--ink); outline-offset:3px}
.sp-strip .sp-shot:focus-visible{outline-offset:-3px}
/* the tile's number, up on hover like All campaigns' label on a tile */
.sp-shot_n{
  position:absolute; left:1rem; bottom:1rem; z-index:1; pointer-events:none;
  padding:.5rem .9rem; border-radius:99px;
  background:color-mix(in srgb, var(--ground) 82%, transparent); color:var(--ink);
  font-family:var(--face-ui); font-size:1.05rem; font-weight:600; letter-spacing:.14em;
  font-variant-numeric:tabular-nums; opacity:0; transition:opacity var(--speed) var(--easing);
}
.sp-shot:hover .sp-shot_n,.sp-shot:focus-visible .sp-shot_n{opacity:1}

/* ---- the biography ---- */
.sp-bio{
  margin:0; max-width:64ch; font-family:var(--face-ui);
  font-size:1.7rem; line-height:1.55; letter-spacing:-0.011em; text-wrap:pretty;
}
.sp-bio + .sp-bio{margin-top:1.4rem}
.sp-empty{
  margin:0; display:inline-block; padding:1.1rem 1.8rem; border-radius:99px;
  border:1px dashed color-mix(in srgb, var(--ink) 30%, transparent);
  font-family:var(--face-ui); font-size:1.4rem; color:var(--soft);
}
.sp .cp-preview{border-color:var(--soft); color:var(--soft)}

/* ---- the campaign: capsule, title, meter, stats row ---- */
.sp-camp{
  position:relative; display:grid; grid-template-columns:minmax(0, 1fr) minmax(0, 1.25fr);
  gap:clamp(2rem, 3vw, 3.2rem); align-items:center;
}
.sp-camp_pic{
  display:block; aspect-ratio:16 / 10; overflow:hidden; border-radius:1.8rem;
  background:color-mix(in srgb, var(--ink) 8%, var(--ground));
}
.sp-camp_pic img{
  display:block; width:100%; height:100%; object-fit:cover; -webkit-user-drag:none;
  transition:transform var(--speed-slow) var(--power3-out);
}
.sp-camp:hover .sp-camp_pic img{transform:scale(1.04)}
.sp-camp_h{
  margin:1rem 0 0; font-family:var(--face-ui); font-weight:600;
  font-size:clamp(1.9rem, 2vw, 2.4rem); line-height:1.25; letter-spacing:-0.015em; text-wrap:balance;
}
.sp-camp_h a{color:inherit; text-decoration:none}
.sp-camp_h a::after{content:""; position:absolute; inset:0; z-index:1}
.sp-camp:has(.sp-camp_h a:focus-visible){outline:2px solid var(--ink); outline-offset:1rem; border-radius:1.8rem}
.sp-camp_h a:focus-visible{outline:none}
.sp-camp_go{position:relative; z-index:2; margin-top:var(--s4)}
.sp-camp_more{margin:var(--s4) 0 0; font-family:var(--face-ui); font-size:1.3rem; color:var(--soft)}

/* ---- PAST CAMPAIGNS, a column beside the running one ----
   The running campaign stays exactly as it is — picture beside the words —
   and the finished ones sit to its right as smaller cards on the page's own
   ground, in a list that scrolls inside the height the running one sets.
   (It first turned the running card picture-on-top, which made it tall
   enough to hold every past card at once, and then nothing scrolled.) */
.sp-campwrap.has-past{
  display:grid; grid-template-columns:minmax(0, 1fr) minmax(0, 32rem);
  gap:clamp(2rem, 2.6vw, 3.6rem); align-items:stretch;
}
.sp-past{display:flex; flex-direction:column; min-width:0; min-height:0}
.sp-past_h{
  margin:0 0 1.2rem; display:flex; align-items:baseline; gap:.8rem;
  font-family:var(--face-ui); font-weight:700; font-size:1.1rem; line-height:1;
  letter-spacing:.14em; text-transform:uppercase; color:var(--soft);
}
.sp-past_h em{font-style:normal; color:var(--ink); font-variant-numeric:tabular-nums}
/* the box takes the running campaign's height; the list scrolls inside it
   and never pushes that height itself */
.sp-past_box{position:relative; flex:1; min-height:26rem}
.sp-past_list{
  position:absolute; inset:0; margin:0; padding:0; list-style:none;
  display:grid; align-content:start; gap:.8rem;
  overflow-y:auto; overscroll-behavior:contain; scroll-snap-type:y proximity;
  scrollbar-width:none; border-radius:1.6rem;
}
.sp-past_list::-webkit-scrollbar{display:none}
.sp-pastrow{
  scroll-snap-align:start;
  display:grid; grid-template-columns:6.4rem minmax(0, 1fr) auto; gap:1.2rem; align-items:center;
  padding:1rem 0;   /* panel fill removed — see .lp-panel in leo.css */
}
.sp-pastrow_pic{
  display:block; aspect-ratio:1; overflow:hidden; border-radius:1rem;
  background:color-mix(in srgb, var(--ink) 8%, var(--ground));
}
/* a little colour taken out: finished, not current */
.sp-pastrow_pic img{display:block; width:100%; height:100%; object-fit:cover; filter:grayscale(.35); -webkit-user-drag:none}
.sp-pastrow_t{min-width:0}
.sp-pastrow_h{
  margin:0; font-family:var(--face-ui); font-weight:600; font-size:1.35rem; line-height:1.3;
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;
}
.sp-pastrow_m{
  margin:.4rem 0 0; font-family:var(--face-ui); font-size:1.05rem; letter-spacing:.12em;
  text-transform:uppercase; color:var(--soft); font-variant-numeric:tabular-nums;
}
.sp-pastrow_m b{color:var(--ink); font-weight:600}
@media (max-width:1000px){
  .sp-campwrap.has-past{grid-template-columns:minmax(0, 1fr)}
  .sp-past_box{min-height:0}
  .sp-past_list{position:static; max-height:30rem}   /* about two cards, then it scrolls */
}

/* Steam's showcase_stats_row: value over label, in a row */
.sp-stats{display:flex; flex-wrap:wrap; gap:1.6rem clamp(2.4rem, 3vw, 4rem); margin-top:var(--s4)}
.sp-stat{display:flex; flex-direction:column-reverse; gap:.4rem; margin:0}
.sp-stat dd{
  margin:0; font-family:var(--face-ui); font-weight:700; font-size:2.6rem; line-height:1;
  letter-spacing:-0.02em; font-variant-numeric:tabular-nums; color:var(--ink);
}
.sp-stat dt{
  font-family:var(--face-ui); font-size:1.1rem; font-weight:600;
  letter-spacing:.14em; text-transform:uppercase; color:var(--soft);
}

/* ---- the niche: an app-icon tile, a name, a stats row ---- */
.sp-nichebox{display:grid; grid-template-columns:auto minmax(0, 1fr); gap:clamp(1.6rem, 2vw, 2.4rem); align-items:start}
.sp-niche_mark{
  width:clamp(7.2rem, 7vw, 9.6rem); height:clamp(7.2rem, 7vw, 9.6rem); border-radius:24%;
  display:grid; place-items:center; background:var(--ink); color:var(--ground);
  font-family:var(--face); font-weight:700; font-size:clamp(3rem, 3vw, 4rem); text-transform:uppercase;
}
.sp-niche_name{
  margin:0; font-family:var(--face); font-weight:700; font-size:clamp(2rem, 2.2vw, 2.8rem);
  line-height:1; letter-spacing:-0.02em; text-transform:uppercase;
}
.sp-niche_d{margin:.8rem 0 0; font-family:var(--face-ui); font-size:1.4rem; color:var(--soft)}
.sp-nichebox .sp-stats{margin-top:1.6rem}
.sp-niche_go{margin-top:var(--s4)}

/* ---- the thread sits under its composer, as on Steam ---- */
.sp-talk .cp-thread{margin-top:var(--s4)}

/* ============================================================
   THE RIGHT COLUMN
   ============================================================ */
.sp-status{
  display:grid; grid-template-columns:auto minmax(0, 1fr); column-gap:1.2rem; align-items:baseline;
  padding:1.8rem 0;   /* panel fill removed — see .lp-panel in leo.css */
}
.sp-status i{
  width:.9rem; height:.9rem; border-radius:50%; align-self:center;
  border:1.5px solid var(--soft);
}
.sp-status.is-live i{background:var(--spark); border-color:var(--spark)}   /* alive — see --spark */
.sp-status b{font-family:var(--face-ui); font-weight:600; font-size:1.5rem}
.sp-status span{grid-column:2; font-family:var(--face-ui); font-size:1.3rem; color:var(--soft); margin-top:.3rem}

.sp-counts{display:grid; gap:.2rem}
.sp-count{
  display:flex; justify-content:space-between; align-items:baseline; gap:1rem;
  padding:1.2rem 1.4rem; border-radius:1.2rem; color:var(--ink); text-decoration:none;
  font-family:var(--face-ui); font-size:1.2rem; font-weight:600; letter-spacing:.14em; text-transform:uppercase;
  transition:background var(--speed) var(--easing);
}
.sp-count b{
  font-weight:700; font-size:1.8rem; letter-spacing:-0.01em; text-transform:none;
  font-variant-numeric:tabular-nums;
}
.sp-count:hover,.sp-count:focus-visible{background:color-mix(in srgb, var(--ink) 8%, var(--ground)); outline:none}
/* THE SECTION YOU ARE READING, lit in the right column as you scroll past it */
.sp-count.is-current{background:color-mix(in srgb, var(--ink) 8%, var(--ground))}
.sp-count > span{display:inline-flex; align-items:center}
.sp-count > span::before{
  content:""; width:0; height:.6rem; margin-right:0; border-radius:50%; background:var(--spark);   /* current — see --spark */
  transition:width var(--speed) var(--power3-out), margin var(--speed) var(--power3-out);
}
.sp-count.is-current > span::before{width:.6rem; margin-right:1rem}

.sp-peers{display:grid; gap:.2rem}
.sp-peerlist{list-style:none; margin:0; padding:0; display:grid; gap:.2rem}
.sp-peer a{
  display:grid; grid-template-columns:4rem minmax(0, 1fr); gap:1.2rem; align-items:center;
  padding:.8rem 1.4rem; border-radius:1.2rem; color:inherit; text-decoration:none;
  transition:background var(--speed) var(--easing);
}
.sp-peer a:hover,.sp-peer a:focus-visible{background:color-mix(in srgb, var(--ink) 8%, var(--ground)); outline:none}
.sp-peer .cp-avatar{width:4rem; height:4rem}
.sp-peer b{display:block; font-family:var(--face-ui); font-weight:600; font-size:1.4rem; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.sp-peer span{display:block; margin-top:.2rem; font-family:var(--face-ui); font-size:1.2rem; color:var(--soft)}

/* the foot runs the page's width, not the campaign page's column */
.sp .cp-foot{max-width:148rem; padding-left:var(--gut); padding-right:var(--gut)}

/* ============================================================
   ONE PHOTOGRAPH, FULL SCREEN — All campaigns' card stack

   grid.css draws the stack, the cards, the veil, the counter and the
   button; this only makes the cards the shape of a photograph. The pictures
   are 3:4, so the card is 3:4 and nothing is cropped — as tall as the
   window allows once the button has its room, and never wider than the
   screen. The flight between tile and card changes shape on the way, so it
   animates the box, not a uniform scale.
   ============================================================ */
.sp-page{
  --ch:min(calc(100vh - 20rem), calc(92vw / .75));
  --cw:calc(var(--ch) * .75);
}
.sp-stack{background:var(--ground); z-index:130; cursor:grab}
.sp-stack.is-dragging{cursor:grabbing}
.sp-stack .cg-card{width:var(--cw); height:var(--ch); margin:calc(var(--ch) / -2) 0 0 calc(var(--cw) / -2)}
.sp-stack .cg-card_in{border-radius:2.4rem}
.sp-at,.sp-back{z-index:140}
.sp-at{top:var(--s3); right:var(--s4)}
.sp-stackname{
  position:fixed; left:var(--s4); top:var(--s3); z-index:140; margin:0;
  font-family:var(--face); font-weight:700; font-size:1.7rem; line-height:1;
  letter-spacing:-0.01em; text-transform:uppercase;
  opacity:0; visibility:hidden;
  transition:opacity var(--speed) var(--easing), visibility var(--speed) var(--easing);
}
.cg-stack.is-open ~ .sp-stackname{opacity:1; visibility:visible}
.sp-clone{position:fixed; z-index:150; margin:0; overflow:hidden; pointer-events:none}
.sp-clone img{display:block; width:100%; height:100%; object-fit:cover}
.sp-clone.is-flying{
  transition:left var(--speed-slow) var(--power2-in-out), top var(--speed-slow) var(--power2-in-out),
             width var(--speed-slow) var(--power2-in-out), height var(--speed-slow) var(--power2-in-out),
             border-radius var(--speed-slow) var(--power2-in-out);
}
.sp-page.is-stacking{overflow:hidden}

/* ============================================================
   NARROW — Steam's responsive order: the header, then the glance, then
   the showcases
   ============================================================ */
@media (max-width:1000px){
  .sp-head_in{grid-template-columns:auto minmax(0, 1fr)}
  .sp-acts{grid-column:1 / -1; justify-content:flex-start; max-width:none}
  .sp-say{text-align:left}
  .sp-cols{grid-template-columns:minmax(0, 1fr); grid-template-areas:"side" "main"}
  .sp-side{position:static; grid-template-columns:repeat(2, minmax(0, 1fr)); align-items:start}
  .sp-status{grid-column:1 / -1}
}
@media (max-width:640px){
  .sp-head_in{grid-template-columns:minmax(0, 1fr)}
  .sp-side{grid-template-columns:minmax(0, 1fr)}
  .sp-camp{grid-template-columns:minmax(0, 1fr)}
  /* on a phone the big one stands alone and the strip turns on its side:
     three portrait tiles across, swiped sideways, the fade at the right edge */
  .sp-shots{grid-template-columns:minmax(0, 1fr); grid-template-rows:auto; aspect-ratio:auto}
  .sp-shot--main{aspect-ratio:3 / 4}
  .sp-strip{
    grid-template-columns:none;
    grid-auto-rows:auto; grid-auto-flow:column; grid-auto-columns:calc((100% - 2.4rem) / 3.35);
    overflow-x:auto; overflow-y:hidden; scroll-snap-type:x mandatory;
  }
  .sp-strip > .sp-shot{aspect-ratio:3 / 4; height:auto}
}
@media (prefers-reduced-motion:reduce){
  .sp-shot,.sp-shot img,.sp-camp_pic img,.sp-caret,.sp-count,.sp-peer a{transition:none}
  .sp-clone{display:none}
}


/* ============================================================
   MOTION — the reference's moves, added 12 September 2026
   (client: "make it more cool").

   Every one of these is progressive: the classes that hide things are
   added by profile.js, so with no script the page is simply all there; and
   under reduced motion the block at the end puts everything at rest.
   ============================================================ */

/* ---- THE NAME RISES OUT OF A MASK, word by word ---- */
.sp-w{display:inline-block; overflow:hidden; vertical-align:top; padding-bottom:.08em; margin-bottom:-.08em}
.sp-w > span{
  display:inline-block; transform:translateY(110%);
  transition:transform 1s var(--power3-out); transition-delay:var(--d, 0s);
}
.sp-head.is-in .sp-w > span{transform:none}
/* and what stands around it follows it in */
.sp-intro{
  opacity:0; transform:translateY(1.4rem);
  transition:opacity .9s var(--easing), transform .9s var(--power3-out);
  transition-delay:var(--d, 0s);
}
.sp-head.is-in .sp-intro{opacity:1; transform:none}

/* ---- PANELS RISE IN AS THEY REACH THE SCREEN ---- */
.sp-rise{
  opacity:0; transform:translateY(3.2rem);
  transition:opacity .9s var(--easing), transform .9s var(--power3-out);
  transition-delay:var(--d, 0s);
}
.sp-rise.is-in{opacity:1; transform:none}
/* the funding ring runs round once its panel is in view */
.sp-ring_arc{transition:stroke-dashoffset 1.6s var(--power3-out) .25s}

@media (prefers-reduced-motion:reduce){
  .sp-head_bg i,.sp-w > span,.sp-intro,.sp-rise,.sp-ring_arc,
  .sp-count > span::before{transition:none}
  .sp-w > span,.sp-intro,.sp-rise{opacity:1; transform:none}
}


/* ============================================================
   THE FUNDING RING (13 September 2026)
   design.cash.app's spinner — viewBox 40, r 18, one thin stroke — as the
   measure of a campaign. The track is the page's rule colour, the arc is
   ink and starts at twelve o'clock. Each size sets its own stroke width in
   viewBox units so the line lands near 2px on screen: 12.8rem is 128px,
   3.2 times the viewBox, so .64; 5.2rem is 1.3 times, so 1.5.
   ============================================================ */
.sp-camp_meter{display:flex; align-items:center; flex-wrap:wrap; gap:1.6rem clamp(2.4rem, 3vw, 4rem); margin-top:var(--s4)}
.sp-camp_meter .sp-stats{margin-top:0}
.sp-ring{position:relative; display:grid; place-items:center; flex:none}
.sp-ring svg{position:absolute; inset:0; width:100%; height:100%; transform:rotate(-90deg); overflow:visible}
.sp-ring circle{fill:none}
.sp-ring_track{stroke:var(--rule)}
.sp-ring_arc{stroke:var(--ink); stroke-linecap:round; stroke-dasharray:100}
.sp-ring.is-zero .sp-ring_arc{opacity:0}
.sp-ring_n{position:relative; display:grid; justify-items:center; line-height:1; text-align:center}
.sp-ring_n b{font-family:var(--face-ui); font-weight:700; font-variant-numeric:tabular-nums; letter-spacing:-0.02em; color:var(--ink)}
.sp-ring_n i{font-style:normal; font-family:var(--face-ui); font-weight:600; text-transform:uppercase; letter-spacing:.14em; color:var(--soft)}

.sp-ring--lg{width:12.8rem; height:12.8rem}
.sp-ring--lg circle{stroke-width:.64}
.sp-ring--lg .sp-ring_n b{font-size:3rem}
.sp-ring--lg .sp-ring_n i{margin-top:.6rem; font-size:1rem}

.sp-ring--sm{width:5.2rem; height:5.2rem}
.sp-ring--sm circle{stroke-width:1.5}
.sp-ring--sm .sp-ring_n b{font-size:1.1rem; letter-spacing:-0.01em}

/* ---- YOUR OWN PROFILE (13 September 2026) ---- */
.sp-empty a{color:var(--ink); text-decoration:underline; text-underline-offset:.24em; text-decoration-color:color-mix(in srgb, var(--ink) 35%, transparent)}
.sp-empty a:hover{text-decoration-color:var(--ink)}
/* the setup page's preview: drawn at rest, every time it is redrawn */
.is-draft *,.is-draft *::before,.is-draft *::after{transition:none !important; animation:none !important}
/* no photographs: the frame stops being a 3:2 grid, so the empty pill is a
   pill and not a dashed outline stretched round half the panel */
.sp-shots:has(> .sp-empty){display:block; aspect-ratio:auto}

/* ---- the artist's own arrangement (22 September 2026) ---- */
/* the measuring box is the parent: a grid cannot size its own rows off
   its own width with cqi, which read a wider box and made squares tall */
.sp-shots--bento{display:block; aspect-ratio:auto; container-type:inline-size}
.sp-bento{
  display:grid; grid-template-columns:repeat(4, minmax(0, 1fr)); gap:1.2rem;
  grid-auto-rows:calc((100cqi - 3 * 1.2rem) / 4); grid-auto-flow:dense;
}
.sp-bento .sp-shot{height:auto}
@media (max-width:640px){
  .sp-bento{grid-template-columns:repeat(2, minmax(0, 1fr)); grid-auto-rows:calc((100cqi - 1.2rem) / 2)}
}

/* THE BIO IS ONE LINE (22 September 2026): it stops where the line ends,
   at 60 characters, and anything longer that arrives is cut with an
   ellipsis rather than running on */
.sp-summary{white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:100%}
