  /* ═══════════ GAME SHELL: screens (only the active one is shown) ═══════════ */
  .screen { display: none; }
  body[data-screen="splash"]       #splash,
  body[data-screen="title"]        #title,
  body[data-screen="map"]          #map,
  body[data-screen="game"]         #game,
  body[data-screen="settings"]     #settings,
  body[data-screen="gallery"]      #gallery,
  body[data-screen="achievements"] #achievements,
  body[data-screen="wardrobe"]     #wardrobe,
  body[data-screen="shop"]         #shop { display: flex; }
  .screen.screenSlideLeft  { animation: screenSlideLeft .24s cubic-bezier(.2,.86,.18,1) both; }
  .screen.screenSlideRight { animation: screenSlideRight .24s cubic-bezier(.2,.86,.18,1) both; }
  @keyframes screenSlideLeft  { from { opacity: .96; transform: translate3d(10%, 0, 0); } to { opacity: 1; transform: translate3d(0, 0, 0); } }
  @keyframes screenSlideRight { from { opacity: .96; transform: translate3d(-10%, 0, 0); } to { opacity: 1; transform: translate3d(0, 0, 0); } }
  html[data-motion="reduced"] {
    .screen.screenSlideLeft,
    .screen.screenSlideRight { animation: none !important; }
  }
  #splash, #title { flex-direction: column; align-items: center; justify-content: center; min-height: var(--app-h); gap: 16px; padding: 24px; text-align: center; }
  #map, #gallery, #achievements, #shop, #wardrobe, #settings { flex-direction: column; min-height: 100vh; }
  /* FIXED viewport height (not min-height) so a tall scrolling board can NEVER push the HUD/palette/action
     bar — the board area is the only thing that scrolls (internally). svh = stable on mobile webviews. */
  #game { flex-direction: column; align-items: center; padding: 6px 12px calc(24px + env(safe-area-inset-bottom,0px)); gap: 11px; height: 100svh; min-height: 0; overflow: hidden; }
  /* during play, swallow touch-drags so dragging empty board margins never scrolls the page (map still scrolls) */
  body[data-screen="game"], body[data-screen="game"] #game { touch-action: none; }

  .iconBtn { min-width: 0; width: 44px; height: 44px; padding: 0; font-size: 18px; }
  /* monochrome line icons — crisp (no wobble) on the clean light theme; inherit color, scale with font-size */
  .ico { width: 1.3em; height: 1.3em; display: inline-block; vertical-align: -0.2em; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
  .navBtn .navIcon .ico { width: 26px; height: 26px; }
  .bigTitle { font-size: 30px; letter-spacing: .5px; }
  .studio { color: var(--muted); font-size: 12px; letter-spacing: 3px; text-transform: uppercase; }
  #splash {
    position: relative;
    width: 100%;
    height: 100vh;
    height: 100svh;
    min-height: 0 !important;
    padding: 0 !important;
    gap: 0 !important;
    background: #fcfcfc;   /* splash clip opens on a white frame (YFI logo) — avoid a black flash before the poster/video paints */
    overflow: hidden;
  }
  #splash .splashVideo {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    object-fit: cover;
    background: #fcfcfc;
  }

  /* ════════ TITLE SCREEN — sprite skin (assets/title/*.png) ════════
     The 848×1264 atlas (aspect 0.67) cannot cover a phone (aspect ~0.46)
     without cropping its edge UI. So it is SLICED into per-element sprites,
     each anchored to its own screen edge → nothing is ever cropped.
     Number-on-bar uses container units (cqi) so digits track the bar size. */
  #title { background: #000; position: relative;
           height: var(--app-h) !important; min-height: 0 !important;
           justify-content: flex-start !important;
           padding: 0 !important; gap: 0 !important; overflow: hidden; }
  /* backdrop fills the contain-letterbox so sides aren't cropped + no black bars (blur removed 2026-06-29 — looked unpolished) */
  .titleSceneBg { position: absolute; inset: 0; z-index: 0;
           background: url('../../assets/title/bg.webp') center / cover no-repeat;
           filter: brightness(.82); transform: scale(1.12);
           pointer-events: none; }
  .titleSceneVideo { position: absolute; inset: 0; z-index: 1;
           width: 100%; height: 100%; object-fit: contain; display: block;
           background: transparent; pointer-events: none;
           opacity: 0; transition: opacity .3s;   /* hidden until playing — prevents browser video placeholder */
           /* top edge feathers into the backdrop; BOTTOM stays sharp — no blur fade (owner 2026-06-25) */
           -webkit-mask-image: linear-gradient(to bottom, transparent 5%, #000 28%, #000 100%);
           mask-image: linear-gradient(to bottom, transparent 5%, #000 28%, #000 100%); }
  /* ── 코스튬 장착 시: greeting 영상 숨기고 Sha 없는 애니메이션 배경(stage_bg_mov_004, cover) +
     코스튬 Sha + 떠다니는 빛입자. base 코스튬은 기존 greeting 영상 그대로. ── */
  .titleHero, .titleAmb, .titleCostumeBg { display: none; }
  #title.costumed .titleSceneVideo { display: none !important; }
  #title.costumed .titleCostumeBg,
  #title.costumed .titleHero,
  #title.costumed .titleAmb { display: block; }
  .titleCostumeBg { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%;
    object-fit: cover; background: transparent; pointer-events: none;
    opacity: 0; transition: opacity .3s; }   /* hidden until playing */
  .titleHero { position: absolute; inset: 0; z-index: 2; pointer-events: none; }
  /* shared CTA anchor: the PLAY button and the costumed hero both derive from these, so the hero always
     sits a fixed gap above the button at every resolution (media queries below re-point the vars once). */
  #title { --cta-bottom: calc(env(safe-area-inset-bottom,0px) + clamp(110px, 28vw, 150px)); --cta-w: clamp(184px, 56vw, 248px); }
  .titleHeroSha { position: absolute; left: 50%; bottom: calc(var(--cta-bottom) + var(--cta-w) * 175 / 463 + clamp(12px, 3.5vw, 24px)); width: min(34.5vw, 165px); transform: translateX(-50%);
    transform-origin: bottom center; filter: var(--sha-tint, brightness(1)) drop-shadow(0 7px 16px rgba(0,0,0,.5));
    animation: titleHeroIdle 4.2s ease-in-out infinite; }
  @keyframes titleHeroIdle { 0%, 100% { transform: translateX(-50%) translateY(0) scale(1); }
    50% { transform: translateX(-50%) translateY(-1.6%) scale(1.014); } }
  .titleAmb { position: absolute; inset: 0; z-index: 1; pointer-events: none; overflow: hidden; }
  .titleAmb i { position: absolute; border-radius: 50%; mix-blend-mode: screen; opacity: 0;
    background: radial-gradient(circle, #fff7d6 0%, #ffe9a0 40%, rgba(255,224,120,0) 70%);
    animation: titleMote var(--d, 5s) ease-in-out var(--delay, 0s) infinite; }
  @keyframes titleMote { 0% { opacity: 0; transform: translateY(8px) scale(.6); } 15% { opacity: .9; }
    50% { transform: translateY(-26px) translateX(var(--dx, 0)) scale(1); } 85% { opacity: .6; }
    100% { opacity: 0; transform: translateY(-54px) translateX(calc(var(--dx, 0) * 1.6)) scale(.7); } }
  html[data-motion="reduced"] {
    #title.costumed .titleCostumeBg { display: none; }   /* static: blurred bg.webp shows instead of the looping video */
    .titleHeroSha, .titleAmb i { animation: none; }
  }
  /* retired / hidden legacy elements */
  #titleWin, #mapBtn, #wardrobeBtn, .titleFoot { display: none !important; }
  /* every sliced sprite: width drives size, height follows intrinsic ratio */
  #title .barSprite, .navIcon img, #titleSettings img {   /* .navIcon img de-scoped from #title: nav is now body-level (shared hub nav) — keeps icons sized to the 76px tile */
           display: block; width: 100%; height: auto;
           -webkit-user-drag: none; user-select: none; pointer-events: none; }

  /* ── top HUD: lives (top-left) + coins (top-right) ── */
  .titleTopLeft { position: absolute !important; z-index: 10 !important; display: block !important;
           top: calc(env(safe-area-inset-top,0px) + clamp(8px,2.5vw,18px)) !important;
           left: calc(env(safe-area-inset-left,0px) + clamp(6px,2.5vw,14px)) !important; }
  .titleTop { position: absolute !important; z-index: 10 !important; display: block !important;
           top: calc(env(safe-area-inset-top,0px) + clamp(8px,2.5vw,18px)) !important;
           right: calc(env(safe-area-inset-right,0px) + clamp(6px,2.5vw,14px)) !important; }
  #title .livesBar, #title .coinsBar {
           position: relative; display: block; cursor: pointer;
           width: clamp(108px, 34vw, 156px); aspect-ratio: 246 / 81;
           height: auto !important; padding: 0 !important; transform: none !important;
           background: none !important; border: none !important; box-shadow: none !important;
           container-type: inline-size; }
  #title .coinsBar { aspect-ratio: 248 / 81; }
  #title .livesBar::before, #title .coinsBar::before { content: none !important; }
  #title .livesPlus, #title .coinsPlus { display: none !important; }
  /* the number floats over the right region of its bar; cqi = % of bar width */
  #title #titleLives, #title #titleCoins {
           position: absolute !important; top: 50% !important;
           transform: translate(-50%, -50%) !important;
           width: auto !important; height: auto !important; padding: 0 !important;
           font-size: clamp(13px, 30cqi, 24px) !important; font-weight: 900 !important;
           line-height: 1 !important; color: #fff !important; text-align: center;
           font-variant-numeric: tabular-nums; display: block !important; z-index: 3; cursor: pointer;
           text-shadow: 1px 1px 0 #5a3510, -1px -1px 0 #5a3510, 1px -1px 0 #5a3510,
                        -1px 1px 0 #5a3510, 0 2px 4px rgba(0,0,0,.7) !important;
           background: none !important; border: none !important; box-shadow: none !important; }
  #title #titleLives { left: 67% !important; }   /* heart icon ends ~34% of bar */
  #title #titleCoins { left: 65% !important; }   /* star icon ends ~31% of bar */
  #title #titleLives svg.ico { display: none !important; }
  #title #titleLives .lifeTimer { font-size: .58em; font-weight: 700; margin-left: 1px; color: #ffe9b0; }
  #title .coinsBar.assetLearnStar,
  #title .livesBar.assetLearnHeart {
    animation: assetHudGlow 1.35s ease-out both;
    filter: drop-shadow(0 0 14px rgba(255,222,108,.65)) drop-shadow(0 4px 7px rgba(0,0,0,.35));
  }
  #title .coinsBar.assetLearnStar #titleCoins,
  #title .livesBar.assetLearnHeart #titleLives {
    animation: assetValuePop 1.15s ease-out both;
  }
  #titleLives.empty { animation: lifePulse 1.8s ease-in-out infinite; }
  @keyframes lifePulse { 0%,100% { filter: none; } 50% { filter: drop-shadow(0 0 6px rgba(232,71,92,.95)); } }

  /* ── logo: top-center, below the HUD ── */
  #title .titleLogo { position: absolute !important; z-index: 4; left: 50%;
           top: calc(env(safe-area-inset-top,0px) + clamp(72px, 17vw, 118px));
           transform: translateX(-50%);
           display: block; height: auto;
           width: clamp(220px, 64vw, 320px); max-width: calc(100vw - 28px);
           filter: drop-shadow(0 6px 14px rgba(0,0,0,.35)); pointer-events: none; }

  /* ── PLAY button: lower-center, above nav, clear of the character ── */
  .titleBottom { position: absolute; inset: 0; display: block;
                 padding: 0 !important; pointer-events: none; z-index: 5; }
  .titleBottom > * { pointer-events: auto; }
  .titleActions { position: absolute !important; left: 50% !important; right: auto !important;
           top: auto !important; transform: translateX(-50%) !important;
           bottom: var(--cta-bottom) !important;
           display: block; pointer-events: auto; z-index: 6; }
  /* play button = green sprite background + dynamic jungle label (JS sets the text) */
  #playBtn { position: relative;
           background: url('../../assets/title/play_btn.webp') center / 100% 100% no-repeat !important;
           border: none !important; box-shadow: none !important;
           width: var(--cta-w) !important; aspect-ratio: 463 / 175;
           height: auto !important; padding: 0 0 3% 0 !important; min-width: 0 !important;
           display: flex; align-items: center; justify-content: center; cursor: pointer;
           /* cream-white text + dark-green outline = the game's green-button convention (.cBtn) — gold text
              competed with the gold frame and read low-contrast on the green (2026-06-24) */
           color: #fffbe8 !important; font-size: clamp(17px, 6vw, 27px) !important; font-weight: 900;
           letter-spacing: .08em; text-transform: uppercase; white-space: nowrap; line-height: 1;
           text-shadow: 1px 1px 0 #25510e, -1px -1px 0 #25510e, 1px -1px 0 #25510e,
                        -1px 1px 0 #25510e, 0 3px 6px rgba(0,0,0,.45) !important;
           -webkit-text-stroke: 1.4px #25510e;
           animation: btnNudge 5.8s ease-in-out infinite; transform-origin: 50% 50%; }
  #playBtn:active { animation: none; transform: scaleX(1.06) scaleY(0.90); }
  @keyframes btnNudge {
    /* periodic sympathetic squish — playful idle nudge on the title Play button */
    0%, 63%, 100% { transform: scale(1); }
    66%  { transform: scaleX(1.06) scaleY(0.92); }
    73%  { transform: scaleX(0.96) scaleY(1.07); }
    80%  { transform: scaleX(1.02) scaleY(0.98); }
    87%  { transform: scaleX(0.99) scaleY(1.01); }
    93%  { transform: scale(1); }
  }

  /* ── settings gear: top-right, under the coins bar (fixed) ── */
  #titleSettings svg.ico { display: none; }
  #titleSettings { position: fixed; z-index: 55;
           top: calc(env(safe-area-inset-top,0px) + clamp(62px, 16vw, 96px));
           right: calc(env(safe-area-inset-right,0px) + clamp(8px, 3vw, 18px));
           width: clamp(40px, 12vw, 54px) !important; height: auto !important; aspect-ratio: 83 / 85;
           background: transparent !important; border: none !important; box-shadow: none !important;
           padding: 0 !important; min-width: 0 !important; }
  body[data-screen="splash"] #titleSettings,
  body[data-screen="settings"] #titleSettings,
  body[data-screen="daily"] #titleSettings,
  body[data-screen="game"] #titleSettings { display: none !important; }
  /* settings gear moved BELOW the top-line HUD/count (top-right), freeing the line for the count */
  body[data-screen="gallery"] #titleSettings,
  body[data-screen="achievements"] #titleSettings {
    display: block !important;
    top: calc(env(safe-area-inset-top,0px) + 64px) !important;
    right: calc(env(safe-area-inset-right,0px) + 14px) !important;
  }
  /* map + shop both carry the 2-row star/heart HUD → gear sits below it, same position */
  body[data-screen="map"] #titleSettings,
  body[data-screen="shop"] #titleSettings {
    display: block !important;
    top: calc(env(safe-area-inset-top,0px) + 86px) !important;
    right: calc(env(safe-area-inset-right,0px) + 14px) !important;
  }

  /* ── bottom nav: 5 tiles, evenly spaced, never overflow (flex 1/0 + min-width 0) ──
     Shared hub nav (2026-06-23): lives at BODY level (not inside #title) and shows on TITLE + MAP only,
     so gallery/badges (title-only before) are reachable from the map hub too. fixed-positioned. */
  .titleNav { display: none !important; position: fixed !important; top: auto !important;
           left: calc(env(safe-area-inset-left,0px) + clamp(6px,2.5vw,14px)) !important;
           right: calc(env(safe-area-inset-right,0px) + clamp(6px,2.5vw,14px)) !important;
           bottom: 0 !important;
           justify-content: space-between; align-items: flex-end;
           gap: clamp(3px, 1.6vw, 10px); z-index: 6;
           width: auto; margin: 0 0 env(safe-area-inset-bottom, 0px); padding: 20px clamp(15px, 5.25vw, 27px) 20px;   /* safe-area를 padding→margin으로: 배경 row.png(100% 100%)가 iPhone 하단 인셋만큼 세로로 늘어나던 문제 해결 (돌판 높이 고정, 인셋은 아래 투명 여백) */
           flex-wrap: nowrap !important;
           /* nav background = row.png stone-slab panel (per owner) */
           background: url('../../assets/setting/row.png') center / 100% 100% no-repeat;
           border: none; border-radius: 0;
           box-shadow: none;
           filter: drop-shadow(0 -3px 7px rgba(0,0,0,.28)); }
  body[data-screen="title"] .titleNav,
  body[data-screen="map"]   .titleNav,
  body[data-screen="gallery"] .titleNav,
  body[data-screen="achievements"] .titleNav,
  body[data-screen="wardrobe"] .titleNav,
  body[data-screen="daily"] .titleNav { display: flex !important; }
  body[data-screen] .titleNav.nav-firstrun { display: none !important; }   /* first play: hide the bottom nav until the player has entered a level (beats the per-screen show rules) */
  .titleNav .navBtn { flex: 1 1 0; min-width: 0; max-width: 76px;
           display: flex; flex-direction: column; align-items: center; gap: 0; cursor: pointer;
           border: none !important; background: transparent !important; box-shadow: none !important;
           filter: none !important; transform: none !important; border-radius: 0 !important; padding: 0 !important; }
  .titleNav .navBtn:hover, .titleNav .navBtn:active {
           background: transparent !important; box-shadow: none !important; }
  .titleNav .navBtn .navIcon { display: block !important; width: 100%; height: auto;
           max-width: clamp(57px, 16vw, 75px); margin-inline: auto;   /* icons sized to sit inside the row.png slab (×1.5 per owner) */
           aspect-ratio: 148 / 159; background: none !important;
           filter: drop-shadow(0 2px 4px rgba(60,30,0,.25)); }
  .titleNav .navBtn .navIcon svg.ico { display: none !important; }
  .titleNav .navBtn span:last-child { display: none; }
  .titleNav .navBtn.is-hidden { display: none !important; }
  .titleNav.nav-2, .titleNav.nav-3, .titleNav.nav-4 { justify-content: center; }
  .titleNav.nav-2 { gap: clamp(18px, 10vw, 46px); }
  .titleNav.nav-3 { gap: clamp(12px, 6vw, 30px); }
  .titleNav.nav-4 { gap: clamp(6px, 3vw, 16px); }
  .titleNav.nav-2 .navBtn,
  .titleNav.nav-3 .navBtn,
  .titleNav.nav-4 .navBtn { flex: 0 1 76px; }
  .titleNav.nav-5 .navBtn { flex: 1 1 0; }
  #dailyNavBtn.locked { opacity: .35; pointer-events: none; }
  #dailyNavBtn.locked .navIcon { filter: grayscale(1); }
  /* gallery/badges before they have content: shown but greyed-out; pointer-events kept so tap shows tooltip */
  .titleNav .navBtn.nav-locked .navIcon { filter: grayscale(1) brightness(.7); opacity: .5; }
  #navLockTooltip {
    position: fixed;
    z-index: 200;
    pointer-events: none;
    display: none;
    max-width: min(72vw, 240px);
    padding: 8px 13px;
    border-radius: 10px;
    background: rgba(30, 20, 10, .88);
    color: #f5e9c8;
    font-size: 13px;
    font-weight: 700;
    line-height: 1.35;
    text-align: center;
    word-break: keep-all;
    box-shadow: 0 4px 14px rgba(0,0,0,.35);
    transform: translateX(-50%);
    opacity: 0;
    transition: opacity .18s ease;
  }
  #navLockTooltip.visible { opacity: 1; }
  #navLockTooltip::after {
    content: "";
    position: absolute;
    bottom: -6px;
    left: 50%;
    transform: translateX(-50%);
    border: 6px solid transparent;
    border-bottom: none;
    border-top-color: rgba(30, 20, 10, .88);
  }
  @keyframes dailyUnlockBounce {
    0% { transform: scale(1); }
    22% { transform: scale(1.32); filter: drop-shadow(0 0 12px #ffd15c) drop-shadow(0 0 4px #fff); }
    44% { transform: scale(0.88); filter: drop-shadow(0 0 8px #ffd15c); }
    65% { transform: scale(1.14); filter: drop-shadow(0 0 5px #ffd15c); }
    82% { transform: scale(0.97); }
    100% { transform: scale(1); filter: drop-shadow(0 2px 4px rgba(60,30,0,.14)); }
  }
  #dailyNavBtn.daily-new .navIcon { animation: dailyUnlockBounce 0.72s ease-out both; }
  .titleNav .navBtn.nav-new .navIcon { animation: dailyUnlockBounce 0.72s ease-out both; }
  .titleNav .navBtn:active .navIcon { animation: navTap .18s ease-out both; }
  @keyframes navTap { 0% { transform: scale(1); } 35% { transform: scale(.86); } 100% { transform: scale(1); } }
  html[data-motion="reduced"] { .titleNav .navBtn .navIcon, #titleLives.empty, #playBtn { animation: none; } }
  /* red-dot nudge: appears on the Badges nav when there are uncollected badge rewards (count if >1).
     Cleared only by actually claiming — see refreshBadgeDot()/unclaimedBadgeCount() in main.js. */
  .titleNav .navBtn { position: relative; }
  .titleNav .navBtn .navDot {
    position: absolute; top: 2px; right: 10%; z-index: 5; pointer-events: none;
    min-width: 17px; height: 17px; padding: 0 4px; box-sizing: border-box;
    border-radius: 999px; background: #ff3b30; border: 2px solid #fff3e2;
    box-shadow: 0 1px 3px rgba(120,12,0,.55);
    display: flex; align-items: center; justify-content: center;
    color: #fff; font-size: 11px; font-weight: 900; line-height: 1;
    animation: navDotPop .42s ease-out both;
  }
  @keyframes navDotPop { 0% { transform: scale(0); } 60% { transform: scale(1.28); } 100% { transform: scale(1); } }
  html[data-motion="reduced"] { .titleNav .navBtn .navDot { animation: none; } }

  /* short screens: shrink logo + PLAY, tighten nav so PLAY clears the character */
  @media (max-height: 700px) {
    .titleLogo { width: clamp(160px, 50vw, 270px);
                 top: calc(env(safe-area-inset-top,0px) + clamp(56px,14vw,88px)); }
    #title { --cta-bottom: calc(env(safe-area-inset-bottom,0px) + clamp(92px,24vw,118px)); --cta-w: clamp(158px, 48vw, 210px); }
    .titleNav .navBtn { max-width: 64px; }
  }
  @media (max-height: 600px) {
    .titleLogo { width: clamp(140px, 42vw, 220px); }
    #title { --cta-bottom: calc(env(safe-area-inset-bottom,0px) + clamp(80px,22vw,104px)); --cta-w: clamp(140px, 42vw, 180px); }
    .titleNav .navBtn { max-width: 56px; }
  }
