/* ==========================================================================
   The panel inside a Telegram Mini App.

   Scoped entirely to html.in-telegram, which partner-tgauth.js sets only when
   Telegram actually handed the page an initData. Nothing here can reach the
   panel in a normal browser.

   Three things are different inside Telegram and none of them are "a narrow
   screen", which the panel already handles well:

   1. 100vh is a lie. The client draws its own header and the sheet can be
      half-height, so the usable area is Telegram's viewport height — and it
      changes as the user drags the sheet. Every fixed 100vh calculation
      overflows or leaves dead space.
   2. There is no browser chrome to anchor against, so elements positioned
      against the top of the window sit under Telegram's header instead.
   3. It is reached by thumb on a short screen, so anything that was merely
      tight on a phone becomes unusable.
   ========================================================================== */

html.in-telegram,
html.in-telegram body {
  /* --tg-vh is written by partner-tgauth.js from viewportStableHeight and
     updated on every viewportChanged, because the CSS variable Telegram
     provides is not present on older clients. */
  height: var(--tg-vh, 100vh);
  min-height: 0;
  overflow: hidden;
}

html.in-telegram #app {
  min-height: 0;
  height: var(--tg-vh, 100vh);
}

html.in-telegram .main-wrapper {
  min-height: 0;
  height: 100%;
  display: flex;
  flex-direction: column;
}

/* The one scrolling surface. With the shell fixed to the viewport, this is what
   moves — which is also what stops Telegram interpreting a content scroll as a
   drag on the sheet and closing the app. */
html.in-telegram .content-pane {
  flex: 1 1 auto;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  padding: 12px 10px calc(16px + env(safe-area-inset-bottom, 0px));
}

/* Telegram draws the title; a second sticky bar underneath wastes a fifth of a
   short screen. */
html.in-telegram .top-bar {
  position: static;
  min-height: 46px;
  padding: 0 10px;
}

/* ------------------------------------------------------------------
   Horizontal strips: draggable, and visibly so.

   These rules are NOT scoped to Telegram — a mouse cannot drag-scroll an
   overflow container in any browser, and hiding the scrollbars removed the only
   clue that a strip had more in it. partner-hscroll.js adds the drag and the
   wheel handling; this is the part you can see.
   ------------------------------------------------------------------ */

/* ------------------------------------------------------------------
   THE DRAWER MUST END WHERE THE SCREEN ENDS

   .sidebar is `position: fixed; inset: 0 auto 0 0` (partner.css:143-144), which
   resolves against the initial containing block -- 100vh. Inside a Mini App the
   visible sheet is --tg-vh, and 100vh is taller than it. .sidebar-menu is flex:1,
   so .sidebar-footer is pinned to the bottom of that too-tall box: the theme
   toggle, the balance and Log out all sit in the band below the sheet.

   Scrolling could never reach them -- the scrollport is the same 100vh box, so
   scrolling to the end still parks the footer's bottom edge at 100vh. This is
   why the theme button reads as broken: it is not hidden, it is off-screen.

   This file rebases every other fixed full-height box onto --tg-vh; the drawer
   is the one it missed.
   ------------------------------------------------------------------ */
html.in-telegram .sidebar {
  height: var(--tg-vh, 100vh);
  bottom: auto;
}

/* ------------------------------------------------------------------
   SCROLLING THE FUNNEL MUST NOT REORDER IT

   .pm-gate-row carries `touch-action: none` (partner.css:4130) and the drag is
   armed from anywhere in the row (partner.js:12968 closest('.pm-gate-row'),
   exempting only input/select/label/button/a/option). The rows are the tallest
   thing on the Withdrawal-errors tab, so a thumb swiping to read further down
   lands on one, the browser is told not to scroll, and 4px of travel
   (PM_GATE_MOVE_PX) lifts the row instead. On release the refusal ORDER has been
   changed and marked unsaved -- a silent edit to which error players hit first,
   caused by trying to scroll.

   Effective touch-action is the intersection of the element and its ancestors,
   so claiming the gesture on the grip alone keeps dragging by its handle while
   the row body scrolls again. A pan begun on the body now fires pointercancel,
   which partner.js already routes to pmGateEndDrag, and that returns early when
   no drag is active. Not scoped to Telegram: a touchscreen anywhere has this.
   ------------------------------------------------------------------ */
.pm-gate-row { touch-action: pan-y; }
.pm-gate-grip {
  touch-action: none;
  /* A bigger target for the one gesture that still belongs to it. */
  padding: 8px 6px;
  margin: -8px -6px;
}

@media (max-width: 768px) {
  /* "Player sees: <value> - your choice" is three flex items on one line with no
     wrap (partner.css:5084). In ~148px they all shrink to min-content: the label
     breaks across two lines and the value pill becomes a vertical stack of single
     words. It is the line that says what the player will actually read. */
  .pm-gate-sees { flex-wrap: wrap; }
}

/* ------------------------------------------------------------------
   CHAT: ONE PANE AT A TIME

   The chat is a thread list beside a conversation. That is a desktop shape, and
   at 390px both panes share the width, which is why neither was usable.

   The panel already carries rules for a `chat-viewing` class meant to do exactly
   this -- but nothing ever sets it: `grep -n chat-viewing js/partner.js` returns
   nothing, so those rules have always been dead. What IS set is `active` on the
   selected thread (partner.js, chat-thread-item${isSelected ? ' active' : ''}),
   and the back arrow clears it again. So that is the hook: list until a
   conversation is picked, conversation after, back arrow returns.
   ------------------------------------------------------------------ */
@media (max-width: 768px) {
  /* The conversation header measured 269px of a 586px chat -- nearly half the
     panel before a single message. 124px of that was the action row alone,
     because .pm-dd (the dressed <select>) is block-level and computed to the
     full 344px, so each of the two dropdowns claimed its own line and five
     compact controls became four stacked rows. Let them size to content and
     they share two lines. */
  .chat-header-actions .pm-dd {
    width: auto !important;
    flex: 0 1 auto !important;
    max-width: 48%;
    /* The agent picker starts with no label, so `width: auto` collapsed it to
       about 50px -- and pmDdOpenList copies the button's width straight onto the
       list (`list.style.width = r.width + 'px'`), so the open menu came out 50px
       wide with every name clipped to two letters. */
    min-width: 92px !important;
  }

  /* Belt and braces: whatever width the button reports, the menu stays readable.
     min-width beats the inline width the script writes. */
  .pm-dd-list {
    min-width: 180px !important;
    max-width: calc(100vw - 20px) !important;
  }
  .chat-header-actions .pm-dd-btn,
  .chat-header-actions .chat-header-btn {
    min-height: 26px;
    font-size: 11px;
    padding: 3px 8px;
  }

  /* The rest of the header, tightened so the messages get the room back. */
  .chat-main-header { padding: 8px 10px !important; gap: 8px !important; }
  .chat-header-avatar { width: 32px !important; height: 32px !important; flex: 0 0 32px !important; }
  .chat-header-name { font-size: 13px !important; }
  .chat-header-sub { font-size: 10.5px !important; }
  .chat-user-context { gap: 4px !important; padding: 4px 10px !important; }
  .chat-ctx-pill { font-size: 10px !important; padding: 2px 7px !important; }

  /* The sound-settings bell is position:fixed at bottom:64px right:12px, and the
     composer's send button lands at exactly the same corner -- measured, the two
     boxes overlap outright, so tapping send hit the bell. Lifted clear, and only
     while a conversation is open, so it stays where it belongs everywhere else. */
  body:has(.chat-thread-item.active) #pm-sound-bell { bottom: 132px; }

  /* Message text was 14px against a 14px root -- the largest thing on the screen
     after the player's name. */
  .chat-bubble { font-size: 12.5px !important; line-height: 1.4 !important; padding: 7px 10px !important; }
  .chat-bubble-time { font-size: 9.5px !important; }
  .chat-date-sep { font-size: 10px !important; margin: 6px 0 !important; }
  .chat-msg-avatar { width: 26px !important; height: 26px !important; flex: 0 0 26px !important; font-size: 11px !important; }
  .chat-msg-row { gap: 6px !important; margin-bottom: 6px !important; }
  .chat-input-field { font-size: 16px !important; }  /* 16 or iOS zooms the page */

  /* Messages must be the part that grows, and the part that scrolls. */
  .chat-main-header { flex: 0 0 auto; }
  .chat-messages-area { flex: 1 1 auto !important; min-height: 0 !important; overflow-y: auto !important; }

  /* The conversation list could not be scrolled at all.

     An earlier pass wrote `:not(.chat-viewing) .chat-thread-list { max-height:
     none !important }` to let the list run full height in list mode. But nothing
     ever sets `chat-viewing` -- it is the same dead class the single-column rules
     had to work around -- so `:not(.chat-viewing)` is permanently true and the
     list has been unbounded ever since. An unbounded list does not scroll: it
     just grows past the bottom of the screen and gets clipped.

     Bound it to the shell instead and let the list itself be the scroller. */
  .chat-shell .chat-sidebar {
    height: 100% !important;
    max-height: 100% !important;
    min-height: 0 !important;
    display: flex !important;
    flex-direction: column !important;
  }
  .chat-thread-list {
    flex: 1 1 auto !important;
    min-height: 0 !important;
    max-height: none !important;
    overflow-y: auto !important;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
  }

  /* In list mode the toolbar above the shell is on screen, and the shell's own
     height already claims nearly the whole pane -- together they overflowed and
     took the bottom of the list with them. Compact the toolbar to one short row
     and give the shell back exactly that much. */
  .chat-global-toolbar {
    gap: 8px !important;
    padding: 8px 10px !important;
    margin-bottom: 8px !important;
  }
  .chat-filter { gap: 4px !important; flex: 1 1 auto; min-width: 0; }
  .chat-filter > span { font-size: 9px !important; }
  .chat-filter select {
    padding: 4px 22px 4px 8px !important;
    font-size: 11px !important;
    min-height: 30px !important;
  }
  .chat-global-summary { font-size: 10px !important; }
  /* The shell's height was a fixed calc that had to guess how much chrome sat
     above it. Every guess has been wrong -- 132px assumed a toolbar that measures
     99px in list mode and 0 in conversation mode -- so it either overflowed the
     screen or left a gap. Stop guessing: make the containers between the scroller
     and the shell a flex column, and let the shell take exactly what is left.
     Self-correcting, whatever the toolbar ends up being. */
  /* Naming the containers by id was wrong: the chat is reachable from two routes
     with different chains -- Team > Player chats goes through #team-shell and
     #team-chat-slot, the standalone Chat page through #tab-chat and
     #tab-chat-slot. The id list only covered the first, so on the Chat page two
     links stayed display:block, the chain broke, and the shell fell back to its
     own height: 468px inside a 650px pane, with 182px of dead space under it.

     Select the chain by what it IS instead -- every element between the scroller
     and the shell is, by definition, an element that contains the shell. Works
     for both routes and for any third one added later. */
  .content-pane:has(.chat-global-shell),
  .content-pane:has(.chat-global-shell) *:has(.chat-global-shell) {
    display: flex !important;
    flex-direction: column !important;
    min-height: 0 !important;
  }
  .content-pane:has(.chat-global-shell) *:has(.chat-global-shell) {
    flex: 1 1 auto !important;
  }

  /* TAB_PANE_LEAK: the chain above must never resurrect a page the router has hidden.
     `*:has(.chat-global-shell)` matches every ancestor of the shell — including its own
     `section.tab-pane` — and `display: flex !important` beats `.tab-pane { display: none }`
     in partner.css. The pane holding the chat therefore stayed on screen on every route, so the
     conversation list appeared under Home and My Sites, and its Domain filter sat on top of the
     "Back to Players" button on the player page. The mount moves between #tab-chat and
     #team-chat-slot, so the leak moved with it.

     Restated positively: a pane that is not the current route is hidden, whatever the chain says.
     Specificity here is (0,4,0) against the chain's (0,3,0), so this holds regardless of order —
     it does not depend on staying below the rule it corrects. The active pane is untouched, so the
     flex column that lets the shell size itself still works exactly as before. */
  .content-pane:has(.chat-global-shell) .tab-pane:not(.active) {
    display: none !important;
  }
  #global-chat-mount .chat-global-shell {
    height: auto !important;
    flex: 1 1 auto !important;
    min-height: 0 !important;
  }
  /* The toolbar keeps its own size instead of being stretched by the column. */
  #global-chat-mount .chat-global-toolbar { flex: 0 0 auto !important; }

  .chat-shell:has(.chat-thread-item.active) .chat-sidebar { display: none !important; }
  .chat-shell:not(:has(.chat-thread-item.active)) .chat-main { display: none !important; }
  .chat-shell .chat-sidebar,
  .chat-shell .chat-main {
    flex: 1 1 100% !important;
    min-width: 0 !important;
    max-width: none !important;
    width: 100% !important;
  }

  /* The toolbar above the shell measures 148px on a phone -- the shell's height
     is calc(--tg-vh - 132px), an offset that assumed a much shorter one, so the
     two together ran 107px past the bottom of the screen and took the composer
     with them. Out of the way entirely once a conversation is open. */
  #global-chat-mount:has(.chat-thread-item.active) .chat-global-toolbar { display: none; }
}

/* ------------------------------------------------------------------
   NUMBER INPUTS: no spinner, anywhere.

   The little up/down stepper appears on hover over every fee and multiplier
   field, overlaps the value, and on a touch screen it is a target nobody can
   hit anyway. Not scoped to phones -- it is unwanted on the desktop too.
   ------------------------------------------------------------------ */
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  appearance: none;
  margin: 0;
}
input[type="number"] {
  -moz-appearance: textfield;
  appearance: textfield;
}

/* ------------------------------------------------------------------
   DENSITY: fit more on the screen.

   Everything was sized for a desktop and then given a 44px touch floor, so a
   Mini App sheet showed about four controls at a time and everything else was a
   scroll away. Dropping the rem base shrinks every rem-based size at once --
   type, padding, gaps -- without touching a single component rule.
   ------------------------------------------------------------------ */
@media (max-width: 768px) {
  html.in-telegram { font-size: 14px; }

  /* 44 was the accessibility floor; 38 is still comfortably tappable and buys
     back six pixels on every control in a column of them. */
  .btn, button, .field-input, select { min-height: 38px; }

  /* A toggle draws itself 38x22 with an 11px radius -- a pill. The touch floor
     above stretched it to 38x44 and the radius stayed, which is the red square
     with the knob stuck at the top. Sized up in proportion instead, so it stays
     a pill and is still easy to hit. */
  /* Doubled selectors on purpose. partner-sounds.js injects its stylesheet into
     the document at runtime, so it lands AFTER this file and wins every tie at
     equal specificity -- measured: height took (min-height beats height whatever
     the order) but width stayed at the module's 38px, leaving the toggle a
     rounded square. Two classes outrank one, without reaching for !important. */
  .pm-snd-toggle.pm-snd-toggle {
    width: 52px; height: 30px; min-height: 30px; border-radius: 15px;
  }
  .pm-snd-toggle.pm-snd-toggle::after { width: 24px; height: 24px; top: 2px; left: 2px; }
  .pm-snd-toggle.pm-snd-toggle.on::after { transform: translateX(22px); }

  /* Same shape of bug, same fix: these draw their own size and must keep it. */
  .pm-kyc-switch { min-height: 26px; }
  input[type="checkbox"], input[type="radio"] { min-height: 0; }

  /* --- Chat --- */

  /* Six controls that are all needed at once. Wrapping shows them all; the
     horizontal scroll they had hid half of them behind a gesture. */
  html.in-telegram .chat-header-actions {
    flex-wrap: wrap;
    overflow-x: visible;
    gap: 4px;
  }
  .chat-header-btn {
    font-size: 11px;
    padding: 4px 8px;
    min-height: 28px;
  }
  .chat-header-actions .pm-dd-btn { min-height: 28px; font-size: 11px; padding: 4px 8px; }

  /* The composer: five things on one line in ~340px. */
  html.in-telegram .chat-input-bar { padding: 6px 8px; gap: 4px; }
  .chat-input-field { min-height: 34px; font-size: 16px; }
  .chat-send-btn { width: 34px; height: 34px; min-height: 34px; flex: 0 0 34px; }

  /* The custom dropdown list opened nearly full-screen over the conversation. */
  .pm-dd-list { max-height: min(260px, calc(var(--tg-vh, 100vh) - 160px)); }
  .pm-dd-opt { min-height: 34px; padding: 7px 10px; font-size: 12px; }
}

/* ------------------------------------------------------------------
   EVERY CONTROL ROW WRAPS ON A PHONE

   77 rows in index.html are written as `display:flex` with no flex-wrap, most of
   them a label on the left and a control pushed right with space-between. At
   360px they cannot resolve, so the label is crushed and the control is jammed
   against the edge -- what the operator kept reporting as "buttons pulled left"
   on Setup, Terms, Luck and the player card. Fixing them one by one would mean
   77 selectors that drift the moment the markup is touched.

   They carry no classes, so the style attribute itself is the only handle. Both
   spellings appear in the markup, hence both selectors. Excluded: anything that
   already states its own flex-wrap (it made a deliberate choice), and columns
   (they stack already).

   Wrapping is a no-op whenever the content already fits, so this only takes
   effect where the row was overflowing anyway.
   ------------------------------------------------------------------ */
@media (max-width: 768px) {
  .content-pane [style*="display:flex"]:not([style*="flex-wrap"]):not([style*="column"]),
  .content-pane [style*="display: flex"]:not([style*="flex-wrap"]):not([style*="column"]) {
    flex-wrap: wrap;
  }

  /* The strips are the exception: they are meant to run off the edge and be
     dragged, and a wrapped strip never overflows, which silently disables
     partner-hscroll.js entirely. */
  .content-pane .pm-ud-tab-rail,
  .content-pane .pm-tab-rail,
  .content-pane .site-hub-nav,
  .content-pane #pm-users-activity > div,
  .content-pane .pm-cs-scroll,
  .content-pane .team-chat-roster-list { flex-wrap: nowrap !important; }

  /* A round avatar is a flex item with a width and a height. Shrinking takes the
     width but never the height, so a 48px circle becomes a tall ellipse. The
     player card had this and so does the team card. */
  #pm-ud-avatar-initial,
  #tm-avatar-initial,
  .avatar-circle { flex: 0 0 auto; }
}

/* ------------------------------------------------------------------
   PHONE FIXES: the theme switch, the Luck dialog, the error-copy editor.

   Two of these live in stylesheets that JS injects at runtime
   (partner-rigging.js writes <style id="pm-rigging-style">), which lands after
   this file in the cascade. Same specificity would lose, so the selectors below
   are doubled to outrank them without reaching for !important.
   ------------------------------------------------------------------ */
@media (max-width: 768px) {

  /* The theme toggle is a 28x28 circle, but the phone block sets
     `.btn, button { min-height: 44px }` and min-height beats height. The circle
     was being drawn 28 wide by 44 tall -- an ellipse, the same failure as the
     avatar. Squaring it up keeps it round AND gives a real touch target. */
  #theme-toggle-btn { width: 44px; height: 44px; min-height: 44px; }

  /* --- Luck (partner-rigging.js) --- */

  /* 100vh is the wrong height inside Telegram: the client draws its own header
     and the sheet can sit at half height, so the CSS viewport is taller than
     anything visible and the dialog's footer -- Save and Cancel -- sat below the
     fold with no way to reach them. --tg-vh is the real height, published by
     partner-tgauth.js; the 100vh fallback keeps a plain phone browser working. */
  .pm-rigging-modal.pm-rigging-modal {
    max-height: calc(var(--tg-vh, 100vh) - 24px);
    width: calc(100vw - 16px);
  }

  /* Title and its action buttons shared one non-wrapping row, so the buttons
     were squeezed against the right edge. */
  .pm-rigging-head.pm-rigging-head { flex-wrap: wrap; }
  .pm-rigging-head-actions.pm-rigging-head-actions { margin-left: 0; width: 100%; }

  /* `1fr 220px`: with ~320px of content width the label column was left about
     100px. One column per line instead. */
  .pm-rigging-row.pm-rigging-row { grid-template-columns: 1fr; }

  /* `90px 1fr 80px 80px` is 250px of fixed columns before any gap, so the
     flexible middle got ~40px and every log line was unreadable. */
  .pm-rigging-log-row.pm-rigging-log-row { grid-template-columns: auto 1fr; }

  .pm-rigging-foot.pm-rigging-foot { flex-wrap: wrap; }
  .pm-rigging-foot .pm-rigging-status { flex: 1 1 100%; }

  /* --- Luck (the rigging screen) ---

     Mounted by partner-rigging.js, which carries its whole stylesheet in one
     injected <style>. Nothing here had ever touched it, and its layout is built
     from grids with hard second columns:

       .pm-rigging-row      grid-template-columns: 1fr 220px
       .pm-rigging-log-row  grid-template-columns: 90px 1fr 80px 80px

     On a ~316px card the 220px column leaves the label about 80px, and the log
     row commits 250px to fixed columns so its 1fr gets ~50px. That is the screen
     the operator described as everything pushed to the left.

     !important throughout: that stylesheet is injected at runtime and would
     otherwise win every tie against this file. */
  .pm-rigging-row {
    grid-template-columns: 1fr !important;
    gap: 8px !important;
    padding: 10px 0 !important;
  }
  .pm-rigging-log-row {
    grid-template-columns: 1fr 1fr !important;
    row-gap: 2px !important;
  }
  .pm-rigging-head,
  .pm-rigging-head-actions,
  .pm-rigging-warn,
  .pm-rigging-foot {
    flex-wrap: wrap !important;
  }
  .pm-rigging-head-actions { margin-left: 0 !important; }
  .pm-rigging-modal {
    width: 100% !important;
    max-width: none !important;
    max-height: calc(var(--tg-vh, 100vh) - 24px) !important;
    overflow-y: auto !important;
  }

  /* --- Withdrawal-error copy editor --- */

  /* .pm-look-row is display:flex with no wrap. .pm-look-key takes an
     unshrinkable 62px, leaving the dropdown and the caption field to split what
     is left -- about 107px and 71px. The caption field is where a 40-character
     button label is typed, at a forced 16px font: roughly four characters
     visible. This is the row the operator kept calling squashed. */
  .pm-look-row { flex-wrap: wrap; }
  .pm-look-row .pm-dd,
  .pm-look-row .pm-wderr-actionlabel { flex: 1 1 100%; }
}

/* ------------------------------------------------------------------
   PLAYER DETAIL HEADER  (index.html, section#tab-player-detail)

   The whole row is written as inline styles: `display:flex; gap:16px` with no
   flex-wrap, a 48x48 avatar with no flex-shrink, a bare wrapper around the name
   and id, and a button pinned right with margin-left:auto.

   On a ~316px card that cannot resolve. The button is .btn, so white-space:nowrap
   makes its min-content its whole label -- about 190px, 60% of the row. The id is
   monospace with no break opportunity, so the wrapper's min-content is the longest
   unbroken run of it. Everything the row cannot take out of those two it takes out
   of the avatar, which shrinks horizontally but not vertically: a 48px circle
   rendered about 15px wide is the ellipse the operator called a distorted avatar,
   and the crushed name beside it is the block they called thrown about.
   ------------------------------------------------------------------ */
@media (max-width: 768px) {
  #tab-player-detail > .glass-panel > div:first-child { flex-wrap: wrap; }

  /* Never a shrink target. This is the same flex-shrink:0 the players-list
     avatar already carries; the detail header simply never got it. */
  #pm-ud-avatar-initial { flex: 0 0 48px; }

  /* min-width:auto is what let the id inflate the row's floor. Zero it and let
     the id break, and the identity block stops fighting the avatar. */
  #pm-ud-title { min-width: 0; overflow-wrap: anywhere; }
  #pm-ud-userid { overflow-wrap: anywhere; }

  /* Its own full-width line instead of 60% of the first one. margin-left:auto is
     inline, hence the !important. */
  #pm-ud-open-site {
    margin-left: 0 !important;
    flex: 1 1 100%;
    white-space: normal;
    justify-content: center;
  }
}

/* The player-detail rail carries `flex-wrap: wrap` as an INLINE style
   (index.html, the .pm-ud-tab-rail div), which beats the `flex-wrap: nowrap`
   in partner.css's phone block because that one has no !important. So the rail
   wrapped into four 44px rows -- ~220px of tabs above every tab body -- and,
   because a wrapped strip never overflows, `scrollWidth > clientWidth` was
   always false: partner-hscroll.js's drag, the wheel handling and the fade were
   all installed and all inert. Beating the inline style is what switches the
   whole strip mechanism on; everything else it needs is already here. */
@media (max-width: 768px) {
  .pm-ud-tab-rail { flex-wrap: nowrap !important; }
}

.pm-tab-rail,
.site-hub-nav,
.pm-ud-tab-rail,
#pm-users-activity > div,
.chat-header-actions {
  /* The gesture belongs to the strip. Without this a sideways swipe inside a
     Telegram sheet is taken by the client as a drag on the sheet itself. */
  touch-action: pan-x;
  position: relative;
}

/* A fade where the content keeps going, toggled from JS as the strip scrolls. */
.hscroll-more {
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 26px), transparent 100%);
  mask-image: linear-gradient(to right, #000 calc(100% - 26px), transparent 100%);
}
.hscroll-more.hscroll-start {
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 22px, #000 calc(100% - 26px), transparent 100%);
  mask-image: linear-gradient(to right, transparent 0, #000 22px, #000 calc(100% - 26px), transparent 100%);
}
.hscroll-start:not(.hscroll-more) {
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 22px);
  mask-image: linear-gradient(to right, transparent 0, #000 22px);
}

/* Nothing may stick.
 *
 * .pm-tab-rail carries `position: sticky; top: 90px` as an INLINE style in
 * index.html — 90px is the height of the sticky top bar it was meant to sit
 * below. Two things here break that: the top bar is no longer sticky, and
 * .content-pane is now the scrolling container, so `sticky` resolves against it
 * instead of the page. The rail ends up parked over the middle of the content,
 * which is the overlap that appears while scrolling the Players screen.
 *
 * !important because it is fighting an inline style; a media query cannot. */
html.in-telegram .pm-tab-rail,
html.in-telegram .site-hub-nav,
html.in-telegram .pm-cs-table thead th {
  position: static !important;
  top: auto !important;
}

/* The notification dropdown is a fixed-width panel anchored to the bell; at
   420px it runs off the right edge. Make it a full-width sheet instead, and
   bound it to the Telegram viewport so its own list scrolls rather than the
   page growing behind it. */
html.in-telegram #pm-notification-dropdown {
  position: fixed !important;
  left: 8px !important;
  right: 8px !important;
  top: 56px !important;
  width: auto !important;
  max-width: none !important;
  max-height: calc(var(--tg-vh, 100vh) - 76px) !important;
  overflow-y: auto;
}

/* ------------------------------------------------------------------
   Chat: one screen at a time.

   The chat is a desktop two-pane layout — a 300px list beside the conversation.
   The phone layer stacks them, so both are on screen together: a squashed list
   above a conversation that starts below the fold. Opening a thread looks like
   it did nothing, because the messages are down past a list you have to scroll
   through every time.

   partner-mobilechat.js decides which pane is showing, from the panel's own
   state — a thread is open when the "choose a conversation" placeholder is gone.
   These rules are what that decision looks like. Not scoped to Telegram: a phone
   browser has exactly the same two panes in the same 420px.
   ------------------------------------------------------------------ */

@media (max-width: 768px) {
  .chat-shell.chat-viewing .chat-sidebar { display: none !important; }
  .chat-shell:not(.chat-viewing) .chat-main { display: none !important; }
  .chat-shell:not(.chat-viewing) .chat-sidebar {
    max-height: none !important;
    border-bottom: none !important;
  }
  .chat-shell:not(.chat-viewing) .chat-thread-list { max-height: none !important; }
}

html.in-telegram .chat-shell.chat-viewing .chat-sidebar { display: none !important; }
html.in-telegram .chat-shell:not(.chat-viewing) .chat-main { display: none !important; }
html.in-telegram .chat-shell:not(.chat-viewing) .chat-sidebar {
  max-height: none !important;
  border-bottom: none !important;
}
html.in-telegram .chat-shell:not(.chat-viewing) .chat-thread-list { max-height: none !important; }

/* The way back. Only drawn on the narrow layout, where it is the only exit. */
.chat-back-btn {
  display: none;
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  margin-right: 8px;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  border-radius: 9px;
  background: var(--bg-card);
  color: var(--text);
  cursor: pointer;
}
.chat-back-btn:active { background: var(--bg-muted); }

@media (max-width: 768px) {
  .chat-shell.chat-viewing .chat-back-btn { display: inline-flex; }
}
html.in-telegram .chat-shell.chat-viewing .chat-back-btn { display: inline-flex; }

/* Every height computed against the window has to be re-based, or the chat and
   the tables run off the bottom of the sheet. The min-heights are the worse
   half: 520px of forced chat in a ~600px viewport leaves nothing for the
   composer.
 *
 * The chat gets a real height rather than `auto`. An earlier version of this
 * file used `height: auto; min-height: 0`, which looked right and broke the
 * conversation: with no fixed height the shell is no longer the scroll
 * container, so `container.scrollTop = container.scrollHeight` does nothing and
 * a new message lands below the fold with the composer pushed off-screen. */
/* Only the OUTER shell gets a height. Giving the inner .chat-shell the same
   absolute height made it as tall as its own parent, so it overflowed the box
   it lives in and took the composer off the bottom of the screen with it —
   which is why there was no way to type a reply. The panel already says
   `.chat-global-shell .chat-shell { height: 100% }`; that is the right rule and
   it only needed the outer height to be real. */
html.in-telegram .chat-global-shell {
  height: calc(var(--tg-vh, 100vh) - 132px) !important;
  min-height: 0 !important;
  max-height: none !important;
  display: flex;
  flex-direction: column;
}
html.in-telegram .chat-global-shell .chat-shell {
  height: 100% !important;
  min-height: 0 !important;
  max-height: none !important;
}
html.in-telegram .chat-shell { display: flex; flex-direction: column; min-height: 0; }
html.in-telegram .chat-main { flex: 1 1 auto; min-height: 0 !important; display: flex; flex-direction: column; }
html.in-telegram .chat-messages-area { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
/* The composer must never be the thing that gets squeezed out. */
html.in-telegram .chat-input-bar { flex: 0 0 auto; }

html.in-telegram .chat-messages,
html.in-telegram .chat-thread-list,
html.in-telegram .pm-ud-table-scroll,
html.in-telegram .table-container {
  max-height: none !important;
}

/* The AI help assistant is gone on small screens.
 *
 * It starts at top:152px on the right, which on a narrow sheet lands on the
 * first row of whatever table is showing — it was sitting on top of a player's
 * name. Moving it only relocated the problem: a floating circle over a 420px
 * screen covers content wherever it is parked, and the panel it opens is a
 * second dialog competing with an already short viewport.
 *
 * display:none rather than any JS change, so the toggle code keeps working and
 * nothing has to be kept in step; !important because that code writes inline
 * display when opening the panel.
 *
 * Both the Mini App and phones — the rule below the media query covers the
 * browser-on-a-phone case, which has exactly the same problem. */
html.in-telegram #ai-help-fab,
html.in-telegram #ai-help-panel {
  display: none !important;
}

@media (max-width: 768px) {
  #ai-help-fab,
  #ai-help-panel {
    display: none !important;
  }
}

/* Same reasoning for the notification bell, which overlapped the same row. */
html.in-telegram #pm-notification-wrapper {
  position: static;
}

/* Toasts belong above the thumb, not under it. */
html.in-telegram #pm-toast-container {
  bottom: calc(64px + env(safe-area-inset-bottom, 0px)) !important;
  right: 10px !important;
  left: 10px !important;
  max-width: none !important;
}

/* The sound bell sits bottom-right where Telegram puts its own controls.
   !important only here: partner-sounds.js injects its own stylesheet at runtime
   and re-creates this button, so the relative order of the two sheets is not
   something this file can depend on. Everywhere else plain specificity is
   enough and is left alone. */
html.in-telegram .pm-snd-btn {
  bottom: calc(64px + env(safe-area-inset-bottom, 0px)) !important;
  right: 12px !important;
  width: 38px !important;
  height: 38px !important;
}

/* The Players activity bar.
 *
 * #pm-users-activity is the real id — the earlier attempt here guessed at class
 * names like .pm-filter-chips that exist nowhere, so it styled nothing while
 * looking plausible. This bar is built in JS and inserted with insertBefore
 * ahead of the .glass-panel it belongs to, which is why the chips sit flush
 * against the screen edge while the search box above them is inset: they are
 * outside the card and inherit none of its padding.
 *
 * Its inner container carries inline styles, so overriding them needs
 * !important — nothing else here does. */
html.in-telegram #pm-users-activity {
  padding: 0 12px;
  margin-bottom: 10px;
}

/* One scrolling strip rather than five wrapped rows, which is most of a short
   screen spent on filters. */
html.in-telegram #pm-users-activity > div {
  flex-wrap: nowrap !important;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  gap: 6px !important;
  padding-bottom: 2px;
}
html.in-telegram #pm-users-activity > div::-webkit-scrollbar { display: none; }
html.in-telegram #pm-users-activity button { flex: 0 0 auto; margin-right: 0 !important; }

/* The 1px decorative divider between the two chip groups strands itself on a
   wrapped row and reads as a stray mark. */
html.in-telegram #pm-users-activity > div > span[style*="width:1px"] { display: none !important; }

/* "Online now: 0 · placed at least one bet" is pushed right with margin-left:auto,
   which on a scrolling strip drags it off the end. Give it its own line. */
html.in-telegram #pm-users-activity > div > span[style*="margin-left:auto"] {
  margin-left: 0 !important;
  flex: 0 0 auto;
  padding-left: 4px;
}

/* A table that refuses to reflow must scroll on its own rather than be clipped
   by the body's overflow:hidden — that is what cut a player's name off with no
   way to reach the rest of the row. */
html.in-telegram table {
  display: block;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  max-width: 100%;
}
html.in-telegram table thead,
html.in-telegram table tbody { display: table; width: 100%; }

/* Modals get the sheet, not a floating card: there is no room around one. */
html.in-telegram .modal-overlay {
  padding: 0 !important;
  align-items: flex-end !important;
}
html.in-telegram .modal-overlay > * {
  width: 100% !important;
  max-width: 100% !important;
  max-height: calc(var(--tg-vh, 100vh) - 40px) !important;
  border-radius: 14px 14px 0 0 !important;
  overflow-y: auto !important;
}

/* Section padding is generous for a desktop card and cramped for a 420px sheet;
   the content matters more than the frame here. */
html.in-telegram .section,
html.in-telegram .glass-panel {
  padding: 12px !important;
  border-radius: 10px;
}

html.in-telegram .metrics-grid,
html.in-telegram .metrics-grid-2 {
  gap: 8px !important;
}


/* ==========================================================================
   Table cards: label above value, both flush left.

   The phone layout turns every row into a card and every cell into
   `label | value` with `justify-content: space-between` and a 34% label track.
   Measured at 420px: the cell is 332px, the label ends at 113px and the value is
   pinned to the right edge — leaving a 168px void down the middle of every row.
   With a two-line value (a figure plus its "In play" sub-line) the label also
   centres itself vertically against it, so nothing lines up with anything.

   Stacking removes the void: the label becomes a small caption on its own line
   and the value sits under it at the left margin, the same place on every row.
   Applied on phones generally, not only in Telegram — it is the same layout and
   the same 420px there.
   ========================================================================== */

/* The row is a two-column grid, so a seven-field record is four short lines
   instead of seven tall ones. Two fields sit side by side; the ones that carry
   an identity or a list of chips take the full width. */
html.in-telegram .glass-table tbody tr {
  display: grid !important;
  grid-template-columns: 1fr 1fr;
  gap: 2px 14px;
  padding: 10px 12px !important;
  align-items: start;
}

html.in-telegram .glass-table td,
html.in-telegram .glass-table tbody td {
  display: block !important;
  text-align: left !important;
  min-height: 0 !important;
  padding: 4px 0 !important;
  border-bottom: none !important;
  gap: 0 !important;
  font-size: 13px !important;
}

/* The caption. Small, quiet, directly above its value — the pairing is what
   makes a dense grid readable rather than a wall of numbers. */
html.in-telegram .glass-table td::before {
  display: block !important;
  flex: none !important;
  max-width: none !important;
  width: auto !important;
  margin: 0 0 1px !important;
  font-size: 9.5px !important;
  line-height: 1.25 !important;
  opacity: 0.6;
}

/* Secondary lines ("In play …", "No deposits") belong under their own figure. */
html.in-telegram .glass-table td .money-main,
html.in-telegram .glass-table td .money-sub {
  display: block !important;
  text-align: left !important;
}
html.in-telegram .glass-table td .money-main { font-size: 13.5px !important; line-height: 1.3 !important; }
html.in-telegram .glass-table td .money-sub { font-size: 10.5px !important; line-height: 1.25 !important; opacity: 0.7; }

/* Only the chip list takes the whole width. Giving the name a full row too left
   Login stranded beside an empty cell, because the full-width Wallets that
   follows it cannot move up — so the pair reads Player | Login instead. */
html.in-telegram #pm-users-table td.wallets-cell {
  grid-column: 1 / -1;
}
html.in-telegram #pm-users-table td.wallets-cell {
  display: flex !important;
  flex-wrap: wrap !important;
  justify-content: flex-start !important;
  gap: 4px 6px !important;
}
/* ::before is a flex item in that cell, so it needs its own full-width line. */
html.in-telegram #pm-users-table td.wallets-cell::before { flex: 0 0 100% !important; }

/* A divider between records, not between every field — seven hairlines inside
   one card is most of why it read as a list of unrelated rows. */
html.in-telegram .glass-table tbody tr + tr {
  border-top: 1px solid var(--border) !important;
}

/* ------------------------------------------------------------------
   The notification-sounds dialog, compacted.

   It was built at 520px with desktop spacing: three bordered groups, each with
   its own 12px padding, a 12px-gap row and a row of three 44px buttons. On a
   420px sheet that is taller than the viewport, so it scrolls internally while
   showing about one and a half settings.

   Nothing is removed — the same controls, tightened, and the three action
   buttons share a row of equal thirds instead of wrapping.
   ------------------------------------------------------------------ */

html.in-telegram .pm-snd-card {
  width: 100% !important;
  max-width: 100% !important;
  max-height: calc(var(--tg-vh, 100vh) - 24px) !important;
  border-radius: 14px 14px 0 0 !important;
}
html.in-telegram .pm-snd-head { padding: 12px 14px !important; }
html.in-telegram .pm-snd-body { padding: 10px 12px 14px !important; }

html.in-telegram .pm-snd-group {
  padding: 9px 10px !important;
  margin-bottom: 8px !important;
}
html.in-telegram .pm-snd-grouphead { margin-bottom: 7px !important; gap: 8px !important; }
html.in-telegram .pm-snd-ico { width: 26px !important; height: 26px !important; }
html.in-telegram .pm-snd-name { font-size: 0.82rem !important; }
html.in-telegram .pm-snd-row { margin-bottom: 7px !important; gap: 8px !important; }
html.in-telegram .pm-snd-lbl { width: 62px !important; font-size: 0.72rem !important; }
html.in-telegram .pm-snd-num { font-size: 0.72rem !important; width: 36px !important; }

/* Three equal buttons on one line rather than a ragged wrap. The state caption
   moves to its own line under them. */
html.in-telegram .pm-snd-actions {
  display: grid !important;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px !important;
}
html.in-telegram .pm-snd-actions .btn,
html.in-telegram .pm-snd-actions label {
  width: 100% !important;
  justify-content: center !important;
  padding: 6px 4px !important;
  font-size: 10.5px !important;
  min-height: 32px !important;
}
html.in-telegram .pm-snd-state {
  grid-column: 1 / -1;
  margin-left: 0 !important;
  text-align: right;
}

/* No hover highlight here.
 *
 * `.glass-table tbody tr:hover td` paints each CELL, which on a desktop table is
 * one continuous band. In this grid the cells are separate boxes with gutters
 * between them, so the same rule paints a row of ragged patches with gaps —
 * which is what it looks like in the screenshot.
 *
 * Removing it rather than moving it to the row: hover is a pointer idea, and on
 * a touch screen it latches after a tap and stays lit on a card the user has
 * already moved on from. */
html.in-telegram .glass-table tbody tr:hover td,
html.in-telegram .glass-table tbody tr:hover {
  background: transparent !important;
}

/* Same layout on a phone browser: identical width, identical problem. */
@media (max-width: 768px) {
  .glass-table tbody tr {
    display: grid !important;
    grid-template-columns: 1fr 1fr;
    gap: 2px 14px;
    padding: 10px 12px !important;
    align-items: start;
  }
  .glass-table td {
    display: block !important;
    text-align: left !important;
    min-height: 0 !important;
    padding: 4px 0 !important;
    border-bottom: none !important;
    font-size: 13px !important;
  }
  .glass-table td::before {
    display: block !important;
    flex: none !important;
    max-width: none !important;
    margin: 0 0 1px !important;
    font-size: 9.5px !important;
    opacity: 0.6;
  }
  .glass-table td .money-main,
  .glass-table td .money-sub { display: block !important; text-align: left !important; }
  .glass-table td .money-sub { font-size: 10.5px !important; opacity: 0.7; }
  #pm-users-table td.wallets-cell { grid-column: 1 / -1; }

  /* Same as above: the per-cell hover paints patches in a grid, and on a touch
     screen it stays lit after the tap. */
  .glass-table tbody tr:hover td,
  .glass-table tbody tr:hover { background: transparent !important; }
  .glass-table tbody tr + tr { border-top: 1px solid var(--border) !important; }
}

/* ==========================================================================
   Findings from the layout audit of the panel markup.

   Every selector below was taken from the source and checked to exist — an
   earlier pass at this file invented plausible names like .pm-filter-chips and
   styled nothing. Where a container is built in JS with inline styles there is
   no class to hook, so the rule keys off the nearest real id and needs
   !important to beat the inline declaration.
   ========================================================================== */

/* [1] wallets cell — superseded by the compact grid above, which lays the
   chips out left-aligned and wrapping. The audit wrote this against the old
   right-hugging flex row; keeping both put the label back on the right. */


/* [2] body > div:has(#approve-confirm-btn)
   approveWithdrawal() builds its own overlay with document.createElement and NO class, so it matches neither `.modal-overlay` in the @media(768) block (css/partner.css:1443-1449 area) nor `html.in-telegram .modal-overlay` (partner-telegram.css:209-219). It keeps `position:fixed; inset:0; align-items:c */
/* #approve-confirm-btn / #approve-cancel-btn / #approve-txhash-input are the only
   real hooks — the overlay and its card carry inline styles and no class. */
html.in-telegram body > div:has(#approve-confirm-btn) {
  height: var(--tg-vh, 100vh) !important;
  align-items: flex-end !important;
  padding: 0 !important;
}
html.in-telegram body > div:has(#approve-confirm-btn) > div {
  width: 100% !important;
  max-width: 100% !important;
  max-height: calc(var(--tg-vh, 100vh) - 40px) !important;
  overflow-y: auto !important;
  padding: 16px !important;
  border-radius: 14px 14px 0 0 !important;
}
/* Cheaper permanent fix: add class="modal-overlay" to the element created at
   partner.js:3133 and it inherits the sheet treatment already written. */

/* [3] money cells — superseded by the compact grid above. The audit rule set
   text-align:right on .money-sub for the old flex row, which is what pushed
   "In play" to the opposite edge from its own figure. */


/* [4] #pm-users-table td[colspan]
   Every empty/loading state in this slice is a single <td colspan=N>. The card layout labels cells by position, so that lone td is nth-of-type(1) and picks up the first column's ::before — the 'no players' message renders as 'PLAYER No referred players matching filter criteria.' with the text jammed i */
html.in-telegram #pm-users-table td[colspan]::before,
html.in-telegram [id^="pm-ud-table-"] td[colspan]::before,
html.in-telegram #pm-clicks-table td[colspan]::before,
html.in-telegram #pm-links-table td[colspan]::before,
html.in-telegram #pm-cm-table td[colspan]::before { content: none !important; }

html.in-telegram #pm-users-table td[colspan],
html.in-telegram [id^="pm-ud-table-"] td[colspan],
html.in-telegram #pm-clicks-table td[colspan],
html.in-telegram #pm-links-table td[colspan],
html.in-telegram #pm-cm-table td[colspan] {
  display: block !important;
  text-align: center !important;
  padding: 14px 0 !important;
}

/* [5] #pm-promo-codes-list [style*="repeat(4,1fr)"]
   The geo-tier editor inside every promo card is a hard 4-column grid. At 420px the promo card's content box is only ~340px, so each tier column is ~76px wide (~58px after its own 9px padding + 3px accent border). Each column has to hold a "Tier 1" heading, the hint "US · UK · DE · AU", a "$" prefix a */
html.in-telegram #pm-promo-codes-list [style*="repeat(4,1fr)"] {
  grid-template-columns: 1fr 1fr !important;
  gap: 6px !important;
}

/* [6] #pm-promo-codes-list div[style*="margin-top:10px; display:flex"]
   The PROMO LINK strip is display:flex with no flex-wrap and three items that cannot shrink: a white-space:nowrap "PROMO LINK:" label with an inline SVG (~95px), a readonly <input style="flex:1"> whose default min-width:auto floors at the input's intrinsic size (~180px once the mobile rule forces font */
html.in-telegram #pm-promo-codes-list div[style*="margin-top:10px; display:flex"] {
  flex-wrap: wrap !important;
  row-gap: 8px !important;
}
html.in-telegram #pm-promo-codes-list div[style*="margin-top:10px; display:flex"] input[readonly] {
  min-width: 0 !important;
  flex: 1 1 100% !important;
  text-overflow: ellipsis;
}

/* [7] #pm-promo-codes-list div[style*="justify-content:space-between; gap:10px;"]
   Header row of every promo card: display:flex + justify-content:space-between with no flex-wrap. The right-hand child holds three buttons (Edit / Disable|Enable / Delete) which on mobile pick up `.btn, button { min-height: 44px }` and cannot shrink below their label width — roughly 48+62+56 + 12px ga */
html.in-telegram #pm-promo-codes-list div[style*="justify-content:space-between; gap:10px;"] {
  flex-wrap: wrap !important;
  align-items: flex-start !important;
  row-gap: 10px !important;
}
html.in-telegram #pm-promo-codes-list div[style*="justify-content:space-between; gap:10px;"] > div:last-child {
  flex: 1 1 100% !important;
  justify-content: flex-start !important;
}

/* [8] #pm-promo-codes-list label[style*="margin-left:auto"]
   The "Pay by country" checkbox label uses margin-left:auto to sit at the right end of a row that IS declared flex-wrap:wrap. At 420px the row wraps (the Bonus-amount label + the $ + a 110px input already fill the ~316px edit panel), so the label lands alone on the second line and margin-left:auto sho */
html.in-telegram #pm-promo-codes-list label[style*="margin-left:auto"] {
  margin-left: 0 !important;
  flex: 1 1 100%;
}

/* [9] #pm-promo-codes-list div[style*="display:flex; align-items:center; gap:8px;"]
   The promo-code identity row (code + type badge + status badge) is display:flex with no flex-wrap. It holds a 15px monospace code, an inline-flex badge reading "DEPOSIT BOOST" or "FREE BALANCE" with an 11px SVG, and an "ACTIVE"/"DISABLED" pill. With 16px of gaps this needs ~230-260px before any of it */
html.in-telegram #pm-promo-codes-list div[style*="display:flex; align-items:center; gap:8px;"] {
  flex-wrap: wrap !important;
  row-gap: 4px !important;
}

/* [10] .pm-legal-textarea
   Setup > Terms: the markdown editor and its preview each carry a fixed height:520px (.pm-legal-textarea line 3606, .pm-legal-preview line 3619 of css/partner.css). @media (max-width:900px) stacks .pm-legal-split into one column, so on a 420x600 Mini App the tab becomes ~1100px of fixed-height boxes o */
html.in-telegram .pm-legal-textarea { height: 240px !important; }
html.in-telegram .pm-legal-preview { height: auto !important; max-height: 280px !important; }

/* [11] #pm-public-table tr.pm-odds-state td
   The Odds tab's empty/loading/error row is injected as a single <td colspan="4">, but the mobile card layout keys its labels off nth-of-type, so this cell matches `#pm-public-table td:nth-of-type(1)::before { content: "Market" }`. On a phone the message "Failed to load markets (timeout or connection  */
html.in-telegram #pm-public-table tr.pm-odds-state td {
  display: block !important;
  text-align: center !important;
  padding: 16px 8px !important;
}
html.in-telegram #pm-public-table tr.pm-odds-state td::before {
  content: none !important;
  display: none !important;
}

/* [12] #pm-legal-status — selector is correct, but the location is index.html:1155 (and index.html:2518 for the #pm-ulegal-status twin), NOT js/partner.js:1155
   The Terms toolbar (index.html:1153-1156, populated by loadPmLegal at partner.js:4283) is a flex-wrap:wrap row of two doc buttons plus this status span pinned right with an inline margin-left:auto. loadPmLegal writes strings like "Custom document · v4 · saved 20/08/2026, 14:22" into it. At 420px the  */
html.in-telegram #pm-legal-status {
  margin-left: 0 !important;
  flex: 1 1 100%;
}

/* [13] #pm-header-title
   openPlatformSettings() writes the brand name into the site-manager header h2, which has no overflow handling at all. MEASURED at 420px: the element's box clamps at x 116-389 (273px wide) and STAYS 273px whether the name is 32 or 39 characters -- the ancestors correctly carry min-width:0, so the box  */
html.in-telegram #pm-header-title {
  font-size: 1.05rem !important;
  overflow: hidden !important;
  text-overflow: ellipsis !important;
  white-space: nowrap !important;
}

/* [14] #dashboard-top-domains
   The container the renderer fills carries an inline `max-height: 200px; overflow-y: auto`. MEASURED at 420x600 with five domains: clientHeight 200 vs scrollHeight 290 -- 90px, i.e. two of the five rows, hidden behind a nested scroll box. On a 600px-tall Telegram Mini App that is the classic nested-sc */
html.in-telegram #dashboard-top-domains {
  max-height: none !important;
  overflow: visible !important;
}

/* [15] .pm-kyc-head
   The KYC card header is a non-wrapping flex row whose status pill is pushed right with `margin-left: auto` and pinned `white-space: nowrap`, while the left column is an unclassed <div> with no min-width:0. The sub-line is `userLabel · submitted <full locale datetime>` and userLabel is commonly an ema */
html.in-telegram .pm-kyc-head { flex-wrap: wrap; }
html.in-telegram .pm-kyc-head > div { min-width: 0; flex: 1 1 100%; }
html.in-telegram .pm-kyc-head .pm-kyc-status { margin-left: 0; order: -1; }
html.in-telegram .pm-kyc-sub { overflow-wrap: anywhere; }

/* [16] .chat-header-actions
   The support-chat header action bar holds six nowrap controls (Join chat, agent <select>, translate <select>, Back to AI, Pin, Ban). Its CSS is `flex: 0 0 auto; margin-left: auto; flex-wrap: wrap` inside `.chat-header-user`, which is `display:flex` with NO flex-wrap. Because flex-shrink is 0 and flex */
html.in-telegram .chat-header-user { flex-wrap: wrap; padding: 10px 12px; }
html.in-telegram .chat-header-actions {
  flex: 1 1 100%;
  margin-left: 0;
  justify-content: flex-start;
  /* Was nowrap + overflow-x:auto, which hid half of six needed controls behind
     a swipe. They are not a menu to flick through -- Join chat, who you appear
     as, the translation mode, pin and ban are all wanted at once. */
  flex-wrap: wrap;
  min-width: 0;
  overflow-x: visible;
  row-gap: 4px;
  scrollbar-width: none;
}
html.in-telegram .chat-header-actions::-webkit-scrollbar { display: none; }
html.in-telegram .chat-header-actions > * { flex: 0 0 auto; }

/* [18] #pm-chat-input
   The composer textarea auto-grows by writing an INLINE height up to 140px. At 420px the field is only ~180px wide (32px emoji btn + 32px attach btn + 38px translate btn + 42px send btn + 4x10px gaps + 32px bar padding are all taken first), so a two-sentence reply already wraps to 5-6 lines and hits t */
html.in-telegram #pm-chat-input { max-height: 84px !important; }
html.in-telegram .chat-input-bar { padding: 8px 10px; gap: 6px; }
html.in-telegram .chat-input-field { min-width: 0; }
html.in-telegram .chat-icon-btn { min-height: 36px; }

/* [19] #team-wallet-history-table
   Team > Wallet > Payout history is the only .glass-table in the panel with no mobile card labels. The `@media (max-width:768px)` layer hides `thead tr` off-screen (`top:-9999px`) and relies on `td:nth-of-type(n)::before { content: "..." }` rules to relabel each cell — every sibling table has them (#p */
@media (max-width: 768px) {
  #team-wallet-history-table td:nth-of-type(1)::before { content: "Date"; }
  #team-wallet-history-table td:nth-of-type(2)::before { content: "Amount"; }
  #team-wallet-history-table td:nth-of-type(3)::before { content: "Crypto"; }
  #team-wallet-history-table td:nth-of-type(4)::before { content: "Address"; }
  #team-wallet-history-table td:nth-of-type(5)::before { content: "Status"; }
  #team-wallet-history-tbody td[colspan] { text-align: center !important; padding: 20px 0 !important; }
  #team-wallet-history-tbody td[colspan]::before { content: none; }
}

/* [20] #team-breakdown-table
   The mobile card labels for the owner-only per-member breakdown are off by one column. partner.css declares six labels ending `nth-of-type(5) -> "Volume"` and `nth-of-type(6) -> "Commission"`, but both the thead in index.html and renderTeamMemberBreakdown() emit exactly five columns: Member / Clicks  */
@media (max-width: 768px) {
  #team-breakdown-table td:nth-of-type(5)::before { content: "Deposits"; }
  #team-breakdown-table td:nth-of-type(6)::before { content: none; }
}

/* [21] .chat-bubble-wrap
   Message bubbles are capped at 70% of the row and sit inside a 20px-padded messages area, both desktop numbers that no phone layer relaxes. At 420px: 400px shell - 40px area padding - 30px avatar - 10px gap = ~320px row, of which the bubble may use 70% = ~224px. Roughly half the sheet's width is padd */
html.in-telegram .chat-messages-area { padding: 12px 10px; }
html.in-telegram .chat-bubble-wrap { max-width: 84%; }
html.in-telegram .chat-bubble { padding: 8px 12px; }

/* [22] .chat-emoji-grid
   The emoji picker is a hard 10-column grid. In a 420px sheet the picker box is ~378px of content, so each of the ten tracks is ~36px wide while the phone layer's `button { min-height: 44px }` makes every cell 44px tall — 36x44 thumb targets in a grid the panel elsewhere guarantees 44px for, with only */
html.in-telegram .chat-emoji-grid {
  grid-template-columns: repeat(6, 1fr);
  gap: 4px;
  max-height: 168px;
}
html.in-telegram .chat-emoji-cell { min-height: 44px; }

/* [23] .pm-wderr-cards
   The withdrawal-error card library is laid out with `grid-template-columns: repeat(auto-fill, minmax(520px, 1fr))` (css/partner.css:4401, overriding the 460px version at 4225). The 520px is the MIN of the minmax, i.e. a hard floor: auto-fill still produces one track and that track is never allowed be */
html.in-telegram .pm-wderr-cards {
  display: block;
  grid-template-columns: none;
}
html.in-telegram .pm-wderr-cards > .pm-wderr-card { margin-bottom: 12px; }

/* [24] #map-custom-tooltip
   The geo map's replacement tooltip is appended to document.body with an inline cssText of `position:fixed` + `min-width:140px`, then positioned at `clientX + 16` with no viewport clamp (contrast aiHelpClampToView/aiHelpPlacePanel a few hundred lines below, which do clamp). Its title line carries `whi */
html.in-telegram [id^="map-custom-tooltip"] {
  left: 8px !important;
  right: 8px !important;
  width: auto !important;
  min-width: 0 !important;
  max-width: calc(100vw - 16px) !important;
  box-sizing: border-box !important;
}
html.in-telegram [id^="map-custom-tooltip"] > div:first-child { white-space: normal !important; }
html.in-telegram [id^="map-custom-tooltip"] > div:last-child > div { gap: 10px !important; }
