/* ============================================================
   RECIPE: gallery-rail
   A swipeable image rail — drinks, dishes, rooms, records.

   Zero-dependency. CSS scroll-snap does the work; JS only adds
   optional arrows for mouse users. **Fully usable with JS off.**

   Why a scroll-snap rail and NOT a JS carousel:
   - Native momentum scrolling and swipe on touch, for free
   - Keyboard-scrollable, screen-reader-navigable, for free
   - No animation loop, no transform maths, no library
   - Degrades to a plain horizontal scroller, never to nothing
   A JS carousel would be the exact "reach for a library" mistake
   .claude/skills/showcase-motion/SKILL.md exists to prevent.

   Usage:
     <div class="rail-wrap">
       <ul class="rail" tabindex="0" role="region" aria-label="Photos">
         <li><figure><img src=… alt=…><figcaption>…</figcaption></figure></li>
         …
       </ul>
       <button class="rail-btn" data-rail-prev hidden aria-label="Previous">←</button>
       <button class="rail-btn" data-rail-next hidden aria-label="Next">→</button>
     </div>

   Theme owns these (declare in your :root, with the register's tempo):
     --rail-item   card width           default 280px
     --rail-gap    gap between cards    default 16px
     --dur-ui      arrow feedback       default 0.2s
   ============================================================ */

.rail-wrap { position: relative; }

.rail {
  display: flex;
  gap: var(--rail-gap, 16px);
  margin: 0;
  padding: 0;
  list-style: none;

  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;

  /* Stops a horizontal swipe from triggering browser back-navigation.
     Without this the rail feels broken on trackpads and iOS. */
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;

  /* Hide the scrollbar without hiding the affordance — the partially
     visible next card is what tells people it scrolls. */
  scrollbar-width: none;
}
.rail::-webkit-scrollbar { display: none; }

.rail > * {
  flex: 0 0 var(--rail-item, 280px);
  scroll-snap-align: start;
  margin: 0;
}

.rail img {
  width: 100%;
  height: var(--rail-img-h, 300px);
  object-fit: cover;
  display: block;
}

.rail figure { margin: 0; }
.rail figcaption {
  font-size: var(--text-label, 12px);
  letter-spacing: 0.04em;
  color: var(--ink-muted, #888);
  padding-top: var(--space-1, 8px);
}

/* ── Full-bleed on small screens ───────────────────────────────
   The rail runs edge to edge, but the first card still lines up
   with the page's text column. scroll-padding keeps snapping honest.
   ------------------------------------------------------------ */
.rail-wrap[data-rail-bleed] .rail {
  padding-inline: var(--rail-bleed, 24px);
  margin-inline: calc(var(--rail-bleed, 24px) * -1);
  scroll-padding-inline-start: var(--rail-bleed, 24px);
}

/* ── Arrows: mouse affordance only ─────────────────────────────
   `hidden` in the markup; gallery.js reveals them. A no-JS visitor
   never sees a dead button, and touch users never see arrows they
   don't need.
   ------------------------------------------------------------ */
.rail-btn {
  position: absolute;
  top: var(--rail-btn-top, calc(var(--rail-img-h, 300px) / 2));
  transform: translateY(-50%);
  z-index: 2;

  width: 44px; height: 44px;          /* 44px = minimum comfortable hit target */
  display: grid; place-items: center;
  cursor: pointer;

  border: 1px solid var(--hairline, rgba(0,0,0,0.15));
  border-radius: var(--radius-pill, 999px);
  background: var(--surface, rgba(255,255,255,0.06));
  backdrop-filter: blur(8px);
  color: var(--ink, inherit);
  font-size: 15px;
  line-height: 1;

  /* Only opacity + border-color animate — both compositor-safe (§6.8). */
  transition: opacity var(--dur-ui, 0.2s) linear,
              border-color var(--dur-ui, 0.2s) linear;
}
.rail-btn[data-rail-prev] { left: 0; }
.rail-btn[data-rail-next] { right: 0; }
.rail-btn:hover, .rail-btn:focus-visible { border-color: var(--ink, currentColor); }
.rail-btn[hidden] { display: none; }

/* At either end the button fades rather than vanishing — no layout shift. */
.rail-btn[data-rail-end] { opacity: 0.25; pointer-events: none; }

/* Touch devices: no hover, so no arrows. Swiping is the interface. */
@media (hover: none) {
  .rail-btn { display: none !important; }
}

/* ── Reduced motion ────────────────────────────────────────────
   Kill smooth scrolling; gallery.js also switches its
   programmatic scrolls to instant. Snapping itself is kept —
   it's a layout behaviour, not an animation.
   ------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  .rail { scroll-behavior: auto; }
  .rail-btn { transition: none; }
}
