/* 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
 * ───────────────────────────────────────────────────────────────────────── */

/* In-page nav: smooth scroll + offset so section titles clear the sticky
 * header (taller now that the logo is a 100px-tall image). Scoped to
 * landing.css so it never affects the game client; respects reduced-motion. */
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}
html { scroll-padding-top: 136px; }
@media (max-width: 768px) {
  html { scroll-padding-top: 96px; }
}

.lp-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: #ffffff;
  transition: 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);
  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: 10px 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 {
  width: 200px;
  height: 100px;
  object-fit: contain;
  display: block;
}
@media (max-width: 768px) {
  .lp-logo img { width: 150px; height: 75px; }
  .lp-header-inner { padding: 5px 20px; }
}

/* 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: 0;
  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-flow: row wrap;
  gap: 12px;
}
.lp-mobile-drawer.is-open { display: flex; }
/* PR-DRAWER-LANG-LINE (2026-06-17): divider line on each top-level
 * drawer entry. Scoped to DIRECT children (>) so it never reaches
 * into the nested language dropdown: the toggle and its menu options
 * (English / Japanese) must render exactly like the desktop/footer
 * dropdown, free of this rule's padding, font-size and border.
 * (A descendant selector here outranks .lp-lang-dropdown-menu button
 * and breaks the option padding/size  hence the child combinator.) */
.lp-mobile-drawer > a,
.lp-mobile-drawer > button {
  padding: 10px 0;
  text-align: left;
  font-size: 15px;
  color: #111;
  border-bottom: 1px solid #f0f0f0;
}
/* PR-DRAWER-2COL (2026-06-25): the section links (Events / News / About /
 * Featured Exhibitors / Articles / Booking) sit 2-per-row to shorten the
 * drawer (it became long once Booking was added). The auth buttons, the
 * account link, and the language dropdown stay full-width on their own rows.
 * The drawer is flex-flow:row wrap (above); the account entry is an <a> too,
 * so it's excluded from the 50% rule via :not(.lp-mobile-account). The 12px
 * column gap means each section link is calc(50% - 6px). */
.lp-mobile-drawer > a:not(.lp-mobile-account) { flex: 0 0 calc(50% - 6px); }
.lp-mobile-drawer > button,
.lp-mobile-drawer > .lp-mobile-account,
.lp-mobile-drawer > .lp-lang-dropdown { flex: 1 0 100%; }
.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;
}
/* PR-DRAWER-LANG-NOBORDER (2026-06-17): no border on the drawer language
 * toggle in ANY state. The :not() on the blanket divider above keeps the
 * flat underline off it; this neutralises the rounded #e5e5e5 outline the
 * shared toggle otherwise paints on hover/open. Uses border-color (not
 * `border:none`) so the 1px box size stays constant  no reflow on open.
 * Each selector outranks the rule it overrides: base (0,1,0), :hover
 * (0,2,0), .is-open (0,3,0). */
.lp-mobile-drawer .lp-lang-dropdown-toggle,
.lp-mobile-drawer .lp-lang-dropdown-toggle:hover,
.lp-mobile-drawer .lp-lang-dropdown.is-open .lp-lang-dropdown-toggle {
  border-color: transparent;
}

/* ─────────────────────────────────────────────────────────────────────────
 * Hero — centre-focused sliding carousel
 *
 * A real carousel: a flex track (.lp-hero-track) of equal-size square cells
 * that translates one step per advance, so the focal image physically slides
 * from the side into the centre (no fade, no duplicate). JS parks the track
 * at a translateX that centres the active cell.
 *
 *   Full-bleed: the strip clips the track to the viewport.
 *     [ … ] [16] [ prev ] [16] [ 640 ] [16] [ next ] [16] [ … ]
 *
 *   The centre cell is the 640×640 focal square (--hero-cell-w + aspect 1/1).
 *   All cells are the same size, so the rail can slide rigidly. Neighbours
 *   peek on each side, clipped by the strip's overflow; the visible edge of
 *   each (prev → right edge, next → left edge) falls out of the clipping, so
 *   no per-cell background-position is needed.
 *
 *   A window of cells ([idx-half … idx+half], sized to the screen in JS) is
 *   kept so a one-step slide always has a buffer cell to fill the leading
 *   edge; after the slide JS recycles the window and re-parks. See
 *   initHeroCarousel in landing.js.
 *
 * Mobile (<768px): --hero-cell-w becomes the full viewport, so one slide
 * shows at a time and the neighbours sit off-screen.
 *
 * 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%;
  margin: 0 auto;
  padding: 0 0 40px;           /* full-bleed: no side gutter; bottom leaves room for play CTA */
}

.lp-hero-strip {
  position: relative;
  width: 100%;
  overflow: hidden;               /* clips the sliding track to the viewport */
  min-height: var(--hero-cell-w, 640px);  /* reserve the focal square before JS builds the cells */
}

/* Sliding track — a flex row of equal-size square cells. JS parks it at a
 * translateX that centres the active cell, and on advance animates it one
 * step (cell width + gap) so the focal image physically slides into the
 * centre. `.is-sliding` is added only for the duration of that animation. */
.lp-hero-track {
  display: flex;
  gap: 16px;
  will-change: transform;
}
.lp-hero-track.is-sliding {
  transition: transform 0.45s ease;
}

/* Cell — one slide. Width is a fixed square set by JS via --hero-cell-w
 * (640px on desktop; the full viewport on mobile, so one slide shows at a
 * time). aspect-ratio 1/1 makes the height follow the width. Neighbours peek
 * on each side, clipped by the strip's overflow — so the natural clip shows
 * the prev tile's right edge and the next tile's left edge, no per-cell
 * background-position needed. */
.lp-hero-cell {
  flex: 0 0 var(--hero-cell-w, 640px);
  aspect-ratio: 1 / 1;
  background-color: #eee;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  border: none;
  padding: 0;
  margin: 0;
}

/* PR-LANDING-CMS-4b — centre cell shows a pointer only when the current
 * slide has a click-through URL. JS toggles .is-clickable on each advance. */
.lp-hero-cell-centre.is-clickable { cursor: pointer; }

/* Neighbour cells step the carousel; dim on hover (eased via opacity). */
.lp-hero-cell-prev,
.lp-hero-cell-next {
  cursor: pointer;
  transition: opacity 0.4s ease;
}
.lp-hero-cell-prev:hover,
.lp-hero-cell-next:hover {
  opacity: 0.75;
}

/* 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: 52px;
}

/* Two reassurance lines under the hero play button (same copy as the
 * about page; reuses landing.about.page.intro.* so wording stays in sync).
 * PR-TAGLINE-BOX (2026-07-01): boxed — 1px black border, square corners,
 * transparent background (none set). fit-content + auto margins shrink-
 * wrap the box to the text and keep it centered (the div otherwise
 * stretches to the hero width). Matches .lp-ap-intro-pill on the About
 * page. */
.lp-hero-taglines {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  margin-top: 42px;
  width: fit-content;
  margin-left: auto;
  margin-right: auto;
  border: 1px solid #000;
  padding: 10px 28px;
}
.lp-hero-taglines span { font-size: 16px; color: #111; }
.lp-hero-taglines span:first-child { font-size: 18px; font-weight: 700; }
.lp-hero-taglines span:last-child { margin-top: -3px; }

.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;
}

.lp-section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 24px;
  gap: 16px;
}
.lp-section-title {
  font-size: 15px;      /* 11px → 15px per admin request (2026-07-10) */
  font-weight: 700;     /* 600 → 700, same request */
  letter-spacing: 1.5px;
  color: #aaa;
  text-transform: uppercase;
  margin: 0;
}
.lp-section-seeall {
  font-size: 14px;      /* 12px → 14px per admin request (2026-07-10) */
  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%;
  /* PR-LANDING-IMG23 (2026-07-13): 1/1 → 2/3 portrait at the BASE, so the
   * events + articles INDEX pages match the home page. This class has
   * exactly four users (home events, home articles, events index,
   * articles index — news renders text rows, no image cards), and all
   * four are 2:3 now, so the former .lp-splitrow / #articles scoped
   * overrides were removed as redundant. */
  aspect-ratio: 2 / 3;
  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;
}

/* ─────────────────────────────────────────────────────────────────────────
 * Events + News split row — PR-LANDING-SPLITROW (2026-07-13)
 *
 * The former separate Events / News .lp-sections are now ONE full-browser-
 * width row (hero-style: no 1280px cap): left 50% = events (3 cards in ONE
 * row, 2:3 portrait thumbs), right 50% = news (3 items, unchanged look).
 * Titles centered, styled like .lp-ap-intro-a (18px / 700 / #111). The
 * "See all" links are pills with .lp-btn-play's exact metrics (incl. its
 * ≥768px size bump). Halves are flex columns so margin-top:auto pins both
 * pills to the bottom edge even when content heights differ. No divider
 * between halves (user choice). Mobile-first: stacked 100% halves, events
 * first via source order; 50/50 from 768px (the site's desktop breakpoint
 * — nav / btn-play / grids all switch there).
 *
 * SCOPE: the 3-column grid is a .lp-splitrow-scoped override and
 * out-specifies the shared rules at every width; the shared
 * .lp-events-grid base look is untouched for the home articles row and
 * the events / articles index pages. (The card IMAGE is 2:3 at the class
 * base since PR-LANDING-IMG23 — all four users share it.) The removed
 * `.lp-section#news { max-width: 800px }` line-length cap (its section no
 * longer exists) is replaced by the 640px cap on the news list below.
 *
 * REUSE — PR-LANDING-CTA2 (2026-07-13): .lp-splitrow-title, -morewrap and
 * -more are ALSO used by the home page's exhibitors, articles and
 * newsletter sections (centered black titles + bottom "See all" pills;
 * newsletter has the title only). They are deliberately not scoped to
 * .lp-splitrow — treat them as the home page's shared section-title/pill
 * components. Inside a non-flex .lp-section, -morewrap's margin-top:auto
 * is simply inert (0); the padding-top does the spacing.
 * ───────────────────────────────────────────────────────────────────────── */

.lp-splitrow {
  display: flex;
  flex-direction: column;     /* mobile: stacked, events half first */
  width: 100%;
}
.lp-splitrow-half {
  display: flex;
  flex-direction: column;
  padding: 48px 20px;
}
.lp-splitrow-title {
  font-size: 18px;            /* = .lp-ap-intro-a (about-page intro line) */
  font-weight: 700;
  color: #111;
  text-align: center;
  margin: 0 0 24px;
}
/* Scoped overrides — see SCOPE note above.
 * PR-LANDING-CTA2d (2026-07-13): the events half's grid is now 2-up on
 * mobile (matching the articles row's base look when the half is 100%
 * wide — 3 items render as 2 + 1) and 3-in-one-row from 768px (the 50/50
 * split); the 3-up rule moved into the media block below.
 * PR-LANDING-IMG23 (2026-07-13): the 2:3 image overrides that lived here
 * (.lp-splitrow / #articles) were removed — 2/3 is the class BASE now
 * (see .lp-event-card-image), covering the index pages too. */
.lp-splitrow .lp-events-grid      { grid-template-columns: repeat(2, 1fr); }
/* News line-length cap inside the wide half — readability. */
.lp-splitrow .lp-news-list { max-width: 640px; width: 100%; margin: 0 auto; }

.lp-splitrow-morewrap {
  margin-top: auto;           /* pins the pill to the half's bottom */
  padding-top: 32px;
  text-align: center;
}
.lp-splitrow-more {
  display: inline-block;      /* <a>, so it needs an explicit block box */
  background: #fff;           /* PR-LANDING-CTA2c (2026-07-13): "See all"
                                 pills now use the .lp-about-btn--ghost
                                 (about-page Account pill) treatment per
                                 user request — white bg, GREY #ddd border,
                                 black text, NO drop shadow, NO hover
                                 effect. Pill metrics (padding / radius /
                                 min-width incl. the ≥768px bump) still
                                 = .lp-btn-play; :active press feedback
                                 kept (it is not a mouse-over effect). */
  color: #111;
  border: 1px solid #ddd;
  padding: 16px 36px;
  border-radius: 999px;
  font-size: 16px;
  font-weight: 600;
  letter-spacing: 0.3px;
  transition: border-color 0.15s, transform 0.1s;
  min-width: 220px;
  text-align: center;
  text-decoration: none;
}
/* PR-LANDING-CTA2d (2026-07-13): hover matches .lp-about-btn--ghost —
 * the grey border turns black (border only; bg/text unchanged). */
.lp-splitrow-more:hover  { border-color: #111; }
.lp-splitrow-more:active { transform: scale(0.98); }

@media (min-width: 768px) {
  .lp-splitrow      { flex-direction: row; }
  .lp-splitrow-half { width: 50%; padding: 48px 32px; }
  /* desktop: 3 event cards in one row inside the 50% half (see CTA2d note) */
  .lp-splitrow .lp-events-grid { grid-template-columns: repeat(3, 1fr); }
  /* keep pill parity with .lp-btn-play's ≥768px bump (see media block below) */
  .lp-splitrow-more { padding: 18px 48px; font-size: 17px; min-width: 260px; }
}

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

.lp-exhibitors-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 14px;   /* PR-LANDING-GRIDUNIFY (2026-07-13): 18 → 14, matching
                * .lp-events-grid so events / exhibitors / articles cards
                * share identical widths + gaps on mobile (18px from 480px
                * via the media block; 6-up desktop unchanged). */
}
.lp-exhibitor-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  /* explicitly NOT a link — purely informational per spec */
  /* PR-LANDING-EXGRID (2026-07-13): 1fr grid tracks have an implicit
   * min-width:auto, so a card with unbreakable content (long name / URL
   * in the description) widened its column and shrank its neighbour on
   * mobile. min-width:0 restores equal columns at every breakpoint
   * (2/3/6-up) — same guard this file already uses elsewhere; the
   * overflow-wrap below lets that content wrap inside the fixed column. */
  min-width: 0;
}
.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;
  overflow-wrap: break-word;   /* PR-LANDING-EXGRID — see card comment */
}
.lp-exhibitor-desc {
  font-size: 12px;
  color: #666;
  line-height: 1.5;
  overflow-wrap: break-word;   /* PR-LANDING-EXGRID — see card comment */
  /* Clamp to 2 lines on landing — full description on detail page */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ─────────────────────────────────────────────────────────────────────────
 * About — WONDER WANDER intro banner (PR-ABOUT-BANNER)
 *
 * Live tagline + uploaded background banner (textures + EXPLORE/SHARE only) +
 * HTML bullet cards + a shared centre circle PNG with HTML pillar wording and
 * orbiting Culture/Art/Design satellites + live buttons. Mobile = halves
 * stacked (2:3); desktop = side by side (2:1). EN/JA banners swap purely in
 * CSS via html[lang] (setLocale() reloads, so <html lang> is always current).
 *
 * IMPORTANT — background-image paths are relative to THIS stylesheet
 * (public/css/landing.css), NOT the page's <base href> (CSS url() ignores
 * base). '../images/...' resolves to <mount>/images/... under both the
 * /world1 alpha mount and a future root mount.
 * ───────────────────────────────────────────────────────────────────────── */

/* Full-width grey band. The section spans the full body width (sections are
 * direct children of <body>, which is full-viewport-width with overflow-x
 * hidden); .lp-about-inner caps the content at 1280 with the 20px gutter,
 * matching the other sections. */
.lp-about-section {
  background: #f0f0f0;
  padding: 48px 0;
}
.lp-about-inner {
  max-width: 1280px;
  margin: 0 auto;
  padding: 0 20px;
}

.lp-about-tagline {
  text-align: center;
  font-size: 20px;
  font-weight: 700;
  letter-spacing: -0.3px;
  color: #111;
  margin: 0 0 24px;
}

.lp-about-banner {
  position: relative;
  container-type: inline-size;                  /* enables cqw for the satellites */
  width: 100%;
  aspect-ratio: 1 / 2;                          /* 800×1600 — two stacked halves */
  background-image: url('../images/landing/about/about-banner-mobile.jpg');
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  overflow: hidden;
}
html[lang="ja"] .lp-about-banner {
  background-image: url('../images/landing/about/about-banner-mobile-ja.jpg');
}

/* Foreground overlays — all LIVE, translatable text (not baked into the
 * banner image). The image now carries only the textures + EXPLORE/SHARE
 * headings; the bullet cards, the centre circle wording, and the
 * Culture/Art/Design satellites' positions are HTML/CSS.
 *
 * Positions marked TUNE are placeholders — adjust them to sit cleanly over
 * your final artwork (use about-preview.html to eyeball desktop + mobile).
 * Mobile-first values below target the stacked 2:3 layout; the 768px block
 * lower in this file overrides them for the side-by-side 2:1 desktop layout. */

.lp-about-card {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  width: 62.4%;                                /* TUNE (was 78%, −20%) */
  background: #fff;
  border-radius: 14px;
  padding: 14px 16px;
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.08);
}
.lp-about-card--explore { top: 30px; }         /* 30px from the top edge */
.lp-about-card--share   { top: auto; bottom: 30px; }  /* 30px from the bottom edge */

.lp-about-bullets {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  text-align: center;
  font-size: 15px;
  font-weight: 600;
  color: #111;
  line-height: 1.3;
}

/* Centre wrapper holds the circle PNG and the pillar text together, so the
 * wording always aligns to the disc no matter the size. Centred on the seam. */
.lp-about-center {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 85%;                                  /* mobile circle diameter */
  max-width: 460px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.lp-about-circle {
  width: 100%;
  height: auto;
  display: block;
}
.lp-about-pillars {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 72%;                                  /* TUNE — inner text area of disc */
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  text-align: center;
  pointer-events: none;
}
.lp-about-pillar {
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.lp-about-pillar-name {
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.5px;
  color: #111;
  line-height: 1.1;
}
.lp-about-pillar-desc {
  font-size: 10px;
  color: #555;
  line-height: 1.2;
}
.lp-about-pillar-x {
  font-size: 11px;
  color: #888;
  margin: 1px 0;
}

/* Culture / Art / Design satellites orbiting the disc (HTML, was baked into the
 * PNG). Each spoke runs from the disc centre to its rim; the orbit ring spins,
 * carrying the spokes, while each label counter-spins at the same rate so the
 * text stays upright. Deliberately very slow (180s/turn). Honours
 * prefers-reduced-motion. The ring shares the disc's box (inset:0), so the
 * satellites scale with the circle at every breakpoint. */
.lp-about-orbit {
  position: absolute;
  inset: 0;
  animation: lp-about-orbit 180s linear infinite;
}
.lp-about-spoke {
  position: absolute;
  top: 12%;
  left: 50%;
  width: 0;
  height: 38%;                                 /* centre → 38% (orbit radius) */
  transform-origin: bottom center;
}
.lp-about-spoke--1 { transform: rotate(0deg); }
.lp-about-spoke--2 { transform: rotate(120deg); }
.lp-about-spoke--3 { transform: rotate(240deg); }
.lp-about-sat {
  position: absolute;
  top: 0;
  left: 50%;
  width: 20cqw;                                /* mobile: 20% of banner width (desktop overrides with px) */
  height: 20cqw;
  border-radius: 50%;
  background: #111;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
}
.lp-about-spoke--1 .lp-about-sat { transform: translate(-50%, -50%) rotate(0deg); }
.lp-about-spoke--2 .lp-about-sat { transform: translate(-50%, -50%) rotate(-120deg); }
.lp-about-spoke--3 .lp-about-sat { transform: translate(-50%, -50%) rotate(-240deg); }
.lp-about-sat-spin {
  display: block;
  animation: lp-about-orbit-rev 180s linear infinite;
}
@keyframes lp-about-orbit     { to { transform: rotate(360deg); } }
@keyframes lp-about-orbit-rev { to { transform: rotate(-360deg); } }
@media (prefers-reduced-motion: reduce) {
  .lp-about-orbit, .lp-about-sat-spin { animation: none; }
}

.lp-about-actions {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin: 54px 0 30px;
}

.lp-about-btn {
  display: inline-block;
  text-align: center;
  padding: 14px 24px;
  border-radius: 999px;
  font-size: 16px;
  font-weight: 600;
  letter-spacing: 0.3px;
  transition: background-color 0.15s, border-color 0.15s, transform 0.1s;
}
.lp-about-btn:active            { transform: scale(0.98); }
.lp-about-btn--primary          { background: #111; color: #fff; }
.lp-about-btn--primary:hover    { background: #333; }
.lp-about-btn--ghost            { background: #fff; color: #111; border: 1px solid #ddd; }
.lp-about-btn--ghost:hover      { border-color: #111; }
.lp-about-btn--accent           { background: #ffe9d6; color: #b45309; }
.lp-about-btn--accent:hover     { background: #ffdcc0; }

/* Logged-in swap: the "Account (L)" link is hidden until checkAuth() adds
 * .is-visible (mirrors .lp-account-icon in the header). The initial sits a
 * touch right of the word; parens come from .lp-account-initial. */
.lp-about-account { display: none; }
.lp-about-account.is-visible { display: inline-block; }
#about-account .lp-account-initial { margin-left: 4px; }

/* Secondary "More about WONDER WANDER" CTA — a black circle with white text,
 * echoing the satellite circles. Centred below the buttons. */
.lp-about-more-wrap { text-align: center; margin: 28px 0 0; }
.lp-about-more {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  width: 140px;
  height: 140px;
  padding: 14px;
  border-radius: 50%;
  background: #111;
  color: #fff;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.35;
  transition: background-color 0.15s, transform 0.1s;
}
.lp-about-more:hover { background: #333; }
.lp-about-more:active { transform: scale(0.97); }

/* ─────────────────────────────────────────────────────────────────────────
 * 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
 * ───────────────────────────────────────────────────────────────────────── */

/* PR-GUEST-CTA-UNIFY (2026-06-17): the login modal's "Continue as Guest"
 * button, single-sourced. Previously each landing page carried its own
 * inline style, which drifted — index.html showed an orange pill while the
 * other 10 pages kept an old dashed-grey style. One class keeps them in
 * lock-step: orange pill, no border. */
.lp-guest-cta {
  width: 100%;
  padding: 10px;
  text-align: center;
  border: none;
  border-radius: 999px;
  background: #ffe9d6;
  color: #b45309;
  font-size: 13px;
  font-family: inherit;
  cursor: pointer;
  transition: background-color 0.12s;
}
.lp-guest-cta:hover { background: #ffdcc0; }

.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-logo img {
  width: 200px;
  height: 100px;
  object-fit: contain;
  display: block;
}
@media (max-width: 768px) {
  .lp-footer-logo img { width: 150px; height: 75px; }
}
.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 {
  /* PR-FOOTER-TOTOP (2026-06-17): flex-centre so the copyright is
   * vertically centred (was display:block + asymmetric padding, which
   * floated it a few px above centre); position:relative anchors the
   * back-to-top button at the right edge. */
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  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: 16px 20px;
  padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  text-align: center;
  font-size: 12px;
  color: #c8c8c8;
  min-height: 56px;
  box-sizing: border-box;
}
/* PR-FOOTER-TOTOP: back-to-top pill, anchored to the right of the
 * (centred) copyright bar so the copyright stays centred. */
.lp-totop {
  position: absolute;
  right: 20px;
  top: 50%;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 6px 12px;
  font-size: 12px;
  font-family: inherit;
  color: #e8e8e8;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 999px;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.lp-totop:hover {
  background: rgba(255, 255, 255, 0.16);
  border-color: rgba(255, 255, 255, 0.34);
  color: #fff;
}

/* ─────────────────────────────────────────────────────────────────────────
 * 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; }
/* PR-GENDER-GLYPH (2026-07-04): the guest-modal gender labels contain the
   ♂/♀ glyphs (U+2642/U+2640). Under html[lang="ja"] the body's Japanese
   stack (see html[lang="ja"] body above) contains these glyphs with clean
   vertical metrics — but the default EN stack's Latin fonts lack them, so
   the browser fell back to a symbol/emoji font whose glyphs sit visibly
   LOWER than the Latin text. This local() alias, restricted to exactly
   those two codepoints, makes BOTH languages render the symbols with the
   same known-good Japanese fonts on every landing page that bakes the
   guest modal (all of them share this stylesheet). Extra local() names
   cover the macOS PostScript / no-space Windows family spellings. If none
   of the fonts are installed, the rule is inert and rendering falls
   through to today's behaviour. The locale strings additionally carry
   U+FE0E (text presentation selector) as a guard against emoji-style
   fallback on systems without these fonts. */
@font-face {
  font-family: "WW Gender Symbols";
  src: local("Hiragino Kaku Gothic ProN"), local("HiraKakuProN-W3"),
       local("Yu Gothic"), local("YuGothic"), local("Meiryo");
  unicode-range: U+2640, U+2642;
}

.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;
  /* PR-GENDER-GLYPH: was `inherit` — now the symbol alias above, then the
     same stack as the body default, so only ♂/♀ change font. Under
     html[lang="ja"] the label text still resolves to the Japanese fonts
     (Latin entries lack CJK glyphs), so JA rendering is unchanged. */
  font-family: "WW Gender Symbols",
               -apple-system, BlinkMacSystemFont, "Helvetica Neue",
               "Hiragino Kaku Gothic ProN", "Yu Gothic", Meiryo, sans-serif;
  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;
}

/* PR-RESEND-VERIFY: resend-verification link + status, shown under the login
   error and on the post-register success screen. Link mirrors .modal-switch
   button (underlined text-button); status is a small muted note below. */
.auth-resend { margin-top: 8px; }
.auth-resend.hidden { display: none; }
.auth-resend-link {
  color: #b45309;
  text-decoration: underline;
  font-size: 13px;
  background: none;
  border: none;
  cursor: pointer;
  font-family: inherit;
  padding: 0;
}
.auth-resend-link:hover { opacity: 0.8; }
.auth-resend-status {
  display: block;
  margin-top: 4px;
  font-size: 12px;
  color: #666;
}

/* PR-NEWSLETTER: landing signup section. */
.lp-newsletter { text-align: center; }
/* PR-NL-BOX (2026-07-10): bordered box around the lead + form — the
   .lp-hero-taglines treatment (1px solid black, transparent background,
   square corners). max-width 496px − 28px side padding each side = the
   form's existing 440px content column, so nothing inside needed resizing. */
.lp-newsletter-box {
  max-width: 496px;
  margin: 0 auto;
  border: 1px solid #000;
  background: #f0f0f0;   /* PR-NL-BOX follow-up: was transparent, per admin request */
  padding: 10px 28px;   /* PR-NL-BOX follow-up: matched to .lp-hero-taglines per admin request */
}
/* Lead is constrained to the same 440px column as the form and left-aligned,
   so its left edge lines up with the consent note below the inputs.
   PR-NL-BOX follow-up: font matched to .lp-hero-taglines span:first-child
   (18px w700 #111) per admin request — layout/alignment unchanged. */
.lp-newsletter-lead { font-size: 18px; font-weight: 700; color: #111; margin: 0 auto 16px; max-width: 440px; text-align: left; }
.lp-newsletter-form {
  max-width: 440px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 10px;
  text-align: left;
}
.lp-newsletter-input {
  padding: 10px 12px;
  border: 1px solid #d8d2c8;
  border-radius: 8px;
  font: inherit;
  font-size: 14px;
}
.lp-newsletter-consent {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-size: 13px;
  color: #555;
  line-height: 1.5;
}
.lp-newsletter-consent input { margin-top: 3px; flex: none; }
.lp-newsletter-consent a { color: #111; text-decoration: underline; }
.lp-newsletter-note { font-size: 12px; color: #888; line-height: 1.6; margin: 0; }
.lp-newsletter-btn {
  /* PR-NL-BOX: +10px on top of the form's 10px flex gap — ~20px of air
     above Subscribe (the note-to-button gap read cramped at gap alone). */
  margin-top: 10px;
  padding: 11px 16px;
  background: #111;
  color: #fff;
  border: none;
  border-radius: 999px;
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: opacity .12s;
}
.lp-newsletter-btn:hover:not(:disabled) { opacity: .85; }
.lp-newsletter-btn:disabled { background: #ccc; cursor: default; }
.lp-newsletter-status { font-size: 13px; color: #2c7a4b; min-height: 18px; }
.lp-newsletter-status.is-error { color: #c22; }
.lp-newsletter-accountlink {
  display: none;
  margin-top: 4px;
  font-size: 13px;
  color: #b45309;
  text-decoration: underline;
}
.lp-newsletter-accountlink.show { display: inline-block; }

/* ─────────────────────────────────────────────────────────────────────────
 * 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;
  /* PR-LANDING-IMG23 (2026-07-13): the fixed square crop (aspect-ratio
   * 1/1 + cover) was removed — on a detail page the image IS the content,
   * so it now renders at its natural proportions, exactly like
   * .lp-detail-block-image below (whose img rules this mirrors). Applies
   * to all four detail kinds (event / news / article / exhibitor — shared
   * template). The #ddd placeholder is gone with it: without a fixed
   * ratio the wrapper has no height until the image loads. */
  overflow: hidden;
}
.lp-detail-image img {
  /* PR-LANDING-IMG-NOUPSCALE (2026-07-30): `width: 100%` was removed. It
   * forced images narrower than the 640px column to stretch up to it,
   * which made them blurry. Without it the global `img` reset (max-width:
   * 100%; height: auto) applies: images render 1:1 at natural size and are
   * only scaled DOWN when wider than the column. `margin: 0 auto` centres
   * the narrow ones. NOTE: this stops upscale blur, not high-DPI softness —
   * for crisp images on 2x screens, upload at ~1280px wide. */
  height: auto;
  display: block;
  margin: 0 auto;
}

/* 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 {
  /* PR-LANDING-IMG-NOUPSCALE (2026-07-30): mirrors .lp-detail-image img
   * above — see the reasoning there. */
  height: auto;
  display: block;
  margin: 0 auto;
}

/* ─────────────────────────────────────────────────────────────────────────
 * 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. */

/* ═══ Standalone About page (PR-ABOUT-PAGE) ═══════════════════════════════
 * Full-width <main>; each .lp-ap-section caps content via .lp-ap-wrap. The
 * Concept section reuses the .lp-about-* banner. Sticky sub-nav sits just
 * under the ~120px header (85px on mobile). */
.lp-ap { width: 100%; }

.lp-ap-section { padding: 56px 0; border-bottom: 1px solid #e5e5e5; scroll-margin-top: 200px; }
#pricing { border-bottom: none; }
/* Why-section grey band (2026-07-10, per admin request): #why gets a
   full-browser-width #f0f0f0 background (sections span the viewport —
   .lp-ap-wrap caps only the content) with BOTH divider lines removed:
   its own border-bottom, and #creators' border-bottom (the line that sat
   on top of it). The white .lp-ap-feat--text cards sit on the band. */
#creators { border-bottom: none; }
#why { background: #f0f0f0; border-bottom: none; }
.lp-ap-section--flush { padding-bottom: 0; }
.lp-ap-wrap { max-width: 1280px; margin: 0 auto; padding: 0 20px; }
/* Concept mirrors the home banner but without the grey band on this page. */
#concept .lp-about-section { background: transparent; padding: 24px 0 0; }

/* Section intros are centred (cards / table keep their own alignment). */
.lp-ap-eyebrow { font-size: 11px; letter-spacing: 1.6px; text-transform: uppercase; color: #888; margin: 0 0 8px; text-align: center; }
.lp-ap-title   { font-size: 28px; font-weight: 800; letter-spacing: -0.5px; color: #111; margin: 0 0 8px; text-align: center; }
.lp-ap-lead    { color: #555; max-width: 680px; margin: 0 auto 28px; line-height: 1.6; text-align: center; }

.lp-ap-subnav {
  position: sticky; top: 120px; z-index: 40;
  display: flex; gap: 6px; justify-content: center; flex-wrap: wrap;
  padding: 10px 12px; background: rgba(255,255,255,0.95);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  overflow-x: auto;
}
.lp-ap-subnav a {
  font-size: 13px; font-weight: 600; color: #555; white-space: nowrap;
  padding: 7px 14px; border-radius: 999px; transition: background 0.15s, color 0.15s;
}
.lp-ap-subnav a:hover { background: #f0f0f0; color: #111; }

.lp-ap-intro { text-align: center; padding: 30px 20px 6px; }
/* PR-TAGLINE-BOX (2026-07-01): boxed to match .lp-hero-taglines on the
 * home page — 1px black border, square corners, transparent background
 * (none set). The pill is already inline-block, so it shrink-wraps. */
.lp-ap-intro-pill { display: inline-block; color: #111; border: 1px solid #000; padding: 10px 28px; }
.lp-ap-intro-a { display: block; font-size: 18px; font-weight: 700; color: #111; margin: 0; }
.lp-ap-intro-b { display: block; font-size: 16px; color: #111; margin: -1px 0 0; }

.lp-ap-grid { display: grid; gap: 24px; }
.lp-ap-grid--3 { grid-template-columns: repeat(3, 1fr); }
.lp-ap-grid--4 { grid-template-columns: repeat(4, 1fr); gap: 20px; }

.lp-ap-img { background: #f0f0f0; border-radius: 10px; overflow: hidden; aspect-ratio: 4 / 3; }
.lp-ap-img--sq { aspect-ratio: 1 / 1; }
.lp-ap-img img { width: 100%; height: 100%; object-fit: cover; display: block; }

.lp-ap-card .lp-ap-img { margin-bottom: 14px; }
.lp-ap-tag { display: inline-block; font-size: 11px; background: #f5f7f0; color: #444; border-radius: 999px; padding: 2px 10px; margin-bottom: 8px; }
.lp-ap-card-title { margin: 0 0 4px; font-size: 18px; color: #111; }
.lp-ap-meta { list-style: none; margin: 8px 0 0; padding: 0; font-size: 13.5px; color: #555; }
.lp-ap-meta li { padding: 4px 0; border-top: 1px solid #eee; }
.lp-ap-meta li:first-child { border-top: 0; }

.lp-ap-feat .lp-ap-img { margin-bottom: 12px; }
.lp-ap-feat-title { margin: 0 0 4px; font-size: 16px; color: #111; }
.lp-ap-feat-desc  { margin: 0; font-size: 13.5px; color: #555; line-height: 1.5; }
/* PR-ABOUT-WHY (2026-07-04): text-only feature cards (the "Why WONDER
   WANDER" section) carry no image box, so without their own chrome they
   read as loose paragraphs. The hairline box matches the site's existing
   card language (white, #e5e5e5, radius 10). Image-ful cards unchanged. */
.lp-ap-feat--text {
  border: 1px solid #e5e5e5;
  border-radius: 10px;
  background: #fff;
  padding: 18px;
}

/* PR-BOOKING-STEPS — 3-step process indicator above the pricing table.
   Three black circles ("Step 1/2/3") in a row, joined by a connector line,
   each with a localised description beneath. Fixed at 3 steps. */
.lp-ap-steps {
  list-style: none;
  margin: 60px auto 60px;
  padding: 0;
  max-width: 680px;
  display: flex;
  justify-content: center;
  position: relative;
}
.lp-ap-steps::before {            /* connector line, sits BEHIND the circles */
  content: "";
  position: absolute;
  top: 35px;                       /* circle 72px → centre ≈ 36px */
  left: 16.667%;                   /* circle-1 centre (each step = 1/3 width) */
  right: 16.667%;                  /* circle-3 centre */
  height: 2px;
  background: #d4d4d4;
  z-index: 0;
}
.lp-ap-step {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  position: relative;
  z-index: 1;                      /* opaque circles cover the line behind them */
}
.lp-ap-step-circle {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  background: #111;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.2px;
}
.lp-ap-step-desc {
  margin-top: 12px;
  font-size: 15px;
  color: #333;
  max-width: 150px;
  line-height: 1.4;
}
@media (max-width: 480px) {
  .lp-ap-steps::before { top: 31px; }                                 /* circle 64px → centre 32px */
  .lp-ap-step-circle { width: 64px; height: 64px; font-size: 12px; }
  .lp-ap-step-desc { font-size: 13px; }
}

.lp-ap-table-wrap { overflow-x: auto; }
.lp-ap-price { width: 100%; border-collapse: collapse; font-size: 14px; min-width: 520px; }
.lp-ap-price th, .lp-ap-price td { text-align: left; padding: 14px 12px; border-bottom: 1px solid #e5e5e5; }
.lp-ap-price th { font-size: 11px; letter-spacing: 1px; text-transform: uppercase; color: #888; font-weight: 600; }
.lp-ap-price-name { display: block; font-weight: 700; color: #111; }
.lp-ap-price-sub  { display: block; font-size: 12.5px; color: #888; }
.lp-ap-price-sale { display: block; font-weight: 700; color: #111; }
.lp-ap-price-was  { display: block; font-size: 12.5px; color: #888; text-decoration: line-through; }
.lp-ap-price-note { font-size: 12px; color: #888; margin: 12px 0 0; }
.lp-ap-apply { margin: 54px 0 30px; text-align: center; }

.lp-ap-cta { padding: 56px 0; }
.lp-ap-cta-row { margin-top: 0; justify-content: center; }
.lp-ap-section-cta { margin-top: 66px; }

@media (max-width: 860px) {
  .lp-ap-grid--3, .lp-ap-grid--4 { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 768px) {
  .lp-ap-subnav { top: 85px; justify-content: flex-start; }
  .lp-ap-section { scroll-margin-top: 150px; }
}
@media (max-width: 560px) {
  /* PR-ABOUT-CARDS: card grids stay 2-per-row on phones (the 860px rule
     above already sets 2 columns; previously this dropped to 1). Tighter
     gap so two cards breathe on narrow screens. */
  .lp-ap-grid--3, .lp-ap-grid--4 { gap: 14px; }
  .lp-ap-title { font-size: 23px; }
}

.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; }

/* View-all link — centered button below the prev/next nav. Links to the
 * current kind's index page. Matches the nav-link treatment (border,
 * background, hover) but stands alone and centered. */
.lp-detail-viewall {
  display: block;
  width: fit-content;
  margin: 16px auto 0;
  padding: 12px 24px;
  border: 1px solid #e5e5e5;
  background: #fafafa;
  color: #555;
  font-size: 13px;
  font-weight: 600;
  text-align: center;
  text-decoration: none;
  transition: border-color 0.15s, color 0.15s, background 0.15s;
}
.lp-detail-viewall:hover {
  border-color: #aaa;
  color: #111;
  background: #fff;
}

/* 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%;
}
/* Inner column mirrors .lp-section: a 1280px cap with the 20px gutter
 * INSIDE the capped box, so content lands at 1240px — flush with the
 * hero, the home-page sections, and the footer. Vertical rhythm (top/
 * bottom) is the index pages' own; only the width pattern is shared.  */
.lp-index-inner {
  max-width: 1280px;
  margin: 0 auto;
  padding: 32px 20px 64px;
}

.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/card transitions + card hover transform
 * ───────────────────────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  .lp-hero-track       { transition: none; }
  .lp-hero-cell        { transition: none; }
  .lp-event-card       { transition: none; }
  .lp-event-card:hover { transform: none; }
}


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

@media (min-width: 480px) {
  .lp-events-grid       { gap: 18px; }
  /* PR-LANDING-GRIDUNIFY (2026-07-13): exhibitors previously switched to
   * 3-up / 20px gap here while events + articles stayed 2-up / 18px,
   * giving visibly narrower exhibitor cards on large phones. Unified:
   * 2-up with the same 18px gap all the way to 768px, where the 6-up
   * desktop layout takes over (unchanged). */
  .lp-exhibitors-grid   { gap: 18px; }
  .lp-section           { padding: 56px 20px; }
  .lp-about-section     { padding: 56px 0; }
}

/* ─────────────────────────────────────────────────────────────────────────
 * 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 20px; }
  .lp-about-section     { padding: 72px 0; }

  .lp-about-tagline     { font-size: 26px; margin-bottom: 32px; }
  .lp-about-banner      { aspect-ratio: 2 / 1; background-image: url('../images/landing/about/about-banner-desktop.jpg'); }
  html[lang="ja"] .lp-about-banner { background-image: url('../images/landing/about/about-banner-desktop-ja.jpg'); }

  /* Cards move to the left/right halves (TUNE to your artwork's card areas) */
  /* Cards move to the left/right halves, vertically centred (TUNE left/right %) */
  .lp-about-card           { width: 19.2%; transform: translateY(-50%); }
  .lp-about-card--explore  { left: 6%;  right: auto; top: 50%; bottom: auto; }
  .lp-about-card--share    { left: auto; right: 6%;  top: 50%; bottom: auto; }
  .lp-about-bullets        { font-size: 16px; gap: 12px; }

  /* Larger centre circle + pillar type on desktop */
  .lp-about-center         { width: 46%; max-width: 560px; }
  .lp-about-pillars        { width: 70%; gap: 4px; }
  .lp-about-pillar-name    { font-size: 22px; }
  .lp-about-pillar-desc    { font-size: 13px; }
  .lp-about-pillar-x       { font-size: 14px; margin: 2px 0; }
  .lp-about-sat            { width: 100px; height: 100px; font-size: 15px; }
  .lp-about-spoke          { top: 15%; height: 35%; }   /* desktop orbit radius 35% */

  /* Equal-width buttons so the middle one sits dead centre */
  .lp-about-actions     { flex-direction: row; justify-content: center; gap: 16px; }
  .lp-about-btn         { width: 320px; padding: 16px 20px; font-size: 17px; white-space: nowrap; }

  .lp-footer-inner      {
    grid-template-columns: 2fr 1fr 1fr 1fr;
    gap: 40px;
    padding: 56px 20px 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-inner       { padding: 56px 20px 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 20px; }
  .lp-about-section     { padding: 88px 0; }
  .lp-about-tagline     { font-size: 28px; }
}

/* ─────────────────────────────────────────────────────────────────────────
 * 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: var(--wc-bg, #111); color: var(--wc-fg, #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; }
/* Admin "Worlds" tab can set a custom background (--wc-bg). For those pills,
   hover darkens their OWN colour instead of jumping to the default grey.
   :not(:disabled) so a blocked (maintenance/access) world still greys out. */
.wc-pill--custom:not(:disabled):hover { background: var(--wc-bg, #111); filter: brightness(0.92); }
.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; }
