/* ============================================================
   MEDIA LAYER - shared across every Kobe site.
   Copied from _template/media.css, the canonical source. Load AFTER
   site.css so the site's own tokens are already defined.

   Mobile first, in the literal sense: every block below is
   written for a 360px phone and only widens at min-width
   breakpoints. Phones are how these shops' customers actually
   arrive, usually standing outside the door.

   Requires from site.css: --bg --bg-2 --line --text --muted
   --accent --accent-ink --font-display --font-body
   ============================================================ */

/* ---------- Shared media primitives ---------- */

.m-figure { position: relative; overflow: hidden; background: var(--bg-2); }
.m-figure img,
.m-figure video { display: block; width: 100%; height: 100%; object-fit: cover; }

/* Reserve space before the image loads so nothing jumps (CLS). */
.m-ratio-1x1 { aspect-ratio: 1 / 1; }
.m-ratio-4x5 { aspect-ratio: 4 / 5; }
.m-ratio-9x16 { aspect-ratio: 9 / 16; }
.m-ratio-16x9 { aspect-ratio: 16 / 9; }

.m-cap {
  margin-top: 0.5rem;
  font-size: 0.82rem;
  line-height: 1.6;
  color: var(--muted);
}

/* ---------- Photo placeholder ----------
   WHY THIS EXISTS. The demos originally used picsum.photos, which
   serves a RANDOM photograph per seed. Opening the pages in a real
   browser showed a yakitori shop with the Eiffel Tower as its hero
   and a charcoal izakaya fronted by a field of blue flowers. No
   code-level check could catch that; only looking could.

   A random irrelevant photo is worse than an honest gap: it makes
   the demo look careless to the one person we need to impress. So a
   missing photo is drawn, in the site's own palette, as a deliberate
   slot that names the shot it is waiting for. It costs no network
   request, cannot 404, never shifts layout, and doubles as a visible
   shot list during the pitch: everything on this page is your real
   information, and the photographs are the one thing we need from you.

   Usage:
     <div class="m-ph m-ratio-4x5" role="img" aria-label="店内の写真">
       <span class="m-ph-label">店内</span>
     </div>
   ---------- */

.m-ph {
  position: relative;
  display: grid;
  place-items: center;
  width: 100%;
  overflow: hidden;
  background-color: var(--bg-2);
  /* Depth from the site's own accent, kept low so it reads as a
     surface rather than as a coloured block. */
  background-image:
    radial-gradient(120% 90% at 22% 12%,
      color-mix(in srgb, var(--accent) 18%, transparent) 0%,
      transparent 60%),
    radial-gradient(90% 80% at 85% 90%,
      color-mix(in srgb, var(--accent) 10%, transparent) 0%,
      transparent 55%),
    repeating-linear-gradient(
      135deg,
      color-mix(in srgb, var(--text) 4%, transparent) 0 2px,
      transparent 2px 9px);
}

/* Browsers without color-mix still get a clean tinted surface. */
@supports not (background: color-mix(in srgb, red 10%, blue)) {
  .m-ph { background-image: repeating-linear-gradient(135deg, rgba(128,128,128,0.06) 0 2px, transparent 2px 9px); }
}

.m-ph::after {
  /* Hairline inset, so the slot reads as a designed frame. */
  content: "";
  position: absolute;
  inset: 0.5rem;
  border: 1px solid color-mix(in srgb, var(--text) 12%, transparent);
  pointer-events: none;
}

.m-ph-label {
  position: relative;
  z-index: 1;
  max-width: 82%;
  padding: 0.4rem 0.75rem;
  font-family: var(--font-body);
  font-size: 0.74rem;
  font-weight: 700;
  line-height: 1.5;
  letter-spacing: 0.06em;
  text-align: center;
  color: var(--muted);
}
.m-ph-label::before {
  content: "";
  display: block;
  width: 22px; height: 1px;
  margin: 0 auto 0.5rem;
  background: var(--accent);
}

/* ---------- Hero video ----------
   Autoplay only works muted + playsinline. The poster carries the
   first frame so the hero is never blank, and under reduced motion
   the video is hidden entirely and the poster stands alone. */

.m-hero-media { position: relative; width: 100%; height: 100%; }
.m-hero-media video {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
.m-hero-media .m-poster {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
.m-hero-media video + .m-poster { opacity: 0; transition: opacity 0.4s; }

@media (prefers-reduced-motion: reduce) {
  .m-hero-media video { display: none; }
  .m-hero-media .m-poster { opacity: 1 !important; }
}

/* A muted-video sound toggle must never be a hover-only control. */
.m-video-btn {
  position: absolute;
  right: 0.75rem; bottom: 0.75rem;
  z-index: 3;
  min-width: 44px; min-height: 44px;
  display: inline-flex; align-items: center; justify-content: center;
  gap: 0.35rem;
  padding: 0 0.8rem;
  font-family: var(--font-body);
  font-size: 0.8rem; font-weight: 700;
  color: #fff;
  background: rgba(0, 0, 0, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.35);
  cursor: pointer;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

/* ---------- Story strip ----------
   The vertical, tap-through format people already understand from
   phones. Horizontally scrollable on mobile with snap points. */

.m-stories {
  display: flex;
  gap: 0.75rem;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
  padding: 0.25rem clamp(1.25rem, 4vw, 3rem) 1rem;
  margin: 0 calc(-1 * clamp(1.25rem, 4vw, 3rem));
  scrollbar-width: none;
}
.m-stories::-webkit-scrollbar { display: none; }

/* .m-story works as a <button> (opens the viewer, when we hold the media)
   or as an <a> (goes to the shop's real Instagram highlight, when we do
   not). Both are 76px wide with a 72px ring, comfortably over the 44px
   touch minimum. */
.m-story {
  flex: 0 0 auto;
  scroll-snap-align: start;
  display: block;
  width: 76px;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  font-family: var(--font-body);
  color: inherit;
  text-align: center;
  text-decoration: none;
}
.m-story-ring {
  width: 72px; height: 72px;
  border-radius: 50%;
  padding: 3px;
  background: var(--accent);
  margin: 0 auto;
}
.m-story-ring img {
  width: 100%; height: 100%;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid var(--bg);
  display: block;
}
/* Ring fallback when we do not hold the real highlight cover. A stock
   photo in a story ring would read as the shop's own content, so the
   ring carries an initial instead until the owner supplies covers. */
.m-story-ring .m-story-mono {
  width: 100%; height: 100%;
  display: grid; place-items: center;
  border-radius: 50%;
  border: 2px solid var(--bg);
  background: var(--bg-2);
  font-family: var(--font-display);
  font-size: 1.4rem;
  font-weight: 700;
  line-height: 1;
  color: var(--accent);
}

.m-story-label {
  display: block;
  margin-top: 0.45rem;
  font-size: 0.72rem;
  line-height: 1.3;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---------- Story viewer (full screen) ---------- */

.m-viewer[hidden] { display: none !important; }
.m-viewer {
  position: fixed; inset: 0;
  z-index: 90;
  display: grid;
  place-items: center;
  background: rgba(8, 8, 10, 0.94);
}
.m-viewer-stage {
  position: relative;
  width: 100%; height: 100%;
  max-width: 460px;
  display: flex; flex-direction: column;
}
.m-viewer-media {
  flex: 1;
  min-height: 0;
  display: grid;
  place-items: center;
  background: #000;
}
.m-viewer-media img,
.m-viewer-media video {
  max-width: 100%; max-height: 100%;
  width: auto; height: auto;
  object-fit: contain;
}
.m-viewer-bars {
  display: flex; gap: 4px;
  padding: 0.6rem 0.75rem 0.4rem;
}
.m-viewer-bar {
  flex: 1; height: 3px;
  background: rgba(255, 255, 255, 0.3);
  overflow: hidden;
}
.m-viewer-bar i {
  display: block; height: 100%; width: 0;
  background: #fff;
}
.m-viewer-bar.is-done i { width: 100%; }
.m-viewer-cap {
  padding: 0.9rem 1rem 1.4rem;
  color: #fff;
  font-size: 0.9rem;
  line-height: 1.7;
  background: linear-gradient(to top, rgba(0,0,0,0.85), rgba(0,0,0,0));
}
/* Tap zones: left third goes back, right two thirds go forward. */
.m-viewer-prev, .m-viewer-next {
  position: absolute; top: 0; bottom: 0;
  z-index: 2;
  border: none; background: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.m-viewer-prev { left: 0; width: 33%; }
.m-viewer-next { right: 0; width: 67%; }
.m-viewer-close {
  position: absolute; top: 0.5rem; right: 0.5rem;
  z-index: 4;
  min-width: 44px; min-height: 44px;
  font-size: 1.5rem; line-height: 1;
  color: #fff; background: none; border: none;
  cursor: pointer;
}

/* ---------- Gallery ---------- */

.m-gallery {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.5rem;
}
.m-gallery button {
  padding: 0; border: none; background: none; cursor: pointer;
  display: block; width: 100%;
}
@media (min-width: 600px) {
  .m-gallery { grid-template-columns: repeat(2, 1fr); gap: 0.75rem; }
  /* Give the grid rhythm rather than a flat wall of equal tiles. */
  .m-gallery > *:nth-child(4n+1) { grid-column: span 2; }
}
@media (min-width: 960px) {
  .m-gallery { grid-template-columns: repeat(3, 1fr); }
  .m-gallery > *:nth-child(4n+1) { grid-column: span 2; grid-row: span 2; }
}

/* ---------- Instagram ----------
   The official embed is heavy (it pulls Instagram's own script), so
   the card renders as a real link with the shop's own photo and only
   upgrades to a live embed when the visitor asks for it. That keeps
   the page fast on a phone on mobile data, which is where these
   customers actually are. */

.m-ig {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.75rem;
}
@media (min-width: 600px) { .m-ig { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 960px) { .m-ig { grid-template-columns: repeat(3, 1fr); } }

.m-ig-card {
  position: relative;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line);
  background: var(--bg-2);
  overflow: hidden;
}
.m-ig-card .m-cap { padding: 0 0.9rem; margin-top: 0.4rem; flex: 1; }

/* The card deliberately shows NO photograph before the embed is loaded.
   Instagram post images cannot be hotlinked, and dropping a stock
   placeholder into an Instagram card would read as the shop's own post
   when it is not. So the card states what the post is, and the real
   image arrives with the real embed on tap. */
.m-ig-kind {
  padding: 0.9rem 0.9rem 0;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  color: var(--accent);
}
.m-ig-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  padding: 0.75rem 0.9rem 0.9rem;
}
.m-ig-actions .btn {
  min-height: 44px;
  padding: 0.5rem 1rem;
  font-size: 0.85rem;
}
.m-ig-open {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 0.25rem;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--muted);
  text-decoration: underline;
}
.m-ig-open:hover { color: var(--text); }

.m-ig-foot {
  display: flex; align-items: center; gap: 0.5rem;
  margin-top: 1rem;
  font-size: 0.9rem;
}
.m-ig-foot a {
  display: inline-flex; align-items: center;
  min-height: 44px;
  color: var(--accent);
  font-weight: 700;
  text-decoration: underline;
}

/* Instagram's own embed sets inline width; keep it inside the grid. */
.m-ig blockquote.instagram-media {
  width: 100% !important;
  min-width: 0 !important;
  margin: 0 !important;
}

/* ---------- Motion ---------- */

@media (prefers-reduced-motion: reduce) {
  .m-stories { scroll-behavior: auto; }
  .m-viewer-bar i { transition: none !important; }
}
