/* ==========================================================================
   PromoChat — responsive layer
   Loaded last so it can correct anything the base sheets set. Phone first,
   then tablet, then desktop. Every tap target is at least 44px.
   ========================================================================== */

/* --tap and the safe-area insets now live in tokens.css, which loads first, so
   app.css and modules.css can reach them too. This sheet owns the breakpoints. */

*{-webkit-tap-highlight-color:rgba(108,61,243,.12)}
html{-webkit-text-size-adjust:100%}
body{overflow-x:hidden}
img,video{max-width:100%;height:auto}

/* Long words — usernames, e-mail addresses, campaign titles, payment reference
   strings — break rather than being clipped by the card they sit in.
   overflow-wrap inherits, so saying it once on body covers every screen; a
   selector list kept missing containers like .post-body. break-word rather than
   anywhere, so it only takes effect when a word would actually overflow and
   intrinsic widths are left alone. */
body{overflow-wrap:break-word}

.skip-link{position:absolute;left:-9999px;top:0;z-index:200;background:#fff;color:var(--purple);padding:12px 18px;border-radius:0 0 12px 0;font-weight:700}
.skip-link:focus{left:0}

/* Anything wide scrolls inside itself rather than pushing the page sideways. */
.table-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch}
.tabs,.filter-bar,.profile-tabs,.feed-tabs{overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none}
.tabs::-webkit-scrollbar,.profile-tabs::-webkit-scrollbar,.feed-tabs::-webkit-scrollbar{display:none}
.tabs a,.tabs button,.profile-tabs a,.feed-tabs a{white-space:nowrap;flex:0 0 auto}

/* The scrollbar is hidden above, so the strip has to say for itself that it
   continues: the right edge fades out until it is scrolled to the end.
   mask-image only dims pixels that are already there, so nothing moves and no
   layout depends on it — a browser without mask support just shows a hard edge.
   scroll-snap keeps a tab from being left half cut off. */
.table-wrap,.tabs,.filter-bar,.profile-tabs,.feed-tabs,.stories{
  scroll-snap-type:x proximity;
  -webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 28px),transparent);
  mask-image:linear-gradient(90deg,#000 calc(100% - 28px),transparent)
}
.tabs a,.tabs button,.profile-tabs a,.feed-tabs a,.stories a{scroll-snap-align:start}

.nav-toggle,.search-jump,.nav-scrim{display:none}

/* ------------------------------------------------------------- phones ---- */
@media (max-width:820px){

  /* Re-point the shell tokens once, and every rule that was written in terms of
     them follows. app.css says .topbar{height:var(--topbar-h)} and
     .app-main{margin-left:var(--rail)}; neither needs a phone-specific copy. */
  :root{
    --rail:0px;
    --topbar-h:58px;
    --bottomnav-h:62px;
    --gutter:12px;
  }

  .topbar{padding:var(--safe-top) 8px 0;gap:6px;
          height:calc(var(--topbar-h) + var(--safe-top));
          padding-left:calc(8px + var(--safe-left));padding-right:calc(8px + var(--safe-right))}
  /* The brand gives way before the controls do. It was flex:0 0 auto, so at
     320px and 360px it held its full width and pushed the account button clean
     off the right edge instead of yielding. */
  .topbar .brand{width:auto;font-size:16px;flex:0 1 auto;min-width:0;gap:8px}
  .brand-copy{min-width:0}
  .brand-copy b{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .brand-copy small{display:none}
  .brand-mark{width:34px;height:34px;font-size:19px;border-radius:12px 12px 12px 4px}
  .global-search{display:none}
  .nav-toggle,.search-jump{display:grid}
  .top-actions{gap:2px;flex:0 0 auto}
  /* Theme lives in the account menu and Messages is a bottom tab, so neither
     needs to compete for room in a 414px bar. */
  .top-divider,.theme-btn,.chat-jump{display:none}
  /* icon() wraps its SVG in <span class="nav-icon">, so hiding every span in
     here hid the plus as well and left a blank purple square. Only the word
     "Create" goes; the button now carries an aria-label in its place. */
  .create-btn{padding:0;width:var(--tap);height:var(--tap)}
  .create-btn>span:not(.nav-icon){display:none}
  .icon-button{width:var(--tap);height:var(--tap)}

  /* avatar() returns an <img> when there is a picture and a <span> when it has
     to fall back to initials, so a bare ".mini-profile>span" hid the avatar
     itself for everyone without an uploaded photo — the audit's ~12x8px blank
     target. Excluding .avatar hides the name/handle only, in both cases. */
  .mini-profile>span:not(.avatar),.mini-profile .caret{display:none}
  .mini-profile{width:var(--tap);height:var(--tap);justify-content:center;padding:0}
  .mini-profile .avatar{width:34px;height:34px;font-size:12px}

  /* Sidebar becomes a drawer instead of vanishing. */
  .sidebar{
    display:flex;position:fixed;top:0;bottom:0;left:0;width:min(82vw,300px);
    padding:calc(var(--safe-top) + 16px) 12px calc(var(--safe-bottom) + 20px);
    transform:translateX(-102%);transition:transform .25s ease;z-index:120;
    box-shadow:12px 0 40px rgba(30,16,70,.18);overflow-y:auto
  }
  .sidebar.is-open{transform:translateX(0)}
  .sidebar-brand{position:static;min-height:var(--tap);height:auto;padding:0 6px 4px}
  .sidebar nav a{min-height:var(--tap);font-size:14px}
  /* Everything in the drawer is reached by finger, not just the nav list. */
  .quick-card a,.sidebar-card a,.mode-card a,.sidebar-signout button{
    min-height:var(--tap);display:flex;align-items:center
  }
  .nav-scrim{display:block;position:fixed;inset:0;background:rgba(24,16,48,.45);z-index:110}
  .nav-scrim[hidden]{display:none}

  /* Top padding clears the fixed topbar, bottom padding clears the fixed bottom
     bar — both from the tokens those elements are sized with, so neither can
     drift out of step and cover the page. */
  .app-main{
    padding:calc(var(--topbar-h) + var(--safe-top) + 12px) var(--gutter)
            calc(var(--bottomnav-h) + var(--safe-bottom) + 16px);
    padding-left:calc(var(--gutter) + var(--safe-left));
    padding-right:calc(var(--gutter) + var(--safe-right))
  }
  .site-footer{display:none}

  /* Bottom bar */
  .mobile-nav{
    position:fixed;left:0;right:0;bottom:0;z-index:80;display:flex;justify-content:space-around;
    height:calc(var(--bottomnav-h) + var(--safe-bottom));padding-bottom:var(--safe-bottom);
    padding-left:var(--safe-left);padding-right:var(--safe-right);
    background:rgba(255,255,255,.96);backdrop-filter:blur(12px);border-top:1px solid var(--line)
  }
  .mobile-nav a{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;color:var(--muted);flex:1 1 0;min-width:0;min-height:var(--tap)}
  .mobile-nav a.active{color:var(--purple)}
  /* The active tab has to be readable as active without relying on colour
     alone, which is the only signal a 9px label can carry. */
  .mobile-nav a.active small{font-weight:800}
  .mobile-nav a.active .nav-icon{transform:translateY(-1px)}
  .mobile-nav a.active::before{
    content:"";position:absolute;top:0;width:26px;height:3px;border-radius:0 0 3px 3px;background:var(--purple)
  }
  .mobile-nav a{position:relative}
  .mobile-nav small{font-size:10px;line-height:1.1;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .mobile-nav .nav-icon{width:21px;height:21px}
  .mobile-nav .compose-tab .nav-icon{
    width:42px;height:42px;display:grid;place-items:center;border-radius:50%;color:#fff;
    background:linear-gradient(135deg,var(--purple),#8f56f4);box-shadow:0 6px 16px rgba(108,61,243,.35);margin-top:-14px
  }
  .mobile-nav .compose-tab .nav-icon svg{width:21px;height:21px}
  .mobile-nav .compose-tab small{margin-top:1px}

  /* Layout collapses to one column everywhere. */
  .three-column,.home-grid,.profile-layout,.two-column-cards,.settings-grid,.two-col{display:block}
  .rightbar,.rail{display:none}
  .feature-strip{grid-template-columns:1fr;padding:14px;border-radius:16px}
  .feature-strip>div+div{border-left:0;border-top:1px solid var(--line);padding:12px 0 0}
  .card-grid,.campaign-grid,.people-grid,.trend-grid,.metric-grid,.risk-grid,.form-grid,.about-grid,.check-grid{grid-template-columns:1fr}
  .content-card,.settings-card,.card{padding:16px;border-radius:16px}
  .page-heading{flex-direction:column;align-items:flex-start;gap:10px}
  .page-heading h1{font-size:21px}

  /* The shortcuts do not fit at 414px, so they scroll instead of clipping.
     They were <span>s when this rule was written and are <button>s now, so the
     old selector matched nothing and "More" was pushed off the screen. Target
     the children, whatever element they happen to be. */
  .composer{padding:14px;grid-template-columns:40px 1fr;gap:10px}
  .composer>div{
    gap:8px;overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch;
    scroll-snap-type:x proximity;
    -webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 24px),transparent);
    mask-image:linear-gradient(90deg,#000 calc(100% - 24px),transparent)
  }
  .composer>div::-webkit-scrollbar{display:none}
  .composer>div>*{flex:0 0 auto;font-size:11.5px;scroll-snap-align:start;min-height:var(--tap)}
  .composer>div>button{padding:0 10px}
  .stories{padding:14px}

  .post-card{border-radius:16px}
  .post-actions button{font-size:0;min-height:var(--tap)}
  .post-actions .nav-icon{width:21px;height:21px}
  .post-meta{padding:8px 8px 8px 14px;font-size:11px}
  .meta-right{gap:9px}
  .post-head{padding:14px 14px 8px}
  .post-body{margin:2px 14px 12px}
  .post-link,.ad-cta{margin-left:14px;margin-right:14px}
  .post-media{max-height:60vh}
  .comment-row input{min-height:var(--tap)}

  /* ---- wide tables become labelled cards ----
     A six-column ledger inside a 320px screen can only be scrolled sideways,
     which puts the amount and the status several swipes away from the row they
     belong to. Each cell carries its own heading in data-label, so the same
     markup reads as a stack of records here and stays a table on a desktop.
     The header row is hidden rather than removed, so the table is still a table
     for assistive technology. */
  .stacking-table,.stacking-table tbody,.stacking-table tr,.stacking-table td{display:block;width:auto}
  .stacking-table thead{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
  .stacking-table tr{
    border:1px solid var(--line);border-radius:14px;padding:10px 12px;margin-bottom:10px;background:var(--card)
  }
  /* wrap, so a long description drops to its own line inside the cell and then
     wraps normally, instead of running off the right edge of the card. */
  .stacking-table td{
    border:0;padding:6px 0;display:flex;flex-wrap:wrap;gap:2px 12px;
    align-items:baseline;justify-content:space-between;text-align:right
  }
  .stacking-table td+td{border-top:1px dashed var(--line)}
  .stacking-table td::before{
    content:attr(data-label);flex:0 0 auto;color:var(--muted);text-align:left;
    font-size:var(--fs-meta);font-weight:700
  }
  .stacking-table td>*{min-width:0}
  /* A campaign name under a description belongs on a line of its own. */
  .stacking-table td>small{flex:1 1 100%;display:block;color:var(--muted)}
  .stacking-table code{word-break:break-all}
  /* The table no longer overflows, so the scroller and its fade come off. */
  .table-wrap:has(.stacking-table){overflow-x:visible;-webkit-mask-image:none;mask-image:none}

  /* ---- discovery: search rows, tabs and list metadata ---- */

  /* A tab is a primary control on these screens; padding alone left it ~40px. */
  .tabs a,.tabs button,.profile-tabs a,.feed-tabs a{
    min-height:var(--tap);display:flex;align-items:center
  }

  .explore-search{flex-wrap:wrap}
  .explore-search input{min-height:var(--tap)}

  /* Secondary text on the discovery lists was 10–11px, which is under the size
     a phone can comfortably read. These are the lines that carry the handle,
     the follower count, the category and the timestamp — not decoration. */
  .notification-list p,.notification-list small,
  .entity-body small,.entity-body p,.entity-body>div span,
  .people-grid span,.people-grid p,.follower-line,
  .trend-grid small,.trend-grid span{font-size:var(--fs-meta)}

  /* Long names must not push a card or a row sideways. */
  .people-grid h3,.entity-body h3,.notification-list b{min-width:0}
  .notification-list>a>div{min-width:0;flex:1}
  .notification-list>a{min-height:var(--tap)}

  /* ---- settings ----
     The section list is the only way between the six Settings screens, so it
     stays put under the topbar instead of scrolling away with the form, and it
     carries the same edge fade as the other horizontal strips. */
  .settings-grid>aside{
    flex-direction:row;overflow-x:auto;gap:6px;margin-bottom:14px;
    position:sticky;top:calc(var(--topbar-h) + var(--safe-top));z-index:40;
    scrollbar-width:none;scroll-snap-type:x proximity;
    -webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 28px),transparent);
    mask-image:linear-gradient(90deg,#000 calc(100% - 28px),transparent)
  }
  .settings-grid>aside::-webkit-scrollbar{display:none}
  .settings-grid>aside a{white-space:nowrap;min-height:var(--tap);display:flex;align-items:center;scroll-snap-align:start;flex:0 0 auto}

  /* Save stays reachable from anywhere in a form that is 1900px tall. */
  .form-sections .form-actions{
    position:sticky;bottom:calc(var(--bottomnav-h) + var(--safe-bottom));
    background:var(--card);padding:12px 0 4px;margin-top:4px;
    border-top:1px solid var(--line);z-index:30
  }
  .form-sections .form-actions .primary-btn{flex:1}
  .form-grid{gap:14px}
  .form-grid small,.settings-card input[type=file]{font-size:var(--fs-meta)}
  .form-grid label,.settings-card label.stack{font-size:var(--fs-meta)}

  /* These labels lay their own checkbox or radio out in a row, so they opt out
     of the shared "control floats beside a block of text" treatment above. */
  .check-grid label,.inline-check,.payout-option{
    display:flex;align-items:center;gap:10px;padding:10px;min-height:var(--tap);
    position:static;font-size:var(--fs-meta)
  }
  .check-grid label>input,.inline-check>input,.payout-option>input{position:static}

  .modal{padding:0;place-items:end}
  .modal-card{width:100%;max-height:92vh;border-radius:20px 20px 0 0;padding:22px 18px calc(22px + var(--safe-bottom))}
  .modal-close{width:var(--tap);height:var(--tap)}

  input,select,textarea{font-size:var(--fs-input)}   /* stops iOS zooming on focus */
  .primary-btn,.secondary-btn{min-height:var(--tap);padding:12px 18px}
  .mini-btn{min-height:var(--tap-sm);padding:8px 12px}

  /* A checkbox or radio is the one control a finger cannot aim at when it is
     drawn at its 13px default. The box grows and the whole label becomes the
     target. The label stays a block, not a flex row: these labels hold a real
     sentence with links in it ("I agree to the Terms and Privacy Policy"), and
     as flex items each word and link became its own column with gaps between
     them. As a block it is one piece of running text again, with the box
     positioned out of the flow beside it. */
  input[type=checkbox],input[type=radio]{width:20px;height:20px;flex:0 0 auto;margin:0}
  label:has(>input[type=checkbox]),label:has(>input[type=radio]){
    display:block;position:relative;min-height:var(--tap);
    padding:11px 0 11px 30px;line-height:1.45
  }
  label:has(>input[type=checkbox])>input,label:has(>input[type=radio])>input{
    position:absolute;left:0;top:11px
  }

  /* ---- moved here from modules.css ----
     These lived in a second, older @media(max-width:760px) block. Between 761px
     and 820px they switched off while the rest of the phone layout was still on,
     which is what pushed the auth panel 12px past the edge of a 768px tablet. */
  .auth-shell{display:block}
  .auth-promo{display:none}
  .auth-panel{min-height:100svh;padding:20px}
  .auth-card{padding:25px}
  .mobile-brand{display:flex;align-items:center;gap:8px;margin-bottom:18px}
  /* Field labels and the recovery link were 11px, and the link had only its own
     text height to be tapped on. Both are real controls on the one screen a
     person has to get through before they can use anything. */
  .auth-card label,.auth-card .switch-auth{font-size:var(--fs-meta)}
  .auth-options{gap:12px;flex-wrap:wrap}
  .auth-options a{font-size:var(--fs-meta);min-height:var(--tap);display:flex;align-items:center}
  .toast{left:12px;right:12px;top:calc(var(--topbar-h) + var(--safe-top) + 8px)}
  .mode-hero,.safety-hero{padding:22px;align-items:flex-start;flex-direction:column}
  .wallet-hero{grid-template-columns:1fr;padding:22px}
  .wallet-hero>div:last-child{grid-template-columns:1fr 1fr;margin-top:20px}
  .wallet-hero>div:last-child span{border-left:0;padding:8px}
  .profile-info>div:last-child{grid-column:1/-1;padding:0}

  /* ---- chat: list and thread become two screens, not a broken split ----
     modules.css used to hide this aside outright at ≤760px, which is what made
     the whole screen look blank on a phone. The list is the first screen now;
     opening a thread puts the section over it. */
  .chat-shell{display:block;height:auto;border:0;box-shadow:none;background:transparent}
  .chat-shell>aside{
    border-right:0;border:1px solid var(--line);border-radius:16px;
    max-height:calc(100dvh - var(--topbar-h) - var(--bottomnav-h) - var(--safe-top) - var(--safe-bottom) - 96px);
    overflow:auto
  }
  /* dvh, not vh: with vh the composer sat under the browser's own toolbar, and
     was pushed off screen entirely when the keyboard came up. dvh tracks the
     visible viewport, so the input stays above the keyboard. */
  .chat-shell>section{
    display:none;position:fixed;inset:0;z-index:130;height:100dvh;
    grid-template-rows:calc(var(--topbar-h) + var(--safe-top)) minmax(0,1fr) auto
  }
  body.chat-open .chat-shell>section{display:grid}
  body.chat-open .chat-shell>aside,body.chat-open .mobile-nav,body.chat-open .topbar{display:none}
  .chat-shell header{
    padding:var(--safe-top) 12px 0;height:calc(var(--topbar-h) + var(--safe-top));gap:6px;
    padding-left:calc(12px + var(--safe-left));padding-right:calc(12px + var(--safe-right))
  }
  /* Back, avatar, name, audio, video, files and the menu already fill the bar,
     so the name takes what is left and truncates rather than wrapping the row
     onto a second line the fixed header has no room for. */
  .chat-head-user{flex:1 1 auto;min-width:0}
  .chat-head-user div{min-width:0}
  .chat-head-user b,.chat-head-user small{
    display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%
  }
  /* The in-thread search box cannot have 90px of a 320px bar. The list's own
     search covers the same ground — search_all_messages() looks through every
     conversation — so only the shared-files link stays up here. */
  .chat-search-inline{margin-left:0;flex:0 0 auto}
  .chat-search-inline input,.chat-search-inline>button{display:none}
  /* app.css sizes .chat-shell header button at 36px with a two-class selector,
     which outranked a bare .chat-back and left every header control below the
     touch minimum. Matched at the same depth here so the phone gets 44px. */
  .chat-shell header button,
  .chat-shell header .chat-back,
  .chat-shell header .media-link{width:var(--tap);height:var(--tap);flex:0 0 auto}
  .chat-shell header .chat-back{
    display:grid;place-items:center;margin-left:0;border:0;background:#f2edff;
    color:var(--purple);border-radius:10px;font-size:20px
  }
  .chat-shell header .chat-head-user .avatar{width:32px;height:32px;font-size:11px}
  .messages{padding:14px}
  .bubble{max-width:82%}
  /* There is no hover on a phone, so these controls live inside the bubble
     rather than floating beside it. Stated in full here — with two classes so
     it also beats the card styling theme.css applies later — instead of
     relying on which of several partial rules happens to win. */
  .messages .bubble-actions,.messages .msg-react-picker{
    position:static;display:flex;transform:none;background:transparent;
    border:0;box-shadow:none;padding:0;margin-top:6px
  }
  .messages .bubble-actions button{width:30px;height:30px}
  .messages .msg-react-picker button{font-size:15px;padding:2px 4px}
  .messages .sent .bubble-actions,.messages .sent .msg-react-picker,
  .sent .bubble-actions,.sent .msg-react-picker{justify-content:flex-end}
  /* Icons take the bubble they sit in: light on purple, muted on grey. */
  .messages .sent .bubble-actions button{color:rgba(255,255,255,.9)}
  .messages .received .bubble-actions button{color:#5c6076}
  /* The composer keeps its controls on one row. .message-box is flex-wrap:wrap
     so the reply bar and the attachment preview can take rows of their own; the
     text input's default min-width:auto meant it refused to shrink past its
     placeholder and pushed Send onto a second line at 390px and below. */
  .message-box{
    padding:10px 12px calc(10px + var(--safe-bottom));gap:6px;
    padding-left:calc(12px + var(--safe-left));padding-right:calc(12px + var(--safe-right))
  }
  .message-box>input[name=body]{flex:1 1 60px;min-width:0;min-height:var(--tap)}
  .message-box .emoji-btn,.message-box .attach,.message-box .voice-record-btn,.message-box .send{
    width:var(--tap);height:var(--tap);flex:0 0 auto
  }
  .chat-person{min-height:64px}
  .start-new button{min-height:var(--tap)}
  /* Both are single-purpose taps inside the thread. */
  .load-older{min-height:var(--tap);display:flex;align-items:center;justify-content:center}
  .voice-play{width:42px;height:42px}
  /* "No conversations yet." was a bare line of text floating in an empty panel.
     It gets room and a settled position, and the Start a conversation list right
     below it is the action. */
  .chat-empty-side{display:grid;place-items:center;text-align:center;padding:28px 18px;color:var(--muted)}
  .chat-empty-side p{margin:0;font-size:var(--fs-meta)}

  /* ---- spaces ---- */
  .space-info{grid-template-columns:74px 1fr;gap:12px;padding:0 14px 18px}
  .space-logo{width:74px;height:74px;margin-top:-36px;border-width:4px;border-radius:18px}
  .space-cover{height:120px}
  .space-info>div:last-child,.profile-cta{grid-column:1/-1}
  .profile-cta{flex-wrap:wrap}
  .profile-cta>*{flex:1 1 auto}
  .profile-cover{height:130px}
  .profile-info{grid-template-columns:76px minmax(0,1fr);padding:0 14px 18px;gap:12px}
  /* A grid item is min-width:auto by default, so an unbreakable handle like
     @venkataraghavan.subramanian widened the column past 1fr and pushed the
     name, bio and stats off the right edge at 320px. */
  .profile-info>div,.profile-info h1,.profile-info p{min-width:0}
  .profile-info h1{font-size:20px}
  .profile-info>div>span,.profile-info>div>small{display:block;min-width:0}
  .profile-avatar{width:76px;height:76px;margin-top:-38px;border-width:4px}
  .follow-stats{gap:14px;flex-wrap:wrap;min-width:0}
  .follow-stats>*{flex:0 0 auto}
  .profile-cta>*{min-width:0}
  .member-row{flex-wrap:wrap}
  .member-row .row-actions{width:100%;padding-left:47px}

  /* ---- release audit: controls still under the 44px floor ----
     Found by walking the rendered page rather than the markup. Each one grows
     its hit area only; nothing here changes where anything sits, because these
     controls all live inside flex rows that centre their contents. */
  .topbar .brand{min-height:var(--tap)}
  .ghost-btn,.new-group-btn,.link-btn{min-height:var(--tap);display:inline-flex;align-items:center;justify-content:center}
  .chat-head-user{min-height:var(--tap)}
  .follow-stats a{min-height:var(--tap);display:inline-flex;flex-direction:column;justify-content:center}
  /* Answering or declining a call is the most time-critical tap in the app and
     these were 38px in a sheet that appears over whatever you were doing. */
  .incoming-call button{width:var(--tap);height:var(--tap)}

  /* ---- calling ---- */
  .call-stage{position:fixed;inset:0;z-index:140;border-radius:0;height:100dvh;min-height:0;max-width:none}
  /* Ring back is a one-tap action from a list row; 36px was not aimable. */
  .call-again button{width:var(--tap);height:var(--tap)}
  .call-row{flex-wrap:wrap;gap:8px}
  .call-row>div{flex:1 1 140px}
  .call-row time{flex:0 0 auto}
  .call-controls{padding-bottom:calc(20px + var(--safe-bottom))}
  #local-video{width:104px;height:150px;right:12px;top:calc(12px + var(--safe-top))}
  .incoming-call{left:10px;right:10px;top:calc(10px + var(--safe-top));width:auto}
}

/* --------------------------------------------------------- small phones ---
   Below ~480px the wordmark, the search jump, Create and the account control
   cannot all sit in one bar. The mark stays — it is still the link home — and
   the word goes, which is what keeps the account button on screen at 320px.  */
@media (max-width:479px){
  .brand-copy{display:none}
  .top-actions{gap:0}
  /* Back, identity, audio, video and the menu are the five things a thread
     header has to keep. The shared-files paperclip is the sixth, and at 320px
     it leaves the name no room at all — it moved into the thread menu, which
     is where the rest of the per-conversation actions already live. */
  .chat-shell header .media-link{display:none}
  .chat-shell header{gap:4px}

  /* Explore's row is field + Search + Clear. Under 480px all three on one line
     cut the placeholder mid-word, so the field takes a line of its own and the
     two buttons share the next one at equal width. */
  .explore-search input{flex:1 1 100%}
  .explore-search .primary-btn,.explore-search .secondary-btn{flex:1 1 0;justify-content:center}
}

/* ------------------------------------------------------------ tablets ---- */
@media (min-width:821px) and (max-width:1180px){
  /* Narrowing the rail token moves the sidebar, topbar and main together.
     modules.css used to also set .sidebar{width:215px} here, which beat the
     token and left the rail three times the width it had been narrowed for. */
  :root{--rail:78px;--gutter:18px}
  .sidebar{padding:0 8px 16px}
  .sidebar-brand{justify-content:center;padding:0}
  .brand-copy{display:none}
  .sidebar nav a{justify-content:center;padding:12px 0}
  .sidebar nav a span,.sidebar-card b,.sidebar-card span{display:none}
  .sidebar nav a .count-badge{position:absolute;transform:translate(14px,-12px)}
  .sidebar nav a{position:relative}
  .sidebar-card{padding:12px;text-align:center}
  /* The rail is too narrow for labelled cards; the same controls live in Settings. */
  .mode-card,.quick-card{display:none}
  .topbar .brand{display:none}
  .create-btn span{display:none}
  .create-btn{padding:0;width:44px}
  .app-main{padding:calc(var(--topbar-h) + 22px) var(--gutter) 26px}
  .three-column,.home-grid{grid-template-columns:minmax(0,1fr);max-width:680px;margin:0 auto}
  .rightbar,.rail{display:none}
  .card-grid,.campaign-grid,.metric-grid,.people-grid,.trend-grid{grid-template-columns:repeat(2,1fr)}
  .profile-layout,.two-col{grid-template-columns:1fr}
  .feature-strip{grid-template-columns:repeat(2,1fr)}
  .feature-strip>div+div{border-left:0;padding-left:0}
}

/* ------------------------------------------------------------ desktop ---- */
@media (min-width:1181px){
  .app-main{margin-left:var(--rail)}
  .topbar .brand{display:none}   /* the brand lives in the sidebar on desktop */
  .three-column{grid-template-columns:minmax(480px,690px) 320px;justify-content:center}
}

/* Between 1181px and 1440px there is only room for one rail, so the second
   one (discovery, leaderboard, ad plan) waits for a wider window. */
@media (min-width:1181px) and (max-width:1439px){
  .home-grid{grid-template-columns:minmax(0,1fr) 302px;max-width:1040px}
  .rail-b{display:none}
  .feature-strip{grid-template-columns:repeat(3,1fr);max-width:1040px}
  .feature-strip>div:nth-child(3n+1){border-left:0;padding-left:0}
}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important
  }
  /* app.css sets html{scroll-behavior:smooth}, which the rule above does not
     reach — smooth scrolling is a separate property, and it is exactly the kind
     of motion this preference is asking to be turned off. */
  html{scroll-behavior:auto!important}
  .tabs,.filter-bar,.profile-tabs,.feed-tabs,.stories,.table-wrap,
  .settings-grid>aside,.composer>div{scroll-behavior:auto!important}
  /* The drawer arrives in place instead of sliding in. */
  .sidebar{transition:none!important}
}
