/* ==========================================================================
   sabrina.css — the fan page, dialled well past the point of taste.

   Loaded only by sabrina.html and scoped entirely to .walju-fan--sabrina, so
   the shared fan styles in landing.css (and /tate, which uses them) are left
   exactly as they were.

   The face crops this leans on are generated from the photos already in
   assets/images: sabrina-face1..16.jpg are tight head crops, one per look, and
   sabrina-wallpaper.jpg is a 4x4 grid of those crops that tiles seamlessly.
   ========================================================================== */

body.walju-fan--sabrina {
  --sab-wall: url('../assets/images/sabrina-wallpaper.jpg');
  --sab-f1: url('../assets/images/sabrina-face1.jpg');
  --sab-f2: url('../assets/images/sabrina-face2.jpg');
  --sab-f3: url('../assets/images/sabrina-face3.jpg');
  --sab-f4: url('../assets/images/sabrina-face4.jpg');
  --sab-f5: url('../assets/images/sabrina-face5.jpg');
  --sab-f6: url('../assets/images/sabrina-face6.jpg');
  --sab-f7: url('../assets/images/sabrina-face7.jpg');
  --sab-f8: url('../assets/images/sabrina-face8.jpg');
  --sab-f9: url('../assets/images/sabrina-face9.jpg');
  --sab-f10: url('../assets/images/sabrina-face10.jpg');
  --sab-f11: url('../assets/images/sabrina-face11.jpg');
  --sab-f12: url('../assets/images/sabrina-face12.jpg');
  --sab-f13: url('../assets/images/sabrina-face13.jpg');
  --sab-f14: url('../assets/images/sabrina-face14.jpg');
  --sab-f15: url('../assets/images/sabrina-face15.jpg');
  --sab-f16: url('../assets/images/sabrina-face16.jpg');
  --sab-hot: #ff3d8b;
  --sab-veil: rgba(248, 246, 239, .74);

  /* One face is 1/4 of the wallpaper tile, so the tile size is 4x the face. */
  --sab-face: 76px;
  /* Thickness of the fixed face border; one face fits it exactly. */
  --sab-frame: calc(var(--sab-face) / 2);

  position: relative;
  isolation: isolate;
  /* The frame is fixed over the viewport edges, so keep the page inside it. */
  padding-inline: var(--sab-frame);
  cursor: url('../assets/images/sabrina-cursor.png') 16 16, auto;
}

/* The frame overlaps the top and bottom edges, which is where the header and
   the footer live. Push both clear of it. */
body.walju-fan--sabrina .walju-header__inner { padding-top: var(--sab-frame); }
body.walju-fan--sabrina .walju-footer { padding-bottom: calc(26px + var(--sab-frame)); }

/* The header is absolute, so its 100% width resolves against the body's padding
   box and would hang off the right edge by the width of the padding. Inset it
   instead, which lands it in the same column as the rest of the page. */
body.walju-fan--sabrina .walju-header {
  width: auto;
  left: var(--sab-frame);
  right: var(--sab-frame);
}

/* The wallpaper. Fixed, so the whole page slides over one continuous face wall
   rather than each section carrying its own. */
body.walju-fan--sabrina::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  background-image: var(--sab-wall);
  background-size: calc(var(--sab-face) * 4);
  background-position: center;
}

/* Anything clickable keeps a face cursor too — the `auto` fallback would
   otherwise hand back a pointer and break the effect on links. */
body.walju-fan--sabrina a,
body.walju-fan--sabrina button,
body.walju-fan--sabrina summary {
  cursor: url('../assets/images/sabrina-cursor.png') 16 16, pointer;
}

body.walju-fan--sabrina ::selection { background: var(--sab-hot); color: #fff; }

/* Face scrollbar. WebKit only; Firefox falls back to the default bar. */
html:has(> body.walju-fan--sabrina)::-webkit-scrollbar { width: 17px; }
html:has(> body.walju-fan--sabrina)::-webkit-scrollbar-track { background: var(--fan-ink); }
html:has(> body.walju-fan--sabrina)::-webkit-scrollbar-thumb {
  background: var(--sab-f6) center / 17px repeat-y;
  border: 1px solid var(--fan-accent);
}

/* --------------------------------------------------------------------------
   Fixed decorative layers
   -------------------------------------------------------------------------- */

/* A border of faces around the viewport, marching clockwise. */
.sabrina-frame {
  position: fixed;
  inset: 0;
  z-index: 40;
  pointer-events: none;
}

.sabrina-frame span {
  position: absolute;
  /* Four faces to a tile, so a tile of 4x the band thickness shows exactly one
     unclipped row (or column) of them. */
  --shift: calc(var(--sab-frame) * 4);
  background-image: var(--sab-wall);
  background-size: var(--shift);
  background-position: 0 0;
}

.sabrina-frame span:nth-child(1),
.sabrina-frame span:nth-child(2) { left: 0; right: 0; height: var(--sab-frame); }
.sabrina-frame span:nth-child(1) { top: 0; animation: sabrina-slide-x 9s linear infinite; }
.sabrina-frame span:nth-child(2) { bottom: 0; animation: sabrina-slide-x 9s linear infinite reverse; }
.sabrina-frame span:nth-child(3),
.sabrina-frame span:nth-child(4) { top: 0; bottom: 0; width: var(--sab-frame); }
.sabrina-frame span:nth-child(3) { left: 0; animation: sabrina-slide-y 9s linear infinite reverse; }
.sabrina-frame span:nth-child(4) { right: 0; animation: sabrina-slide-y 9s linear infinite; }

/* Shifting by exactly one tile keeps the loop seamless whatever the tile size,
   so every user of these sets its own --shift to match its background-size. */
@keyframes sabrina-slide-x { from { background-position-x: 0; } to { background-position-x: var(--shift); } }
@keyframes sabrina-slide-y { from { background-position-y: 0; } to { background-position-y: var(--shift); } }

/* Falling faces and the cursor trail. Both are filled in by js/sabrina.js and
   simply stay empty when scripting is off. */
.sabrina-rain,
.sabrina-trail {
  position: fixed;
  inset: 0;
  z-index: 35;
  overflow: hidden;
  pointer-events: none;
}

.sabrina-rain b {
  position: absolute;
  top: -140px;
  width: 64px;
  height: 64px;
  background: var(--sab-f1) center / cover;
  border: 2px solid var(--fan-accent);
  border-radius: 50%;
  animation: sabrina-fall linear infinite;
}

@keyframes sabrina-fall {
  from { transform: translateY(0) rotate(0deg); }
  to { transform: translateY(calc(100vh + 280px)) rotate(540deg); }
}

.sabrina-trail b {
  position: absolute;
  width: 46px;
  height: 46px;
  margin: -23px 0 0 -23px;
  background: var(--sab-f6) center / cover;
  border-radius: 50%;
  animation: sabrina-poof 900ms ease-out forwards;
}

@keyframes sabrina-poof {
  from { opacity: .95; transform: scale(.5) rotate(0deg); }
  to { opacity: 0; transform: scale(1.5) rotate(160deg); }
}

/* --------------------------------------------------------------------------
   Hero
   -------------------------------------------------------------------------- */

/* The ink block is dropped to a veil so the fixed wallpaper reads through it,
   with a second face wall layered on top at a different scale. */
body.walju-fan--sabrina .walju-landing-hero {
  position: relative;
  background:
    linear-gradient(rgba(43, 31, 43, .8), rgba(43, 31, 43, .86)),
    var(--sab-wall) center / calc(var(--sab-face) * 9) fixed;
}

/* One enormous face behind the headline, breathing. */
.sabrina-halo {
  position: absolute;
  top: 50%;
  left: 50%;
  width: min(94vw, 880px);
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  background: var(--sab-f7) center / cover;
  border-radius: 50%;
  opacity: .26;
  mix-blend-mode: screen;
  animation: sabrina-breathe 7s ease-in-out infinite;
  pointer-events: none;
}

@keyframes sabrina-breathe {
  50% { transform: translate(-50%, -50%) scale(1.09); opacity: .34; }
}

/* A ring of faces orbiting the headline. Each face counter-rotates so it stays
   upright while the ring turns. */
.sabrina-orbit {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
  animation: sabrina-spin 34s linear infinite;
  pointer-events: none;
}

.sabrina-orbit b {
  position: absolute;
  width: 84px;
  height: 84px;
  margin: -42px 0 0 -42px;
  background-size: cover;
  background-position: center;
  border-radius: 50%;
  box-shadow: 0 0 0 3px var(--fan-accent);
  transform: rotate(var(--a)) translateX(min(44vw, 520px)) rotate(calc(var(--a) * -1));
  animation: sabrina-counter-spin 34s linear infinite;
}

@keyframes sabrina-spin { to { transform: rotate(360deg); } }
@keyframes sabrina-counter-spin {
  to { transform: rotate(var(--a)) translateX(min(44vw, 520px)) rotate(calc(var(--a) * -1 - 360deg)); }
}

body.walju-fan--sabrina .walju-landing-hero__grid { position: relative; z-index: 1; }

body.walju-fan--sabrina .walju-landing-hero h1 {
  text-shadow: 0 3px 0 var(--fan-accent-deep), 0 0 42px rgba(0, 0, 0, .65);
}

/* Every heading gets a face bolted to each side of it. */
body.walju-fan--sabrina h1 .sabrina-chip,
body.walju-fan--sabrina h2 .sabrina-chip {
  display: inline-block;
  width: .7em;
  height: .7em;
  margin: 0 .12em;
  vertical-align: baseline;
  background: var(--sab-f4) center / cover;
  border-radius: 50%;
  animation: sabrina-wobble 2.6s ease-in-out infinite;
}

@keyframes sabrina-wobble { 50% { transform: rotate(18deg) scale(1.14); } }

body.walju-fan--sabrina .walju-landing-hero__eyebrow {
  padding: 6px 12px 6px 40px;
  background: rgba(0, 0, 0, .4) var(--sab-f2) 6px center / 26px no-repeat;
  border: 1px solid var(--fan-accent);
  border-radius: 999px;
  display: inline-block;
}

body.walju-fan--sabrina .walju-landing-hero__intro {
  padding: 16px 18px;
  background: rgba(20, 12, 20, .66);
  border-left: 5px solid var(--fan-accent);
}

/* The button becomes a face that a label happens to sit on. */
body.walju-fan--sabrina .walju-button {
  position: relative;
  background: var(--fan-accent) var(--sab-f6) center / cover;
  border-color: var(--fan-accent);
  color: #fff;
  text-shadow: 0 2px 6px rgba(0, 0, 0, .9);
  box-shadow: 0 0 0 4px rgba(255, 61, 139, .55);
}

body.walju-fan--sabrina .walju-button:hover {
  background-image: var(--sab-f3);
  color: #fff;
}

/* Tally strip under the hero copy. */
.sabrina-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 26px 0 0;
  padding: 0;
  list-style: none;
}

.sabrina-stats li {
  padding: 8px 12px 8px 38px;
  background: rgba(20, 12, 20, .72) var(--sab-f5) 6px center / 24px no-repeat;
  border: 1px solid rgba(242, 163, 199, .55);
  font-size: 11px;
  font-weight: 750;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--fan-accent);
}

.sabrina-stats b { color: #fff; font-size: 13px; }

body.walju-fan--sabrina .sabrina-stats + .walju-button { margin-top: 26px; }

/* --------------------------------------------------------------------------
   Marquees
   -------------------------------------------------------------------------- */

/* Faces threaded between the words, in place of the middle dots. */
body.walju-fan--sabrina .walju-fan-marquee__track i {
  display: block;
  flex: none;
  width: 30px;
  height: 30px;
  margin-right: 20px;
  background-size: cover;
  background-position: center;
  border-radius: 50%;
  box-shadow: 0 0 0 2px var(--fan-ink);
}

body.walju-fan--sabrina .walju-fan-marquee { padding: 8px 0; }
body.walju-fan--sabrina .walju-fan-marquee--fast .walju-fan-marquee__track { animation-duration: 13s; }
body.walju-fan--sabrina .walju-fan-marquee--reverse .walju-fan-marquee__track { animation-direction: reverse; }
body.walju-fan--sabrina .walju-fan-marquee--deep { background: var(--fan-accent-deep); }
body.walju-fan--sabrina .walju-fan-marquee--deep span { color: #fff; }

/* A marquee of nothing but faces, no text at all. */
.sabrina-face-belt {
  --shift: calc(var(--sab-face) * 1.4);
  height: calc(var(--sab-face) * 1.4);
  background: var(--fan-ink) var(--sab-wall) 0 0 / var(--shift) repeat-x;
  animation: sabrina-slide-x 6s linear infinite;
  border-block: 4px solid var(--fan-accent);
}

/* --------------------------------------------------------------------------
   Body section
   -------------------------------------------------------------------------- */

/* Translucent, so the fixed wallpaper scrolls behind the copy. */
body.walju-fan--sabrina .walju-landing-links { background: var(--sab-veil); }

/* The copy blocks stay on solid paper, framed by faces, so the page is still
   readable with a face wall behind every pixel of it. */
/* A band of whole faces around the copy: the wallpaper on the outer box, an
   opaque panel inset from it. */
body.walju-fan--sabrina .walju-fan-note {
  position: relative;
  max-width: 740px;
  /* A band one face wide: four faces to a tile, so the tile is 4x the band and
     the band lands on exactly one unclipped row of them. */
  padding: var(--sab-frame);
  background: var(--sab-wall) 0 0 / calc(var(--sab-frame) * 4);
  box-shadow: 10px 10px 0 var(--fan-accent-deep);
}

body.walju-fan--sabrina .walju-fan-note p,
body.walju-fan--sabrina .walju-fan-note > .walju-text-link {
  display: block;
  max-width: none;
  margin: 0;
  padding: 20px 22px;
  background: var(--walju-cream);
}

body.walju-fan--sabrina .walju-fan-note > .walju-text-link {
  border-bottom: 0;
  text-align: center;
}

/* A column of faces down the left edge, the rest veiled for the type. */
body.walju-fan--sabrina .walju-landing-heading {
  position: relative;
  padding: 20px 22px 20px calc(var(--sab-face) + 22px);
  background:
    linear-gradient(rgba(248, 246, 239, .93), rgba(248, 246, 239, .93)) var(--sab-face) 0 / calc(100% - var(--sab-face)) 100% no-repeat,
    var(--sab-wall) 0 0 / calc(var(--sab-face) * 4);
}

/* The photo grid gets a face behind every gap. */
body.walju-fan--sabrina .walju-fan-grid {
  padding: var(--sab-frame);
  background: var(--sab-wall) 0 0 / calc(var(--sab-frame) * 4);
  box-shadow: inset 0 0 0 4px var(--fan-accent-deep);
}

body.walju-fan--sabrina .walju-fan-grid figure:hover { transform: translateY(-3px) rotate(-2deg) scale(1.04); }

/* --------------------------------------------------------------------------
   The wall — a section that is only her face.
   -------------------------------------------------------------------------- */

.sabrina-wall {
  position: relative;
  min-height: 74vh;
  display: grid;
  place-items: center;
  background: var(--sab-wall) center / calc(var(--sab-face) * 2);
  border-block: 6px solid var(--fan-accent);
  overflow: hidden;
  transition: background-size 600ms cubic-bezier(.2, .7, .3, 1);
}

.sabrina-wall:hover { background-size: calc(var(--sab-face) * 3.4); }

.sabrina-wall__plate {
  position: relative;
  max-width: min(92vw, 620px);
  margin: 40px 20px;
  padding: 30px 28px;
  text-align: center;
  background: rgba(43, 31, 43, .9);
  border: 5px solid var(--fan-accent);
  color: var(--walju-cream);
  box-shadow: 0 24px 60px rgba(0, 0, 0, .45);
}

.sabrina-wall__plate h2 {
  margin: 0 0 14px;
  font-size: clamp(34px, 6vw, 62px);
  line-height: .95;
  letter-spacing: -.06em;
  font-weight: 750;
}

.sabrina-wall__plate h2 em { font-family: var(--walju-serif); font-weight: 400; color: var(--fan-accent); }
.sabrina-wall__plate p { margin: 0; font-size: 14px; line-height: 1.7; color: var(--fan-muted); }
.sabrina-wall__plate p + p { margin-top: 14px; }

.sabrina-wall__count {
  display: block;
  margin-top: 18px;
  font-size: 11px;
  font-weight: 750;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--fan-accent);
}

/* --------------------------------------------------------------------------
   Chrome
   -------------------------------------------------------------------------- */

body.walju-fan--sabrina .walju-landing-header__context {
  padding-left: 30px;
  background: var(--sab-f1) 5px center / 18px no-repeat;
}

body.walju-fan--sabrina .walju-footer {
  background:
    linear-gradient(rgba(43, 31, 43, .72), rgba(43, 31, 43, .72)),
    var(--sab-wall) center / calc(var(--sab-face) * 2);
}

body.walju-fan--sabrina .walju-footer__inner { position: relative; z-index: 1; }

body.walju-fan--sabrina .walju-text-link:hover { color: var(--fan-accent); }

@media (max-width: 760px) {
  body.walju-fan--sabrina { --sab-face: 54px; }
  .sabrina-orbit b { width: 54px; height: 54px; margin: -27px 0 0 -27px; }
  .sabrina-wall { min-height: 62vh; }
  body.walju-fan--sabrina .walju-landing-hero,
  body.walju-fan--sabrina .walju-footer { background-attachment: scroll; }
}

/* Faces still everywhere, just holding still. The global reduced-motion rule in
   styles.css already stops the animations; this stops the fixed backgrounds
   from juddering on touch scroll and hides the rain, which has nothing left to
   do once it cannot fall. */
@media (prefers-reduced-motion: reduce) {
  body.walju-fan--sabrina .walju-fan-marquee__half i:last-child { display: none; }
  body.walju-fan--sabrina .walju-landing-hero,
  body.walju-fan--sabrina .walju-footer { background-attachment: scroll; }
  .sabrina-rain,
  .sabrina-trail { display: none; }
}
