  /* ── Daily / event intro card (opens from the Daily nav button before the puzzle) ── */
  #dailyCard { position: fixed; inset: 0; z-index: 72; display: none; align-items: center; justify-content: center;
    padding: 24px;
    /* no backdrop blur: the modal_canvas frame edge clashes with a blurred backdrop (same as #win/#noDrags) */
    background: radial-gradient(circle at 50% 42%, rgba(255,231,112,.16), transparent 44%), rgba(26,33,21,.6); }
  #dailyCard.show { display: flex; animation: dcFade .28s ease both; }
  #dailyCard .dcCard {
    position: relative; width: min(86vw, 340px);
    display: flex; flex-direction: column; align-items: center; gap: 9px;
    padding: 22px 24px 22px;
    /* premium modal frame + corner gems via 9-slice — same asset/sizing as #noDrags/#ask (was the plainer map_card_bg) */
    border-style: solid; border-width: 44px;
    border-image: url('../../assets/common/modal_canvas.webp') 120 fill / 44px / 0 stretch;
    border-radius: 0; background: transparent;
    box-shadow: 0 0 34px rgba(255,218,76,.34), 0 22px 46px rgba(45,23,7,.42);
    color: #6b3912; text-align: center; overflow: visible;
    animation: dcPop .44s cubic-bezier(.2,1.4,.4,1) both;
  }
  /* warm light aura behind the stone frame — same magic glow as #win/#noDrags so the daily reads as premium */
  #dailyCard .dcCard::before {
    content: ""; position: absolute; inset: -72px -64px;
    background: url('../../assets/win/light_burst.webp') center / contain no-repeat;
    opacity: .24; mix-blend-mode: screen; pointer-events: none; z-index: -1;
    animation: winAuraSpin 12s linear infinite;
  }
  /* carved amber-stone knob — echoes the frame's gem corners + uses the game's SVG icon language
     (was a flat dark CSS lozenge with a font ✕ that clashed with the painted frame) */
  #dailyCard .dcClose {
    position: absolute; top: 6px; right: 6px; width: 36px; height: 36px; min-width: 0; box-sizing: border-box;
    border-radius: 50%; display: grid; place-items: center; padding: 0; cursor: pointer; z-index: 3;
    color: #5e3410;                                   /* icon stroke = the card's warm brown */
    border: 1px solid #d9a866;
    background: radial-gradient(120% 120% at 50% 28%, #fbe6bd, #e9c489 46%, #c98f4e 100%);
    box-shadow: inset 0 1px 1px rgba(255,255,255,.78),  /* top sheen */
                inset 0 -2px 4px rgba(120,70,20,.42),   /* carved bottom shade */
                0 3px 6px rgba(40,20,6,.4);             /* soft drop */
  }
  #dailyCard .dcClose .ico { width: 18px; height: 18px; stroke-width: 2.4; }
  #dailyCard .dcClose:active { transform: translateY(1px);
    box-shadow: inset 0 2px 5px rgba(120,70,20,.5), 0 1px 2px rgba(40,20,6,.4); }
  #dailyCard .dcKicker { font-size: 12px; font-weight: 900; letter-spacing: .12em; text-transform: uppercase;
    color: #c8862f; text-shadow: 0 1px 0 rgba(255,246,205,.6); }
  #dailyCard .dcTitle { margin: 0; font-size: clamp(22px, 6vw, 28px); font-weight: 950; color: #5e3410;
    text-shadow: 0 1px 0 rgba(255,246,205,.7); }
  /* puzzle silhouette preview — shows today's shape (crystal blue) without spoiling the regions */
  #dailyCard .dcPreview { width: 62%; max-width: 172px; display: flex; align-items: center; justify-content: center; margin: 2px 0; }
  #dailyCard .dcSil { display: grid; gap: 3px; width: 100%; filter: drop-shadow(0 4px 8px rgba(40,30,10,.3)); }
  #dailyCard .dcSil i { aspect-ratio: 1; }
  #dailyCard .dcSil i.f { background: linear-gradient(145deg, #7ad0ff, #2f7fce 70%, #1e5ea0); border-radius: 3px;
    box-shadow: inset 0 1px 0 rgba(255,255,255,.45); }
  #dailyCard .dcSil i.v { background: transparent; }
  #dailyCard .dcMeta { display: flex; align-items: center; gap: 14px; font-weight: 900; }
  #dailyCard .dcReward { display: inline-flex; align-items: center; gap: 4px; font-size: 18px; color: #6b3912; }
  #dailyCard .dcReward::before { content: "★"; color: #f5a623; font-size: 1.05em; }
  #dailyCard .dcDay { font-size: 13px; font-weight: 800; color: #a06e3c; }
  #dailyCard .dcDone { margin: 0; font-size: 13px; font-weight: 700; color: #a06e3c; display: none; }
  #dailyCard.is-done .dcDone { display: block; }
  #dailyCard #dailyStart {
    width: 100%; max-width: 240px; aspect-ratio: 467 / 146; margin-top: 4px; padding: 0 8% 3%;
    border: none; border-radius: 0; background: url('../../assets/common/btn_green.png') center / 100% 100% no-repeat;
    display: flex; align-items: center; justify-content: center;
    color: #fff8e9; font-size: clamp(17px, 5vw, 21px); font-weight: 900;
    text-shadow: 0 2px 0 #2c7a1f, 0 3px 5px rgba(18,55,8,.5); cursor: pointer; transition: transform .08s, filter .12s;
  }
  #dailyCard #dailyStart:active { transform: translateY(2px) scale(.985); filter: brightness(.95); }
  @keyframes dcFade { from { opacity: 0; } to { opacity: 1; } }
  @keyframes dcPop { 0% { opacity: 0; transform: scale(.7) translateY(16px); } 70% { opacity: 1; transform: scale(1.04); } 100% { opacity: 1; transform: scale(1); } }
  html[data-motion="reduced"] { #dailyCard.show, #dailyCard .dcCard, #dailyCard .dcCard::before { animation: none; } }

  /* badges list */
  /* ── badges: jungle bg + stone-bar rows, painted icon left + text right ── */
  #achievements { position: fixed; inset: 0; background: url('../../assets/stage/bg.webp') center / cover no-repeat; overflow: hidden; isolation: isolate; }
  #achievements .mapBar { background: none; position: absolute; left: 0; right: 0; top: 0; z-index: 8; padding-right: 70px; }
  #achievements #achBack {
    width: 56px !important; height: 56px !important; min-width: 0 !important; padding: 0 !important;
    background: url('../../assets/badge/back_round.png') center / contain no-repeat !important;
    border: none !important; box-shadow: none !important; font-size: 0 !important; color: transparent !important;
  }
  #achievements #achBack svg { display: none; }
  #achievements .mapTitle {
    flex: 1; text-align: center; align-self: center; height: 50px; line-height: 50px;
    background: url('../../assets/badge/row_bar.png') center / 100% 100% no-repeat;
    color: #fff6e2; font-weight: 900; font-size: 22px;
    text-shadow: 0 2px 0 #4a3214, -1px 0 0 #4a3214, 1px 0 0 #4a3214, 0 2px 5px rgba(0,0,0,.5);
    padding: 0 8px; max-width: 58%; margin: 0 auto;
  }
  #achievements #achCount {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 64px; height: 42px; padding: 0 10px; color: #fff2cf; font-weight: 900; font-size: 15px;
    background: url('../../assets/badge/count_tab.png') center / 100% 100% no-repeat;
    text-shadow: 0 1px 2px rgba(40,20,4,.8);
  }
  #achievements .screenWalletVal {
    color: #fff2cf; font-weight: 900;
    text-shadow: 0 1px 2px rgba(40,20,4,.8);
  }
  .achHrt { width: 17px; height: 17px; color: #ff8fa8; fill: currentColor; flex-shrink: 0; vertical-align: -0.25em; filter: drop-shadow(0 1px 2px rgba(40,14,4,.85)); }
  #achList { padding-top: calc(env(safe-area-inset-top,0px) + 120px) !important;
             padding-bottom: calc(env(safe-area-inset-bottom,0px) + 132px) !important; }  /* clear taller nav */
  .achSectionHead {
    position: relative; z-index: 1; margin: 0 8px 12px; font-size: clamp(13px, 3.7vw, 15px);
    font-weight: 900; letter-spacing: .05em; text-transform: uppercase;
    /* light cream + dark outline so the label reads on the dark stage bg (matches .mapTitle) */
    color: #fdeec6;
    text-shadow: 0 1px 0 #3a2710, -1px 0 0 #3a2710, 1px 0 0 #3a2710, 0 2px 5px rgba(0,0,0,.55);
  }
  .achSectionHead:not(:first-child) { margin-top: clamp(18px, 4.5vw, 26px); }
  .badge {
    position: relative; display: flex; align-items: center; gap: 12px;
    min-height: 82px; margin-bottom: clamp(14px, 3vw, 22px); padding: 8px 18px 8px 92px;
    background: none; border: none; border-radius: 0; box-shadow: none;
  }
  .badge::before {
    content: ""; position: absolute; inset: 0; z-index: 0;
    background: url('../../assets/badge/row_bar.png') center / 100% 100% no-repeat;
  }
  .badge.locked::before { filter: brightness(.66) saturate(.18) contrast(.96); }   /* greyed-out = clearly "not yet" */
  .badge > * { position: relative; z-index: 1; }
  .badge .bIcon {
    position: absolute; left: 4px; top: 50%; transform: translateY(-50%); z-index: 1;
    width: 80px; height: 80px;
    background-position: center; background-size: contain; background-repeat: no-repeat;
    filter: drop-shadow(0 2px 3px rgba(30,16,4,.5));
  }
  .badge .bIcon svg { display: none; }
  .badge.locked .bIcon { background-image: url('../../assets/badge/padlock.png') !important; }
  .badge .bText b { display: block; font-size: clamp(16px, 4.8vw, 20px); font-weight: 900; }
  .badge .bText span { font-size: clamp(12px, 3.4vw, 14px); font-weight: 700; }
  /* Clear earned/locked color coding:
     EARNED = warm GOLD (the reward color — stars/coins) with a dark edge so it stays crisp on the
     lit stone bar → obviously "got it". LOCKED = flat desaturated grey on a greyed-out bar (below)
     → obviously "not yet". The two differ in HUE (warm gold vs cool grey), so the state reads instantly. */
  .badge.got .bText b {
    color: #ffd56a; -webkit-text-stroke: .8px #6b4309; paint-order: stroke fill;
    text-shadow: 0 1px 1px rgba(45,27,4,.5);
  }
  .badge.got .bText span {
    color: #f1d295; -webkit-text-stroke: .5px #6b4309; paint-order: stroke fill;
    text-shadow: 0 1px 1px rgba(45,27,4,.45);
  }
  .badge.locked .bText b { color: #a9a395; text-shadow: 0 1px 2px rgba(0,0,0,.45); }
  .badge.locked .bText span { color: #837d70; text-shadow: 0 1px 2px rgba(0,0,0,.4); }
  .badge.nextGoal::before {
    filter: brightness(.86) saturate(.62) contrast(1.02);
  }
  .badge.locked.nextGoal::before {
    filter: brightness(.76) saturate(.46) contrast(1.04);
  }
  .badge.nextGoal .bIcon {
    filter: drop-shadow(0 2px 3px rgba(30,16,4,.5)) brightness(1.08);
  }
  .badge.nextGoal .bText b {
    color: #efe0bd;
    text-shadow: 0 1px 0 #3a2710, 0 2px 4px rgba(0,0,0,.5);
  }
  .badge.nextGoal .bText span {
    color: #cfc1a0;
    text-shadow: 0 1px 2px rgba(0,0,0,.45);
  }
  .badge .nextGoalTag {
    position: absolute; right: 20px; top: -7px; z-index: 2;
    max-width: 42%;
    padding: 3px 9px 4px;
    border-radius: 999px;
    border: 1px solid rgba(255,230,154,.74);
    background: linear-gradient(180deg, #dca44e, #825223);
    color: #fff5cf;
    font-size: 11px; font-weight: 900; line-height: 1;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    text-shadow: 0 1px 1px rgba(53,29,7,.7);
    box-shadow: inset 0 1px 0 rgba(255,246,205,.48), 0 2px 4px rgba(20,10,2,.36);
  }
  /* reward claim: an emerald "받기" button on an earned-but-unclaimed badge → collect the tiered reward.
     Subtle glow draws the eye (the 2-step funnel's second beat); turns into a ✓ marker once claimed. */
  .badge .claimBtn {
    margin-left: auto; flex: 0 0 auto; z-index: 2;
    display: flex; flex-direction: column; align-items: center; gap: 1px;
    padding: 6px 14px; border-radius: 12px; border: 1px solid rgba(255,236,170,.85);
    background: linear-gradient(180deg, #4bbf6a, #2e8f4c); color: #fff; cursor: pointer;
    box-shadow: inset 0 1px 0 rgba(255,255,255,.35), 0 3px 6px rgba(10,40,20,.4);
    animation: claimBtnGlow 1.8s ease-in-out infinite;
  }
  .badge .claimBtn:active { transform: translateY(1px); filter: brightness(.96); }
  .badge.claiming .claimBtn,
  .badge .claimBtn:disabled {
    cursor: default; animation: none;
    background: linear-gradient(180deg, #d7a94d, #8f5d25);
    border-color: rgba(255,238,178,.96);
    box-shadow: inset 0 1px 0 rgba(255,255,255,.4), 0 0 12px rgba(255,190,78,.55), 0 3px 6px rgba(40,20,8,.42);
  }
  .badge .claimBtn .claimLabel { font-size: 13px; font-weight: 900; line-height: 1; }
  .badge .claimBtn .claimReward {
    display: inline-flex; align-items: center; gap: 4px;
    font-size: 11px; font-weight: 800; line-height: 1; color: #eafff0; white-space: nowrap;
  }
  @keyframes claimBtnGlow {
    0%,100% { box-shadow: inset 0 1px 0 rgba(255,255,255,.35), 0 3px 6px rgba(10,40,20,.4); }
    50%     { box-shadow: inset 0 1px 0 rgba(255,255,255,.5), 0 0 12px rgba(96,232,142,.85), 0 3px 6px rgba(10,40,20,.4); }
  }
  .badge .claimedMark {
    margin-left: auto; flex: 0 0 auto; z-index: 2;
    font-size: 12px; font-weight: 900; color: #bfe9c8; white-space: nowrap;
    text-shadow: 0 1px 2px rgba(0,0,0,.4);
  }
  .badge.claimed::before { filter: brightness(.92) saturate(.92); }   /* gently settled vs an unclaimed "got" */
  .badge.claimBurst::after {
    content: ""; position: absolute; inset: 3px 14px 3px 80px; z-index: 1; pointer-events: none;
    border-radius: 14px;
    background: linear-gradient(105deg, transparent 0 28%, rgba(255,246,186,.9) 45%, rgba(255,214,95,.36) 56%, transparent 74% 100%);
    mix-blend-mode: screen;
    animation: claimSweep .78s ease-out both;
  }
  @keyframes claimSweep {
    0% { opacity: 0; transform: translateX(-34%) skewX(-9deg); }
    22% { opacity: 1; }
    100% { opacity: 0; transform: translateX(42%) skewX(-9deg); }
  }
  .badge .claimFly {
    position: absolute; right: clamp(80px, 26vw, 118px); top: 50%; z-index: 5; pointer-events: none;
    transform: translateY(-50%); white-space: nowrap;
    padding: 4px 11px 5px; border-radius: 999px; border: 1.5px solid rgba(255,247,210,.92);
    color: #fff3c4; font-weight: 950; font-size: clamp(17px, 5.2vw, 24px);
    background: radial-gradient(circle at 35% 25%, rgba(255,255,220,.65), transparent 32%), linear-gradient(180deg, #b47421, #6a3a10);
    box-shadow: 0 0 13px rgba(255,205,82,.72), 0 3px 7px rgba(30,12,2,.48);
    text-shadow: 0 2px 0 #5a3a08, 0 2px 6px rgba(0,0,0,.5);
    animation: claimFly 1.05s ease-out both;
  }
  @keyframes claimFly {
    0%   { opacity: 0; transform: translateY(-50%) scale(.7); }
    18%  { opacity: 1; transform: translateY(-70%) scale(1.08); }
    64%  { opacity: 1; transform: translateY(-112%) scale(1); }
    100% { opacity: 0; transform: translateY(-160%) scale(.96); }
  }
  html[data-motion="reduced"] {
    .badge .claimBtn { animation: none; }
    .badge.claimBurst::after { animation: none; opacity: .35; }
    .badge .claimFly { animation-duration: .01s; }
  }

  /* shop rows */
  #shop {
    position: fixed;
    inset: 0;
    background:
      linear-gradient(180deg, rgba(14,26,14,.14), rgba(13,28,16,.36)),
      url('../../assets/shop/bg.webp') center / cover no-repeat;
    overflow: hidden;
  }
  #shop::after {
    content: "";
    position: absolute;
    inset: auto 0 0;
    height: 36%;
    pointer-events: none;
    background: linear-gradient(180deg, transparent, rgba(13,42,22,.34));
  }
  #shop .mapBar {
    position: absolute;
    left: 0;
    right: 0;
    top: calc(env(safe-area-inset-top,0px) + 10px);
    z-index: 8;
    width: 100%;
    max-width: 460px;
    height: 86px;
    margin: 0 auto;
    padding: 0 14px;
    background: none;
    display: grid;
    grid-template-columns: 64px minmax(0, 1fr) clamp(112px, 32vw, 140px);
    align-items: center;
    gap: 8px;
    pointer-events: none;
  }
  #shop .mapBar > * { pointer-events: auto; }
  #shop .shopHudCombo { justify-self: end; }
  #shopBack {
    width: 60px !important;
    height: 60px !important;
    min-width: 0 !important;
    padding: 0 !important;
    border: none !important;
    border-radius: 50% !important;
    background: url('../../assets/badge/back_round.png') center / contain no-repeat transparent !important;
    box-shadow: none !important;
    font-size: 0 !important;
    color: transparent !important;
  }
  #shopBack .ico { display: none; }
  /* shop title = MAP-tone stone banner (row_bar), centered */
  #shop .mapTitle {
    justify-self: stretch; align-self: center; margin: 0 auto;
    display: block; width: 100%; max-width: 196px; height: 50px; line-height: 50px;
    text-align: center; background: url('../../assets/badge/row_bar.png') center / 100% 100% no-repeat;
    color: #fff6e2; font-size: clamp(19px, 5.4vw, 23px); font-weight: 900;
    text-shadow: 0 2px 0 #4a3214, -1px 0 0 #4a3214, 1px 0 0 #4a3214, 0 2px 5px rgba(0,0,0,.5);
    overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
  }
  /* coins + lives = MAP-style combined stone HUD (.levelHudCombo) for cross-screen unity */
  #shop .mapScroll {
    position: relative;
    z-index: 1;
    max-width: 430px;
    padding: calc(env(safe-area-inset-top,0px) + 102px) 14px calc(50px + env(safe-area-inset-bottom,0px));
    justify-content: flex-start;
    gap: clamp(14px, 3.6vw, 20px);
    /* top fade so rows DISSOLVE as they scroll UNDER the floating (background-less) HUD instead of hard-
       overlapping it — same technique as #map .mapScroll. Bar bottom ≈ safe-area + 96px; a soft bottom
       fade mirrors it. */
    -webkit-mask-image: linear-gradient(to bottom,
      transparent 0,
      transparent calc(env(safe-area-inset-top,0px) + 54px),
      #000 calc(env(safe-area-inset-top,0px) + 98px),
      #000 calc(100% - 40px),
      transparent 100%);
    mask-image: linear-gradient(to bottom,
      transparent 0,
      transparent calc(env(safe-area-inset-top,0px) + 54px),
      #000 calc(env(safe-area-inset-top,0px) + 98px),
      #000 calc(100% - 40px),
      transparent 100%);
  }
  /* shop row = 9-slice card (no stretch warp): [icon+qty | name+desc | star price] */
  .shopRow {
    position: relative;
    display: flex; align-items: center; gap: 15px;
    width: 100%; min-height: 108px;
    border-style: solid; border-width: 26px;
    border-image: url('../../assets/map/card_bg.webp') 96 fill / 26px / 0 stretch;
    border-radius: 0; background: transparent; box-shadow: none !important;
    color: #6b3912; text-align: left;
  }
  .shopIcon {
    position: relative; flex-shrink: 0;
    width: 56px; height: 56px;
    filter: drop-shadow(0 3px 3px rgba(72,30,4,.25));
    /* base background removed — every .shopIcon is under #shop or #settings, which set their own bg */
  }
  .shopIconLife { background: none; display: flex; align-items: center; justify-content: center; }
  .lifeHeart { width: 52px; height: 52px; color: #e8453c; filter: drop-shadow(0 3px 3px rgba(72,30,4,.28)); }
  .shopQty {
    position: absolute; right: -9px; bottom: -6px;
    background: #e8453c; color: #fff;
    font-size: 12px; font-weight: 900; line-height: 1;
    padding: 3px 7px; border-radius: 10px; border: 2px solid #fff7ea;
    box-shadow: 0 2px 4px rgba(80,20,10,.3);
  }
  .shopInfo { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
  .shopName { font-size: 19px; font-weight: 950; color: #6b3912; text-shadow: 0 1px 0 rgba(255,246,205,.7); white-space: nowrap; }
  .shopDesc { font-size: 12.5px; font-weight: 700; color: #a06e3c; }
  .shopPrice {
    flex-shrink: 0; min-width: 84px; height: 40px;
    padding: 0 15px 0 34px;
    display: inline-flex; align-items: center; justify-content: flex-end;
    background: url('../../assets/stage/hud_star.webp') left center / contain no-repeat;
    color: #5a3510; font-size: 17px; font-weight: 950; text-shadow: none;
  }
  /* popular: gold ribbon to steer the eye to the value pick */
  .shopRibbon {
    position: absolute; top: -12px; right: 18px; z-index: 4;
    background: linear-gradient(180deg, #ffb43a, #ef7a1c);
    color: #fff; font-size: 12px; font-weight: 900; letter-spacing: .5px;
    padding: 3px 13px; border-radius: 11px; border: 2px solid #fff7e6;
    box-shadow: 0 3px 7px rgba(120,50,8,.4);
  }
  /* coming-soon: dimmed, neutral price chip */
  .shopRow.soon { filter: saturate(.72); }
  .shopPrice.soon {
    background: rgba(78,50,24,.16); border-radius: 13px;
    min-width: 92px; height: 34px; padding: 0 14px; justify-content: center;
    color: rgba(107,57,18,.66); font-size: 13px;
  }
  .shopRow:disabled:not(.soon) { opacity: .55; filter: grayscale(.35) saturate(.8); }
  .shopRow:not(:disabled):active { transform: scale(.985); }

  /* ── shop reskin: jungle-temple stone rows (shared settings stone bar) + green buy buttons over bg_shop ── */
  #shop .shopRow {
    position: relative; display: flex; align-items: center; gap: 10px;
    width: 100%; flex-shrink: 0; aspect-ratio: 610 / 138; min-height: clamp(76px, 21vw, 88px);
    border: none !important; border-image: none !important; border-radius: 0;
    background: transparent; box-shadow: none !important;
    padding: 0 4% 0 22%; color: #f3ead2; text-align: left;
  }
  #shop .shopRow::before {
    content: ""; position: absolute; inset: 0; z-index: -1;
    background: url('../../assets/setting/row.png') center / 100% 100% no-repeat;
    filter: drop-shadow(0 3px 4px rgba(18,28,12,.4));
  }
  /* icon sits in the gold frame on the left; make it feel like a small relic pedestal */
  #shop .shopIcon {
    position: absolute; left: 11%; top: 50%; transform: translate(-50%, -50%);
    width: 13.5%; height: auto; aspect-ratio: 1; flex-shrink: 0;
    border: 2px solid rgba(255,219,143,.52);
    border-radius: 13px;
    background:
      radial-gradient(circle at 34% 25%, rgba(255,247,198,.74) 0 9%, transparent 19%),
      radial-gradient(circle at 50% 56%, #715238 0 42%, #46311f 68%, #21170f 100%) !important;
    display: flex; align-items: center; justify-content: center; filter: none;
    box-shadow:
      inset 0 2px 3px rgba(255,237,190,.32),
      inset 0 -4px 7px rgba(24,13,6,.5),
      0 2px 4px rgba(18,10,4,.36);
    overflow: visible;
  }
  #shop .lifeHeart {
    width: 70%; height: 70%;
    color: #ff6860;
    filter: drop-shadow(0 1px 0 #5a1410) drop-shadow(0 2px 3px rgba(20,6,2,.5));
  }
  #shop .shopIcon .starIco {
    width: 73%; height: 73%;
    filter: drop-shadow(0 1px 0 #6c4510) drop-shadow(0 2px 3px rgba(20,12,2,.5));
  }   /* painted 별빛 star sits inside the relic slot */
  #shop .shopSvg {
    width: 64%; height: 64%; color: #e8c465; fill: none; stroke: currentColor; stroke-width: 2.1; stroke-linecap: round; stroke-linejoin: round;
    filter: drop-shadow(0 1px 0 #5a3a12) drop-shadow(0 2px 3px rgba(18,10,2,.5));
  }
  #shop .shopSvg path[fill="currentColor"] { fill: currentColor; }
  #shop .shopQty {
    right: -9px; bottom: -7px; font-size: 11px;
    border-color: #fff0c4;
    background: linear-gradient(180deg, #cf5d4b, #8d2d25);
    box-shadow: 0 2px 4px rgba(30,10,4,.35), inset 0 1px 0 rgba(255,255,255,.28);
  }
  #shop .shopInfo { flex: 1; min-width: 0; gap: 1px; }
  #shop .shopName { font-size: clamp(15px, 4.2vw, 18px); font-weight: 900; color: #f7eed3; white-space: nowrap;
    text-shadow: 0 2px 0 #3a2810, -1px 0 0 #3a2810, 1px 0 0 #3a2810, 0 2px 4px rgba(0,0,0,.55); }
  #shop .shopDesc { font-size: clamp(10.5px, 3vw, 12.5px); font-weight: 700; color: #cdbe98; text-shadow: 0 1px 2px rgba(0,0,0,.5); }
  /* price = carved gold plate, not a modern green CTA */
  #shop .shopPrice {
    flex-shrink: 0; min-width: clamp(84px, 24vw, 104px); height: clamp(34px, 9.5vw, 40px);
    display: inline-flex; align-items: center; justify-content: center; gap: 4px; padding: 0 9px 2px;
    border: 2px solid rgba(255,228,157,.9);
    border-radius: 14px;
    background:
      linear-gradient(180deg, rgba(255,255,224,.34), transparent 45%),
      linear-gradient(180deg, #b78a3f 0%, #8a5b25 55%, #5b3517 100%);
    color: #fff7e6; font-size: clamp(14px, 4vw, 17px); font-weight: 900;
    text-shadow: 0 2px 0 #3d2411, 0 1px 2px rgba(0,0,0,.45);
    box-shadow:
      inset 0 1px 0 rgba(255,249,210,.5),
      inset 0 -3px 5px rgba(44,23,8,.48),
      0 3px 6px rgba(17,9,3,.35);
  }
  #shop .shopPrice::before { content: "★"; color: #ffd84a; font-size: .92em; text-shadow: 0 1px 1px rgba(60,30,2,.5); }
  /* ad→별빛 row: same plate, but a ▶ play glyph instead of a ★ price (it's an EARN action, not a cost) */
  #shop .shopPrice.adWatch::before { content: none; }
  /* coming-soon price: neutral chip, no green button */
  #shop .shopPrice.soon { background: rgba(20,30,16,.56) !important; border: 1px solid rgba(255,240,190,.25); border-radius: 12px;
    min-width: 92px; height: 32px; padding: 0 12px; color: #d9cba6; font-size: 12.5px; text-shadow: 0 1px 2px rgba(0,0,0,.5); }
  #shop .shopPrice.soon::before { content: none; }
  #shop .shopRibbon { top: -10px; }
  /* ribbon color variants steer the eye by intent: best=teal, first-buy=violet, beginner=green */
  #shop .shopRibbon.best  { background: linear-gradient(180deg,#37d0c0,#1593a6); right: auto; left: 18px; }
  #shop .shopRibbon.first { background: linear-gradient(180deg,#b07bff,#7a45e0); }
  #shop .shopRibbon.new   { background: linear-gradient(180deg,#7ad06a,#3f9a3a); right: auto; left: 18px; }

  /* section dividers between shop groups */
  .shopSectionHead {
    align-self: flex-start; flex-shrink: 0; margin: 14px 4px 6px 6px; padding: 0;
    font-size: clamp(13px, 3.6vw, 15px); font-weight: 900; letter-spacing: .4px;
    color: #ffe7bd; text-shadow: 0 1px 3px rgba(0,0,0,.6); text-transform: uppercase;
  }
  .shopSectionHead:first-child { margin-top: 2px; }

  /* real-money (IAP) price pill: emerald "buy" plate, currency text — no ★ prefix */
  #shop .shopPrice.cash {
    border-color: rgba(180,255,205,.85);
    background:
      linear-gradient(180deg, rgba(230,255,236,.32), transparent 45%),
      linear-gradient(180deg, #46b86b 0%, #2c8a4c 55%, #176235 100%);
    letter-spacing: .2px;
  }
  #shop .shopPrice.cash::before { content: none; }

  /* dummy rows: very slight desaturation so they read as "preview", still tappable */
  #shop .shopRow.mock { filter: saturate(.95); }
  /* lead remove-ads offer: soft gold glow draws the eye (alignment-tolerant; the row keeps its baked frame) */
  #shop .shopRow.removeAdsLead { filter: none; }
  #shop .shopRow.removeAdsLead::after {
    content: ""; position: absolute; inset: 0; z-index: -1; border-radius: 16px;
    box-shadow: 0 0 16px 2px rgba(255,200,80,.42); pointer-events: none;
  }
  /* pack rows carry a 2-line description (bundle contents) → give them extra height */
  #shop .shopRow.pack { aspect-ratio: auto; min-height: clamp(86px, 24vw, 100px); }
  #shop .shopRow.pack .shopDesc { white-space: normal; line-height: 1.25; }
  /* one quiet caption flagging the cash lineup as a non-wired design mockup */
  .shopMockNote {
    margin: 14px 8px calc(8px + env(safe-area-inset-bottom,0px)); padding: 0;
    font-size: 11.5px; font-weight: 700; line-height: 1.4; text-align: center;
    color: rgba(231,219,182,.66); text-shadow: 0 1px 2px rgba(0,0,0,.5);
  }

  /* purchase feel: bounce the coin counter on a successful buy.
     #shopCoins is .hudStarVal — centered by a base transform: translate(-50%,-50%). The pulse MUST keep
     that translate, else a bare scale() drops the number down/right for the animation then snaps it back
     (the "숫자가 아래로 이동했다 원상복구" bug — same class as heartSpendPulse / the 2026-06-23 wallet fix). */
  @keyframes shopBuyPulse { 0%,100% { transform: translate(-50%,-50%) scale(1); } 42% { transform: translate(-50%,-50%) scale(1.16); } }
  #shopCoins.buyPulse { animation: shopBuyPulse .32s ease; }

  /* badge-earned toast — premium pill: depth-kit card + the real painted badge medallion + a kicker */
  #achvToast { position: fixed; z-index: 90; top: calc(env(safe-area-inset-top,0px) + 14px); left: 50%; transform: translateX(-50%) translateY(-160%);
    display: flex; align-items: center; gap: 12px; max-width: 340px; padding: 10px 20px 10px 13px; border-radius: 16px;
    background: var(--grad-card); border: 1px solid var(--line);
    box-shadow: var(--lift-lg), var(--sheen); pointer-events: none; opacity: 0; }
  #achvToast.show { animation: toastDrop 2.8s ease both; }
  @keyframes toastDrop { 0% { transform: translateX(-50%) translateY(-160%); opacity: 0; } 10%,82% { transform: translateX(-50%) translateY(0); opacity: 1; } 100% { transform: translateX(-50%) translateY(-160%); opacity: 0; } }
  /* painted achievement medallion (assets/badge/icons/*) — same treatment as the gallery, no double frame */
  #achvToast .atIcon { flex: none; width: 48px; height: 48px;
    background-position: center; background-size: contain; background-repeat: no-repeat;
    filter: drop-shadow(0 2px 3px rgba(30,16,4,.45)); }
  #achvToast.show .atIcon { animation: atBadgePop .5s cubic-bezier(.2,1.6,.4,1) .12s both; }
  @keyframes atBadgePop { 0% { transform: scale(.3) rotate(-12deg); opacity: 0; } 60% { transform: scale(1.12) rotate(3deg); } 100% { transform: scale(1) rotate(0); opacity: 1; } }
  #achvToast .atText { display: flex; flex-direction: column; gap: 1px; min-width: 0; text-align: left; }
  #achvToast .atKicker { font-size: 10px; font-weight: 900; letter-spacing: .14em; text-transform: uppercase; color: #c8862f; text-shadow: 0 1px 0 rgba(255,246,205,.6); }
  #achvToast .atText b { font-size: 15px; font-weight: 950; color: #5e3410; line-height: 1.15; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  #achvToast #atDesc { font-size: 12px; color: var(--muted); }
  #badgeClaimToast {
    position: fixed; z-index: 92; top: calc(env(safe-area-inset-top,0px) + 18px); left: 50%;
    transform: translateX(-50%) translateY(-150%); opacity: 0; pointer-events: none;
    max-width: min(340px, calc(100vw - 36px)); padding: 10px 18px 11px; border-radius: 999px;
    border: 1.5px solid rgba(255,236,170,.9);
    background: linear-gradient(180deg, #4b2b14, #25160c);
    color: #fff1bd; font-size: 15px; font-weight: 950; line-height: 1; text-align: center; white-space: nowrap;
    text-shadow: 0 1px 2px rgba(20,8,2,.8);
    box-shadow: 0 5px 14px rgba(24,10,2,.45), 0 0 14px rgba(255,205,82,.42), inset 0 1px 0 rgba(255,246,205,.3);
  }
  #badgeClaimToast.show { animation: claimToastDrop 1.8s ease both; }
  @keyframes claimToastDrop {
    0% { transform: translateX(-50%) translateY(-150%); opacity: 0; }
    12%,78% { transform: translateX(-50%) translateY(0); opacity: 1; }
    100% { transform: translateX(-50%) translateY(-150%); opacity: 0; }
  }
  html[data-motion="reduced"] { #achvToast.show, #badgeClaimToast.show { animation-timing-function: linear; } #achvToast.show .atIcon { animation: none; } }
