/* v5. NOTE: this file is served with Cache-Control: max-age=604800.
 * Editing it in place strands returning visitors on the old copy for a week --
 * v1 was edited five times and none of those changes reached anyone who had
 * already loaded the page. Always ship a NEW filename and repoint index.html.
 */
/* JPAccess landing - coverflow proof carousel (replaces the 3D ring `Sm`).
 *
 * Two behaviours from one component, split purely by viewport:
 *
 *   desktop (>=768px)  the wrapper is tall and the frame sticks, so page
 *                      scroll drives the carousel. Same feel as the ring it
 *                      replaces: you scroll through the items.
 *   mobile  (<768px)   no pinning at all. The module is normal height and the
 *                      page scrolls straight past it; you move through the
 *                      items by swiping sideways. Pinning a carousel on a
 *                      phone traps the scroll, which is the thing being fixed.
 *
 * Card width is the only measured quantity - pitch, recession and perspective
 * are all derived from it, so the rake scales with the card at any size.
 */

.cf-wrap{ position:relative; }

/* Desktop: tall wrapper + sticky frame = scroll drives the carousel. */
@media (min-width:768px){
  .cf-wrap{ height:230vh; }
  /* Shorter than the viewport on purpose. The frame is centre-aligned, so
     every spare pixel of its height becomes dead space under the caption, and
     that gap is what made the pitch line below read as a separate section.
     86vh still clears the tallest card plus caption on a short laptop. */
  .cf-frame{
    position:sticky; top:7vh;
    height:86vh;
    display:flex; flex-direction:column;
    align-items:center; justify-content:center;
  }
}

/* Mobile: plain block, no sticky, no reserved scroll. */
@media (max-width:767px){
  .cf-frame{ display:flex; flex-direction:column; align-items:center; padding:0.5rem 0 0; }
}

/* Pinned with the cards, so "This is what a normal day looks like" stays on
   screen for the whole scroll instead of leaving the moment the pin starts. */
.cf-title{
  margin:0 0 .25rem;
  text-align:center;
  font-size:clamp(1.6rem, 3.2vw, 2.5rem);
  font-weight:700;
  line-height:1.14;
  letter-spacing:-.03em;
  color:hsl(var(--fg));
}
@media (max-width:767px){ .cf-title{ font-size:clamp(1.4rem, 6.4vw, 2rem); margin-bottom:.5rem; } }

.cf-stage{
  /* Square, and bigger again. 8 of the 12 item photos are 1000x1000 and the
     rest are 0.75-0.84, so a 0.72 portrait card was cropping ~28% off the width
     of every square shot. A 1:1 card plus object-fit:contain means nothing is
     cut off at all. The min() against vh stops a wide-but-short window
     (1600x800) sizing a card taller than the frame that has to hold it. */
  --cf-card: min(clamp(190px, 28vw, 380px), 34vh);
  width:100%;
  perspective: calc(var(--cf-card) * 3);
  /* Vertical padding keeps the card shadows clear of the overflow clip. */
  padding: 2.25rem 0;
  overflow:hidden;
  outline:none;
}
@media (max-width:767px){
  .cf-stage{
    --cf-card: clamp(240px, 84vw, 420px);   /* fills most of the phone width */
    padding: 1.5rem 0;
    /* Sideways drag is ours; the page keeps vertical scrolling. */
    touch-action: pan-y;
    cursor:grab;
  }
  .cf-stage:active{ cursor:grabbing; }
}

.cf-track{
  position:relative;
  height: var(--cf-card);                /* square: matches 8 of the 12 photos exactly */
  transform-style: preserve-3d;
  user-select:none;
}

.cf-card{
  position:absolute; left:50%; top:0;
  width: var(--cf-card);
  height: var(--cf-card);
  overflow:hidden;
  border-radius:1rem;
  background:#fff;
  box-shadow:0 2px 8px hsl(var(--deep)/.10), 0 18px 50px hsl(var(--deep)/.16);
  /* No will-change. Every card's transform already contains translateZ(), so
     it is composited anyway; the hint only pinned 12 layers permanently. */
  backface-visibility:hidden;
}
.cf-card img{
  width:100%; height:100%;
  /* Every photo in img/sq is exactly 1:1, so cover and contain are identical
     here -- cover is used so a future non-square file fills the card rather
     than showing a bar. */
  object-fit:cover; display:block;
  user-select:none; -webkit-user-drag:none;
}

/* The numbers live under the image now, not burned onto it. */
/* Framed on purpose. The caption and the pitch line below were both centred
   text on the same ground, so they read as one long column with an odd gap in
   it. Boxing the caption makes it belong to the carousel, which leaves the
   pitch standing on its own. */
.cf-caption{
  width:100%; max-width:20rem;
  padding:1rem 1.35rem 1.15rem;
  text-align:center;
  margin-top:0.25rem;
  border:1px solid hsl(var(--line));
  border-radius:1rem;
  background:hsl(var(--bg));
  box-shadow:0 1px 2px hsl(var(--deep)/.04), 0 10px 30px hsl(var(--deep)/.05);
}
/* Fixed rows. The panel must not resize card to card, so the logo row and the
   name row both have a set height and the name is clamped to two lines. */
.cf-brand{
  font-size:10px; text-transform:uppercase; letter-spacing:.18em;
  color:hsl(var(--fg-subtle));
  /* Fixed height even as plain text, so the panel stays the same size on every
     card (the reason the logo row was fixed in the first place). */
  height:18px; display:flex; align-items:center; justify-content:center;
}
@media (max-width:767px){ .cf-brand{ height:17px; } }
.cf-name{
  margin-top:.15rem;
  font-size:16px; font-weight:600; line-height:1.25;
  color:hsl(var(--fg));
  height:2.5em;                                  /* exactly two lines, always */
  display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:2;
  overflow:hidden;
}
.cf-meta{ margin-top:.9rem; border-top:1px solid hsl(var(--line-strong)); padding-top:.6rem; }
.cf-row{ display:flex; align-items:baseline; justify-content:space-between; gap:.75rem; padding:.16rem 0; }
.cf-row dt{ font-size:10px; text-transform:uppercase; letter-spacing:.12em; color:hsl(var(--fg-subtle)); }
.cf-row dd{ font-size:12px; color:hsl(var(--fg-muted)); margin:0; }
.cf-row-profit{ padding-top:.4rem; }
.cf-row-profit dd{ font-size:20px; font-weight:600; line-height:1; color:hsl(var(--fg)); }

/* Swipe affordance. Pointless on desktop, where scroll drives it. */
.cf-dots{ display:none; }
@media (max-width:767px){
  .cf-dots{ display:flex; justify-content:center; gap:.4rem; margin-top:1.1rem; }
  .cf-dot{
    width:6px; height:6px; border-radius:999px; border:0; padding:0;
    background:hsl(var(--fg)); opacity:.25; transition:opacity .2s;
  }
  .cf-dot[aria-current="true"]{ opacity:.9; }
}

@media (prefers-reduced-motion:reduce){
  .cf-card{ transition:none; }
}

/* A short rule under the module, so the eye registers a break before the pitch
   rather than reading straight on down one centred column. */
.cf-rule{
  width:132px; height:1px;
  margin:2.75rem auto 0;
  background:hsl(var(--line-strong));
}
@media (max-width:767px){ .cf-rule{ margin-top:1.6rem; width:104px; } }
