  /* =====================================================================
     main-13 — MOBILE-LAYER (2026-07). Kein Teil des alten main.css-Splits
     (01..12); laedt als LETZTES Stylesheet und darf deshalb ueberall
     ueberschreiben. Inhalt:
       1) Phone-Shell (<=700px): Sidebar als Off-Canvas-Drawer + Hamburger-FAB
       2) Brett-Screen-Feinschliff fuer Phones
       3) Icon-Rail-Reparaturen (abgeschnittene Texte in der kollabierten Nav)
       4) Seiten-/Modal-Feinschliff fuer schmale Viewports
     Der JS-Anteil (body.mp-phone / body.mp-nav-open) lebt in app/side-nav.js.
     ===================================================================== */

  /* ---------- Hamburger-FAB + Backdrop (nur Phone sichtbar) ---------- */
  .mobileNavFab {
    display: none;
    position: fixed;
    top: calc(10px + env(safe-area-inset-top, 0px));
    left: calc(10px + env(safe-area-inset-left, 0px));
    z-index: 330;
    width: 42px;
    height: 42px;
    place-items: center;
    padding: 0;
    border: 1px solid rgba(216, 177, 90, .45);
    background: rgba(9, 12, 18, .82);
    color: var(--rift-gold-bright, #f0d283);
    box-shadow: 0 4px 18px rgba(0, 0, 0, .45), inset 0 0 0 1px rgba(255, 255, 255, .04);
    backdrop-filter: blur(6px);
    cursor: pointer;
  }
  .mobileNavBackdrop {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 335;
    background: rgba(4, 6, 9, .62);
    backdrop-filter: blur(3px);
  }
  .mobileTabBar { display: none; }
  /* "Zurueck zur Partie"-Banner der Startseite: nur Phone (Desktop/Tablet haben
     den Sidebar-Slot #navResume; auf dem Phone steckt der im Drawer). */
  .homeResume { display: none; }

  @media (max-width: 700px) {
    /* Hamburger-FAB ist durch die Tab-Bar unten ersetzt („Mehr" oeffnet den
       Drawer); er bleibt nur als Fallback-Markup im DOM. */
    body.mp-phone .mobileNavFab { display: none !important; }
    body.mp-phone.mp-nav-open .mobileNavBackdrop { display: block; }
    body.mp-phone.mp-nav-open { overflow: hidden; }

    /* ---------- Bottom-Tab-Bar (Inhalts-Seiten) ---------- */
    /* Inhalt endet nicht unter der Tab-Bar (Styles im 1180er-Block unten). */
    body.mp-phone #modeScreen { padding-bottom: calc(72px + env(safe-area-inset-bottom, 0px)); }
    /* Status-Badge (gruenes „Online: …"/„White to move"-Feld) ist im Drawer
       nur Rauschen. Selektor muss den Restore aus main-05
       (body:not(.side-nav-collapsed) header.sideNav #modeBadge, !important)
       schlagen — gleiche Spezifitaet, spaetere Kaskade. */
    body.mp-phone header.sideNav #modeBadge { display: none !important; }
    /* Drawer liegt ueber der Tab-Bar (z 340 > 336) — Backdrop dimmt sie. */

    /* ---------- Shell: einspaltig, Nav-Spalte kollabiert auf 0 ---------- */
    body.mp-phone,
    body.mp-phone.mode-select,
    body.mp-phone.mode-profile,
    body.mp-phone.mode-collection,
    body.mp-phone.mode-community,
    body.mp-phone.mode-ranked,
    body.mp-phone.mode-lessons,
    body.mp-phone.mode-puzzle,
    body.mp-phone.mode-messages,
    body.mp-phone.mode-info,
    body.mp-phone.mode-play,
    body.mp-phone.mode-demo,
    body.mp-phone.mode-lab {
      --side-nav-width: 0px;
      grid-template-columns: minmax(0, 1fr);
    }
    body.mp-phone main,
    body.mp-phone #modeScreen {
      grid-column: 1;
    }

    /* ---------- Sidebar als Drawer: fixiert, volle Nav, herausgeschoben ---------- */
    body.mp-phone header.sideNav,
    body.mp-phone.mode-demo:not(.side-nav-collapsed) header.sideNav {
      position: fixed;
      inset: 0 auto 0 0;
      width: min(304px, 86vw);
      height: 100dvh;
      max-height: 100dvh;
      z-index: 340;
      overflow-y: auto;
      overflow-x: hidden;
      padding: 16px 14px calc(14px + env(safe-area-inset-bottom, 0px));
      align-items: stretch;
      transform: translateX(-104%);
      transition: transform 230ms ease;
      box-shadow: 22px 0 44px rgba(0, 0, 0, .55);
    }
    body.mp-phone.mp-nav-open header.sideNav,
    body.mp-phone.mp-nav-open.mode-demo:not(.side-nav-collapsed) header.sideNav {
      transform: translateX(0);
    }
    @media (prefers-reduced-motion: reduce) {
      body.mp-phone header.sideNav { transition: none; }
    }
    /* Desktop-Einklapp-Knopf hat im Drawer keine Funktion. */
    body.mp-phone .sideNavToggle { display: none !important; }

    /* Im Spiel (mode-demo) erzwingen aeltere Blöcke eine Icon-Rail — der Drawer
       zeigt IMMER die volle Navigation. Alles Wichtige wieder herstellen. */
    body.mp-phone.mode-demo header.sideNav .brandBlock { display: grid !important; }
    body.mp-phone.mode-demo header.sideNav .sideAccount { display: block !important; }
    body.mp-phone.mode-demo.exposure-public header.sideNav .authPanel:not([hidden]) { display: block !important; }
    body.mp-phone.mode-demo header.sideNav .sideUser span:not(.sideAvatar) { display: inline !important; }
    body.mp-phone.mode-demo header.sideNav .sideNavLabel { display: block !important; }
    body.mp-phone.mode-demo header.sideNav .sideNavList { justify-items: stretch; width: 100%; padding: 18px 0; margin: 0; }
    body.mp-phone.mode-demo header.sideNav .sideNavList button,
    body.mp-phone.mode-demo header.sideNav .sideNavList button:disabled,
    body.mp-phone.mode-demo header.sideNav .sideNavList button:hover,
    body.mp-phone.mode-demo header.sideNav .sideNavList button:focus-visible {
      width: 100% !important;
      max-width: none !important;
      min-height: 42px;
      display: grid;
      grid-template-columns: 26px 1fr auto;
      justify-content: initial;
      padding: 0 10px !important;
      color: var(--text, #e8dec5) !important;
      font-size: 13.5px !important;
    }
    body.mp-phone.mode-demo header.sideNav .sideNavList button .navLabel { display: inline !important; color: inherit; font-size: inherit; }
    body.mp-phone.mode-demo header.sideNav .sideNavList button .navBadge:not([hidden]) { display: inline-flex !important; }
    body.mp-phone.mode-demo header.sideNav .sideStatus {
      width: auto;
      height: auto;
      min-height: 44px;
      padding: 8px 10px;
      display: grid;
    }
    body.mp-phone.mode-demo header.sideNav .sideStatusMeta { display: grid !important; }

    /* Touch: groessere Nav-Ziele im Drawer */
    body.mp-phone header.sideNav .sideNavList button { min-height: 44px; }
    /* main-05 (<=820) versteckt .navLabel per !important und stellt nur Farbe/
       Groesse wieder her — Buttons mit Label-Span (Play/Training/Puzzle/
       Community/Admin) waeren im Drawer icon-only. */
    body.mp-phone header.sideNav .sideNavList button .navLabel {
      display: inline !important;
      color: inherit;
      font-size: inherit;
    }
    body.mp-phone header.sideNav .sideNavList button .navBadge:not([hidden]) {
      display: inline-flex !important;
      width: auto;
      justify-self: end;
    }
    body.mp-phone header.sideNav .sideNavList button,
    body.mp-phone header.sideNav .sideNavList button:disabled,
    body.mp-phone header.sideNav .sideNavList button:hover,
    body.mp-phone header.sideNav .sideNavList button:focus-visible {
      width: 100% !important;
      max-width: none !important;
      display: grid;
      grid-template-columns: 26px 1fr auto;
      justify-content: initial;
      padding: 0 10px !important;
      color: var(--text, #e8dec5) !important;
      font-size: 13.5px !important;
    }
    /* Start/Puzzle/Collection liegen schon in der Tab-Bar unten — im
       „Mehr"-Drawer waeren sie doppelt, also dort ausblenden. Die Gruppen-
       Ueberschrift „Sammlung" stuende sonst leer da (Collection ist ihr
       einziger Eintrag) — via :has() gleich mit. */
    body.mp-phone header.sideNav #navHome,
    body.mp-phone header.sideNav #navPuzzle,
    body.mp-phone header.sideNav #navCollection,
    body.mp-phone header.sideNav .sideNavLabel:has(+ #navCollection) {
      display: none !important;
    }
    /* Desktop laesst NUR die Nav-Liste scrollen (main-06) — im gestauchten
       Drawer verschwinden dadurch Eintraege (Collection/Community) unsichtbar
       im Innen-Scroll. Auf dem Phone scrollt stattdessen der ganze Drawer. */
    body.mp-phone header.sideNav .sideNavList {
      flex: 0 0 auto;
      min-height: auto;
      overflow: visible;
    }

    /* ---------- Inhalts-Seiten: volle Breite, kompakteres Padding ---------- */
    body.mp-phone .modeScreen { padding: 16px 10px 32px; }
    body.mp-phone.mode-collection .collectionPage,
    body.mp-phone.mode-community .communityPage,
    body.mp-phone.mode-lessons .lessonsPage,
    body.mp-phone.mode-puzzle .puzzlePage,
    body.mp-phone.mode-messages .messagesPage,
    body.mp-phone.mode-info .infoPage,
    body.mp-phone.mode-play .playPage {
      width: 100%;
      padding: 64px 14px 56px;
    }
    body.mp-phone .profilePage {
      width: min(calc(100% - 20px), 720px);
    }
    body.mp-phone .startTopbar { padding-inline: 16px; }

    /* ---------- Profil: Hero-Karte kompakt ----------
       main-05 stapelt die Karte ab 640px in eine Spalte (96px-Diamant,
       riesiger Name, viel Polster) — auf dem Phone frass das den halben
       Viewport. Hier: Avatar schrumpft und bleibt NEBEN dem Namen (Zeile
       statt Spalte), Typo/Polster ruecken zusammen, die lange user_-ID
       verschwindet (steht unveraendert im Account-Tab). */
    body.mp-phone.mode-profile .profilePage { padding-top: 36px; padding-bottom: 48px; }
    body.mp-phone .profileTopCard {
      flex-direction: row;
      flex-wrap: nowrap;
      align-items: center;
      gap: 14px;
      padding: 14px 16px;
    }
    body.mp-phone .ptAvatar { width: 58px; height: 58px; font-size: 17px; }
    body.mp-phone .ptInfo { flex: 1 1 0; }
    body.mp-phone .ptNameRow { gap: 6px 10px; margin-bottom: 3px; }
    body.mp-phone .ptName { font-size: clamp(19px, 5.6vw, 24px); letter-spacing: 1px; }
    body.mp-phone .ptRankChip .rankBadge { padding: 3px 8px; gap: 6px; font-size: 11px; }
    body.mp-phone .ptType { margin-bottom: 5px; font-size: 9px; letter-spacing: 2px; }
    body.mp-phone .ptStatus { margin-bottom: 5px; font-size: 13.5px; }
    body.mp-phone .ptMeta { gap: 3px 12px; font-size: 11px; }
    body.mp-phone .ptMeta .ptId,
    body.mp-phone .ptMeta .ptIdDot { display: none; }
    body.mp-phone .profileTabs { margin: 6px 0 16px; }
    body.mp-phone .profileTab { padding: 11px 14px; }

    /* ---------- Profil: Unterseiten in die Phone-Breite zwingen ----------
       Die Panels sassen auf auto-Grid-Spuren; Spielverlauf-Tabelle und
       Freunde-Zeilen diktierten die Spurbreite -> alle Boxen ragten rechts
       abgeschnitten aus dem Viewport (Spur-Fix minmax(0,1fr) in main-05).
       Hier schrumpft der Inhalt aufs Phone-Mass: Tab-Leiste kompakt (alle
       fuenf Reiter sichtbar, Rest scrollt unsichtbar), Tabelle ohne
       Elo-Neben-Spalte mit fixen Spaltenbreiten (Namen ellipsen statt
       schieben), Freunde-Buttons duerfen in die zweite Zeile umbrechen. */
    body.mp-phone .profileTabs {
      overflow-x: auto;
      scrollbar-width: none;
    }
    body.mp-phone .profileTabs::-webkit-scrollbar { display: none; }
    body.mp-phone .profileTab {
      flex: 1 0 auto;
      padding: 11px 4px;
      font-size: 9.5px;
      letter-spacing: 1px;
    }
    body.mp-phone .profilePage .profilePanel { padding: 16px 12px; }
    body.mp-phone .profilePage .sideWidget { padding: 16px 12px; }
    body.mp-phone .statCards { gap: 10px; }
    body.mp-phone .statCard { padding: 14px 12px 12px; }
    body.mp-phone .scValue { font-size: 28px; }
    body.mp-phone .profileGamesBody { overflow-x: auto; }
    body.mp-phone .gameTable { table-layout: fixed; }
    body.mp-phone .gameTable th,
    body.mp-phone .gameTable td { padding-inline: 5px; }
    body.mp-phone .gameTable th.gtModeH { width: 30px; }
    body.mp-phone .gameTable th.gtScoreH { width: 32px; }
    body.mp-phone .gameTable th.gtDeltaH { width: 42px; }
    body.mp-phone .gameTable th.gtDateH { width: 62px; }
    body.mp-phone .gtPElo { display: none; }
    body.mp-phone .gtDate { font-size: 10.5px; }
    body.mp-phone .friendAddRow button {
      flex: none;
      font-size: 10px;
      letter-spacing: 1.4px;
      padding: 0 12px;
    }
    body.mp-phone .friendRow { flex-wrap: wrap; }

    /* ---------- Home-Hero entruempelt (war ueberfuellt) ----------
       - Kicker nur noch einzeilig („Online Prototyp"); der zweite Teil und
         die vier Alpha-Chips wiederholten sich gegenseitig bzw. die
         Queue-Box direkt darunter.
       - Sekundaer-Buttons teilen sich eine Reihe; Play bleibt der Held.
       - Inschrift zentriert als ruhiger Abschluss vor der Queue-Box. */
    body.mp-phone .startKicker .kickerSep,
    body.mp-phone .startKicker .kickerSep ~ span {
      display: none;
    }
    body.mp-phone .alphaStrip { display: none; }
    body.mp-phone .startHero { padding: 26px 0 4px; min-height: 0; }
    body.mp-phone .startHero > p { font-size: 16px; line-height: 1.5; }
    body.mp-phone .modeChoices {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: 10px;
      margin-top: 6px;
    }
    body.mp-phone .modeChoices #startPlay { grid-column: 1 / -1; }
    body.mp-phone .modeChoices button {
      width: 100%;
      min-height: 48px;
      padding-inline: 10px;
      font-size: 10.5px;
      letter-spacing: 1.8px;
      white-space: normal;
      line-height: 1.35;
    }
    body.mp-phone .worldInscription {
      justify-content: center;
      text-align: center;
      margin-top: 18px;
      opacity: .85;
    }
    body.mp-phone .queuePanel { margin: 20px auto 6px; }

    /* Sektions-Koepfe: Titel lief rechts aus dem Viewport. */
    body.mp-phone .startSectionTitle {
      font-size: clamp(24px, 7.2vw, 30px);
      line-height: 1.18;
      overflow-wrap: anywhere;
    }
    body.mp-phone .startSectionDesc { font-size: 15px; line-height: 1.5; }

    /* Daily-Login-Panel: kompakter Kopf, 7 Tage als 4er-Raster statt 2er-Turm. */
    body.mp-phone .loginStreakPanel .daily { padding: 18px 14px; }
    body.mp-phone .loginStreakPanel .sigil { width: 44px; height: 44px; }
    body.mp-phone .loginStreakPanel .daily-title { font-size: 22px; }
    body.mp-phone .loginStreakPanel .daily-sub { font-size: 14px; margin-top: 5px; }
    body.mp-phone .loginStreakPanel .fil-div { margin: 16px 0 12px; }
    body.mp-phone .loginStreakPanel .streak {
      grid-template-columns: repeat(4, minmax(0, 1fr));
      gap: 8px;
    }
    body.mp-phone .loginStreakPanel .day { padding: 10px 4px 9px; }
    body.mp-phone .loginStreakPanel .day .d-k { margin-bottom: 6px; letter-spacing: 1.4px; }
    body.mp-phone .loginStreakPanel .day .d-v { font-size: 15px; }
    body.mp-phone .loginStreakPanel .lvl-xp { margin-top: 5px; }

    /* Quest-Panel: Kopfleiste + Karten + Notiz mit engeren Polstern.
       Die Desktop-Karten (main-09) sind fuers Phone zu monumental — kleinere
       Icon-Raute, engere Typo, flacherer Status-Button. */
    body.mp-phone .dailyQuestPanel .grid { gap: 12px; }
    body.mp-phone .dailyQuestPanel .quest { padding: 16px 16px 14px; }
    body.mp-phone .dailyQuestPanel .q-head { margin-bottom: 10px; align-items: center; }
    body.mp-phone .dailyQuestPanel .q-ico { width: 38px; height: 38px; }
    body.mp-phone .dailyQuestPanel .q-emoji { font-size: 17px; }
    body.mp-phone .dailyQuestPanel .q-reward { padding: 4px 10px; font-size: 13px; }
    body.mp-phone .dailyQuestPanel .q-title { font-size: 18px; }
    body.mp-phone .dailyQuestPanel .q-sub { font-size: 14px; margin-bottom: 12px; }
    body.mp-phone .dailyQuestPanel .q-prog { margin-bottom: 12px; }
    body.mp-phone .dailyQuestPanel .q-prog-head { margin-bottom: 6px; }
    body.mp-phone .dailyQuestPanel .q-btn { padding: 10px; }
    body.mp-phone .dailyQuestPanel .note {
      margin-top: 16px;
      padding: 12px 14px;
      font-size: 14px;
      gap: 10px;
    }
    body.mp-phone .dailyQuestPanel .note .drop { font-size: 24px; }
    /* Abgeholte Quests machen auf dem Phone Platz: quests.js spielt beim
       Abholen Teal-Puls (.q-vanish-flash) + Zuklappen (.q-vanish), danach —
       und bei jedem weiteren Render/Reload — blendet diese Regel die Karte
       ganz aus. Desktop behaelt die gedimmte claimed-Karte (main-09). */
    body.mp-phone .dailyQuestPanel .quest.claimed { display: none; }
    body.mp-phone .dailyQuestPanel .quest.q-vanish-flash {
      border-color: rgba(77, 208, 196, 0.55);
      animation: qVanishPulse 460ms ease;
    }
    body.mp-phone .dailyQuestPanel .quest.q-vanish {
      height: 0 !important; /* schlaegt die von quests.js gesetzte Start-Hoehe */
      padding-top: 0 !important;
      padding-bottom: 0 !important;
      border-width: 0;
      opacity: 0;
      transform: scale(0.94) translateY(-10px);
      overflow: hidden;
      transition:
        height 420ms cubic-bezier(0.4, 0, 0.2, 1),
        padding 420ms cubic-bezier(0.4, 0, 0.2, 1),
        transform 420ms cubic-bezier(0.4, 0, 0.2, 1),
        border-width 420ms ease,
        opacity 300ms ease;
    }
    @keyframes qVanishPulse {
      0% { transform: scale(1); box-shadow: inset 0 0 0 1px rgba(77, 208, 196, 0.1), 0 0 0 rgba(77, 208, 196, 0); }
      35% { transform: scale(1.025); box-shadow: inset 0 0 0 1px rgba(77, 208, 196, 0.3), 0 0 42px rgba(77, 208, 196, 0.3); }
      100% { transform: scale(1); box-shadow: inset 0 0 0 1px rgba(77, 208, 196, 0.12), 0 0 18px rgba(77, 208, 196, 0.1); }
    }

    /* ---------- Startseite: 64px-Gutter der Desktop-Baender auf 16px ----------
       .startPage nutzt padding 0 64px + Full-Bleed-Abschnitte mit margin 0 -64px
       (main-04/05/06/09). Auf dem Phone schrumpft beides synchron auf 16px. */
    body.mp-phone .startPage {
      --home-gutter: 16px;
      width: 100%;
      padding: 0 16px 64px;
      grid-template-columns: minmax(0, 1fr);
    }
    body.mp-phone .startPage > * { min-width: 0; max-width: 100%; }
    /* width:100% aus den Basis-Styles loest gegen die Grid-SPUR auf — der
       negative Margin verschob die Baender nur nach links (rechts blieb eine
       32px-Luecke, Panel wirkte aussermittig). Breite explizit mitwachsen. */
    body.mp-phone .visionGrid,
    body.mp-phone .factionShowcase,
    body.mp-phone .startSectionHead,
    body.mp-phone .dailyQuestSection,
    body.mp-phone .loginStreakSection {
      margin-inline: -16px;
      width: calc(100% + 32px);
      max-width: none;
    }
    body.mp-phone .visionGrid { padding: 0 var(--home-gutter, 16px) 44px; }
    body.mp-phone .startSectionHead { flex-wrap: wrap; gap: 14px; }
    body.mp-phone .startHero {
      max-width: 100%;
      min-height: min(620px, calc(100dvh - 120px));
      padding-top: 28px;
    }
    /* ---------- "Zurueck zur Partie" oben auf der Phone-Startseite ----------
       Gefuettert von app/resume-game.js (gleiche Quelle wie #navResume).
       Farbsprache wie der Sidebar-Slot: Teal = Partie laeuft, Gold = du bist
       am Zug. [hidden] muss das display:flex schlagen (wie .sideResume). */
    body.mp-phone .homeResume {
      display: flex;
      align-items: center;
      gap: 11px;
      width: 100%;
      margin: 14px 0 -6px;
      padding: 13px 14px;
      appearance: none;
      font: inherit;
      text-align: left;
      cursor: pointer;
      border: 1px solid rgba(77, 208, 196, .38);
      background: linear-gradient(rgba(35, 155, 149, .14), rgba(35, 155, 149, .05)), rgba(9, 12, 18, .72);
      box-shadow: 0 4px 18px rgba(0, 0, 0, .35);
      backdrop-filter: blur(4px);
      color: var(--mp-ink, #aea58c);
    }
    body.mp-phone .homeResume[hidden] { display: none !important; }
    /* Kollabierte Desktop-Nav versteckt .sideStatusMeta/.sideResumeArrow global
       (main-06, body.side-nav-collapsed) — der Zustand kann auf dem Phone noch
       kleben. Im Banner immer zeigen (main-13 laedt zuletzt). */
    body.mp-phone .homeResume .sideStatusMeta { display: block; }
    body.mp-phone .homeResume .sideResumeArrow { display: inline-flex; margin-left: auto; color: var(--mp-teal-2, #4dd0c4); }
    body.mp-phone .homeResume .sideStatusTitle { color: var(--mp-teal-2, #4dd0c4); font-size: 13px; }
    body.mp-phone .homeResume .sideStatusInfo { font-size: 11.5px; }
    body.mp-phone .homeResume.yourTurn .sideStatusTitle,
    body.mp-phone .homeResume.yourTurn .sideResumeArrow {
      color: var(--mp-gold, #d4af37);
    }
    body.mp-phone .homeResume.yourTurn .sideStatusDot {
      background: var(--mp-gold, #d4af37);
      color: var(--mp-gold, #d4af37);
    }
    body.mp-phone .homeResume.yourTurn { border-color: rgba(212, 175, 55, .45); }
    /* Kicker-Zeile brach nicht um und blaehte die Grid-Spalte auf (min-content
       ~380px -> Seite lief rechts raus). */
    body.mp-phone .startKicker {
      flex-wrap: wrap;
      row-gap: 4px;
      max-width: 100%;
    }
    body.mp-phone .queuePanel {
      width: 100%;
      margin: -8px 0 36px;
    }
    body.mp-phone .alphaStrip { flex-wrap: wrap; }

    /* ---------- Brett-Screen (mode-demo) ---------- */
    body.mp-phone.mode-demo {
      --rail-size: 44px;
      --effect-chip-size: 40px;
      --board-size: min(calc(100vw - 18px), calc(100dvh - 310px));
    }
    body.mp-phone.mode-demo main {
      min-width: 0;
      padding: 54px 4px calc(74px + env(safe-area-inset-bottom, 0px));
      justify-content: flex-start;
      overflow-x: hidden;
    }
    body.mp-phone.mode-demo #boardStage,
    body.mp-phone.mode-demo #boardWrap,
    body.mp-phone.mode-demo .effectRail,
    body.mp-phone.mode-demo #gamePanel,
    body.mp-phone.mode-demo #pieceInfo {
      width: min(calc(var(--board-size) + 12px), calc(100vw - 8px));
      max-width: 100%;
    }
    body.mp-phone.mode-demo #boardWrap { padding: 4px; border-radius: 8px; }
    body.mp-phone.mode-demo #ranks,
    body.mp-phone.mode-demo #files { display: none; }
    /* Effektleiste = exakt der Tablet-Look (Spieler-Karte oben, runde Chips
       darunter): die Portrait-Bloecke in main-02/07 gelten jetzt auch <=700px.
       Hier nur Phone-Feintuning — Chip-Groesse kommt aus --effect-chip-size. */
    body.mp-phone.mode-demo .effectRailHeader {
      min-height: 60px;
      padding: 8px 10px;
    }
    body.mp-phone.mode-demo .effectGroups,
    body.mp-phone.mode-demo .effectRail.left .effectGroups,
    body.mp-phone.mode-demo .effectRail.right .effectGroups {
      max-width: calc(100vw - 96px);
    }
    /* Live-Figurenkarten-Dock: auf dem Phone kein Platz neben dem Brett —
       Figuren-Details gibt es weiterhin ueber das Figuren-Popup. */
    body.mp-phone.mode-demo .lcxDock { display: none; }
    /* Aktions-/Footer-Karten passen nicht in die schmale Zeile — ausblenden
       (identisch zum Tablet-Portrait-Layout; Aufgeben/Remis liegen unterm Brett). */
    body.mp-phone.mode-demo .effectRailFooter { display: none; }
    body.mp-phone.mode-demo #gamePanel {
      grid-template-columns: minmax(0, 1fr);
      align-items: stretch;
      padding: 8px 0 0;
    }
    body.mp-phone.mode-demo #gameActions { justify-content: center; flex-wrap: wrap; }
    /* Aktions-Prompt (z.B. Seehexe "Opfer waehlen") schwebte IM Brett und
       verdeckte genau die Zielfelder der oberen Reihen — auf dem Phone uebers
       Brett heben; darf Gegner-Karte + Effektleiste ueberlappen. */
    body.mp-phone.mode-demo #boardWrap .actionStatus {
      top: auto;
      bottom: calc(100% + 6px);
      max-width: calc(100vw - 16px);
    }
    /* Touch hat kein ESC: Tasten-Hinweis weg, Abbrechen als echter Knopf.
       Der Trennpunkt direkt vor dem Knopf (letzter Sep der Zeile) haengt ohne
       ESC-Text verwaist in der Luft — mit ausblenden. */
    body.mp-phone.mode-demo #boardWrap .actionStatusEsc {
      min-height: 30px;
      padding: 5px 12px;
      border: 1px solid rgba(77, 208, 196, .40);
      border-radius: 3px;
      background: rgba(77, 208, 196, .12);
    }
    body.mp-phone.mode-demo #boardWrap .actionStatusEsc kbd { display: none; }
    body.mp-phone.mode-demo #boardWrap .actionStatusHint .actionStatusSep:last-of-type { display: none; }

    /* ---------- Play-Hub / Akademie / Ranglisten (geteilte .duell-Klassen) ----
       Titel-Mindestgroesse 64px + Matchup-Padding 28px sprengten die 390px. */
    body.mp-phone .playGrid,
    body.mp-phone .lessonsGrid,
    body.mp-phone .rankedGrid,
    body.mp-phone .puzzleGrid,
    body.mp-phone .duell {
      min-width: 0;
      max-width: 100%;
    }
    body.mp-phone .duell-title {
      font-size: clamp(34px, 11.5vw, 56px);
      letter-spacing: 2px;
      overflow-wrap: anywhere;
    }
    body.mp-phone .duell-sub { font-size: 17px; }
    body.mp-phone .duell .matchup { padding: 16px 12px; }
    body.mp-phone .duell .matchup-col,
    body.mp-phone .duell .col-head { min-width: 0; }
    body.mp-phone .duell .col-head { flex-wrap: wrap; }
    /* Abstaende kompakter: 38px Head-Margin + 34px nach den Kacheln + 56px
       nach der Ready-Bar schoben Deck und CTA weit unter den Falz. */
    body.mp-phone .duell-head { margin-bottom: 22px; }
    body.mp-phone .duell .mode-row { gap: 8px; margin-bottom: 22px; }
    body.mp-phone .duell .ready-bar { padding: 14px 14px 16px; margin-bottom: 34px; }
    /* Bedenkzeit-Segment (Blitz/Schnell/Standard) lief rechts aus dem Panel:
       Label+Buttons duerfen umbrechen, Buttons schlanker. */
    body.mp-phone .duell .ready-left { gap: 12px 20px; }
    body.mp-phone .duell .difficulty { flex-wrap: wrap; row-gap: 8px; }
    body.mp-phone .duell .df-seg { max-width: 100%; }
    body.mp-phone .duell .df-seg button { padding: 8px 10px; }
    body.mp-phone .duell .match-summary { flex-wrap: wrap; row-gap: 4px; }
    body.mp-phone .duell .friend-card { gap: 14px; padding: 14px 16px; }
    body.mp-phone .duell .friend-card .fc-ico { width: 40px; height: 40px; }
    /* Text quetschte sich einspaltig zwischen Diamant und OEFFNEN-Aktion —
       Aktion bricht stattdessen in die zweite Zeile um (flex-wrap ab 640px). */
    body.mp-phone .duell .friend-card .fc-text { flex: 1 1 200px; }

    /* Modus-Kacheln: die Hochkant-Karten (34px-Diamant oben, Text darunter,
       ~130px hoch) stapelten sich einspaltig auf >500px — auf dem Phone als
       kompakte Listenzeilen: Diamant links, Name+Beschreibung rechts, Haken
       statisch in der dritten Spalte (absolut kollidierte er mit dem Text). */
    body.mp-phone .duell .mode-tile {
      display: grid;
      grid-template-areas: "ico name check" "ico desc check";
      grid-template-columns: auto minmax(0, 1fr) auto;
      align-items: center;
      column-gap: 14px;
      row-gap: 2px;
      padding: 10px 14px;
    }
    body.mp-phone .duell .mode-tile .mt-ico {
      grid-area: ico;
      width: 26px;
      height: 26px;
      margin: 6px 4px;
    }
    body.mp-phone .duell .mode-tile .mt-ico > svg { width: 14px; height: 14px; }
    body.mp-phone .duell .mode-tile .mt-name {
      grid-area: name;
      align-self: end;
      margin: 0;
      font-size: 15px;
    }
    body.mp-phone .duell .mode-tile .mt-desc {
      grid-area: desc;
      align-self: start;
      font-size: 11px;
    }
    body.mp-phone .duell .mode-tile .mt-check {
      grid-area: check;
      position: static;
      align-self: center;
    }

    /* ---------- Collection („Das Gewölbe") ----------
       #collectionGrid traegt noch das alte auto-fill(148px)-Raster; als
       Flex-Item mit min-width:auto blaeht es sich zirkulaer auf (888px bei
       390px Viewport). Im Vault-UI gibt es nur EIN Kind (.col-root). */
    body.mp-phone.mode-collection .collectionPage { min-width: 0; max-width: 100vw; }
    body.mp-phone #collectionGrid { grid-template-columns: minmax(0, 1fr); }
    /* Kopf: rechte Stat-Spalte hat min 360px (Desktop-Grid) und sprengte den
       Phone-Viewport; Titel-Clamp startete bei 48px + 6px Letter-Spacing. */
    body.mp-phone .col-header-inner {
      grid-template-columns: minmax(0, 1fr);
      gap: 18px;
    }
    body.mp-phone .col-title {
      font-size: clamp(30px, 10vw, 46px);
      letter-spacing: 2px;
    }
    /* Stat-Kacheln (Entdeckt/Gesamt/Sigille/Decks): 4 feste 202px-Spuren
       (~830px) sprengten die Seite — auf dem Phone als 2x2-Raster. */
    body.mp-phone .col-stats {
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: 10px;
    }
    /* Fraktions-Roster (Pieces -> Fraktion): der Kopf (Titel links, Entdeckt-
       Balken rechts mit min-width 260) war zusammen ~573px breit und schnitt
       den Mythos-/Story-Kasten ab — auf dem Phone zweizeilig. */
    body.mp-phone .col-faction .rr-hero {
      flex-wrap: wrap;
      align-items: flex-start;
      gap: 12px;
    }
    body.mp-phone .rr-hero-r {
      min-width: 0;
      width: 100%;
      text-align: left;
    }
    body.mp-phone .rr-lore { padding: 24px 16px 22px; }

    /* ---------- Puzzle-Hub: Ring-Karten stapeln ----------
       .pz-meters ist flex mit flex:1/min-width:0-Karten — sie wrappen nie,
       sondern quetschen sich (Ring + Texte ueberlappen). */
    body.mp-phone .pz-root .pz-meters { flex-direction: column; }
    body.mp-phone .pz-root .pz-ring-card { width: 100%; }
    /* SOLVE-Button ganz nach oben, UEBER das Brett-Preview: die Haupt-Spalte
       aufloesen und den Start-Knopf per order vorziehen. */
    body.mp-phone .pz-root .pz-main-col { display: contents; }
    body.mp-phone .pz-root .pz-hero { gap: 14px; }
    body.mp-phone .pz-root #puzzleStart { order: -1; }

    /* ---------- Puzzle-Loesen: alles auf einen Blick, kein Scrollen ----------
       Spieler-/Gegner-Karten sind im Puzzle bedeutungslos (kein Gegner, keine
       Uhr) — raus. Aufgabe + Werte kompakt, Aktionen als Button-Zeile. */
    body.mp-phone.puzzle-active #effectBar,
    body.mp-phone.puzzle-active #effectBarEnemy {
      display: none !important;
    }
    /* Faehigkeiten-Puzzles: die eigene Leiste traegt den Effekt-Chip (Loesungs-
       Ausloeser) und muss deshalb auch am Phone sichtbar bleiben — als kompakte
       Karte in Brettbreite unter dem Brett. */
    body.mp-phone.puzzle-active.puzzle-has-abilities #effectBar {
      display: flex !important;
      width: min(calc(var(--board-size) + 12px), calc(100vw - 8px));
      margin: 0 auto;
      min-height: 0;
    }
    /* Rail aufloesen: die Panels werden direkte Flex-Items von <main>
       (Spalten-Flexbox) — Aufgabe UEBER dem Brett, Aktionen darunter. */
    body.mp-phone.puzzle-active #puzzleRail { display: contents; }
    body.mp-phone.puzzle-active #puzzleTopHud,
    body.mp-phone.puzzle-active #puzzleBar {
      width: min(calc(var(--board-size) + 12px), calc(100vw - 8px));
      margin: 0 auto;
    }
    body.mp-phone.puzzle-active #puzzleTopHud { order: -1; }
    body.mp-phone.puzzle-active #puzzleBar .pzPanel-inner { padding: 8px 10px 10px; }
    body.mp-phone.puzzle-active #puzzleBar .actions {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
      gap: 8px;
    }
    body.mp-phone.puzzle-active #puzzleBar .act {
      min-height: 44px;
      padding: 0 6px;
      justify-content: center;
      font-size: 10.5px;
      letter-spacing: 1.2px;
      white-space: nowrap;
    }

    /* ---------- Akademie-Lektion: alles auf einen Screen ----------
       Der Desktop-Coach (Gegner-Leiste + grosse Katze + Namensblock +
       Sprechblase) stapelte sich ueber dem Brett auf >500px — Brett und
       Spielerkarte lagen unterm Falz. Auf dem Phone: Gegner-Leiste raus
       (wie im Puzzle — die Lektion braucht nur die EIGENE Leiste fuer
       Mana/Chips), das Panel wird zum kompakten Streifen: kleine Katze
       links, Aufgabe + Erklaerung rechts. Das Brett rechnet den Coach in
       sein Hoehen-Budget ein. */
    body.mp-phone.mode-demo.tutorial-active {
      --board-size: max(240px, min(calc(100vw - 18px), calc(100dvh - 470px)));
    }
    body.mp-phone.tutorial-active #tutorialRail {
      width: 100%;
      max-height: none;
      overflow: visible;
    }
    body.mp-phone.tutorial-active #tutorialRail > #effectBarEnemy { display: none; }
    /* Eigene Leiste: die fix reservierte Chip-Zeile (chip + 18px) staende in
       chiplosen Lektionen leer im Budget — beide Zeilen auto; Friedhof ist
       in der Lektion Rauschen. */
    body.mp-phone.tutorial-active #effectBar { grid-template-rows: auto auto; }
    body.mp-phone.tutorial-active #effectBar .effectGroup-graveyard { display: none; }
    body.mp-phone.tutorial-active .coachPanel-card {
      display: grid;
      grid-template-columns: 52px minmax(0, 1fr);
      grid-template-areas:
        "head head"
        "stage speech"
        "hint hint"
        "msg msg";
      gap: 6px 10px;
      padding: 8px 10px 10px;
    }
    body.mp-phone.tutorial-active .coachPanel-head { grid-area: head; }
    body.mp-phone.tutorial-active .coachPanel-x { width: 26px; height: 26px; }
    body.mp-phone.tutorial-active .coachPanel-stage {
      grid-area: stage;
      align-self: start;
      padding-top: 6px;
    }
    body.mp-phone.tutorial-active .coachCat { width: 52px; }
    body.mp-phone.tutorial-active .coachPanel-name { display: none; }
    body.mp-phone.tutorial-active .coachPanel-speech {
      grid-area: speech;
      margin-top: 0;
      padding: 8px 10px 9px;
      /* Sicherheitsnetz fuer sehr lange Erklaerungen: der Kasten scrollt
         innen, statt die Seite unter den Falz zu druecken. Auf kurzen
         Viewports (SE & Co.) zieht der dvh-Anteil den Deckel weiter runter. */
      max-height: clamp(72px, calc(100dvh - 552px), 168px);
      overflow-y: auto;
      scrollbar-color: rgba(216, 177, 90, .22) transparent;
      scrollbar-width: thin;
    }
    /* Sprechblasen-Tail zeigt zur Katze LINKS statt nach oben. */
    body.mp-phone.tutorial-active .coachPanel-tail {
      top: 14px;
      left: -8px;
      transform: rotate(-45deg);
    }
    body.mp-phone.tutorial-active .coachPanel-task {
      font-size: 14.5px;
      line-height: 1.4;
      min-height: 0;
    }
    body.mp-phone.tutorial-active .coachPanel-copy {
      margin-top: 6px;
      padding-top: 6px;
      font-size: 13.5px;
      line-height: 1.48;
    }
    body.mp-phone.tutorial-active .coach-rail-hint {
      grid-area: hint;
      margin-top: 0;
      font-size: 10.5px;
    }
    body.mp-phone.tutorial-active .coachPanel-msg {
      grid-area: msg;
      padding: 6px 10px;
      font-size: 12.5px;
    }

    /* ---------- Feier-Karte (Puzzle geloest/gescheitert, Lektion fertig) ----
       .pzCelebrateLayer sitzt absolut IM #boardWrap (overflow:hidden) — das
       Brett ist auf dem Phone kleiner als die Checkmate-Karte, Wappen + Buttons
       wurden abgeschnitten. Auf dem Phone wird der Layer zum Vollbild-Overlay
       zwischen Spiel-Leiste (z 320) und Tab-Bar (z 336) — beide bleiben
       bedienbar (Zurueck/Tab-Wechsel als Ausweg neben Next/Replay). */
    /* Gotcha: der drop-shadow-Filter auf #boardStage macht es zum Containing
       Block fuer position:fixed — der Layer wuerde sonst weiter am Brett
       kleben. Der Schatten ist auf dem Phone ohnehin praktisch unsichtbar. */
    body.mp-phone.mode-demo #boardStage { filter: none; }
    body.mp-phone .pzCelebrateLayer {
      position: fixed;
      inset: 0;
      z-index: 310;
      overflow-y: auto;
      overflow-x: hidden;
      overscroll-behavior: contain;
      padding: calc(52px + env(safe-area-inset-top, 0px)) 10px calc(66px + env(safe-area-inset-bottom, 0px));
    }
    /* Sieg-Root laeuft im Fluss mit (statt absolut inset:0), damit der Layer
       auf kleinen Viewports scrollen kann; Padding reserviert Platz fuer das
       ueberstehende Wappen-Medaillon. */
    body.mp-phone .pzCelebrateLayer .pzcWin {
      position: relative;
      inset: auto;
      /* start statt center: ist die Karte hoeher als der Scrollport, wuerde
         place-items:center den Kopf ueber die Scroll-Kante schieben —
         unerreichbar. min-height:100% zentriert kurze Karten trotzdem. */
      align-self: start;
      width: 100%;
      min-width: 0;
      min-height: 100%;
      padding: 44px 0 12px;
    }
    /* Cinzel-Titel („SCHACHMATT!") ist breiter als die Karte und wuerde als
       min-content das Sieg-Root aus dem Viewport druecken — fluid skalieren. */
    body.mp-phone .pzCelebrateLayer .pzcTitle {
      font-size: clamp(22px, 8.4vw, 44px);
      letter-spacing: 1px;
    }
    /* Lektion-Abschluss: „ABGESCHLOSSEN" (13 Zeichen Cinzel) ist laenger als
       „SCHACHMATT!" — mit der Puzzle-Formel ragte das Wort ueber die
       Kartenkante (N abgeschnitten). Nur hier kleiner skalieren. */
    body.mp-phone .pzCelebrateLayer .tutorialWin .pzcTitle {
      font-size: clamp(18px, 6vw, 34px);
      letter-spacing: .5px;
    }
    /* „Naechstes Puzzle" + „Wiederholen" passen nicht nebeneinander in die
       schmale Karte — stapeln, volle Tap-Breite. */
    body.mp-phone .pzCelebrateLayer .pzcActions { flex-direction: column; }
    body.mp-phone .pzCelebrateLayer .pzcBtn { min-height: 46px; }

    /* ---------- Community („Werkstatt") ---------- */
    body.mp-phone .comm { min-width: 0; max-width: 100%; }
    body.mp-phone .comm .cs-cell { min-width: 0; }
    body.mp-phone .comm-main { grid-template-columns: minmax(0, 1fr); }

    /* ---------- Seelenschmiede (Entzaubern, .dwx) ----------
       Die 1fr-Spur der Karten hat einen min-content-Floor (~460px) und ragte
       aus dem Panel; Karten brechen jetzt um (Bild oben, Werte+Slider unten). */
    body.mp-phone .dwx { width: min(560px, calc(100vw - 16px)); }
    body.mp-phone .dwx-ov { padding: 10px; }
    body.mp-phone .dwx-title { font-size: 30px; }
    body.mp-phone .dwx-grid { grid-template-columns: minmax(0, 1fr); }
    body.mp-phone .dwx-card { flex-wrap: wrap; }
    body.mp-phone .dwx-body { flex: 1 1 100%; min-width: 0; }
    body.mp-phone .dwx-row1,
    body.mp-phone .dwx-meta { flex-wrap: wrap; }
    body.mp-phone .dwx-tab {
      flex: 1 1 auto;
      min-width: 0;
      padding: 9px 10px;
    }

    /* ---------- Modals / Overlays ----------
       Gotcha: die Overlay-Container sind display:grid mit place-items:center.
       Ein Panel mit fester Breite blaeht die Grid-Spur auf; max-width:100%
       loest gegen DIE SPUR auf (nicht den Viewport) und begrenzt nichts.
       Darum hier explizite min(...px, calc(100vw - 24px))-Breiten. */
    .wm { width: min(580px, calc(100vw - 24px)); }
    .si { width: min(452px, calc(100vw - 24px)); }
    .fb { width: min(520px, calc(100vw - 24px)); }
    /* Feedback-Popup kompakter: 4 gestapelte Kategorien + Textfeld + gestapelte
       Buttons sind sonst hoeher als kleine Phones (Rest faengt der Overlay-Scroll
       aus main-12 ab). */
    .fb-ov { padding: 12px; }
    .fb-head { padding: 20px 18px 12px; }
    .fb-title { font-size: 22px; }
    .fb-close { top: 14px; right: 14px; }
    .fb-body { padding: 2px 18px 0; }
    .fb-cats { gap: 7px; margin-bottom: 18px; }
    .fb-cat { padding: 11px 12px; }
    .fb-text { min-height: 96px; }
    .fb-foot { padding: 14px 18px 18px; gap: 9px; }
    .fb-btn { padding: 13px 18px; }
    .mmPanel { width: min(520px, calc(100vw - 24px)); }
    .pmPanel { width: min(440px, calc(100vw - 24px)); }
    .wm-ov { padding: 14px; }
    .wm-head, .wm-list { padding-inline: 20px; }
    .wm-note { margin-inline: 20px; }
    .wm-foot { padding: 18px 20px 22px; flex-direction: column; }
    .wm-title { font-size: clamp(26px, 8.5vw, 34px); }
    .wm-sub { font-size: 16px; }

    /* Toasts nicht breiter als der Viewport. Auf dem Phone kommen sie OBEN
       statt unten (User-Wunsch): 60px+safe raeumt Hamburger-FAB (endet
       52px+safe) und Spiel-Leiste (48px+safe) frei; die Tab-Bar unten bleibt
       unverdeckt. column-reverse laesst den neuesten Toast zuoberst stehen. */
    #toast { max-width: calc(100vw - 24px); }
    body.mp-phone #toast,
    body.mp-phone .mp-toasts {
      top: calc(60px + env(safe-area-inset-top, 0px));
      bottom: auto;
    }
    /* Toasts kompakt: das Desktop-Format (38px-Siegel, 16px-Serif, 14er-
       Polster) war auf dem Phone zu wuchtig. (Dass nur noch EIN Toast
       gleichzeitig lebt, regelt app/toasts.js mit MAX=1.) */
    body.mp-phone .mp-toasts { gap: 8px; }
    body.mp-phone .mp-toast { gap: 10px; padding: 9px 12px 10px; }
    body.mp-phone .mp-toast-ico { width: 28px; height: 28px; }
    body.mp-phone .mp-toast-ico > svg { width: 15px; height: 15px; }
    body.mp-phone .mp-toast-title { margin-bottom: 2px; letter-spacing: 1.4px; }
    body.mp-phone .mp-toast-text { font-size: 14px; }
    body.mp-phone .mp-toast-text .mono { font-size: 12.5px; }
  }

  /* =====================================================================
     BOTTOM-TAB-BAR — nur Phone (alle Seiten, auch im Spiel). Auf dem
     Tablet bewusst NICHT (User-Entscheid): Inhalts-Seiten haben die
     Sidebar, im Spiel reicht die Spiel-Leiste oben.
     ===================================================================== */
  @media (max-width: 700px) {
    body.mp-phone .mobileTabBar {
      position: fixed;
      left: 0;
      right: 0;
      bottom: 0;
      z-index: 336;
      display: grid;
      grid-template-columns: repeat(5, 1fr);
      height: calc(58px + env(safe-area-inset-bottom, 0px));
      padding: 6px max(env(safe-area-inset-right, 0px), 2px) env(safe-area-inset-bottom, 0px) max(env(safe-area-inset-left, 0px), 2px);
      background: linear-gradient(180deg, rgba(10, 13, 19, .94), rgba(7, 9, 13, .99));
      border-top: 1px solid rgba(216, 177, 90, .30);
      box-shadow: 0 -10px 26px rgba(0, 0, 0, .38);
      backdrop-filter: blur(9px);
    }
    body.mode-lab .mobileTabBar { display: none !important; }
    .mtb-btn {
      position: relative;
      display: grid;
      justify-items: center;
      align-content: center;
      gap: 4px;
      min-height: 44px;
      padding: 0;
      background: none;
      border: 0;
      color: var(--mp-ink-dim, #8f8c86);
      font-weight: 700;
      font-size: 9px;
      letter-spacing: 1.2px;
      text-transform: uppercase;
      cursor: pointer;
    }
    .mtb-btn svg { width: 20px; height: 20px; color: var(--mp-gold-2, #d8b15a); opacity: .72; }
    .mtb-btn > span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    /* Aktiver Tab: Teal (Haus-Sprache „teal = aktiv") + Indikator-Linie oben.
       Im Spiel gilt Play als aktiv (Brett gehoert zum Play-Flow). */
    body.mp-phone.mode-select [data-mtab="navHome"],
    body.mp-phone.mode-play [data-mtab="navPlay"],
    body.mode-demo [data-mtab="navPlay"],
    body.mp-phone.mode-puzzle [data-mtab="navPuzzle"],
    body.mp-phone.mode-collection [data-mtab="navCollection"],
    body.mp-phone.mp-nav-open #mobileTabMore {
      color: var(--mp-teal-1, #80e8df);
    }
    body.mp-phone.mode-select [data-mtab="navHome"] svg,
    body.mp-phone.mode-play [data-mtab="navPlay"] svg,
    body.mode-demo [data-mtab="navPlay"] svg,
    body.mp-phone.mode-puzzle [data-mtab="navPuzzle"] svg,
    body.mp-phone.mode-collection [data-mtab="navCollection"] svg,
    body.mp-phone.mp-nav-open #mobileTabMore svg {
      color: var(--mp-teal-1, #80e8df);
      opacity: 1;
      filter: drop-shadow(0 0 6px rgba(77, 208, 196, .45));
    }
    body.mp-phone.mode-select [data-mtab="navHome"]::before,
    body.mp-phone.mode-play [data-mtab="navPlay"]::before,
    body.mode-demo [data-mtab="navPlay"]::before,
    body.mp-phone.mode-puzzle [data-mtab="navPuzzle"]::before,
    body.mp-phone.mode-collection [data-mtab="navCollection"]::before {
      content: "";
      position: absolute;
      top: -6px;
      left: 22%;
      right: 22%;
      height: 2px;
      background: linear-gradient(90deg, transparent, var(--mp-teal-1, #80e8df), transparent);
    }
    /* Puzzle/Akademie laufen auch auf dem Brett (mode-demo): dort gilt nicht
       Play, sondern Puzzle (bzw. gar kein Tab bei Training). */
    body.mode-demo.puzzle-active [data-mtab="navPlay"],
    body.mode-demo.tutorial-active [data-mtab="navPlay"] {
      color: var(--mp-ink-dim, #8f8c86);
    }
    body.mode-demo.puzzle-active [data-mtab="navPlay"] svg,
    body.mode-demo.tutorial-active [data-mtab="navPlay"] svg {
      color: var(--mp-gold-2, #d8b15a);
      opacity: .72;
      filter: none;
    }
    body.mode-demo.puzzle-active [data-mtab="navPlay"]::before,
    body.mode-demo.tutorial-active [data-mtab="navPlay"]::before {
      content: none;
    }
    body.mode-demo.puzzle-active [data-mtab="navPuzzle"] { color: var(--mp-teal-1, #80e8df); }
    body.mode-demo.puzzle-active [data-mtab="navPuzzle"] svg {
      color: var(--mp-teal-1, #80e8df);
      opacity: 1;
      filter: drop-shadow(0 0 6px rgba(77, 208, 196, .45));
    }
    body.mode-demo.puzzle-active [data-mtab="navPuzzle"]::before {
      content: "";
      position: absolute;
      top: -6px;
      left: 22%;
      right: 22%;
      height: 2px;
      background: linear-gradient(90deg, transparent, var(--mp-teal-1, #80e8df), transparent);
    }
  }

  /* =====================================================================
     SPIEL-LEISTE (Handy + Tablet, <=1180px im Brett-Modus)
     Im Spiel verschwindet die Seitennavigation KOMPLETT (auch die Icon-Rail
     und der Hamburger-FAB). Stattdessen: eine schlanke fixe Leiste oben —
     links „Zurück" (fuehrt in den Hub, aus dem das Brett kam), mittig die
     Partie-Krume, rechts die Zug-Navigation ◀ ▶. Logik: app/game-topbar.js.
     ===================================================================== */
  .gameTopBar { display: none; }

  @media (max-width: 1180px) {
    body.mode-demo header.sideNav { display: none !important; }
    body.mode-demo .mobileNavFab { display: none !important; }
    /* Kebab-FAB (Feedback/Zahnrad, report.js) ist im Spiel redundant: das
       Zahnrad sitzt jetzt in der Leiste, Feedback bleibt ueber Zurueck->Nav. */
    body.mode-demo .gameFab { display: none !important; }
    body.mode-demo,
    body.mode-demo:not(.side-nav-collapsed) {
      --side-nav-width: 0px;
      grid-template-columns: minmax(0, 1fr);
    }
    body.mode-demo main { grid-column: 1; }

    body.mode-demo .gameTopBar {
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      z-index: 320;
      display: flex;
      align-items: center;
      gap: 10px;
      height: calc(48px + env(safe-area-inset-top, 0px));
      padding: env(safe-area-inset-top, 0px) calc(10px + env(safe-area-inset-right, 0px)) 0 calc(6px + env(safe-area-inset-left, 0px));
      background: linear-gradient(180deg, rgba(10, 13, 19, .95), rgba(8, 10, 15, .84));
      border-bottom: 1px solid rgba(216, 177, 90, .30);
      box-shadow: 0 10px 26px rgba(0, 0, 0, .38);
      backdrop-filter: blur(9px);
    }
    /* Platz fuer die fixe Spiel-Leiste oben; Portrait-Bloecke setzen padding
       als Shorthand, Longhand gewinnt. (Tab-Bar unten gibt es nur auf dem
       Phone — dessen padding-bottom regelt der Phone-Block.) */
    body.mode-demo main {
      padding-top: calc(56px + env(safe-area-inset-top, 0px));
    }

    .gbBack {
      flex: 0 0 auto;
      display: inline-flex;
      align-items: center;
      gap: 7px;
      min-height: 38px;
      padding: 0 12px 0 8px;
      background: none;
      border: 1px solid transparent;
      color: var(--rift-gold-bright, #f0d283);
      font-weight: 700;
      font-size: 11px;
      letter-spacing: 2px;
      text-transform: uppercase;
      cursor: pointer;
    }
    .gbBack:hover,
    .gbBack:focus-visible {
      border-color: rgba(216, 177, 90, .38);
      background: rgba(216, 177, 90, .08);
    }
    .gbBack:active {
      border-color: rgba(77, 208, 196, .55);
      color: var(--mp-teal-1, #80e8df);
    }

    .gbCrumb {
      flex: 1 1 auto;
      min-width: 0;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: 8px;
      opacity: .78;
    }
    .gbDiamond {
      width: 5px;
      height: 5px;
      background: var(--mp-gold-1, #d8b15a);
      transform: rotate(45deg);
      box-shadow: 0 0 6px rgba(216, 177, 90, .55);
    }
    .gbCrumbText {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      font-family: var(--mp-mono, ui-monospace, monospace);
      font-size: 9.5px;
      letter-spacing: 3px;
      text-transform: uppercase;
      color: var(--mp-ink-dim, #8f8c86);
    }

    /* Versteckte Leisten-Elemente (z. B. Chat-Button ohne aktiven Chat) duerfen
       nicht durch display-Overrides wieder auftauchen. */
    .gameTopBar [hidden] { display: none !important; }

    .gbTools {
      flex: 0 0 auto;
      display: inline-flex;
      gap: 8px;
      margin-right: 4px;
      padding-right: 12px;
      border-right: 1px solid rgba(216, 177, 90, .18);
    }
    .gbChat { position: relative; }
    .gbChatBadge {
      position: absolute;
      top: -5px;
      right: -5px;
      min-width: 16px;
      height: 16px;
      padding: 0 4px;
      display: grid;
      place-items: center;
      border-radius: 999px;
      background: var(--mp-teal-1, #80e8df);
      color: #06231f;
      font-size: 9.5px;
      font-weight: 800;
      line-height: 1;
      border: 1px solid rgba(6, 35, 31, .5);
    }

    .gbReplay {
      flex: 0 0 auto;
      display: inline-flex;
      gap: 8px;
    }
    .gbNavBtn {
      width: 42px;
      height: 38px;
      display: grid;
      place-items: center;
      padding: 0;
      background: rgba(13, 18, 29, .66);
      border: 1px solid rgba(216, 177, 90, .30);
      color: var(--rift-gold-bright, #f0d283);
      cursor: pointer;
    }
    .gbNavBtn:hover,
    .gbNavBtn:focus-visible {
      border-color: rgba(240, 210, 131, .6);
      background: rgba(240, 210, 131, .10);
    }
    .gbNavBtn:active {
      border-color: rgba(77, 208, 196, .6);
      color: var(--mp-teal-1, #80e8df);
      transform: translateY(1px);
    }

    /* In-Game-Chat: das Unten-links-Panel weicht einem zentrierten Popup
       ueberm Brett; eingeklappt ist es KOMPLETT unsichtbar — der Zugang ist
       der Chat-Button der Leiste (mit Unread-Badge). Der box-shadow-Spread
       dimmt den Hintergrund wie ein Backdrop. */
    /* Zentrierung ohne transform — die gcRise-Animation endet auf
       transform:none und wuerde ein translate(-50%) aufheben. */
    body.mode-demo .gameChat {
      left: 0;
      right: 0;
      margin-inline: auto;
      top: calc(60px + env(safe-area-inset-top, 0px) + 4dvh);
      bottom: auto;
      width: min(430px, calc(100vw - 20px));
      max-width: none;
      max-height: min(66dvh, 520px);
      z-index: 350;
      box-shadow: 0 0 0 100vmax rgba(4, 6, 9, .58), 0 30px 70px rgba(0, 0, 0, .6);
    }
    body.mode-demo .gameChat.is-collapsed { display: none; }

    /* Akademie/Puzzle haben eigene Fluesse (Coach-Panel, Puzzle-HUD): dort nur
       „Zurück" zeigen — Replay wuerde mit Lektion/Loesen kollidieren. */
    body.tutorial-active .gbReplay,
    body.puzzle-active .gbReplay,
    body.tutorial-active .gbCrumb,
    body.puzzle-active .gbCrumb {
      display: none;
    }
  }

  /* Sehr schmale Phones: Krumen-Text weicht den Buttons (Diamant bleibt). */
  @media (max-width: 430px) {
    .gbCrumbText { display: none; }
  }

  /* Brett-Budget: fixe Leiste (48px) einrechnen, Raender knapp halten —
     das Brett soll den Viewport maximal ausnutzen. */
  @media (orientation: portrait) and (min-width: 701px) and (max-width: 1180px) {
    body.mode-demo {
      --board-size: min(calc(100vw - 40px), calc(100dvh - 456px), 880px);
    }
  }
  @media (orientation: landscape) and (min-width: 701px) and (max-width: 1180px) {
    body.mode-demo {
      --board-size: max(380px, calc(min(calc(100dvh - 146px), calc(100vw - 44px - var(--rail-size) * 2)) * .99));
    }
  }

  /* ---------- Home (Tablet + Handy): Hero kompakt, Queue-Box direkt darunter --
     Der Hero erzwang volle Viewport-Hoehe (min-height 100vh) — die Queue-
     Status-Box strandete darunter im Leerraum („zu weit unten"). Auf schmalen
     Screens endet der Hero nach seinem Inhalt und die Box folgt zentriert. */
  @media (max-width: 1100px) {
    .startHero {
      min-height: 0;
      padding: 36px 0 10px;
    }
    .queuePanel {
      width: min(100%, 440px);
      margin: 26px auto 10px;
    }
  }

  /* ---------- Hero-Titel (.duell-title) auf Tablet bremsen ----------
     Basis-Clamp startet bei 64px — „RANGLISTEN"/„COMMUNITY" liefen neben der
     280px-Nav aus dem Viewport. */
  @media (min-width: 701px) and (max-width: 1180px) {
    .duell-title {
      font-size: clamp(44px, 6.5vw, 84px);
      overflow-wrap: anywhere;
    }
  }

  /* ---------- Collection-Overlays vs. Navigation (Stacking-Context-Falle) ----
     .col-root und .collectionPage bilden mit position:relative + z-index:1
     eigene Stacking-Contexte — die fixed-Overlays darin (Deck-Builder,
     Rang-Picker, Entzaubern, Pack-Reveal) koennen die Nav (z 80) NIE
     ueberdecken, egal wie hoch ihr z-index ist. Statt die Kontexte zu
     entkernen (Ambient-Glow-Ordnung!), senken wir die Nav ab, solange ein
     Overlay offen ist — der Backdrop dimmt sie dann mit. */
  body:has(.db-builder-backdrop) header.sideNav,
  body:has(.builder-picker-backdrop) header.sideNav,
  body:has(.dwx-ov) header.sideNav,
  body:has(.po.on) header.sideNav,
  body:has(.db-builder-backdrop) .mobileNavFab,
  body:has(.builder-picker-backdrop) .mobileNavFab,
  body:has(.dwx-ov) .mobileNavFab,
  body:has(.po.on) .mobileNavFab {
    z-index: 0;
  }

  /* Collection: die Sections sind Grid-Items von .col-root — mit min-width:auto
     kann die Fraktions-Leiste (.faction-rail, overflow-x:auto) nie schmaler
     werden als die Summe ihrer Tabs (~888px) und blaeht Phone UND Tablet auf. */
  .col-root > .section { min-width: 0; }

  /* ---------- Ranked: fehlte in der Zweispalten-Grid-Liste (main-02) ----------
     body.mode-ranked behielt das Desktop-3-Spalten-Grid (min 1240px) und lief
     auf Tablets rechts aus dem Viewport. */
  body.mode-ranked {
    grid-template-columns: var(--side-nav-width) minmax(0, 1fr);
  }

  /* ---------- Play: Matchup-Box (Dein Deck / VS / Gegner) auf Tablet stapeln --
     wie in der Handy-Ansicht (main-11 stapelt erst ab 900px). */
  @media (min-width: 901px) and (max-width: 1280px) {
    .duell .matchup { grid-template-columns: 1fr; gap: 22px; }
    .duell .matchup-vs { flex-direction: row; padding: 4px 0; }
    .duell .matchup-vs .vs-line {
      height: 1px;
      width: 100%;
      background: linear-gradient(90deg, transparent, rgba(216, 177, 90, 0.3), transparent);
    }
    .duell .vs-medallion { margin: 0 16px; }
  }

  /* ---------- Effektleisten-Puls (Tablet/Phone) ----------
     Nur der GRUPPEN-Puls (skalierte bis 1.18 und liess die Leiste sichtbar
     wandern) laeuft ohne Scale. Der Chip-Puls (tabletEffectChipReadyPulse,
     main-07) behaelt sein Atmen (scale .98-1.06) — seit die Rail keinen
     eigenen Kasten mehr hat, verschiebt sich dabei nichts mehr. */
  @keyframes tabletEffectGroupPulse {
    0%, 100% { opacity: .72; transform: none; }
    50%      { opacity: 1; transform: none; }
  }

  /* ---------- Effektleiste: Trenner-Kanten im Chip-Streifen entfernen ----------
     Die vertikalen border-left-Linien (zwischen Effekt-Gruppen + vor dem
     Friedhofs-Zaehler) standen als sichtbare Kante rechts neben den Chips. */
  @media (orientation: portrait) and (max-width: 1180px) {
    body.mode-demo .effectGroups .effectGroup + .effectGroup {
      border-left: 0 !important;
      padding-left: 6px;
    }
    body.mode-demo .effectRail > .effectGroup-graveyard {
      border-left: 0;
      padding-left: 6px;
    }
    /* Der aeltere <=820-Block deckelt die Rail auf 116px — die zweizeilige
       Chip-Rail (Header + Chips) braucht mehr, sonst ragen die Chips aus der
       Box heraus. Ausserdem: kein eigener Kasten (Border + dunkler Fond
       endeten als sichtbare Glow-Kante links/rechts) — Spieler-Karte und
       Chips schweben frei, wie der restliche panel-lose Look. */
    body.mode-demo .effectRail {
      max-height: none;
      overflow-x: hidden;
      overflow-y: visible;
      border: 0;
      background: transparent;
      box-shadow: none;
    }
    /* Chips MITTIG und OHNE Scroller (main-07 setzte justify-self:end +
       overflow-x:auto — rechtsbuendig, Glows rechteckig abgeschnitten).
       Ohne Scroller gibt es kein Clipping; bei vielen Chips bricht die
       Zeile um (Rail waechst, max-height ist offen). */
    body.mode-demo .effectRail { justify-content: center; }
    body.mode-demo .effectGroups,
    body.mode-demo .effectRail.left .effectGroups,
    body.mode-demo .effectRail.right .effectGroups {
      height: auto;
      max-height: none;
      width: auto;
      max-width: none;
      justify-self: center;
      justify-content: center;
      flex-wrap: wrap;
      overflow: visible;
      padding: 2px 0;
      margin: 0;
    }
  }

  /* ---------- Animierte Live-Figurenkarte: auf Handy UND Tablet ausblenden ----
     (Spiel-Rail .lcxDock, Puzzle #puzzleLiveCard, Akademie #tutorialLiveCard).
     Details gibt es weiterhin ueber das Figuren-Popup. 1366px deckt auch das
     iPad Pro im Querformat ab. */
  @media (max-width: 1366px) {
    body.mode-demo .lcxDock,
    #puzzleLiveCard,
    #tutorialLiveCard {
      display: none !important;
    }
  }

  /* ---------- Icon-Rail (kollabierte Nav, alle Breiten >700px) ----------
     Footer-Texte passen nicht in die 68px-Rail und ragten abgeschnitten ins
     Brett (Tablet-Portrait): alles Textliche ausblenden, Knoepfe zentrieren. */
  body.side-nav-collapsed .sideLegal,
  body.side-nav-collapsed .sideCodexText,
  body.side-nav-collapsed .sideSupportText,
  body.side-nav-collapsed .sideMembershipText,
  body.side-nav-collapsed .sideMembershipTag,
  body.side-nav-collapsed .sideStatusMeta,
  body.side-nav-collapsed .sideResumeArrow {
    display: none !important;
  }
  body.side-nav-collapsed .sideFooter {
    width: 100%;
    padding: 0;
    justify-items: center;
  }
  body.side-nav-collapsed .sideSupport,
  body.side-nav-collapsed .sideCodex,
  body.side-nav-collapsed .sideStatus {
    width: 38px;
    min-height: 38px;
    display: grid;
    place-items: center;
    padding: 0;
  }
  body.side-nav-collapsed .sideUtilityRow {
    flex-direction: column;
    align-items: center;
    gap: 6px;
  }
