/* Publifia Control Room — phones and tablets.

   The Control Room design was drawn against a fixed 1440-wide frame: a 244px
   sidebar beside a 12-column bento, one header row carrying six controls, and
   modals sized in pixels. dash-app.css already reflows that for narrow laptops,
   but below 880px dashboard3.css hides the sidebar outright — and nothing takes
   its place, so a phone gets a dashboard with no navigation at all.

   Everything here lives inside a width query, so desktop is untouched. This file
   is linked last in the dashboard layout, which is what lets these rules win
   against the equally-specific ones they correct. */

/* ==========================================================================
   1. Shell — page scroll, and the sidebar becomes a bottom tab bar
   ========================================================================== */

@media (max-width: 900px) {
  /* The desktop shell pins the viewport and scrolls an inner div. On a phone
     that costs you momentum scrolling and stops the browser's URL bar from
     collapsing, so the document scrolls instead. `dvh` rather than `vh`: mobile
     Safari's `vh` is measured against the *expanded* URL bar, so a 100vh shell
     is always taller than what you can actually see. */
  html, body { height: auto; overflow: visible; }

  .app3 {
    display: block;
    min-width: 0;
    height: auto;
    min-height: 100dvh;
  }

  /* --- the sidebar, rebuilt as a fixed bottom tab bar --- */
  .sb {
    display: flex !important;   /* beats dashboard3.css's `display: none` */
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 70;
    flex-direction: row;
    align-items: stretch;
    gap: 2px;
    padding: 6px 8px;
    /* Sits above the iPhone home indicator rather than under it. Resolves to 0
       on Android and on any device without an inset, so it costs nothing. */
    padding-bottom: calc(6px + env(safe-area-inset-bottom, 0px));
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
    background: rgba(16, 16, 19, 0.94);
    -webkit-backdrop-filter: blur(18px);
    backdrop-filter: blur(18px);
    border-top: 1px solid var(--line2);
    scrollbar-width: none;
  }
  .sb::-webkit-scrollbar { display: none; }

  /* The logo, the section eyebrows and the flex spacer are all vertical-layout
     furniture with nothing to do in a tab bar. */
  .sb-logo,
  .sb-eyebrow,
  .sb-sp,
  .region { display: none; }

  .sb-nav { flex-direction: row; flex: none; gap: 2px; }

  .sb-item {
    position: relative;
    flex-direction: column;
    justify-content: center;
    gap: 5px;
    /* 58px wide × 52px tall clears the ~44px minimum comfortable touch target
       on both platforms. */
    min-width: 58px;
    min-height: 52px;
    padding: 7px 10px;
    font-size: 10.5px;
    font-weight: 600;
    line-height: 1;
    white-space: nowrap;
    text-align: center;
  }
  .sb-item svg { width: 21px; height: 21px; opacity: .8; }

  /* `margin-left: auto` pushed the count to the right of a row; in a column it
     would sit under the label as a third line. Corner badge instead — the
     convention every native tab bar already uses. */
  .sb-item .ct {
    position: absolute;
    top: 1px; right: 4px;
    margin: 0;
    padding: 0 5px;
    font-size: 9.5px;
    line-height: 15px;
  }

  /* The avatar doubles as the settings button; the name and address beside it
     don't fit and aren't needed. */
  .sb-user {
    flex: none;
    /* dash-settings.css gives this `width: 100%` for the vertical sidebar; left
       alone it claims the full bar width as a single 374px tab. */
    width: auto;
    align-items: center;
    margin: 0 0 0 2px;
    padding: 4px 6px;
  }
  .sb-user > div { display: none; }
  .sb-user .av { width: 34px; height: 34px; }

  /* --- main column --- */
  .mn {
    margin: 0;
    height: auto;
    min-height: 100dvh;
    overflow: visible;
    border-left: 0;
    border-top-left-radius: 0;
    /* clears the fixed tab bar */
    padding-bottom: calc(72px + env(safe-area-inset-bottom, 0px));
  }
  .mn-scroll {
    overflow: visible;
    padding: 8px 16px 20px;
  }

  /* Chat is the one section that wants to fill the screen rather than scroll
     the page: dash3-chat.css builds it as a flex column that measures itself
     against a bounded .mn-scroll. Now that the document scrolls instead, that
     bound is gone and the thread collapses — so give it back explicitly. The
     header is hidden on this section, so the whole viewport minus the tab bar
     is available. */
  .mn-scroll:has(.chat) {
    height: calc(100dvh - 72px - env(safe-area-inset-bottom, 0px));
    min-height: 0;
    overflow: hidden;
  }
  /* Scaled up to fill a wide empty column; on a phone it just overflows. */
  .chat.empty .chat-thread { zoom: 1; padding: 0 16px; }
  .ct-head { padding: 14px 16px; }
}

/* Landscape on a notched iPhone puts the notch and the rounded corner beside
   the content rather than above it, so the horizontal insets are the ones that
   matter. `viewport-fit=cover` in the root layout is what makes these non-zero. */
@media (max-width: 900px) and (orientation: landscape) {
  .mn-scroll, .mn-top, .sb {
    padding-left: max(16px, env(safe-area-inset-left, 0px));
    padding-right: max(16px, env(safe-area-inset-right, 0px));
  }
}

/* ==========================================================================
   2. Header — one desktop row becomes three stacked bands
   ========================================================================== */

@media (max-width: 900px) {
  /* Sticky so switching sections and searching stay reachable without
     scrolling back up, which matters more on a short screen. */
  .mn-top {
    position: sticky;
    top: 0;
    z-index: 30;
    flex-wrap: wrap;
    gap: 10px;
    padding: 12px 16px;
    padding-top: calc(12px + env(safe-area-inset-top, 0px));
    /* Solid rather than a translucent blur on purpose. `backdrop-filter` makes
       an element the containing block for its `position: fixed` descendants,
       and both .search-scrim and .notif-scrim are fixed inset:0 children of
       this header — under a blur they would collapse to the header's own box,
       so tapping the page to dismiss either popover would stop working. */
    background: #101013;
    border-bottom: 1px solid var(--line);
  }

  /* Title · bell · CTA on the first line, then search, then the date range —
     ordered rather than reordered in markup so the desktop DOM is untouched. */
  .mn-top > div:first-child { order: 1; flex: 1 1 auto; min-width: 0; }
  .mn-top .sp { display: none; }
  .notif-wrap { order: 2; flex: none; }
  .mn-top .cta { order: 3; flex: none; }
  .search-wrap { order: 4; flex: 1 0 100%; }
  .daterange { order: 5; flex: 1 0 100%; justify-content: space-between; }

  /* Section names and city labels vary a lot in length; truncating keeps the
     bell and the CTA on the same line whatever the section is called. */
  .mn-top h1 {
    font-size: 19px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .mn-top .eyebrow { font-size: 11px; margin-bottom: 2px; }
  .mn-top .cta { padding: 9px 13px; font-size: 12.5px; }

  .mn-search { width: 100%; }
  /* A hardware keyboard hint is noise on a device that has no Ctrl key. */
  .mn-search .kbd { display: none; }

  .daterange button { flex: 1; text-align: center; }

  /* Both popovers were pixel-width and right-anchored to a wide header. */
  .search-pop {
    width: 100%;
    max-height: 60vh;
  }
  .notif-pop {
    width: min(340px, calc(100vw - 24px));
    right: -4px;
  }
  .np-list { max-height: 50vh; }
}

/* ==========================================================================
   3. Bento grid and the tiles inside it
   ========================================================================== */

@media (max-width: 900px) {
  .bento { gap: 12px; }
  .tile { padding: 16px; }

  .hero, .c5, .c7, .c8, .greet, .act { grid-column: span 12; }
  .c3, .c4, .c6 { grid-column: span 6; }
  .r2 { grid-row: auto; }

  .hero .big { font-size: 44px; }
  .kmini .v { font-size: 25px; margin-top: 10px; }
  .kmini .nm { font-size: 11.5px; }
  .greet .hi { font-size: 22px; }
  .greet .gsub { font-size: 13px; }
  .greet .gbtns { flex-wrap: wrap; }

  /* The map fills its tile from `position: absolute`, so it contributes no
     height. Once `.r2` stops spanning two rows the tile has nothing left to
     hold it open and collapses to the height of its overlay. */
  .maptile { min-height: 320px; }
  .cv-filter { top: 12px; right: 12px; }
  .mt-readout { flex-wrap: wrap; gap: 8px; }
  .mt-stat { flex: 1 1 44%; padding: 10px 12px; }
  .mt-stat .v { font-size: 18px; }

  /* Label column was a fixed 110px against a 44px value column — on a 390px
     screen that leaves the bar itself about 90px wide. */
  .bz { grid-template-columns: minmax(0, 1fr) 1.1fr 38px; gap: 9px; }

  .cov-tabs { flex-wrap: wrap; gap: 10px; }
  .cov-sync { margin-left: 0; }
  .cov-tabrow { width: 100%; }

  .donut-mini { flex-wrap: wrap; }

  /* Filter chips, a spacer and a button on one nowrap line. The chip row alone
     is wider than a phone. */
  .viewbar { flex-wrap: wrap; gap: 10px; margin-bottom: 14px; }
  .viewbar .sp { display: none; }
  /* Grows to fill the row, so the button stays alongside on a tablet and drops
     below only once the chips need the whole width. */
  .fchips { flex: 1 1 auto; flex-wrap: wrap; gap: 6px; }
  .fchip { padding: 7px 12px; font-size: 12px; }

  /* Copy and CTA sit either side of a map that fades in from the left. Below
     about 600px there isn't room for both, so the button drops under the text
     and the fade is squared up to cover the full card. */
  .explore-tile .ex-overlay { flex-wrap: wrap; gap: 12px; padding: 20px; }
  .explore-tile .ex-title { font-size: 18px; }
  .explore-tile .ex-fade {
    background: linear-gradient(180deg, var(--surface) 6%, color-mix(in oklab, var(--surface) 78%, transparent) 55%, transparent 100%);
  }

  .cc-stats { gap: 6px; margin: 13px 0 12px; }
  .cc-stat { padding: 9px 10px; }
  .cc-stat .n { font-size: 17px; }
}

@media (max-width: 560px) {
  /* Two KPI tiles per row survive down to about here; below it the numbers and
     their sparklines start colliding. */
  .c3, .c4, .c6 { grid-column: span 12; }
  .hero .big { font-size: 38px; }
}

/* ==========================================================================
   4. Records tables
   ========================================================================== */

@media (max-width: 900px) {
  /* .mn-scroll already supplies the side gutter on mobile; keeping the desktop
     28px here on top of it would inset the tables by 44px a side. */
  .rc { padding: 0 0 28px; }

  /* `nowrap` on a bar holding a search field, a count and three buttons forces
     a horizontal overflow of the whole page. */
  .rc-bar { flex-wrap: wrap; gap: 8px; }
  .rc-sp { display: none; }
  .rc-meta { flex: 1 0 100%; white-space: normal; }
  .rc-search { flex: 1 1 100%; }
  .rc-search input { width: 100%; }

  /* The table itself keeps its 1060px min-width and scrolls inside its own
     wrapper — a phone-width column layout would make these records unreadable.
     What matters is that the *page* doesn't scroll sideways with it. */
  .rc-tw {
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
  }

  .kb-grid { grid-template-columns: minmax(0, 1fr); }
  .kb-ed-row { flex-wrap: wrap; }
  .kb-ed-row select, .kb-ed-row input { flex: 1 1 100%; }
}

/* ==========================================================================
   5. Modals — full-screen on a phone rather than a floating card
   ========================================================================== */

@media (max-width: 720px) {
  .se-overlay, .act-overlay, .cdt-scrim, .mx-overlay, .kx-overlay {
    padding: 0;
  }

  .se-modal,
  .act-modal,
  .cdt-modal,
  .mx-modal,
  .kx-modal {
    width: 100% !important;
    max-width: none !important;
    height: 100dvh !important;
    max-height: 100dvh !important;
    min-width: 0 !important;
    border: 0;
    border-radius: 0;
  }

  /* A full-bleed sheet runs under the status bar and the home indicator. */
  .se-head, .act-head, .cdt-head, .mx-head, .kx-head {
    padding-top: calc(18px + env(safe-area-inset-top, 0px));
  }
  .se-body, .act-list, .cdt-list, .mx-body, .kx-scroll {
    padding-bottom: calc(20px + env(safe-area-inset-bottom, 0px));
  }

  .se-modal { grid-template-columns: 1fr; }
  .se-rail { flex-direction: row; overflow-x: auto; align-items: center; flex: none; }
  .se-body { padding-left: 18px; padding-right: 18px; }
  .se-head { padding-left: 18px; padding-right: 18px; }

  .mx-modal { resize: none; }
  .mx-body { flex-direction: column; }
  .mx-list { width: auto; max-height: 34dvh; border-right: 0; border-bottom: 1px solid var(--line); }
  .mx-map { min-height: 300px; }

  .cdt-head { flex-wrap: wrap; padding-left: 18px; padding-right: 18px; }
  .cdt-stats { gap: 18px; padding-left: 18px; padding-right: 18px; }
  .cdt-stats b { font-size: 18px; }
  /* Publication · contact · outcome across three columns leaves each about
     100px wide. Stack them and let the row breathe instead. */
  .cdt-row {
    grid-template-columns: minmax(0, 1fr) !important;
    gap: 8px;
  }
  .cdt-state { justify-content: flex-start; flex-wrap: wrap; }
  .cdt-log { flex: 1 1 100%; }
  .cdt-log input { width: 100%; flex: 1; }
  .cdt-foot { padding-left: 18px; padding-right: 18px; flex-wrap: wrap; }

  .act-head { padding-left: 18px; padding-right: 18px; }
  .act-item { align-items: flex-start; }
  .act-time { align-self: flex-start; }

  .kx-head { flex-wrap: wrap; padding-left: 18px; padding-right: 18px; }
  .kx-big { padding-left: 18px; }
}

/* ==========================================================================
   6. Campaign wizard (the full-screen .ob flow)
   ========================================================================== */

@media (max-width: 900px) {
  .ob-bar {
    flex-wrap: wrap;
    gap: 10px;
    padding: 12px 14px;
    padding-top: calc(12px + env(safe-area-inset-top, 0px));
  }
  .ob-bar img { height: 24px; }
  .ob-bar .ob-steps { margin-left: auto; }
  .ob-steps span { display: none; }

  .ob-body { padding: 20px 14px calc(44px + env(safe-area-inset-bottom, 0px)); }
  .ob-h { margin-bottom: 20px; }
  .ob-h h1 { font-size: 24px; }
  .ob-h p { font-size: 14px; }
  .ob-pad { padding: 18px; }

  .ob-row, .ob-row3, .ncf-grid { grid-template-columns: minmax(0, 1fr); }
  .ob-foot { flex-wrap: wrap; }
  .ob-btn { padding: 12px 18px; font-size: 14px; }

  .ob-map { height: 300px; }
  .ob-mailb { max-height: none; }
  .ob-tools { gap: 8px; }
  .ob-test-input { width: 100%; }
  .ob-tone-menu { width: min(268px, calc(100vw - 32px)); }

  .nc-body { padding: 18px 14px; }
  .nc-head { flex-wrap: wrap; gap: 10px; padding: 14px 16px; }
  .nc-head .nc-sub { display: none; }
  .nc-steps .sep { width: 8px; }
  .nc-foot { padding: 14px 16px calc(14px + env(safe-area-inset-bottom, 0px)); flex-wrap: wrap; }
  .ob-foot { padding-bottom: env(safe-area-inset-bottom, 0px); }
  .nc-foot .hint { flex: 1 0 100%; order: 3; }
}

/* ==========================================================================
   7. Studio, schedule, team
   ========================================================================== */

@media (max-width: 900px) {
  .pstudio { gap: 24px; }
  .pstep-head { flex-wrap: wrap; gap: 10px; }
  .pstep-tt { font-size: 15.5px; }
  .lib-bar { flex-wrap: wrap; }
  .lib-search { flex: 1 1 100%; }
  .canvas-foot { flex-wrap: wrap; }
  .canvas-area { min-height: 240px; }

  /* Seven day columns plus a time gutter cannot fit a phone. The calendar keeps
     its shape and scrolls sideways inside its own card. */
  .cal { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .cal-grid, .cal-month { min-width: 660px; }

  /* Five columns — member, email, role, pitches, menu — reflow into a card:
     the person and the overflow menu on one line, then the address, then role
     and pitch count together. The header row is dropped, so the pitch count
     gets a label of its own rather than reading as a bare number. */
  .trow { display: flex; flex-wrap: wrap; align-items: center; gap: 7px 11px; padding: 13px 14px; }
  .trow.head { display: none; }
  .trow .tperson { order: 1; flex: 1 1 auto; min-width: 0; }
  .trow .gear { order: 2; flex: none; margin-left: auto; }
  .trow .tmeta { order: 3; flex: 1 1 100%; overflow-wrap: anywhere; }
  .trow > span:nth-child(3) { order: 4; }
  .trow .tnum { order: 5; }
  .trow .tnum::after { content: ' pitches'; font-weight: 500; color: var(--txt3); }
  .ws-feat { grid-template-columns: minmax(0, 1fr); }
  .ws-empty-body { padding: 34px 20px 38px; }
  .ws-statusbar { flex-wrap: wrap; gap: 10px; padding: 14px 16px; }
  .tm-join-row { flex-wrap: wrap; }
  .act-foot { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .act-kpis { gap: 18px; }
}

/* ==========================================================================
   8. Floating furniture — the AI button and the status banner
   ========================================================================== */

@media (max-width: 900px) {
  /* Both used to sit at the bottom of the viewport, which is now the tab bar. */
  .aifab {
    right: 14px;
    bottom: calc(78px + env(safe-area-inset-bottom, 0px));
    gap: 10px;
  }
  .ai-dot { width: 50px; height: 50px; }
  .ai-panel { width: min(360px, calc(100vw - 28px)); }

  .dash-banner {
    left: 12px; right: 12px;
    width: auto;
    max-width: none;
    transform: none;
    bottom: calc(78px + env(safe-area-inset-bottom, 0px));
  }

  .dash-error-card { padding: 24px 20px; }
  .dash-error-actions { flex-wrap: wrap; }
  .dash-error-btn { flex: 1 1 auto; }
}

/* ==========================================================================
   9. Touch and text-input behaviour
   ========================================================================== */

@media (max-width: 900px) {
  /* iOS Safari zooms the page in whenever you focus a control whose text is
     smaller than 16px, and it does not zoom back out afterwards — the single
     most common reason a working layout "goes wrong" on an iPhone. The design
     sizes most fields at 12–13.5px, so they are all raised to 16px here.
     Checkboxes and radios are excluded: their size is their box, not their
     text. */
  .app3 input:not([type="checkbox"]):not([type="radio"]),
  .app3 textarea,
  .app3 select,
  .ob input:not([type="checkbox"]):not([type="radio"]),
  .ob textarea,
  .ob select,
  .se-modal input, .se-modal textarea, .se-modal select,
  .cdt-modal input,
  .mx-modal input {
    font-size: 16px !important;
  }

  /* Stop a long unbroken URL or outlet name from widening the whole page. */
  .mn, .mn-scroll, .rc, .ob-body { max-width: 100vw; }
  .np-msg, .act-msg, .sp-t, .sp-s, .kb-body, .cdt-pub, .cdt-contact {
    overflow-wrap: anywhere;
  }
}

/* Controls the design only revealed on hover are unreachable on a touchscreen,
   where there is no hover state to enter. Keyed off the input device rather
   than the width, so a touch laptop gets this too. */
@media (hover: none) {
  .sp-row .sp-arrow { opacity: 1; }
  .ob-mailb .ob-edithint { opacity: 1; }
  .kmini .kx-open { opacity: 1; }
}
