  /* ─── VICTORY VARIANT — "the light endures" ─────────────────────────────
     Shares the structure of the death ceremony (fade timeline, letter
     cascade shape, stain bloom, embers, epitaph) but re-themes every
     colour-bearing surface to gold + green. Triggered by adding .victory
     to #death-ceremony on the survived path. Letters are replaced by JS
     to VICTORY (7 chars, no gap) so the animation-delay rules here
     target nth-child(1..7) instead of the death 1/2/3/5/6/7/8. */
  #death-ceremony.victory {
    background:
      radial-gradient(ellipse 70% 60% at 50% 60%,
        rgba(60, 40, 0, 0.6) 0%,
        rgba(12, 22, 6, 0.88) 48%,
        #040804 92%),
      #040804;
  }
  #death-ceremony.victory .dc-stain {
    background: radial-gradient(ellipse 50% 50% at 50% 50%,
      rgba(255, 200, 90, 0.75) 0%,
      rgba(200, 140, 30, 0.45) 35%,
      rgba(40, 80, 30, 0) 70%);
  }
  #death-ceremony.victory .dc-title {
    /* Pure uppercase Cinzel, gold-honey core with green-tinted shadows
       instead of crimson. Same layered text-shadow recipe: inner warm
       highlight, dark drop-carve, close warm glow, wider halo, far
       emerald bleed so the victory feels both regal AND natural. */
    color: #ffe07a;
    text-shadow:
      0 1px 0 rgba(255, 250, 220, 0.7),
      0 5px 0 rgba(80, 50, 0, 0.95),
      0 7px 2px rgba(20, 18, 0, 0.85),
      0 0 14px rgba(255, 200, 90, 0.95),
      0 0 42px rgba(255, 170, 60, 0.7),
      0 0 90px rgba(140, 220, 120, 0.55);
  }
  #death-ceremony.victory.active .dc-title span {
    /* VICTORY is 7 letters with no gap — stagger each by 0.12s starting
       at 0.2s, same rhythm as the death cascade without the gap-span
       skip. The tremble runs 0.7s after each letter lands; feels like
       pride-shiver rather than death-shake because colour carries it. */
    animation: dc-letter 0.7s cubic-bezier(.22,.7,.25,1.0) forwards,
               dc-tremble 2.2s ease-in-out forwards;
  }
  #death-ceremony.victory.active .dc-title span:nth-child(1) { animation-delay: 0.20s, 0.90s; }
  #death-ceremony.victory.active .dc-title span:nth-child(2) { animation-delay: 0.32s, 1.02s; }
  #death-ceremony.victory.active .dc-title span:nth-child(3) { animation-delay: 0.44s, 1.14s; }
  #death-ceremony.victory.active .dc-title span:nth-child(4) { animation-delay: 0.56s, 1.26s; }
  #death-ceremony.victory.active .dc-title span:nth-child(5) { animation-delay: 0.68s, 1.38s; }
  #death-ceremony.victory.active .dc-title span:nth-child(6) { animation-delay: 0.80s, 1.50s; }
  #death-ceremony.victory.active .dc-title span:nth-child(7) { animation-delay: 0.92s, 1.62s; }
  #death-ceremony.victory .dc-epitaph {
    color: rgba(255, 235, 180, 0.5);
  }
  /* Gold-green embers — warmer + a touch of emerald at the halo. */
  #death-ceremony.victory .dc-embers span {
    background: radial-gradient(circle,
      rgba(255, 245, 200, 0.95) 0%,
      rgba(220, 200, 90, 0.6) 40%,
      rgba(100, 180, 80, 0) 75%);
    box-shadow: 0 0 6px rgba(240, 220, 130, 0.6);
  }
  /* Canvas filter removed for the same reason as body.dying #canvas —
     the 5-function filter stack rasterized the entire viewport each
     frame for 5.6s. Victory overlay covers the canvas via its own
     opacity ramp + radial void. */
  @media (max-width: 720px) {
    /* 10% smaller than the previous mobile size — the old 56px +
       letter-spacing 3px was edge-to-edge on narrow phones. Desktop
       (.dc-title font-size: 108px) is left at its original size. */
    #death-ceremony .dc-title { font-size: 50px; letter-spacing: 2.5px; }
    #death-ceremony .dc-gap { width: 16px; }
    #death-ceremony .dc-epitaph { font-size: 13px; letter-spacing: 3px; }
    #death-ceremony .dc-stain { width: 520px; margin-left: -260px; height: 260px; margin-top: -130px; }
  }
  @media (prefers-reduced-motion: reduce) {
    #death-ceremony .dc-title span,
    #death-ceremony .dc-epitaph,
    #death-ceremony .dc-embers span,
    #death-ceremony .dc-stain {
      animation: none !important;
      opacity: 1 !important;
      transform: none !important;
    }
  }

  /* Shop screen */
  #shop-screen {
    position: fixed; inset: 0; z-index: var(--z-controls);
    display: none; flex-direction: column; align-items: center; justify-content: center;
    background: rgba(10,14,30,0.88);
  }
  #shop-screen.visible { display: flex; }
  #shop-screen h2 { font-family: 'Space Grotesk', sans-serif; font-size: 42px; color: #ffd700; margin: 0; letter-spacing: 2px; }
  #shop-screen p { color: rgba(246,248,254,0.72); margin: 6px 0 22px; font-size: 14px; }
  #shop-screen #shop-score { color: #ffd700; font-weight: 700; }
  #shop-choices {
    display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px;
    max-width: 820px; padding: 0 24px;
  }
  .shop-card {
    background: var(--card-bg);
    border: 1px solid rgba(255,215,0,0.4);
    border-radius: var(--radius-lg);
    padding: 18px; min-width: 220px;
    cursor: pointer; transition: transform 0.12s, border-color 0.12s, box-shadow 0.12s;
    color: var(--fg);
  }
  .shop-card:hover { transform: translateY(-3px); border-color: #ffd700; box-shadow: 0 10px 30px rgba(255,215,0,0.2); }
  .shop-card.locked { opacity: 0.4; cursor: not-allowed; }
  .shop-card .sc-icon  {
    width: 42px; height: 42px;
    margin: 0 auto 6px;
    font-size: 32px; line-height: 42px;
    display: flex; align-items: center; justify-content: center;
  }
  .shop-card .sc-icon svg { width: 100%; height: 100%; display: block; }
  .shop-card .sc-name  { font-weight: 700; font-size: 15px; letter-spacing: 0.6px; }
  .shop-card .sc-desc  { font-size: 12px; opacity: 0.75; margin: 4px 0 10px; line-height: 1.4; }
  .shop-card .sc-cost  { color: #ffd700; font-weight: 700; font-size: 13px; }
  #shop-skip {
    margin-top: 22px;
    background: transparent; border: 1px solid var(--card-border); color: var(--fg);
    padding: 10px 22px; border-radius: var(--radius-pill);
    font-family: inherit; font-size: 13px; font-weight: 600; letter-spacing: 1.2px;
    cursor: pointer;
  }
  #shop-skip:hover { background: var(--card-bg); }

  /* Reroll button inside powerup screen */
  #reroll-btn {
    margin-top: 14px; background: transparent;
    border: 1px solid rgba(184,155,255,0.5); color: var(--lilac);
    padding: 8px 18px; border-radius: var(--radius-pill);
    font-family: inherit; font-size: 12px; font-weight: 600; letter-spacing: 1.2px;
    cursor: pointer;
  }
  #reroll-btn:disabled { opacity: 0.4; cursor: not-allowed; }
  #reroll-btn:hover:not(:disabled) { background: rgba(184,155,255,0.1); }

  /* Pickup orbs pulse (applied via CSS custom prop on pickups — actually 3D, no-op here) */

  /* ─── TOUCH / MOBILE ─────────────────────────────────────────────────── */
  #joystick, #cam-pad { display: none; }

  /* Joystick + cam-pad apply on every touch device — phones AND tablets.
     iPad has the desktop HUD layout but still needs the on-screen joystick
     because iOS Safari has no pointer-lock API and bare iPads have no
     keyboard, so touch is the only input. Hence plain body.touch (no
     :not(.tablet) negation) here. */
  body.touch #joystick {
    display: block;
    position: fixed; left: 0; top: 0; width: 50vw; height: 100%;
    touch-action: none; pointer-events: auto; z-index: 15;
    user-select: none; -webkit-user-select: none; -webkit-touch-callout: none;
  }
  body.touch #joystick .j-base {
    position: absolute; width: 120px; height: 120px; border-radius: 50%;
    background: rgba(18, 24, 44, 0.35);
    border: 1.5px solid rgba(184, 155, 255, 0.55);
    box-shadow: 0 4px 18px rgba(10, 14, 30, 0.35);
    display: none; pointer-events: none;
    transform: translate(-50%, -50%);
  }
  body.touch #joystick.active .j-base { display: block; }
  body.touch #joystick .j-knob {
    position: absolute; left: 50%; top: 50%;
    width: 52px; height: 52px; border-radius: 50%;
    background: rgba(184, 155, 255, 0.85);
    box-shadow: 0 2px 12px rgba(184, 155, 255, 0.5);
    transform: translate(-50%, -50%);
  }

  body.touch #cam-pad {
    display: block;
    position: fixed; right: 0; top: 0; width: 50vw; height: 100%;
    touch-action: none; pointer-events: auto; z-index: 14;
    user-select: none; -webkit-user-select: none; -webkit-touch-callout: none;
  }

  /* HUD chrome rules apply on touch devices in BOTH orientations. The
     vertical mobile HUD (top-bar pills + split HP/XP + bottom action bar)
     is kept identical between portrait and landscape so a player rotating
     mid-game doesn't see a layout shuffle. Landscape-specific size
     overrides for the ability bar + limit-break live in the
     body.touch.landscape:not(.tablet) block further down. body.portrait /
     body.landscape are toggled by src/input.js. */
  body.touch:not(.tablet) #minimap { display: none; }

  /* Pause (storybook parchment redesign) — keep the frame thin and let the
     inner parchment panel own the scroll height on phones. */
  body.touch:not(.tablet) #pause-screen .pause-card { padding: 11px; }
  body.touch:not(.tablet) #pause-screen .pause-inner { max-height: 82vh; }

  body.touch:not(.tablet) #top-bar { gap: 4px; top: calc(8px + env(safe-area-inset-top)); }
  body.touch:not(.tablet) .stat-block { padding: 3px 8px; min-width: 0; gap: 5px; }
  body.touch:not(.tablet) #kills-block { display: none; }
  body.touch:not(.tablet) .stat-block .value { font-size: 13px; }
  body.touch:not(.tablet) .stat-block .label { font-size: 8.5px; letter-spacing: 0.9px; }
  /* Extra-tight enraged pill on mobile — the top-bar's 4-block row leaves
     only ~90px per pill on a 375px screen, and "☠ ENRAGED" clips/overflows
     at the desktop 13px size. Drop to 10.5px + 0 letter-spacing so the
     skull and text stay inside the pill. */
  body.touch:not(.tablet) .stat-block.enraged .value {
    font-size: 10.5px; letter-spacing: 0;
  }

  /* HP + XP bars split the top row on mobile — HP left, XP right */
  body.touch:not(.tablet) #health-bar-wrap,
  body.touch:not(.tablet) #xp-bar-wrap {
    top: calc(40px + env(safe-area-inset-top));
    bottom: auto; transform: none;
    width: calc(50vw - 12px);
  }
  body.touch:not(.tablet) #health-bar-wrap { left: 8px;  right: auto; }
  body.touch:not(.tablet) #xp-bar-wrap     { left: auto; right: 8px; }
  body.touch:not(.tablet) .bar-label { font-size: 9.5px; letter-spacing: 0.9px; margin-bottom: 3px; }
  body.touch:not(.tablet) .bar-bg    { height: 10px; }

  body.touch:not(.tablet) #ability-bar {
    pointer-events: none; z-index: 16;
    bottom: calc(16px + env(safe-area-inset-bottom));
    top: auto; left: 50%; right: auto;
    transform: translateX(-50%);
    flex-direction: row; gap: 12px;
  }
  body.touch:not(.tablet) .ability { width: 56px; height: 56px; padding: 0 4px; box-sizing: border-box; }
  /* Tap-target tweaks apply on every touch device — desktop stays mouse-only,
     but tablets (iPads) need pointer-events:auto so ability buttons remain
     tappable inside the desktop HUD layout. */
  body.touch .ability { pointer-events: auto; touch-action: manipulation; }
  body.touch:not(.tablet) .ability .ab-key  { display: none; }
  body.touch:not(.tablet) .ability .ab-ico  { font-size: 20px; }
  /* Touch ability cards drop nowrap so long localized labels (Russian
     "Перегрузка", Italian "Sovraccarico") wrap to a 2nd line instead of
     clipping past the card edge. Line-height tightens so 2-line labels
     stay inside the card footer. */
  body.touch:not(.tablet) .ability .ab-name { font-size: 7.5px; letter-spacing: 0; text-transform: none; line-height: 1.1; }

  /* Landscape-specific tweaks for the bottom HUD cluster. In landscape
     the viewport height is ~390px (iPhone 14 Pro), so the default 56px
     ability buttons + 24px limit-break + insets eat ~150px of vertical
     space — too much. Compress everything to ~75px total: 44px buttons,
     tighter gaps, limit-break sitting just above the buttons rather
     than 96px up. The horizontal width is plentiful so we can shrink
     vertically without crowding. */
  body.touch.landscape:not(.tablet) #ability-bar {
    bottom: calc(8px + env(safe-area-inset-bottom));
    gap: 8px;
  }
  body.touch.landscape:not(.tablet) .ability {
    width: 44px; height: 44px;
  }
  body.touch.landscape:not(.tablet) .ability .ab-ico  { font-size: 16px; }
  /* Landscape phone: drop the ability labels entirely. The icons are
     well-known and dropping the text saves vertical space on a short
     screen — buttons stay icon-only. Labels remain in the DOM (and
     visible in portrait) for accessibility. */
  body.touch.landscape:not(.tablet) .ability .ab-name { display: none; }
  body.touch.landscape:not(.tablet) #ability-bar #pause-btn { margin-left: 10px; }

  /* Landscape phone: half-width HP + XP bars centered as a pair in
     the middle of the top row. The default touch rule above gives
     each bar 50vw (8px-from-edge each) — too wide on a phone where
     the long viewport stretches the bar visually. 25vw each, tucked
     toward the centre, matches the density of the rest of the HUD.
     Inset values keep an 8px gap at the centre — same gap the
     portrait rule above produces between the two bars. */
  body.touch.landscape:not(.tablet) #health-bar-wrap,
  body.touch.landscape:not(.tablet) #xp-bar-wrap {
    width: calc(25vw - 8px);
  }
  body.touch.landscape:not(.tablet) #health-bar-wrap { left: calc(25vw + 4px); right: auto; }
  body.touch.landscape:not(.tablet) #xp-bar-wrap     { left: auto; right: calc(25vw + 4px); }
  body.touch.landscape:not(.tablet) #limit-break-meter {
    width: 200px; font-size: 9.5px;
    /* Sit ~12px above the now-44px ability buttons. */
    bottom: calc(60px + env(safe-area-inset-bottom));
  }
  body.touch.landscape:not(.tablet) #limit-break-meter .lb-bar { height: 6px; }
  body.touch.landscape:not(.tablet) #limit-break-meter #limit-break-icon {
    width: 16px; height: 16px;
  }

  /* Portrait phone — narrow the limit-break meter (2026-06-08, owner: "too
     long for mobile, I accidentally press it"). The 220px bar was centered at
     the bottom and straddled screen-centre, reaching ~110px into EACH thumb
     zone (joystick = left half, cam-pad = right half, both full-height). When
     .ready it sits at z:16 and fires on pointerdown, so a thumb drifting toward
     centre mid-drag tripped the limit break. Drop the width to 150px; the label
     wraps to a centred 2nd row (flex-wrap) so the charge BAR stays readable
     (~98px) instead of collapsing. Centre overlap falls to ~75px per side.
     Portrait-scoped (landscape keeps its single-row 200px above — a 2nd row
     would eat the scarce vertical space there). */
  body.touch:not(.landscape):not(.tablet) #limit-break-meter {
    width: 150px;
    flex-wrap: wrap;
    justify-content: center;
    row-gap: 3px;
    padding-top: 5px; padding-bottom: 6px;
  }
  body.touch:not(.landscape):not(.tablet) #limit-break-meter .lb-label {
    flex-basis: 100%;
    text-align: center;
    letter-spacing: 1px;
  }

  /* Tablet HUD (iPad and similar). Hybrid layout: HP/XP bars sit at the
     TOP centered (mobile-landscape style) so the bottom is clear for the
     ability cluster, which gets centered horizontally with the limit-break
     meter floating above it. The desktop bottom-center HP/XP + bottom-left
     ability bar layout collides on iPad-portrait widths (~820 px wide), so
     tablets get this orientation-independent variant. */
  body.tablet #health-bar-wrap,
  body.tablet #xp-bar-wrap {
    top: calc(16px + env(safe-area-inset-top));
    bottom: auto;
    transform: none;
    width: 320px;
  }
  body.tablet #health-bar-wrap { left: calc(50% - 324px); right: auto; }
  body.tablet #xp-bar-wrap     { left: calc(50% + 4px);   right: auto; }

  /* Ability bar centered at the bottom in both orientations on iPad. */
  body.tablet #ability-bar {
    bottom: calc(18px + env(safe-area-inset-bottom));
    left: 50%;
    right: auto;
    transform: translateX(-50%);
  }

  /* Limit-break meter sits ~16 px above the 72 px ability tiles, centered. */
  body.tablet #limit-break-meter {
    bottom: calc(106px + env(safe-area-inset-bottom));
  }

  body.touch:not(.tablet) #requirements       { display: none; }
  body.touch:not(.tablet) #touch-requirements { display: inline-flex; }

  /* Level-up modal — portrait: the parchment "storybook" layout in
     css/levelup.css (cqw-based, proportional) now owns the level-up screen on
     EVERY viewport. The old fixed-px portrait overrides that lived here were
     removed — they predated the parchment redesign and clobbered it on phones
     (46vw/170px card, 42px icon, 13/11px text), so mobile looked cramped vs
     desktop. Mobile now scales the same layout down proportionally. */

  /* Shop — portrait */
  body.touch:not(.landscape):not(.tablet) #shop-screen h2 { font-size: 26px; }
  body.touch:not(.landscape):not(.tablet) #shop-screen p  { font-size: 12px; margin-bottom: 12px; }
  body.touch:not(.landscape):not(.tablet) #shop-choices   { grid-template-columns: 1fr; gap: 10px; max-width: 100vw; padding: 0 16px; }
  body.touch:not(.landscape):not(.tablet) .shop-card      { min-width: 0; padding: 12px 14px; }
  body.touch:not(.landscape):not(.tablet) .shop-card .sc-icon { width: 34px; height: 34px; font-size: 24px; line-height: 34px; margin: 0 auto 4px; }
  body.touch:not(.landscape):not(.tablet) .shop-card .sc-name { font-size: 13px; }
  body.touch:not(.landscape):not(.tablet) .shop-card .sc-desc { font-size: 11px; margin: 2px 0 6px; }
  body.touch:not(.landscape):not(.tablet) #shop-skip      { margin-top: 14px; padding: 10px 18px; }

  /* Gameover — portrait */
  body.touch:not(.landscape):not(.tablet) #gameover h1    { font-size: 40px; margin-bottom: 12px; }
  body.touch:not(.landscape):not(.tablet) #gameover-stats { margin-bottom: 14px; padding: 0 18px; }

  /* Phones / narrow windows — shrink hero typography and stack the primary
     CTAs vertically so SHARE + PLAY AGAIN both sit above the fold. */
  @media (max-width: 520px) {
    #gameover h1 { font-size: 34px; letter-spacing: 0.5px; margin-bottom: 10px; }
    #gameover-hero { margin-bottom: 14px; gap: 4px; }
    #gameover-hero .go-score { font-size: 44px; }
    #gameover-hero .go-score-label { font-size: 9.5px; letter-spacing: 2px; }
    #gameover .go-badge { font-size: 10px; padding: 4px 10px; letter-spacing: 1.1px; }
    .go-stat-strip { gap: 16px; }
    .go-chip { min-width: 54px; }
    .go-chip .go-chip-v { font-size: 19px; }
    .go-chip .go-chip-l { font-size: 9.5px; letter-spacing: 1.4px; }
    #gameover-earned { gap: 10px; font-size: 11.5px; margin-bottom: 18px; }
    #gameover-actions {
      flex-direction: column; gap: 20px;
      width: min(360px, 86vw); margin-bottom: 12px;
    }
    /* Column flex — reset basis to auto so buttons size to content height
       instead of claiming 160px of vertical space each. */
    #gameover-actions > button {
      flex: 0 0 auto;
      width: 100%; min-width: 0;
      padding: 13px 22px; font-size: 15px;
    }
    #gameover-secondary { gap: 10px; }
  }

  /* Landscape phones (and small landscape windows) — short viewport.
     The default 60px title + 64px score + 220px share-card preview
     overflow vertically and clip "GAME OVER" / "VICTORY" at the top
     and the secondary "View Rankings / Title screen" row at the
     bottom. Crush typography + margins, hide the inline share-card
     (still rendered on demand via SHARE), keep buttons side-by-side
     since horizontal room is plentiful. */
  @media (orientation: landscape) and (max-height: 720px) {
    #gameover h1 {
      font-size: 28px; letter-spacing: 0.5px; margin-bottom: 6px;
    }
    #gameover-hero { margin: 0 0 8px; gap: 2px; }
    #gameover-hero .go-score { font-size: 36px; }
    #gameover-hero .go-score-label { font-size: 9px; letter-spacing: 1.8px; }
    #gameover-hero .go-badges { margin-top: 2px; gap: 6px; }
    #gameover .go-badge { font-size: 9.5px; padding: 3px 9px; letter-spacing: 1px; }
    #gameover-stats { margin: 0 0 8px; }
    .go-stat-strip { gap: 18px; }
    .go-chip { min-width: 50px; gap: 2px; }
    .go-chip .go-chip-v { font-size: 17px; }
    .go-chip .go-chip-l { font-size: 9px; letter-spacing: 1.2px; }
    #gameover-earned { gap: 10px; font-size: 11px; margin: 0 0 10px; }
    /* Hide the inline share-card preview — its 1200/630 ratio at 80vw
       claims most of the viewport on a landscape phone. Player still
       sees the card after pressing SHARE; portrait keeps the inline
       preview as before. */
    #gameover-card-preview { display: none !important; }
    #gameover-relic-hint { margin: 0 auto 10px; padding: 8px 12px; }
    #gameover-actions {
      gap: 14px; margin: 0 auto 6px;
      width: min(440px, 80vw);
    }
    #gameover-actions > button { padding: 10px 18px; font-size: 14px; }
    #gameover-secondary { gap: 14px; }
    #gameover-secondary button { font-size: 11.5px; padding: 4px 8px !important; }
  }

