/* ---------- portfolio: albums as magazines on a clothes rail ---------- */
/* --w is the width of a hanging magazine = 30 cm in real life, so 1 cm = --w / 30.
   The hanger and the rail are made in Blender (blender/hanger_en_rail.py) -- on the page
   they are drawn live in 3D by portfolio-chrome.js, the renders are the fallback -- seen
   from 45 degrees to the side with a bit of perspective, right-hand end nearer, like the
   reference photo. The hook goes from front to back: the neck rises in front of the rail
   and the tip bends over it and down behind it. Sizes below come from
   blender/uitvoer/layout.json, as multiples of --w:
     hanger picture   31.9 cm wide x 28.2 cm tall        = 1.0621 W x 0.9392 W
     rail centre      4.62 cm below the picture's top     = 0.154 W
     hook centre      42.8 % from its left edge, the neck 50 %
   Every album is a 3D magazine rendered in Blender (blender/magazijn.py): a stack of
   sheets folded over the hanger's bottom bar, hanging in a gentle curve. Its picture is
   as wide as the hanger's and lies over it, starting 0.752 W below the hanger's top, so
   the bar runs through the fold and its ends stick out on both sides. */

.rail-header{ padding-bottom:1.5rem; }
.rail-header .label{ display:block; margin-bottom:1.2rem; }

.rail-section{
  --w:260px;
  position:relative;
  padding:0;
  height:calc(var(--w) * 2.5 + 3rem);
  /* the slanted rail may reach above the section, so only the sides are clipped */
  overflow-x:clip;
  overflow-y:visible;
}

/* chrome rail (render), full width; the picture is stretched sideways, which is
   invisible on a tube whose reflections all run lengthways */
.rail{
  position:absolute; left:-6%; right:-6%;
  /* rail centre 0.154 W below the hangers' top, minus half the picture (0.07 W) */
  top:calc(2.6rem + var(--w) * 0.084);
  height:calc(var(--w) * 0.14);
  background:url(assets-portfolio/rail.webp) center / 100% 100% no-repeat;
  filter:drop-shadow(0 7px 6px rgba(20,15,5,0.16));
  z-index:2;
  /* the rail hangs a little slanted (the same angle as TILT in portfolio-rail.js) */
  transform:rotate(2.4deg);
  transform-origin:50% 50%;
}

.rail-items{
  position:absolute; left:0; right:0; top:2.6rem; bottom:0;
  z-index:3;
}

.hanger-item{
  position:absolute; top:0; left:0;
  width:calc(var(--w) * 1.0621);
  /* tips around the hook on the rail */
  transform-origin:42.8% calc(var(--w) * 0.154);
  will-change:transform;
  -webkit-tap-highlight-color:transparent;
  outline:none;
}
.hanger-body{ position:relative; }
/* the magazine hangs below the hanger picture, so the clickable box has to reach down to the
   magazine's lower edge (top of the sprite 0.752 W + its height 0.964 W), or the lower part of the
   album would not react to the pointer */
.hanger-item{ height:calc(var(--w) * 1.72); }
.hanger-body{ height:100%; }

/* the chrome hanger (render with transparent background; the part of the hook that
   belongs behind the rail is already cut away, the rest passes in front of it) */
.hanger-img{
  position:relative; z-index:2;
  display:block; width:100%; height:auto;
  pointer-events:none; user-select:none;
  filter:drop-shadow(0 3px 3px rgba(20,15,5,0.2));
}

/* the magazine: a Blender render laid over the hanger (see the header) */
.mag-sprite{
  position:absolute; z-index:3;
  left:0; top:calc(var(--w) * 0.752);
  width:100%; height:auto;
  pointer-events:none; user-select:none;
  filter:drop-shadow(calc(var(--w) * 0.02) calc(var(--w) * 0.04) calc(var(--w) * 0.045) rgba(20,15,5,0.24));
}
/* with the 3D version running, the flat cover is only there for browsers without JS */
.rail-enhanced .mag-flat{ display:none; }
.mag-face{
  position:absolute; left:50%; top:50%;
  width:calc(var(--w) * 0.75);
  height:var(--w);
  /* a quarter turn clockwise: the spine ends up on top, over the bar, and the
     masthead runs top-to-bottom like VOGUE in the photo */
  transform:translate(-50%, -50%) rotate(90deg);
}
.mag img{
  position:absolute; inset:0;
  width:100%; height:100%;
  object-fit:cover;
  pointer-events:none;
  /* Safari left the photo unpainted inside the tilted, turned magazine without
     its own stacking layer */
  z-index:0;
}
/* masthead in the style of a fashion magazine; size is fitted per title in JS */
.mag-title{
  position:absolute; left:6%; right:6%; top:6%;
  z-index:1;
  font-family:'Bodoni Moda', 'Didot', 'Bodoni 72', serif;
  font-weight:700;
  font-size:var(--title-fs, calc(var(--w) * 0.15));
  line-height:0.86;
  letter-spacing:-0.01em;
  text-transform:uppercase;
  color:#fff;
  text-shadow:0 1px 14px rgba(0,0,0,0.28);
  text-wrap:balance;
  pointer-events:none;
}
.mag-meta{
  position:absolute; left:6%; bottom:4.5%;
  z-index:1;
  font-family:'Space Grotesk', sans-serif;
  font-size:max(0.58rem, calc(var(--w) * 0.027));
  font-weight:500;
  letter-spacing:0.16em;
  text-transform:uppercase;
  color:#fff;
  text-shadow:0 1px 8px rgba(0,0,0,0.35);
  pointer-events:none;
}

.basket{
  position:absolute; left:50%;
  top:calc(var(--w) * 1.95);
  width:calc(var(--w) * 1.2);
  height:auto;
  transform:translateX(-50%);
  pointer-events:none;
  user-select:none;
}
/* split along the basket's front rim (traced on the picture): everything above
   it sits behind a falling magazine, the front rim and front wires over it.
   The back is cut ~1px lower so the two halves overlap without a seam. */
.basket-back{
  z-index:0;
  clip-path:polygon(0 0, 100% 0, 100% 37.6%, 66% 35.4%, 34% 34.6%, 0 31.6%);
}
.basket-front{
  z-index:99;
  clip-path:polygon(0 31.2%, 34% 34.2%, 66% 35%, 100% 37.2%, 100% 100%, 0 100%);
}

.hanger-item:focus-visible .mag-group{ outline:2px solid var(--accent); outline-offset:4px; }

/* live 3D version (portfolio-chrome.js): the canvases replace the pictures */
.rail-canvas{ position:absolute; inset:0; width:100%; height:100%; display:block; }
.chrome-live .rail{ background:none; }
.hanger-canvas{ display:block; }

/* without JS: a plain wrapping row of covers */
html:not(.rail-enhanced) .rail-section{ height:auto; }
html:not(.rail-enhanced) .rail{ display:none; }
html:not(.rail-enhanced) .rail-items{
  position:static;
  display:flex; flex-wrap:wrap; gap:2rem; padding:0 2.2rem 4rem;
}
html:not(.rail-enhanced) .hanger-item{ position:relative; --w:220px; width:220px; }
html:not(.rail-enhanced) .hanger-item .mag{ position:relative; display:block; aspect-ratio:3/4; overflow:hidden; }

/* ---------- portfolio page title ---------- */
.rail-section{ margin-top:4.6rem; }
.portfolio-head{ padding:8.5rem 0 1rem; }
.portfolio-title{
  font-family:'Fraunces', serif;
  font-style:italic;
  font-weight:400;
  font-size:clamp(3.6rem, 11vw, 9rem);
  line-height:0.92;
  letter-spacing:-0.025em;
  color:var(--accent);
}

/* ---------- placeholders (albums still to come) ---------- */
/* flat fallback only (no JS): a coloured card; with JS the Blender magazine takes over */
.hanger-item.is-placeholder{ cursor:default; }
html:not(.rail-enhanced) .mag[class*="ph-"]{ display:flex; align-items:flex-end; padding:1rem; background:var(--accent); }
html:not(.rail-enhanced) .mag[class*="ph-"] .mag-title{ position:static; font-size:1.1rem; color:var(--bg); }
html:not(.rail-enhanced) .mag.ph-2{ background:#ff9ccf; } html:not(.rail-enhanced) .mag.ph-3{ background:#ffd23f; }
html:not(.rail-enhanced) .mag.ph-4{ background:#27b774; } html:not(.rail-enhanced) .mag.ph-5{ background:#ff6b35; }
html:not(.rail-enhanced) .mag.ph-6{ background:#b8a0ff; } html:not(.rail-enhanced) .mag.ph-7{ background:#e63b2e; }
