/* ============================================================================
   WHY THIS FILE IS FULL OF NARROW SELECTORS

   Three regressions in one week, all the same shape: a rule written for one
   screen, applied to every element matching a utility class on that page.

     [data-p="sap"] .flex { flex-wrap: wrap }
        -> the kanban's five columns stacked vertically and dragging broke
     [data-p="sap"] button { white-space: nowrap }
        -> card content ran off the white panel onto the dark ground
     [data-p="sap"] .flex { flex-wrap: wrap }   (again)
        -> the Edit-task modal, being flex-col with a max height, wrapped into
           a second column and half the form went off the right of the screen

   A utility class like .flex or .grid matches hundreds of elements. You can
   picture two of them. Before adding a rule here, prefer, in order:
     1. a purpose-built class on the element itself
     2. a structural selector that can only match the thing you mean
        (e.g. .overflow-x-auto:has(> .zc-well) is the board, and nothing else)
     3. a bare utility class - only with a comment saying what else it hits
   ========================================================================== */

/* ============================================================================
   mobile.css - the one mobile layer for the whole dashboard + SAP.
   Injected into every HTML response by _mobile_layer() in app.py, together with
   data-p="<page>" on <body>, so every rule below can be scoped to one screen.

   Nothing here is loaded on a laptop: every layout rule sits inside a media
   query. Desktop renders exactly as it did before.
   ========================================================================== */

/* ---- things that are safe at every width -------------------------------- */
html { -webkit-text-size-adjust: 100%; }
img, video { max-width: 100%; height: auto; }

/* the drawer + its scrim exist at all widths but only show under the query */
.m-burger, .m-scrim { display: none; }
.zc-hdr-more { display: none; }

@media (max-width: 860px) {

  /* =========================== shared shell =============================== */
  body { overflow-x: hidden; }

  .m-burger {
    position: fixed; left: 10px; top: 9px; z-index: 200;
    width: 40px; height: 40px; padding: 0;
    display: none; align-items: center; justify-content: center;
    border-radius: 12px; cursor: pointer;
    border: 1px solid rgba(128, 128, 140, .38);
    background: rgba(128, 128, 140, .20); color: inherit;
    -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
    font: 17px/1 system-ui, sans-serif;
  }
  body.m-navready .m-burger { display: flex; }

  .m-scrim {
    position: fixed; inset: 0; z-index: 90;
    background: rgba(0, 0, 0, .5); display: none;
  }
  body.m-navopen .m-scrim { display: block; }
  body.m-navopen { overflow: hidden; }

  /* =========================== THE WAR ROOM  /chat ======================== */
  /* The page carries its own responsive design now. All this layer still owes
     it is the drawer: the channel + officer column moves off-canvas. */
  /* It cannot scroll, so everything below the fold is unreachable: channels render first and the
     fourteen officers sit under them, past the bottom of a phone screen. A desktop column is tall
     enough to show the lot, which is why this only ever broke on mobile. */
  [data-p="chat"] .side {
    position: fixed; left: 0; top: 0; bottom: 0; width: 272px; z-index: 100;
    transform: translateX(-100%); transition: transform .22s ease;
    box-shadow: 0 0 40px rgba(0, 0, 0, .5);
    overflow-y: auto; overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    padding-bottom: calc(24px + env(safe-area-inset-bottom));
  }
  [data-p="chat"].m-navopen .side { transform: none; }
  [data-p="chat"] .side .brand { padding-left: 52px; }   /* clear of the menu button */

  /* =========================== THE SPINE  /spine ========================== */
  /* the table picker becomes a scrolling strip above the table, not a column */
  [data-p="spine"] .wrap { flex-direction: column; min-height: 0; }
  [data-p="spine"] .side {
    width: 100%; flex: none; border-right: 0;
    border-bottom: 1px solid var(--edge);
    display: flex; gap: 7px; padding: 10px 12px;
    overflow-x: auto; -webkit-overflow-scrolling: touch;
  }
  [data-p="spine"] .side .t {
    flex: 0 0 auto; gap: 7px; padding: 7px 12px;
    border: 1px solid var(--edge); border-radius: 20px; white-space: nowrap;
  }
  [data-p="spine"] .main { padding: 14px 12px; }
  [data-p="spine"] th, [data-p="spine"] td { max-width: 190px; }

  /* =========================== THE COCKPIT  /founder ====================== */
  [data-p="founder"] .wrap { padding: 20px 14px 80px; }
  [data-p="founder"] .brands { grid-template-columns: 1fr !important; }
  [data-p="founder"] .cols { grid-template-columns: 1fr !important; }
  [data-p="founder"] .prow { flex-wrap: wrap; row-gap: 6px; }
  [data-p="founder"] .plead { min-width: 0; flex: 1 0 100%; }
  [data-p="founder"] .prex { min-width: 0; }
  [data-p="founder"] .pstg { display: flex; flex-wrap: wrap; gap: 6px; }
  [data-p="founder"] .wrow { flex-wrap: wrap; row-gap: 3px; }
  [data-p="founder"] .wname { min-width: 0; }
  [data-p="founder"] .wnote { flex: 1 0 100%; white-space: normal; }
  [data-p="founder"] .frow { flex-wrap: wrap; row-gap: 3px; }
  [data-p="founder"] .fwho { min-width: 0; }
  [data-p="founder"] .fmid { flex: 1 0 100%; }
  [data-p="founder"] .funnel { overflow-x: auto; flex-wrap: nowrap; padding-bottom: 4px; }
  [data-p="founder"] .fchip { flex: 0 0 auto; }
  [data-p="founder"] .lcard { width: 100%; max-width: 340px; }
  [data-p="founder"] .links { flex-wrap: wrap; }

  /* =========================== THE FLOOR  /floor ========================== */
  [data-p="floor"] .wrap { padding: 18px 14px 80px; }
  [data-p="floor"] .grid { grid-template-columns: repeat(auto-fill, minmax(148px, 1fr)); }
  [data-p="floor"] .ov { padding: 0; align-items: flex-end; }
  [data-p="floor"] .ov > * { border-radius: 20px 20px 0 0; max-height: 88dvh; width: 100%; }

  /* =========================== THE DESK  /desk ============================ */
  [data-p="desk"] .wrap { padding: 16px 14px 84px; }
  [data-p="desk"] .top, [data-p="desk"] .bar { flex-wrap: wrap; row-gap: 8px; }
  [data-p="desk"] .fun { grid-template-columns: repeat(auto-fit, minmax(104px, 1fr)); }
  [data-p="desk"] .askrow { flex-wrap: wrap; }
  [data-p="desk"] .askrow input { min-width: 0; flex: 1 0 100%; font-size: 16px; }
  [data-p="desk"] .rejrow { flex-wrap: wrap; }
  [data-p="desk"] .rejrow b { min-width: 0; flex: 1 0 100%; }
  [data-p="desk"] table { display: block; overflow-x: auto; white-space: nowrap; }
  [data-p="desk"] .ov { padding: 0; align-items: flex-end; }
  [data-p="desk"] .ov > * { border-radius: 20px 20px 0 0; max-height: 88dvh; width: 100%; }
  [data-p="desk"] .dock { right: 12px; bottom: calc(12px + env(safe-area-inset-bottom)); }
  [data-p="desk"] .dockpanel { width: min(92vw, 420px); }

  /* ================= THE BOARDS  /crm  /delivery ========================== */
  /* a kanban column that is wider than the phone shows half of itself and
     half of the next one. Snap one full column per screen instead. */
  [data-p="crm"] .board, [data-p="delivery"] .board {
    scroll-snap-type: x mandatory; scroll-padding-inline: 14px;
    padding: 14px 14px 60px; gap: 10px;
  }
  [data-p="crm"] .board .col, [data-p="delivery"] .board .col {
    flex: 0 0 min(86vw, 320px); scroll-snap-align: start;
  }
  [data-p="crm"] .bar, [data-p="delivery"] .bar { flex-wrap: wrap; row-gap: 8px; padding: 12px 14px; }
  [data-p="crm"] .filters, [data-p="delivery"] .filters { padding: 10px 14px; }
  [data-p="crm"] .filters input, [data-p="crm"] .filters select { font-size: 16px; }
  [data-p="crm"] .ov, [data-p="delivery"] .ov { padding: 0; align-items: flex-end; }
  [data-p="crm"] .modal, [data-p="delivery"] .modal {
    width: 100%; max-height: 90dvh; overflow-y: auto;
    border-radius: 18px 18px 0 0; padding: 18px 15px;
  }
  [data-p="crm"] .grid, [data-p="delivery"] .grid { grid-template-columns: 1fr !important; }
  [data-p="crm"] .f input, [data-p="crm"] .f select, [data-p="crm"] .f textarea { font-size: 16px; }
  [data-p="crm"] .wrap2 { padding: 0 14px 60px; }

  /* /crm/dashboard */
  [data-p="crm-dashboard"] .wrapd { padding: 16px 14px 60px; }
  [data-p="crm-dashboard"] .kpis { grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); }
  [data-p="crm-dashboard"] .brow { grid-template-columns: 96px 1fr 44px; gap: 8px; }

  /* =========================== small screens ============================== */
  [data-p="report"] .wrap { padding: 22px 14px 70px; }
  [data-p="report"] .card { grid-template-columns: 48px 1fr; gap: 12px; padding: 13px 14px; }
  [data-p="tokens"] .grid, [data-p="leads"] .grid {
    grid-template-columns: repeat(auto-fit, minmax(148px, 1fr));
  }

  /* =========================== SAP  /sap ================================== */
  /* The rail was a permanent 72px of unlabelled icons. Off-canvas it, open at
     full width so the labels come back, and give the content the whole phone. */
  [data-p="sap"] aside.zc-side {
    position: fixed !important; left: 0; top: 0; bottom: 0;
    width: 258px !important; height: 100dvh !important;
    padding: 20px 16px !important; z-index: 100;
    transform: translateX(-100%); transition: transform .22s ease;
    box-shadow: 0 0 40px rgba(0, 0, 0, .45);
  }
  [data-p="sap"].m-navopen aside.zc-side { transform: none; }
  /* the in-rail collapse toggle makes no sense once the rail is a drawer */
  [data-p="sap"] aside.zc-side > div:first-child > button.zc-nav { display: none !important; }
  /* ... and the wordmark has to clear the button that opened the drawer */
  [data-p="sap"] aside.zc-side > div:first-child { padding-left: 50px !important; }
  [data-p="sap"] header { padding-left: 58px !important; }

  /* seven unlabelled circles wrapping onto two rows was the first thing on the
     screen. On a phone they live behind one "More" control instead. */
  [data-p="sap"] .zc-hdr-rest { display: none !important; }
  [data-p="sap"] .zc-hdr-more { display: block !important; }
  [data-p="sap"] header { padding: 10px 14px 10px 58px !important; }

  /* every desktop-width grid collapses to one column */
  [data-p="sap"] .grid-cols-2, [data-p="sap"] .grid-cols-3,
  [data-p="sap"] .grid-cols-4, [data-p="sap"] .grid-cols-5,
  [data-p="sap"] .grid-cols-6 { grid-template-columns: minmax(0, 1fr) !important; }

  /* the kanban: one full column per screen, snapped */
  /* Only the KANBAN snaps. Applied to every .overflow-x-auto on the page, mandatory snap
     also caught chip rows and toolbars, which then refuse to rest between items and feel
     stuck. :has(> .zc-well) is the board and nothing else; where :has is unsupported the
     board simply does not snap, which is a nicety, not a function. */
  [data-p="sap"] .overflow-x-auto:has(> .zc-well) { scroll-snap-type: x mandatory; scroll-padding-inline: 2px; }
  /* 76vw, not 86: the next column PEEKS. It shows there is somewhere else to put this, and it
     gives a drag an on-screen target - at 86vw the column you are dragging to was off the edge,
     so the only route was to hold the card against the border and wait for auto-scroll. */
  [data-p="sap"] .overflow-x-auto > .zc-well.shrink-0 {
    width: min(76vw, 300px) !important; scroll-snap-align: start;
  }
  [data-p="sap"] .overflow-x-auto > .zc-well.shrink-0 { padding: 8px !important; }

  /* ------------------------- THE MOVE CONTROL ---------------------------
     The reliable way to move a task on a phone, and now the obvious one.

     Dragging across a board where one column fills the screen is a poor
     interaction however well it is implemented - the target is not visible.
     Mature apps answer this with a "move to" control and offer dragging
     alongside it. This card already had one: the status select. It was 11px,
     grey, and last, so it read as a label rather than the way through. */
  [data-p="sap"] .zc-card select {
    min-height: 44px !important;          /* a thumb, not a cursor */
    font-size: 14px !important;
    font-weight: 600 !important;
    margin-top: 10px !important;
    padding: 11px 12px !important;
    border-radius: 12px !important;
    border-width: 1.5px !important;
    background-position: right 12px center !important;
  }

  /* --------------------------- COMPACT CARDS ---------------------------
     Two cards per screen meant scrolling to see a column. Tighter padding,
     a clamped title and no decorative counts fit four. */
  [data-p="sap"] .zc-card { padding: 10px !important; border-radius: 14px !important; }
  [data-p="sap"] .zc-card > .text-sm { font-size: 13.5px !important; margin-bottom: 6px !important; }
  [data-p="sap"] .zc-card > .text-sm > span.flex-1 {
    display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
    overflow: hidden; line-height: 1.32;
  }
  [data-p="sap"] .zc-card .flex.flex-col.gap-3 { gap: 8px !important; }

  /* ---------------------------- THE GRIP -------------------------------
     Touching this can only mean "move this card", so the drag starts on
     contact - no hold to wait out, no movement threshold to trip. That is
     what makes it reliable where long-press-anywhere could not be: on a
     board, a finger moving sideways is equally a drag and a scroll, and any
     threshold has to guess which. This does not guess.

     touch-action:none is the half that stops the browser reclaiming the
     gesture mid-drag (measured: touchcancel at ~645ms, repeatedly). It is
     confined to the grip, so the rest of the card still scrolls normally. */
  [data-p="sap"] .zc-card { position: relative; padding-left: 30px !important; }
  [data-p="sap"] .zc-grip {
    position: absolute; left: 0; top: 0; bottom: 0; width: 26px;
    touch-action: none; cursor: grab; z-index: 2;
    border-radius: 12px 0 0 12px;
    background:
      radial-gradient(circle at 50% 50%, currentColor 1.6px, transparent 1.7px) 50% 50% / 7px 7px repeat-y;
    color: rgba(140,140,150,.55);
  }
  [data-p="sap"] .zc-grip:active { color: rgba(140,140,150,.9); }

  /* --------------- THE GRIP BELONGS TO LANDSCAPE ------------------------
     Portrait shows one column, so a drag has nowhere visible to land and the
     grip is only stealing width from the title. The dropdown moves a task
     there. Landscape shows three columns at once, which is when dragging
     earns its place. */
  @media (orientation: portrait) {
    [data-p="sap"] .zc-grip { display: none !important; }
    [data-p="sap"] .zc-card { padding-left: 10px !important; }
  }

  /* ------------------- THE COLUMN HEADER STAYS PUT ----------------------
     Dragging a card down a long column, the header scrolls away and you can
     no longer see which column you are in - so you cannot tell where the card
     is about to land. Pinned, it answers that without looking away. It needs
     its own background or the cards scroll through the text. */
  /* Each column scrolls ITSELF. Without this the header was sticky and had nothing to stick to:
     sticky needs an ancestor that actually scrolls, the columns did not, and the board container
     had no height so it never scrolled vertically either. dvh, not vh - vh ignores the phone's
     browser chrome and buries the last card under the address bar. */
  [data-p="sap"] .zc-well.shrink-0 {
    max-height: calc(100dvh - 200px);
    overflow-y: auto; overflow-x: hidden;
    /* No touch-action here. pan-y permits ONLY vertical panning for a touch starting on this
       element, so a sideways swipe - which always starts on a column, because the columns are the
       board - was not allowed to pan anything, including the board itself. I disabled the exact
       gesture I meant to protect. The native chain already does the right thing: a column that
       scrolls vertically inside a board that scrolls horizontally hands each gesture to whichever
       can use it. contain stays, on the vertical axis only, so a column reaching its end does not
       start dragging the page. */
    overscroll-behavior-y: contain;
    -webkit-overflow-scrolling: touch;
  }
  [data-p="sap"] .zc-well > .flex.items-center.justify-between:first-child {
    position: sticky; top: 0; z-index: 3;
    margin: -8px -8px 6px; padding: 10px 10px 8px;
    border-radius: 12px 12px 0 0;
    background: var(--zc-wellbg, rgba(246,245,242,.94));
    -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  }
  /* while a card is in the air, the headers are the only landmarks - lift them clear */
  body.m-dragging [data-p="sap"] .zc-well > .flex.items-center.justify-between:first-child {
    z-index: 5; box-shadow: 0 6px 16px rgba(20,25,40,.10);
  }

  body.m-dragging [data-p="sap"] .zc-grip { cursor: grabbing; }

  /* anything the app pins to a desktop pixel width stops at the screen edge */
  [data-p="sap"] .min-w-\[200px\] { min-width: 0 !important; }
  [data-p="sap"] table { display: block; overflow-x: auto; white-space: nowrap; }
  [data-p="sap"] input, [data-p="sap"] select, [data-p="sap"] textarea { font-size: 16px !important; }

  /* Buttons keep their words whole and the ROW wraps instead. Three controls sharing 300px was
     breaking "Plan my day" over four lines; each is now sized to its label and drops to the next
     line when it will not fit. */
  /* ROWS only. A COLUMN must never wrap: `flex-col` with a max height turns wrapping into a
     second column beside the first, which is how the Edit-task modal ended up half off the
     screen with its title clipped at both ends. */
  [data-p="sap"] .flex:not(.flex-col) { flex-wrap: wrap; }
  [data-p="sap"] .flex-col { flex-wrap: nowrap !important; }
  /* ...but never a horizontal scroller. Wrapping the kanban stacked its five columns vertically
     and broke dragging between them. */
  [data-p="sap"] .overflow-x-auto,
  [data-p="sap"] .flex.overflow-x-auto { flex-wrap: nowrap !important; }
  [data-p="sap"] button { white-space: nowrap; }

  /* Content must not run past the screen. The page background is 100% of the viewport, so anything
     wider ends up sitting on the black behind it - measured at 303px past the edge on a 412px
     phone. The kanban is excluded: it is meant to be wider, that is what makes it a scroller. */
  /* THE WIDEST RULE IN THIS FILE. It touches every element inside <main> on the SAP page.
     It earns its place - without it long titles and wide rows run past the white panel onto
     the dark ground - but if something on this page is mysteriously clamped, look here
     first, and narrow this rather than adding another one beside it. */
  [data-p="sap"] main *:not(.overflow-x-auto):not(.overflow-x-auto *) { max-width: 100%; }

  /* ---------------------------- MODALS ---------------------------------
     A modal is `fixed inset-0`, so it is not inside <main> and none of the
     safety nets above reach it. On a phone it should use the width it has,
     scroll its body, and never push the page sideways. */
  [data-p="sap"] .fixed.inset-0 > div { max-width: calc(100vw - 24px) !important; }
  [data-p="sap"] .fixed.inset-0 > div > div { min-width: 0; }
  [data-p="sap"] .fixed.inset-0 .grid.grid-cols-2 { grid-template-columns: 1fr; }
  [data-p="sap"] .fixed.inset-0 input,
  [data-p="sap"] .fixed.inset-0 textarea,
  [data-p="sap"] .fixed.inset-0 select { font-size: 16px; max-width: 100%; }  /* 16px stops iOS zooming on focus */

  [data-p="sap"] .flex > button { flex: 0 0 auto; }

  /* the board filters were 34px tall - under what a thumb can reliably hit */
  [data-p="sap"] select { min-height: 44px; }

  /* ======================= THE PHONE ITSELF ==============================
     Three things every screen needs and none of them had. */

  /* 1. clear the home bar. A page that ends flush with the bottom of the glass
        puts its last row under the gesture area, where it cannot be tapped. */
  [data-p="sap"] main,
  [data-p="founder"] .wrap,
  [data-p="crm"] .board, [data-p="crm-dashboard"] .wrap,
  [data-p="delivery"] .wrap, [data-p="leads"] .wrap,
  [data-p="report"] .wrap, [data-p="tokens"] .wrap,
  [data-p="spine"] .main, [data-p="floor"] .wrap, [data-p="desk"] .wrap {
    padding-bottom: calc(28px + env(safe-area-inset-bottom)) !important;
  }
  /* landscape, where the notch eats a side */
  .app, [data-p="sap"] main, [data-p="founder"] .wrap {
    padding-left: max(env(safe-area-inset-left), 0px);
    padding-right: max(env(safe-area-inset-right), 0px);
  }

  /* 2. the header stays. One swipe used to be enough to forget which board you
        were on, which matters most on SAP where the boards look alike. */
  [data-p="sap"] header {
    position: sticky; top: 0; z-index: 40;
    -webkit-backdrop-filter: blur(18px) saturate(150%);
    backdrop-filter: blur(18px) saturate(150%);
  }
  [data-p="founder"] .mission, [data-p="desk"] .head { scroll-margin-top: 8px; }

  /* 3. a thumb needs 44px. Several controls were under thirty. */
  [data-p="sap"] button, [data-p="sap"] a[role="button"],
  [data-p="crm"] button, [data-p="delivery"] button,
  [data-p="founder"] button, [data-p="desk"] button, [data-p="leads"] button {
    min-height: 44px;
  }
  /* icon-only controls stay square rather than becoming tall pills */
  [data-p="sap"] button:empty, [data-p="sap"] button > svg:only-child { min-width: 44px; }
  .chan, .offr { min-height: 44px; }

  /* momentum scrolling on every horizontal strip, so a kanban feels native */
  [data-p="sap"] .overflow-x-auto, [data-p="spine"] .side,
  [data-p="founder"] .funnel, [data-p="crm"] .board {
    -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain;
  }

}

@media (max-width: 560px) {
  input, select, textarea { font-size: 16px; }   /* stops iOS zooming on focus */
  [data-p="founder"] .mission h1, [data-p="floor"] h1 { font-size: clamp(24px, 7vw, 34px); }
  [data-p="desk"] .fun { grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); }
}

/* ============================================================================
   MOTION — the phone layer
   SAP's animation was ~74 hover transitions, and a phone has no hover: on touch
   the app simply snapped. This adds the three things an iOS app does and this
   one did not — content arrives, taps answer, and quantities grow.

   Rules held throughout:
     · only transform and opacity animate. Never width, height, top or left.
     · every hidden state is applied BY JAVASCRIPT (.m-rv). If the script fails
       the page renders exactly as before rather than staying blank.
     · prefers-reduced-motion turns all of it off.
   ========================================================================== */

/* Apple's settle curve: fast out, long soft landing. */
:root { --m-ease: cubic-bezier(.32, .72, 0, 1); }

@media (prefers-reduced-motion: no-preference) {

  /* ---- content arrives ---- */
  .m-rv {
    opacity: 0;
    transform: translate3d(0, 15px, 0);
    transition: opacity .52s var(--m-ease), transform .52s var(--m-ease);
    will-change: opacity, transform;
  }
  .m-rv.m-in { opacity: 1; transform: none; }
  .m-rv.m-done { will-change: auto; }

  /* ---- quantities grow ---- */
  /* scaleX, not width: a bar is a leaf, so this is one GPU transform and the
     surrounding layout never reflows. */
  .m-bar { transform: scaleX(0); transform-origin: left center;
           transition: transform .78s var(--m-ease); }
  .m-bar.m-in { transform: scaleX(1); }

  /* ---- a new message lands ---- */
  .m-msg { animation: m-land .42s var(--m-ease) both; }
  @keyframes m-land {
    from { opacity: 0; transform: translate3d(0, 10px, 0) scale(.985); }
    to   { opacity: 1; transform: none; }
  }
}

/* ---- taps answer ----
   The one thing hover was doing that touch lost. Kept outside the
   reduced-motion guard: a press state is feedback, not decoration, and it is
   under 100ms. */
@media (hover: none) and (pointer: coarse) {
  [data-p="sap"] button:active,
  [data-p="sap"] .zc-card:active,
  [data-p="chat"] .chan:active,
  [data-p="chat"] .offr:active,
  [data-p="chat"] .m:active {
    transform: scale(.972);
    transition: transform .08s ease-out;
  }
  /* hover lift is meaningless on a phone and leaves cards stuck raised after a tap */
  [data-p="sap"] .zc-card:hover { transform: none; }
}

/* ---- touch drag: the card follows the finger, the target column answers ---- */
/* touch-action:none tells the browser this gesture is ours. Without it Chrome decides a
   long press that moves is a pan - the card sits in a board that scrolls both ways, so it
   has every reason to - and fires touchcancel mid-drag. Measured: cancelled at ~650ms,
   twice, reproducibly. Only while dragging: permanently, it would break scrolling the
   board with a finger that happens to land on a card. */
body.m-dragging { -webkit-user-select: none; user-select: none; overflow: hidden;
                  touch-action: none; }
body.m-dragging .zc-card, body.m-dragging .zc-well { touch-action: none; }
body.m-dragging * { -webkit-touch-callout: none; }
/* while dragging, snap fights the auto-scroll and the strip never moves */
body.m-dragging .overflow-x-auto { scroll-snap-type: none !important; scroll-behavior: auto !important; }

.m-ghost {
  opacity: .95;
  box-shadow: 0 18px 44px rgba(0, 0, 0, .30);
  transition: none !important;
}
[data-p="sap"] .zc-well.m-dropzone {
  outline: 2px dashed rgba(130, 130, 145, .55);
  outline-offset: -3px;
  transition: outline-color .12s ease;
}


/* ============================================================================
   THE DROP BAR
   A phone shows one kanban column at a time, so there is no second column to
   drag onto. This appears only while a card is in the air on a board that is
   wider than the screen; drop on a name and the card goes there.
   ========================================================================== */
.m-movebar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 10000;
  display: flex; gap: 6px;
  padding: 10px 10px calc(10px + env(safe-area-inset-bottom, 0px));
  background: rgba(12,12,14,.94); backdrop-filter: blur(8px);
  border-top: 1px solid rgba(255,255,255,.12);
}
.m-movechip {
  flex: 1 1 0; min-width: 0; text-align: center;
  padding: 13px 4px; border-radius: 12px;
  font: 600 11.5px/1.15 system-ui, sans-serif; letter-spacing: .01em;
  color: #d4d5da; background: #23252b; border: 1px solid #34373f;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.m-movechip.on {
  background: #FB7185; border-color: #FB7185; color: #17171a; transform: translateY(-2px);
}
