/* public/css/landing.css
 *
 * PR-LANDING (2026-05-25) — stylesheet for index.html, event.html, news.html,
 * events.html, news-index.html (the last four ship in commit 2).
 *
 * ── Conventions ──────────────────────────────────────────────────────────
 *
 *  - Mobile-first: base styles target ~360px width, then progressively widen.
 *  - Breakpoints: 480px (small tablet portrait), 768px (tablet / small laptop),
 *    1024px (desktop). The 768 boundary is where the header switches from
 *    hamburger to inline nav and grids spread from 2-up to N-up.
 *  - Class names use `lp-` prefix (landing-page) to avoid colliding with
 *    anything in components.css / layout.css. The landing page deliberately
 *    re-uses ONLY reset.css from the existing stylesheets — every other
 *    visual rule lives here.
 *  - Tap targets: minimum 44×44 px (Apple HIG / WCAG). `touch-action:
 *    manipulation` on interactive elements suppresses iOS double-tap zoom.
 *
 * ── Palette ──────────────────────────────────────────────────────────────
 *
 *  Background:        #f5f7f0  (page cream)
 *  Card surface:      #ffffff
 *  Card surface alt:  #fafaf6  (footer)
 *  Ink primary:       #111
 *  Ink secondary:     #555
 *  Ink muted:         #888
 *  Ink faint:         #aaa / #bbb
 *  Rule:              #e5e5e5
 *  Rule light:        #f0f0f0
 *  CTA:               #111 (black pill) — matches existing landing button
 *  CTA hover:         #333
 *  Tag pill default:  derived from slug-hash → HSL (see landing.js)
 *
 * Inspired by 543life / ytmoca / Casa Brutus — quiet editorial palette,
 * lots of whitespace, no heavy shadows, no gradients (except hero image).
 */

/* ─────────────────────────────────────────────────────────────────────────
 * Page shell
 * ───────────────────────────────────────────────────────────────────────── */

body {
  background: #ffffff;
  color: #111;
  font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue",
               "Hiragino Kaku Gothic ProN", "Yu Gothic", Meiryo, sans-serif;
  font-size: 14px;
  line-height: 1.6;
  overflow-x: hidden;
  overflow-y: auto;
  /* PR-LANDING-CMS-4a (2026-05-25) — iOS footer cropping fix.
   *
   * 100vh is broken on iOS Safari: it doesn't shrink to account for the
   * bottom URL bar, so the body ends up taller than the visible viewport.
   * Footer content (language switcher, copyright line) sits below the
   * visible area until the user scrolls down — which they often don't.
   *
   * 100dvh (dynamic viewport height) is the same value but recalculates
   * when the bottom bar appears/disappears, fitting actual visible area.
   * Supported in iOS 15.4+, Chrome 108+, Firefox 101+.
   *
   * Browsers that don't understand 100dvh ignore that rule and use the
   * earlier 100vh value. We list 100vh FIRST so cascade order works:
   * legacy browsers stop at the supported rule, modern ones advance to
   * the dvh rule.
   *
   * Also see meta viewport-fit=cover in index.html — required for
   * env(safe-area-inset-*) to be non-zero on iOS, which the footer's
   * padding-bottom uses for the home-indicator clearance. */
  min-height: 100vh;
  min-height: 100dvh;
}

/* When the lang-switcher / header should render in JP-flavoured stack first */
html[lang="ja"] body {
  font-family: "Hiragino Kaku Gothic ProN", "Yu Gothic", Meiryo,
               -apple-system, BlinkMacSystemFont, "Helvetica Neue", sans-serif;
}

a {
  color: inherit;
  text-decoration: none;
}

button {
  font-family: inherit;
  font-size: inherit;
  color: inherit;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  touch-action: manipulation;
}

img {
  display: block;
  max-width: 100%;
  height: auto;
}

/* Visually-hidden — accessibility helper for skip links and screen-reader-only
 * labels. Standard pattern from a11y-project. */
.lp-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ─────────────────────────────────────────────────────────────────────────
 * Header — sticky, white background
 * ───────────────────────────────────────────────────────────────────────── */

.lp-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: #ffffff;
  border-bottom: 1px solid transparent;
  transition: border-color 0.2s, background 0.2s, box-shadow 0.2s;
}
.lp-header.is-scrolled {
  background: rgba(255, 255, 255, 0.96);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-bottom-color: #ebebeb;
  box-shadow: 0 1px 0 rgba(0,0,0,0.02);
}

/* Taller nav row — per PR-LANDING-LAYOUT-V2 request. Padding bumped from
 * 14px to 22px vertical so the section links breathe. Logo + actions
 * remain centre-aligned with the heightened row.                       */
.lp-header-inner {
  max-width: 1280px;
  margin: 0 auto;
  padding: 22px 20px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.lp-logo {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -0.3px;
  color: #111;
}
.lp-logo img {
  height: 28px;
  width: auto;
}

/* Desktop nav — two groups (sections / actions) so we can space them.
 * `.lp-nav` is the container, hidden below 768px; the inner groups
 * become `display:flex` only when the parent is visible.                */
.lp-nav {
  display: none;
  flex: 1;
  align-items: center;
  justify-content: space-between;
  margin-left: 32px;
  gap: 16px;
}
.lp-nav-sections {
  display: flex;
  align-items: center;
  gap: 22px;
  font-size: 14px;
}
.lp-nav-actions {
  display: flex;
  align-items: center;
  gap: 14px;
  font-size: 13px;
}
.lp-nav-link {
  color: #555;
  text-decoration: none;
  transition: color 0.15s;
  padding: 6px 0;
}
.lp-nav-link:hover { color: #111; }
.lp-nav-sections .lp-nav-link { font-weight: 500; }

/* Logout button — hidden by default; .is-visible toggled by checkAuth() */
.lp-btn-logout-header { display: none; }
.lp-btn-logout-header.is-visible { display: inline-block; }

/* PR-LANDING-CMS-4b — account link.
 *
 * Was: 32px black circle with the user's initial. The icon-only form
 * gave no affordance on hover and wasn't clear that it was a link to
 * the Account page.
 * Now: "Account (P)" text link, styled to match the other nav links
 * (logout button, Events/News/About links). Same color (#555 → #111
 * on hover) and same weight (500 inside .lp-nav-sections via the
 * existing rule on line 193) so the header chrome reads as one
 * consistent text-link group.
 *
 * The initial in parentheses is filled by landing.js / landing-detail.js
 * / etc. when /auth/me confirms a logged-in user. The label
 * ("Account" / "アカウント") localises via data-i18n.
 *
 * Hidden by default — .is-visible toggled by checkAuth() once the
 * logged-in state is known. */
.lp-account-icon {
  display: none;            /* shown only when logged in */
  align-items: baseline;
  gap: 4px;
  font-size: 13px;
  color: #555;
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.15s;
}
.lp-account-icon.is-visible { display: inline-flex; }
.lp-account-icon:hover { color: #111; }

/* Letter in parentheses — slightly muted colour so the "Account" word
 * reads as the primary affordance. Weight stays inherited from the
 * parent so the whole link is consistent in weight. */
.lp-account-initial {
  color: #888;
}
.lp-account-initial:empty { display: none; }
.lp-account-initial:not(:empty)::before { content: '('; }
.lp-account-initial:not(:empty)::after  { content: ')'; }

/* Mobile menu button — visible <768px */
.lp-menu-btn {
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
  color: #111;
  border-radius: 6px;
}
.lp-menu-btn:hover { background: #f3f3f3; }

/* Mobile drawer — full-width slide-down panel */
.lp-mobile-drawer {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  background: #fff;
  border-bottom: 1px solid #e5e5e5;
  padding: 16px 20px 20px;
  flex-direction: column;
  gap: 12px;
}
.lp-mobile-drawer.is-open { display: flex; }
.lp-mobile-drawer a,
.lp-mobile-drawer button {
  padding: 10px 0;
  text-align: left;
  font-size: 15px;
  color: #111;
  border-bottom: 1px solid #f0f0f0;
}
.lp-mobile-drawer .lp-lang-dropdown {
  padding-top: 8px;
}
/* In mobile drawer, login/register/logout visibility mirrors header */
.lp-mobile-drawer .lp-mobile-logout { display: none; }
.lp-mobile-drawer .lp-mobile-logout.is-visible { display: block; }
.lp-mobile-drawer .lp-mobile-login.is-hidden,
.lp-mobile-drawer .lp-mobile-register.is-hidden { display: none; }

/* PR-LANDING-CMS-4b — mobile Account link.
 *
 * Visible only when logged in (mirrors desktop .lp-account-icon).
 * Inherits .lp-mobile-drawer a styling (padding, border, color) so it
 * looks consistent with the other drawer entries. The initial slot
 * gets the same muted colour + parentheses treatment as the desktop
 * version. */
.lp-mobile-drawer .lp-mobile-account { display: none; text-decoration: none; }
.lp-mobile-drawer .lp-mobile-account.is-visible { display: block; }
.lp-mobile-account-initial {
  margin-left: 4px;
  color: #888;
}
.lp-mobile-account-initial:empty { display: none; }
.lp-mobile-account-initial:not(:empty)::before { content: '('; }
.lp-mobile-account-initial:not(:empty)::after  { content: ')'; }

/* ─────────────────────────────────────────────────────────────────────────
 * Language dropdown — custom (not native <select>) for editorial fit.
 * Same component on desktop nav, mobile drawer, and footer.
 *
 * Closed: shows current language label + caret.
 * Open:   shows full language list; current is bold/inert, others are
 *         click-to-switch (setLocale → page reload).
 * Closes on outside click, Escape key, or selection.
 * ───────────────────────────────────────────────────────────────────────── */

.lp-lang-dropdown {
  position: relative;
  display: inline-block;
}
.lp-lang-dropdown-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  font-size: 13px;
  color: #555;
  background: none;
  border: 1px solid transparent;
  border-radius: 6px;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.lp-lang-dropdown-toggle:hover { color: #111; border-color: #e5e5e5; }
.lp-lang-dropdown.is-open .lp-lang-dropdown-toggle {
  color: #111;
  border-color: #e5e5e5;
  background: #fafafa;
}
.lp-lang-caret {
  font-size: 10px;
  color: #aaa;
  transition: transform 0.15s;
}
.lp-lang-dropdown.is-open .lp-lang-caret { transform: rotate(180deg); }

.lp-lang-dropdown-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  min-width: 140px;
  background: #fff;
  border: 1px solid #e5e5e5;
  border-radius: 8px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.08);
  padding: 6px 0;
  margin: 0;
  list-style: none;
  z-index: 60;
  display: none;
}
.lp-lang-dropdown.is-open .lp-lang-dropdown-menu { display: block; }

.lp-lang-dropdown-menu li {
  margin: 0;
}
.lp-lang-dropdown-menu button {
  display: block;
  width: 100%;
  padding: 8px 14px;
  text-align: left;
  font-size: 13px;
  color: #555;
  background: none;
  border: none;
  cursor: pointer;
  transition: background 0.1s, color 0.15s;
}
.lp-lang-dropdown-menu button:hover { background: #f7f7f7; color: #111; }
.lp-lang-dropdown-menu button.is-current {
  color: #111;
  font-weight: 600;
  cursor: default;
  background: #f3f3f3;
}

/* Footer variant — dropdown opens upward (footer is at page bottom).
 * Always-visible toggle border so the dropdown is recognisable as a
 * button against the cream footer background even when not hovered
 * (mobile has no hover state). Without this the toggle was visually
 * indistinguishable from plain text. */
.lp-lang-dropdown-footer .lp-lang-dropdown-toggle {
  border-color: #e0e0e0;
  background: #ffffff;
}
.lp-lang-dropdown-footer .lp-lang-dropdown-menu {
  top: auto;
  bottom: calc(100% + 6px);
  left: 0;
  right: auto;
}

/* PR-LANDING-CMS-cleanup — mobile drawer dropdown alignment.
 *
 * The drawer's contents are left-aligned (text-align: left in
 * .lp-mobile-drawer button), so the language toggle sits at the LEFT
 * edge of the drawer. The default .lp-lang-dropdown-menu opens with
 * `right: 0` (anchored to the toggle's right edge), which in the
 * full-width drawer puts the popup off near the right side of the
 * screen — far from the toggle text on the left.
 *
 * Override here so the menu opens at the LEFT edge of the toggle,
 * directly under the visible language label. Desktop header + footer
 * use the default right-edge anchoring; only the mobile drawer needs
 * this flip. */
.lp-mobile-drawer .lp-lang-dropdown-menu {
  left: 0;
  right: auto;
}

/* ─────────────────────────────────────────────────────────────────────────
 * Hero — filmstrip carousel
 *
 * Layout: 3 tiles in a flex row [prev | centre | next].
 *
 *   At full content max-width (1280px):
 *     [304] [16] [640] [16] [304]  = 1280
 *
 *   Below 1280, the same 304:640:304 ratio scales down proportionally.
 *   Centre is always a TRUE SQUARE via aspect-ratio 1/1.
 *
 *   Side tiles show the EDGE of their slide image:
 *     - prev → right edge ("...45")
 *     - next → left  edge ("12...")
 *   So the strip reads as a filmstrip "...45 | 12345 | 12...".
 *
 * Implementation: flex-grow ratios 304 / 640 / 304 split the available
 * space (strip width minus 32px of gaps). At full width, leftover =
 * 1280 - 32 = 1248, split as 304+640+304 = 1248. ✓
 *
 * Mobile (<768px): side tiles hidden, only centre square shows full-width.
 *
 * No background gradient overlay — clean image-only tiles. The play
 * button sits below the strip, not on top of any individual tile.
 *
 * No image rounding — tiles render with square corners per design spec.
 * ───────────────────────────────────────────────────────────────────────── */

.lp-hero {
  position: relative;
  width: 100%;
  max-width: 1280px;
  margin: 0 auto;
  padding: 24px 20px 88px;        /* bottom padding leaves room for play CTA */
}

.lp-hero-strip {
  display: flex;
  align-items: stretch;
  gap: 16px;
  width: 100%;
  /* Strip layout: [304][16][640][16][304] = 1280 at full width.
   *
   * Flex grow values 304 / 640 / 304 split the available space
   * (strip width minus 32px of gaps) in exactly that ratio. At
   * strip = 1280, the leftover after gaps is 1248 = 304+640+304. ✓
   *
   * Below 1280 the same ratio scales down proportionally: at strip
   * width W, leftover = W - 32, split as 24.36% / 51.28% / 24.36%.
   *
   * margin: 0 auto centres the strip inside the hero section when
   * the viewport is wider than 1280px.
   *
   * Note: no explicit viewport-height cap. On very short windows
   * (e.g. landscape phone) the centre square may push the play
   * button below the fold — acceptable per current spec. */
  max-width: 1280px;
  margin: 0 auto;
}

.lp-hero-tile {
  position: relative;
  background-color: #eee;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  overflow: hidden;
  border: none;
  padding: 0;
  cursor: default;
  opacity: 1;
  min-width: 0;                   /* required for flex shrink with grow */
  transition: opacity 0.4s ease, transform 0.2s ease;
}

/* Centre tile — square. flex-grow: 640 dictates its share of strip space.
 * Combined with aspect-ratio 1/1, the height equals the width — always
 * a true square at every viewport size. */
.lp-hero-tile-centre {
  flex: 640 1 0;
  aspect-ratio: 1 / 1;
}
/* PR-LANDING-CMS-4b — clickable cursor only when the current slide has
 * a `url` set. JS toggles .is-clickable on every advance via paintTiles. */
.lp-hero-tile-centre.is-clickable { cursor: pointer; }

/* Side tiles — flex-grow 304 means they get 304/1248 of the post-gap
 * space, exactly matching the spec at full width and scaling
 * proportionally below.
 *
 * Background-position anchors on the EDGE adjacent to the centre tile:
 *   - prev → right (shows right edge of slide; eye reads "…45")
 *   - next → left  (shows left  edge of slide; eye reads "12…")     */
.lp-hero-tile-prev,
.lp-hero-tile-next {
  flex: 304 1 0;
  cursor: pointer;
  transition: opacity 0.4s ease, transform 0.2s ease;
}
.lp-hero-tile-prev { background-position: right center; }
.lp-hero-tile-next { background-position: left center; }

.lp-hero-tile-prev:hover,
.lp-hero-tile-next:hover {
  transform: translateY(-2px);
}

/* Brief opacity dip during crossfade — JS toggles .is-fading mid-swap */
.lp-hero-tile.is-fading { opacity: 0.25; }

/* Carousel dot indicator — sits below the strip, centred */
.lp-hero-dots {
  display: flex;
  justify-content: center;
  gap: 8px;
  margin-top: 18px;
}
.lp-hero-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #ddd;
  border: none;
  padding: 0;
  cursor: pointer;
  transition: background 0.2s, transform 0.15s;
}
.lp-hero-dot.is-active {
  background: #111;
  transform: scale(1.3);
}
.lp-hero-dot:hover { background: #aaa; }
.lp-hero-dot.is-active:hover { background: #111; }

/* Play button — sits below the strip, centred. NOT overlapping any tile. */
.lp-hero-cta {
  display: flex;
  justify-content: center;
  margin-top: 22px;
}

.lp-btn-play {
  background: #111;
  color: #fff;
  padding: 16px 36px;
  border-radius: 999px;
  font-size: 16px;
  font-weight: 600;
  letter-spacing: 0.3px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.12);
  transition: background 0.15s, transform 0.1s;
  min-width: 220px;
  text-align: center;
}
.lp-btn-play:hover  { background: #333; }
.lp-btn-play:active { transform: scale(0.98); }
.lp-btn-play:disabled {
  background: #888;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

/* ─────────────────────────────────────────────────────────────────────────
 * PR-MINI-PLAY — smaller Play CTA in the sticky header.
 *
 * Same visual identity as the hero .lp-btn-play (pill, dark fill, white
 * label, hover-lift) but compact enough to sit inside the header
 * alongside other nav chrome. Two instances exist:
 *
 *   #btn-play-mini         — inside .lp-nav-actions (desktop only)
 *   #btn-play-mini-mobile  — inside .lp-header-inner before #btn-menu
 *                            (mobile only)
 *
 * Both are hidden by default. landing.js attaches an IntersectionObserver
 * to the hero CTA (#btn-play) and adds .is-visible to BOTH mini buttons
 * when the hero leaves the viewport — so only one Play button (either
 * the big hero one OR the small header one) is ever on screen at once.
 *
 * The desktop/mobile show/hide is handled by media queries below, NOT
 * by JS — keeps the visibility rules declarative and lets the browser
 * compute layout without flicker on viewport resize.
 * ───────────────────────────────────────────────────────────────────── */
.lp-btn-play-mini {
  /* Base state — out of layout, transparent. Two classes drive the
   * fade-in (see landing.js _showMiniPlay):
   *   .is-mounted   → display: inline-block (enters layout, opacity still 0)
   *   .is-visible   → opacity 1 (fade animates from the just-mounted state)
   * The two-class split is needed because browsers short-circuit
   * transitions when display and opacity change in the same frame —
   * the element wasn't in layout at frame N-1, so the transition has
   * no "from" state to interpolate from. */
  display: none;
  background: #111;
  color: #fff;
  padding: 8px 18px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.2px;
  /* Subtle shadow only — the hero CTA's stronger shadow would be too
   * heavy against the white header. */
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity 0.15s ease, transform 0.15s ease, background 0.15s;
}
.lp-btn-play-mini.is-mounted { display: inline-block; }
.lp-btn-play-mini.is-mounted.is-visible {
  opacity: 1;
  transform: translateY(0);
}
.lp-btn-play-mini:hover  { background: #333; }
.lp-btn-play-mini:active { transform: scale(0.97) translateY(0); }
.lp-btn-play-mini:disabled {
  background: #888;
  cursor: not-allowed;
  transform: translateY(0);
  box-shadow: none;
}
/* Desktop variant — only inside .lp-nav-actions (hidden below 768px
 * along with the rest of .lp-nav). Above 768px the mobile variant is
 * forcibly hidden so the desktop one is the only candidate.
 *
 * Mobile variant — only above the 768px breakpoint, the mobile one is
 * hidden; below it, the desktop one is hidden because .lp-nav is
 * display:none anyway. Two simple overrides keep them mutually
 * exclusive without JS. */
@media (min-width: 768px) {
  #btn-play-mini-mobile { display: none !important; }
}
/* PR-MINI-PLAY-mobile-layout-fix — wrapper around the mobile play
 * button + hamburger so .lp-header-inner only sees TWO flex children
 * ([Logo] [Wrapper]). Without this wrapper, header-inner had three
 * children and `justify-content: space-between` spread the play button
 * to the visual center of the header instead of next to the hamburger.
 *
 * Layout inside the wrapper: a small flex row with an 8px gap, so the
 * play button hugs the hamburger naturally. Hidden on desktop (see
 * @media min-width:768px override at the bottom of this file).
 *
 * Replaces the prior `#btn-play-mini-mobile.is-mounted { margin-right:
 * 8px }` rule — the gap on this wrapper achieves the same spacing and
 * applies symmetrically whether or not the button is currently mounted. */
.lp-mobile-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

@media (max-width: 767px) {
  /* The desktop one is inside .lp-nav which is already display:none on
   * mobile, so no explicit override needed for #btn-play-mini.
   * The mobile-only one inherits its spacing from .lp-mobile-actions's
   * gap, so no per-button margin rule is needed here anymore. */
}

/* Hero maintenance banner — top-centre overlay above the filmstrip */
.lp-hero-maint {
  position: absolute;
  top: 36px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 4;
  display: none;
  background: rgba(255, 243, 205, 0.96);
  color: #6c4f00;
  border: 1px solid #ffeaa7;
  border-radius: 6px;
  padding: 10px 16px;
  font-size: 13px;
  text-align: center;
  max-width: calc(100% - 40px);
}
.lp-hero-maint.is-on { display: block; }
.lp-hero-maint strong { display: block; margin-bottom: 2px; }

/* ─────────────────────────────────────────────────────────────────────────
 * Generic section frame — used by Events, News, Exhibitors, About
 * ───────────────────────────────────────────────────────────────────────── */

.lp-section {
  max-width: 1280px;
  margin: 0 auto;
  padding: 48px 20px;
}

/* PR-LANDING-CMS-4b — news section is pure text (title + 2-line body
 * excerpt + meta). At 1280px the lines are uncomfortably long for prose
 * reading. Cap the news section's effective container to 800px so lines
 * stay under ~80 chars. Mobile is unchanged because viewport is already
 * narrower than 800px on phones and tablets. Other sections (events,
 * exhibitors, about) keep the 1280px width since they're card-grid
 * layouts that benefit from horizontal space. */
.lp-section#news {
  max-width: 800px;
}

.lp-section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 24px;
  gap: 16px;
}
.lp-section-title {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 1.5px;
  color: #aaa;
  text-transform: uppercase;
  margin: 0;
}
.lp-section-seeall {
  font-size: 12px;
  color: #888;
  text-decoration: underline;
  white-space: nowrap;
}
.lp-section-seeall:hover { color: #111; }

/* ─────────────────────────────────────────────────────────────────────────
 * Events row — 4 cards, 2×2 on mobile
 * ───────────────────────────────────────────────────────────────────────── */

.lp-events-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 14px;
}
.lp-event-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  text-decoration: none;
  color: inherit;
  transition: transform 0.15s;
}
.lp-event-card:hover { transform: translateY(-2px); }
.lp-event-card-image {
  width: 100%;
  aspect-ratio: 1 / 1;
  background: #ddd;
  overflow: hidden;
}
.lp-event-card-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.lp-event-card-title {
  font-size: 14px;
  font-weight: 600;
  color: #111;
  line-height: 1.35;
}
.lp-event-card-date {
  font-size: 11px;
  color: #bbb;
}
.lp-event-card-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 2px;
}

/* ─────────────────────────────────────────────────────────────────────────
 * News list — text-only items, 3 visible on landing page
 * ───────────────────────────────────────────────────────────────────────── */

.lp-news-list {
  display: flex;
  flex-direction: column;
}
.lp-news-item {
  padding: 18px 0;
  border-bottom: 1px solid #f0f0f0;
  display: block;
  text-decoration: none;
  color: inherit;
}
.lp-news-item:last-child { border-bottom: none; }
.lp-news-item-title {
  font-size: 14px;
  font-weight: 600;
  color: #111;
  margin-bottom: 4px;
  transition: color 0.15s;
}
.lp-news-item:hover .lp-news-item-title { color: #555; }
.lp-news-item-body {
  font-size: 13px;
  color: #666;
  line-height: 1.6;
  margin-bottom: 8px;
  /* Clamp to ~2 lines on landing — full body on detail page */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.lp-news-item-meta {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 11px;
  color: #bbb;
}
.lp-news-item-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

/* ─────────────────────────────────────────────────────────────────────────
 * Exhibitors row — 6 cards, 2×3 on mobile, no click
 * ───────────────────────────────────────────────────────────────────────── */

.lp-exhibitors-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 18px;
}
.lp-exhibitor-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  /* explicitly NOT a link — purely informational per spec */
}
.lp-exhibitor-image {
  width: 100%;
  aspect-ratio: 1 / 1;
  background: #ddd;
  overflow: hidden;
}
.lp-exhibitor-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.lp-exhibitor-name {
  font-size: 13px;
  font-weight: 600;
  color: #111;
}
.lp-exhibitor-desc {
  font-size: 12px;
  color: #666;
  line-height: 1.5;
}

/* ─────────────────────────────────────────────────────────────────────────
 * About / handcraft section — placeholder layout
 * ───────────────────────────────────────────────────────────────────────── */

.lp-about {
  display: grid;
  grid-template-columns: 1fr;
  gap: 24px;
  align-items: center;
}
.lp-about-image {
  width: 100%;
  aspect-ratio: 4 / 3;
  background: linear-gradient(135deg, #ebede5 0%, #d8dbcf 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #aaa;
  font-size: 13px;
  letter-spacing: 1px;
  text-transform: uppercase;
}
.lp-about-text {
  font-size: 15px;
  color: #333;
  line-height: 1.8;
}
.lp-about-title {
  font-size: 22px;
  font-weight: 700;
  color: #111;
  margin: 0 0 12px;
  letter-spacing: -0.3px;
}

/* ─────────────────────────────────────────────────────────────────────────
 * Tag pills — small inline labels, optionally clickable
 * ───────────────────────────────────────────────────────────────────────── */

.lp-tag {
  display: inline-flex;
  align-items: center;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.3px;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 999px;
  background: #ebede5;
  color: #555;
  text-decoration: none;
  /* Per-tag colour set inline by JS via --tag-bg / --tag-fg.            */
  background: var(--tag-bg, #ebede5);
  color: var(--tag-fg, #555);
  transition: opacity 0.15s;
}
a.lp-tag:hover { opacity: 0.8; }

/* ─────────────────────────────────────────────────────────────────────────
 * Footer
 * ───────────────────────────────────────────────────────────────────────── */

.lp-footer {
  background: #6e6e6e;
  /* PR-LANDING-CMS-cleanup — border-top removed. The previous 1px
   * solid #5a5a5a edge looked like a stray divider against the
   * already-darker tone of the footer; without it the section reads
   * as one continuous grey band rolling off the page above. */
  margin-top: 32px;
  color: #e0e0e0;
}
.lp-footer-inner {
  max-width: 1280px;
  margin: 0 auto;
  /* Mobile gets generous padding-bottom so the language dropdown
   * sits clearly above the copyright row. Desktop overrides this in
   * the 768px breakpoint to a tighter value.                          */
  padding: 40px 20px 36px;
  display: grid;
  grid-template-columns: 1fr;
  gap: 32px;
}
.lp-footer-brand {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.lp-footer-logo {
  font-size: 18px;
  font-weight: 700;
  color: #ffffff;
}
.lp-footer-tagline {
  font-size: 12px;
  color: #d0d0d0;
  line-height: 1.6;
  max-width: 280px;
}
.lp-footer-col {
  display: flex;
  flex-direction: column;
  gap: 8px;
  /* Prevent any single col from forcing parent overflow (defensive
   * against long-string content or wide dropdown menus on mobile). */
  min-width: 0;
}
.lp-footer-col-title {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.5px;
  color: #b8b8b8;
  text-transform: uppercase;
  margin-bottom: 6px;
}
.lp-footer-col a {
  font-size: 13px;
  color: #e0e0e0;
  text-decoration: none;
}
.lp-footer-col a:hover { color: #ffffff; }

.lp-footer-social {
  display: flex;
  gap: 12px;
  margin-top: 4px;
}
.lp-footer-social a {
  width: 32px;
  height: 32px;
  flex: 0 0 32px;             /* defensive — never shrink, never grow */
  display: flex;
  align-items: center;
  justify-content: center;
  color: #d0d0d0;
  border: 1px solid #909090;
  border-radius: 50%;
  transition: color 0.15s, border-color 0.15s;
}
.lp-footer-social a:hover { color: #ffffff; border-color: #ffffff; }
.lp-footer-social svg { width: 16px; height: 16px; }

/* Copyright row — must be reliably visible at the very bottom of the
 * page on any device.
 *   - generous bottom padding (28px + iOS safe-area inset) so phone
 *     chrome (dynamic browser toolbar, home indicator) never crops it
 *   - min-height ensures the row exists even if content collapses
 *   - slightly darker tone than the columns above so the row reads
 *     as a distinct band                                              */
.lp-footer-bottom {
  display: block;
  background: #5a5a5a;
  /* PR-LANDING-CMS-cleanup — border-top removed (matches .lp-footer
   * change above). The bg-tone change from #6e6e6e to #5a5a5a is
   * already enough visual separation; the extra hairline read as a
   * stray rule. */
  padding: 20px 20px calc(28px + env(safe-area-inset-bottom, 0px));
  text-align: center;
  font-size: 12px;
  color: #c8c8c8;
  min-height: 56px;
  box-sizing: border-box;
}

/* ─────────────────────────────────────────────────────────────────────────
 * Logged-in state — in PR-LANDING-LAYOUT-V2 the logged-in chrome moved
 * entirely into the header. The hero CTA is a single button regardless
 * of auth state; checkAuth() in landing.js swaps its label between
 * "Play Now" (logged out → opens login modal) and "Enter World"
 * (logged in → jumps to client.html). No separate Enter/Logout/name
 * trio under the play button anymore.
 * ───────────────────────────────────────────────────────────────────────── */

/* ─────────────────────────────────────────────────────────────────────────
 * Modals (preserved from previous index.html — auth flow unchanged)
 * Same selectors as before so existing JS keeps working; only namespaced
 * with `.lp-` on the wrapper for safety.
 * ───────────────────────────────────────────────────────────────────────── */

.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.35);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 200;
  padding: 20px;
}
.modal-overlay.hidden { display: none; }

.modal-box {
  background: #fff;
  border: 1px solid #e5e5e5;
  border-radius: 10px;
  padding: 28px 24px 20px;
  width: 100%;
  max-width: 360px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);
}
.modal-title    { font-size: 17px; font-weight: 600; color: #111; }
.modal-sub      { font-size: 12px; color: #888; margin-top: -8px; }
.modal-field    { display: flex; flex-direction: column; gap: 5px; }
.modal-field label { font-size: 12px; font-weight: 500; color: #555; }
.modal-field input {
  padding: 9px 12px;
  border: 1px solid #e5e5e5;
  border-radius: 6px;
  font-size: 15px;
  color: #111;
  background: #fff;
  outline: none;
  font-family: inherit;
  transition: border-color 0.15s;
}
.modal-field input:focus { border-color: #aaa; }

/* PR-REGISTER-COMPACT: the register modal has 6 fields and can exceed shorter
   mobile viewports. Tighten its field spacing + input height. Scoped to
   #modal-register so the login/guest modals keep their roomier spacing. */
#modal-register .modal-box        { gap: 9px; }
#modal-register .modal-field      { gap: 3px; }
#modal-register .modal-field input { padding: 6px 10px; font-size: 14px; }

.modal-gender { display: flex; gap: 8px; }
.gender-btn {
  flex: 1;
  padding: 10px;
  border: 1px solid #e5e5e5;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 500;
  color: #555;
  background: #fff;
  cursor: pointer;
  transition: all 0.12s;
  font-family: inherit;
  touch-action: manipulation;
}
.gender-btn.selected {
  background: #111;
  color: #fff;
  border-color: #111;
}

.modal-error { color: #c22; font-size: 12px; min-height: 16px; }
.modal-actions { display: flex; gap: 8px; margin-top: 4px; }
.btn-modal-cancel {
  flex: 1;
  padding: 10px;
  border: 1px solid #e5e5e5;
  border-radius: 6px;
  background: #fff;
  color: #555;
  cursor: pointer;
  font-size: 13px;
  font-family: inherit;
  font-weight: 500;
  touch-action: manipulation;
}
.btn-modal-confirm {
  flex: 2;
  padding: 10px;
  background: #111;
  color: #fff;
  border-radius: 6px;
  cursor: pointer;
  font-size: 13px;
  font-weight: 600;
  font-family: inherit;
  touch-action: manipulation;
}
.btn-modal-confirm:disabled { background: #999; cursor: not-allowed; }
.modal-divider {
  border: none;
  border-top: 1px solid #f0f0f0;
  margin: 0;
}
.modal-switch {
  font-size: 12px;
  color: #888;
  text-align: center;
}
.modal-switch button {
  color: #111;
  text-decoration: underline;
  font-size: 12px;
  background: none;
  border: none;
  cursor: pointer;
  font-family: inherit;
  padding: 0;
}

/* ─────────────────────────────────────────────────────────────────────────
 * Detail pages (event.html + news.html)  —  PR-LANDING commit 2
 *
 * Single-column article layout. Same width cap as landing-page sections
 * (1280px max, side padding). The hero image (event only) is a square
 * that scales down on mobile.
 * ───────────────────────────────────────────────────────────────────────── */

.lp-detail {
  width: 100%;
  padding: 32px 20px 64px;
}
.lp-detail-content {
  max-width: 720px;             /* article column — narrower than full-width */
  margin: 0 auto;
}

.lp-detail-loading {
  color: #888;
  font-size: 14px;
  text-align: center;
  padding: 60px 0;
}

/* PR-LANDING-CMS-4a (2026-05-25) — top bar on detail pages.
 *
 * Row containing the back link (left) and the kind label (right). Lets
 * users see "what KIND of thing is this?" at a glance without reading
 * the URL bar — useful on mobile in landscape where the address bar is
 * collapsed.
 *
 * The back-link's old standalone bottom margin (24px) moves onto this
 * topbar so the spacing under it stays the same as before; .lp-detail-back
 * itself now has no bottom margin.
 *
 * Title-case "Event" / "News" / "Exhibitor" is set via i18n keys
 * landing.detail.kind.{event|news|exhibitor}. */
.lp-detail-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 24px;
  gap: 12px;
}

.lp-detail-back {
  display: inline-block;
  font-size: 13px;
  color: #555;
  text-decoration: none;
  transition: color 0.15s;
}
.lp-detail-back:hover { color: #111; }

.lp-detail-kind {
  font-size: 12px;
  font-weight: 600;
  color: #888;
  letter-spacing: 0.3px;
}

.lp-detail-title {
  font-size: 24px;
  font-weight: 700;
  color: #111;
  line-height: 1.25;
  margin: 0 0 12px;
  letter-spacing: -0.3px;
}

.lp-detail-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
  font-size: 12px;
  color: #aaa;
  margin-bottom: 28px;
}
.lp-detail-date { color: #888; }
.lp-detail-tags {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 6px;
}

/* Event detail hero image — square, 640 max (matches landing hero centre).
 * On narrow viewports it shrinks naturally to article column width. */
.lp-detail-image {
  width: 100%;
  max-width: 640px;
  margin: 0 auto 32px;
  aspect-ratio: 1 / 1;
  background: #ddd;
  overflow: hidden;
}
.lp-detail-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* PR-LANDING-BLOCKS (2026-06-07) — content blocks on detail pages.
 * Text blocks carry .lp-detail-body too, so typography is inherited; the
 * wrapper only adds vertical rhythm between stacked blocks. Image blocks
 * match the hero's column width (640px, centred) but keep the image's
 * NATURAL aspect ratio — height follows the image, no square crop. */
.lp-detail-block-text,
.lp-detail-block-image {
  margin: 0 auto 32px;
}
.lp-detail-block-text:last-child,
.lp-detail-block-image:last-child {
  margin-bottom: 0;
}
.lp-detail-block-image {
  width: 100%;
  max-width: 640px;
  overflow: hidden;
}
.lp-detail-block-image img {
  width: 100%;
  height: auto;
  display: block;
}

/* ─────────────────────────────────────────────────────────────────────────
 * PR-LANDING-CMS-4b — exhibitor detail page styles.
 *
 * Layout (post-Phase-2 redesign) matches the event/news detail flow:
 * name → image → description → URL link → prev/next. So we no longer
 * need a custom .lp-detail-exhibitor-image — the standard
 * .lp-detail-image works fine.
 *
 * What's exhibitor-specific:
 *   - .lp-detail-exhibitor-url       — block container for the URL row
 *   - .lp-detail-exhibitor-url-label — "Visit website:" label (locale-driven)
 *   - .lp-detail-exhibitor-url-link  — the clickable URL itself, truncated
 *     visually if >40 chars but `href` always full
 * ───────────────────────────────────────────────────────────────────── */

.lp-detail-exhibitor-url {
  margin: 20px 0 32px;
  font-size: 14px;
  line-height: 1.6;
  color: #555;
}
.lp-detail-exhibitor-url-label {
  margin-right: 6px;
  color: #888;
  font-weight: 500;
}
.lp-detail-exhibitor-url-link {
  color: #1a6fc0;
  text-decoration: none;
  word-break: break-all;       /* fallback if a non-truncated URL ever slips through */
  border-bottom: 1px solid transparent;
  transition: border-color 0.12s, color 0.12s;
}
.lp-detail-exhibitor-url-link:hover {
  color: #0d4d8a;
  border-bottom-color: currentColor;
}

/* ─────────────────────────────────────────────────────────────────────────
 * About page (standalone /about) — currently a stub with title + body.
 * Uses the same .lp-detail-* font palette but is its own container so
 * future admin-managed content can grow without conflicting with
 * event/news/exhibitor pages. */

.lp-about-page {
  max-width: 720px;
  margin: 0 auto;
  padding: 48px 20px 80px;
}
.lp-about-page-title {
  font-size: 28px;
  font-weight: 700;
  color: #111;
  line-height: 1.25;
  margin: 0 0 18px;
  letter-spacing: -0.3px;
}
.lp-about-page-body {
  font-size: 16px;
  color: #555;
  line-height: 1.7;
}

/* "Read more →" link inside the landing-page about section. Sits below
 * the placeholder paragraph as its own line. Same visual treatment as
 * the section "See all" links so it reads as a sibling CTA. */
.lp-about-readmore {
  display: inline-block;
  margin-top: 14px;
  font-size: 14px;
  font-weight: 500;
  color: #555;
  text-decoration: none;
  transition: color 0.15s;
}
.lp-about-readmore:hover { color: #111; }

.lp-detail-body {
  font-size: 15px;
  color: #333;
  line-height: 1.7;
}
.lp-detail-body p {
  margin: 0 0 16px;
}
.lp-detail-body p:last-child { margin-bottom: 0; }

/* Prev/Next nav at the bottom of a detail page.
 *
 * Layout: two columns — prev on the left, next on the right. Each side
 * is a link (or a disabled span at the boundaries). Mobile shows just
 * the arrow + label ("← Previous" / "Next →"); desktop also reveals a
 * truncated title preview.
 *
 * The disabled state (no neighbour in that direction) renders faded so
 * the nav block height stays constant — no layout shift at boundaries.
 *
 * Top border separates this nav from the body content above. Generous
 * top margin so the user sees the body ends before the nav begins.   */
.lp-detail-nav {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin-top: 48px;
  padding-top: 24px;
  border-top: 1px solid #ebebeb;
}

.lp-detail-nav-link {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 14px 16px;
  border: 1px solid #e5e5e5;
  background: #fafafa;
  color: #555;
  font-size: 13px;
  text-decoration: none;
  line-height: 1.4;
  transition: border-color 0.15s, color 0.15s, background 0.15s;
  min-height: 56px;             /* keeps disabled and active rows level */
  min-width: 0;                  /* allow inner flex children to truncate */
}
.lp-detail-nav-link:hover {
  border-color: #aaa;
  color: #111;
  background: #fff;
}

/* prev sits on the left, content is left-aligned with arrow first */
.lp-detail-nav-prev { justify-content: flex-start; text-align: left; }
/* next sits on the right, content is right-aligned with arrow last */
.lp-detail-nav-next { justify-content: flex-end;   text-align: right; }

.lp-detail-nav-arrow {
  color: #888;
  font-size: 16px;
  flex: 0 0 auto;
}
.lp-detail-nav-link:hover .lp-detail-nav-arrow { color: #111; }

.lp-detail-nav-label {
  font-weight: 600;
  flex: 0 0 auto;
}

/* Title preview — desktop only. Truncates with ellipsis on long titles
 * to keep the nav block from blowing up vertically. Hidden via the
 * 768px breakpoint media query below. */
.lp-detail-nav-title {
  color: #888;
  font-weight: 400;
  display: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
  flex: 1 1 auto;
}

/* Disabled state — at the boundaries (no prev for newest, no next for
 * oldest). Same shape as the active link but greyed and non-interactive. */
.lp-detail-nav-link.is-disabled {
  background: #f7f7f7;
  color: #bbb;
  border-color: #ececec;
  cursor: not-allowed;
}
.lp-detail-nav-link.is-disabled .lp-detail-nav-arrow { color: #ccc; }

/* Not-found state — same column, slightly muted treatment so it reads
 * as a contained error rather than a missing-content gap. */
.lp-detail-notfound .lp-detail-title {
  color: #555;
}
.lp-detail-notfound .lp-detail-body {
  color: #888;
  margin-bottom: 24px;
}

/* ─────────────────────────────────────────────────────────────────────────
 * Index pages (events.html + news-index.html)  —  PR-LANDING commit 2
 *
 * Full-width list with an optional filter bar at the top. Re-uses the
 * existing .lp-events-grid (4-up on desktop, 2-up on mobile) for the
 * events index, and .lp-news-list for the news index — same components
 * as the landing-page rows, just unbounded by item count.
 * ───────────────────────────────────────────────────────────────────────── */

.lp-index {
  width: 100%;
  padding: 32px 20px 64px;
}
.lp-index-inner {
  max-width: 1280px;
  margin: 0 auto;
}

.lp-index-title {
  font-size: 22px;
  font-weight: 700;
  color: #111;
  letter-spacing: -0.3px;
  margin: 0 0 24px;
}

/* Filter bar — shown only when ?tag=<slug> is active.
 * Layout: "Filter: <Tag>"  +  "Clear filter →" right-aligned on a single
 * row that wraps cleanly on narrow viewports.                            */
.lp-filter-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  background: #f6f6f0;
  border: 1px solid #ebebe2;
  margin-bottom: 24px;
  font-size: 13px;
}
.lp-filter-bar[hidden] { display: none; }
.lp-filter-label {
  color: #555;
  font-weight: 500;
  flex: 1 1 auto;
  min-width: 0;
}
.lp-filter-clear {
  color: #555;
  text-decoration: underline;
  font-size: 12px;
  white-space: nowrap;
}
.lp-filter-clear:hover { color: #111; }

.lp-index-loading {
  color: #888;
  font-size: 14px;
  text-align: center;
  padding: 60px 0;
}

/* Empty state — text + "clear filter" link. Shown when the active
 * filter yields zero results. */
.lp-index-empty {
  text-align: center;
  padding: 60px 20px;
  color: #888;
  font-size: 14px;
}
.lp-index-empty[hidden] { display: none; }
.lp-index-empty p { margin: 0 0 12px; }
.lp-index-empty-clear {
  color: #555;
  text-decoration: underline;
  font-size: 13px;
}
.lp-index-empty-clear:hover { color: #111; }

/* ─────────────────────────────────────────────────────────────────────────
 * Reduced motion — disable hero fade + card hover transforms
 * ───────────────────────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  .lp-hero-tile        { transition: none; }
  .lp-hero-tile-prev:hover,
  .lp-hero-tile-next:hover { transform: none; }
  .lp-event-card       { transition: none; }
  .lp-event-card:hover { transform: none; }
}

/* ─────────────────────────────────────────────────────────────────────────
 * Mobile (<768px) — hero shows centre only; side tiles hidden.
 * Default styles target this state.
 * ───────────────────────────────────────────────────────────────────────── */

@media (max-width: 767.98px) {
  .lp-hero-tile-prev,
  .lp-hero-tile-next { display: none; }
  /* Centre takes the full strip width on mobile */
  .lp-hero-tile-centre { flex: 1 1 100%; }
}

/* ─────────────────────────────────────────────────────────────────────────
 * Breakpoint: 480px (small tablet portrait)
 * ───────────────────────────────────────────────────────────────────────── */

@media (min-width: 480px) {
  .lp-events-grid       { gap: 18px; }
  .lp-exhibitors-grid   { grid-template-columns: repeat(3, 1fr); gap: 20px; }
  .lp-section           { padding: 56px 24px; }
}

/* ─────────────────────────────────────────────────────────────────────────
 * Breakpoint: 768px (tablet / laptop) — header inline, grids spread,
 * hero filmstrip shows all 3 tiles.
 * ───────────────────────────────────────────────────────────────────────── */

@media (min-width: 768px) {
  body { font-size: 15px; }

  .lp-menu-btn          { display: none; }
  /* PR-MINI-PLAY-mobile-layout-fix — hide the whole mobile-actions
   * wrapper on desktop. Its children (mobile play + hamburger) are
   * already hidden individually (`.lp-menu-btn` above, and
   * `#btn-play-mini-mobile` via the min-width:768px rule earlier in
   * this file), but hiding the wrapper too keeps a zero-width empty
   * flex item from skewing the header's `space-between` distribution. */
  .lp-mobile-actions    { display: none; }
  .lp-mobile-drawer     { display: none !important; }
  .lp-nav               { display: flex; }

  .lp-btn-play          { padding: 18px 48px; font-size: 17px; min-width: 260px; }

  .lp-events-grid       { grid-template-columns: repeat(4, 1fr); gap: 20px; }
  .lp-exhibitors-grid   { grid-template-columns: repeat(6, 1fr); gap: 18px; }

  .lp-section           { padding: 72px 32px; }

  .lp-about             { grid-template-columns: 1fr 1.2fr; gap: 40px; }
  .lp-about-title       { font-size: 28px; }

  .lp-footer-inner      {
    grid-template-columns: 2fr 1fr 1fr 1fr;
    gap: 40px;
    padding: 56px 32px 32px;
  }

  /* Detail + index pages — slightly more breathing room at desktop sizes */
  .lp-detail            { padding: 56px 32px 96px; }
  .lp-detail-title      { font-size: 32px; }
  .lp-detail-body       { font-size: 16px; }
  .lp-index             { padding: 56px 32px 96px; }
  .lp-index-title       { font-size: 28px; }

  /* Prev/Next nav — reveal the title preview on desktop. Mobile keeps
   * only the arrow + label so the buttons stay compact. */
  .lp-detail-nav-title  { display: inline; }
  .lp-detail-nav-link   { padding: 16px 20px; font-size: 14px; }
}

/* ─────────────────────────────────────────────────────────────────────────
 * Breakpoint: 1024px (desktop) — slight upscale of about typography
 * ───────────────────────────────────────────────────────────────────────── */

@media (min-width: 1024px) {
  .lp-section           { padding: 88px 32px; }
  .lp-about-title       { font-size: 32px; }
}

/* ─────────────────────────────────────────────────────────────────────────
 * World chooser (PR-WORLD-CHOOSER-SHARED, 2026-06-07)
 *
 * Pills for the "choose a world" modal (#modal-worldselect), shared across
 * every landing page. Moved here from an inline <style> block in index.html
 * so all pages get the same styling from the one stylesheet they all load.
 * The .wc-pill mirrors .lp-btn-play's pill look.
 * ───────────────────────────────────────────────────────────────────────── */

.wc-list { display: flex; flex-direction: column; gap: 14px; margin: 8px 0 4px; }
.wc-item { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.wc-pill {
  background: #111; color: #fff;
  padding: 16px 36px; border-radius: 999px;
  font-size: 16px; font-weight: 600; letter-spacing: 0.3px;
  box-shadow: 0 6px 24px rgba(0,0,0,0.12);
  transition: background 0.15s, transform 0.1s;
  min-width: 220px; text-align: center;
  border: none; cursor: pointer; font-family: inherit;
}
.wc-pill:hover  { background: #333; }
.wc-pill:active { transform: scale(0.98); }
.wc-pill:disabled {
  background: #888; cursor: not-allowed; transform: none; box-shadow: none;
}
.wc-maint {
  font-size: 12px; color: #b00; display: none;   /* shown only when that world is blocked */
}
.wc-item.is-maint .wc-maint { display: block; }
