/* ============================================================
   responsive.css — BRAIN Mobile & Touch Layer
   Loaded LAST on every page, so it wins the cascade over the
   per-page stylesheets without needing !important everywhere.

   Requires: app.css (design tokens).
   Companion JS: assets/js/components/mobile-nav.js — injects the
   top bar + scrim and drives the drawer.

   Breakpoints (kept in step with the ones already used across the
   page stylesheets, so nothing fights):
     <= 1024px  tablet — tighten dense desktop chrome
     <=  900px  phone/small tablet — sidebar becomes a drawer
     <=  600px  phone — single column everywhere
     <=  380px  small phone — last-resort compaction
   ============================================================ */

/* ══════════════════════════════════════════════════════════════
   1 · VIEWPORT & BASE
   ══════════════════════════════════════════════════════════════ */
:root {
    /* Content height of the injected mobile top bar, before the notch
       inset is added on top of it. */
    --mbar-h: 54px;

    /* The bar's full occupied height. Anything position:fixed and
       top-anchored has to start below this or it renders under the bar —
       the bar sits at z-index 900 inside .app-shell's stacking context,
       which is higher than any page's own fixed panel. */
    --mbar-total: calc(var(--mbar-h) + var(--safe-t));

    /* Safe-area insets, resolved once. env() is unsupported on old
       Android WebView, where these correctly fall back to 0px. */
    --safe-t: env(safe-area-inset-top,    0px);
    --safe-r: env(safe-area-inset-right,  0px);
    --safe-b: env(safe-area-inset-bottom, 0px);
    --safe-l: env(safe-area-inset-left,   0px);
}

html {
    /* Stops iOS/Android inflating text in landscape. */
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
}

body {
    /* A single overflowing child used to shift the whole page sideways
       and leave a dead strip of background — very visible on a phone. */
    overflow-x: hidden;
    /* Kills the grey flash on every tap in mobile WebKit/Blink. */
    -webkit-tap-highlight-color: transparent;
}

/* dvh tracks the collapsing URL bar; vh does not, which is what makes
   full-height app shells scroll by ~60px on mobile Safari/Chrome. The
   vh line stays as the fallback for browsers without dvh. */
@supports (height: 100dvh) {
    .app-shell        { height: 100vh; height: 100dvh; }
    .BRAIN-sidebar    { height: 100vh; height: 100dvh; }
}

/* Momentum scrolling + no scroll chaining into the page behind. */
.messages-container,
.sb-tab-pane,
.list-scroll,
.read-scroll,
.task-table-wrap,
.contacts-content,
.cal-scroll,
.profile-modal,
.pm-body {
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
}

/* ══════════════════════════════════════════════════════════════
   2 · MOBILE TOP BAR
   Injected by mobile-nav.js as the first child of .app-shell.
   Hidden entirely on desktop — the sidebar is the navigation there.
   ══════════════════════════════════════════════════════════════ */
.brain-mobilebar {
    display: none;
    align-items: center;
    gap: var(--sp-2);
    flex-shrink: 0;
    height: var(--mbar-total);
    padding: var(--safe-t) calc(var(--sp-2) + var(--safe-r)) 0 calc(var(--sp-2) + var(--safe-l));
    background: var(--bg-surface);
    backdrop-filter: blur(22px) saturate(160%);
    -webkit-backdrop-filter: blur(22px) saturate(160%);
    border-bottom: 1px solid var(--border-default);
    z-index: 900;
}

.brain-mobilebar-btn {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    flex-shrink: 0;
    border-radius: var(--r-md);
    color: var(--text-secondary);
    background: none;
    border: none;
    transition: background var(--t-fast), color var(--t-fast);
}
.brain-mobilebar-btn svg { width: 21px; height: 21px; }
.brain-mobilebar-btn:active { background: var(--brand-dim); color: var(--text-primary); }

.brain-mobilebar-logo {
    width: 24px;
    height: 24px;
    flex-shrink: 0;
    object-fit: contain;
    filter: drop-shadow(0 0 8px var(--brand-glow));
}

.brain-mobilebar-title {
    flex: 1;
    min-width: 0;
    font-family: var(--font-ui);
    font-size: var(--text-md);
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Mirrors the sidebar's unread count, which is behind the drawer. */
.brain-mobilebar-badge {
    position: absolute;
    top: 6px;
    inset-inline-end: 6px;
    min-width: 15px;
    height: 15px;
    padding: 0 4px;
    border-radius: var(--r-pill);
    background: linear-gradient(135deg, var(--brand), var(--brand-light));
    color: #fff;
    font-size: 0.56rem;
    font-weight: 700;
    line-height: 15px;
    text-align: center;
    box-shadow: 0 0 0 2px var(--bg-base);
    pointer-events: none;
}

/* Legal links inside the drawer footer — a drawer-only affordance;
   on desktop the page footer carries them. */
.sb-legal { display: none; }

/* Dim layer behind the open drawer. */
.brain-scrim {
    position: fixed;
    inset: 0;
    z-index: 1100;
    background: rgba(3, 7, 14, 0.62);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--t-slow), visibility var(--t-slow);
}
body.brain-drawer-open .brain-scrim { opacity: 1; visibility: visible; }

/* ══════════════════════════════════════════════════════════════
   3 · TABLET — <= 1024px
   ══════════════════════════════════════════════════════════════ */
@media (max-width: 1024px) {
    :root { --sb-w: 224px; }

    /* Dense desktop paddings waste a lot of a tablet's width. */
    .todo-main,
    .contacts-main,
    .page-root      { padding-inline: var(--sp-4); }
}

/* ══════════════════════════════════════════════════════════════
   4 · PHONE — <= 900px · SIDEBAR BECOMES A DRAWER
   ══════════════════════════════════════════════════════════════ */
@media (max-width: 900px) {

    .brain-mobilebar { display: flex; }

    /* app-shell is a row of [sidebar | page] on desktop. With the sidebar
       lifted out of flow it becomes [top bar / page]. Children are matched
       generically because every page names its own wrapper (.chat-wrap,
       .mail, .todo-wrap, .cal-wrap, …).

       Scoped to .has-mobile-nav, which mobile-nav.js sets on the shells it
       actually mounts into. The admin console has its own .app-shell with
       its own row layout and no drawer — an unscoped rule would flip it to
       a column and stretch its sidebar across the screen. */
    .app-shell.has-mobile-nav {
        flex-direction: column;
        width: 100%;
        max-width: 100%;
    }
    /* .notes-rail and its backdrop are excluded for the same reason as
       .BRAIN-sidebar: below 1200px the notes rail is a position:fixed
       off-canvas drawer, and flex:1/width:100% would stretch it across the
       whole screen and leave the backdrop as a permanent grey sheet. */
    .app-shell.has-mobile-nav > *:not(.BRAIN-sidebar):not(.brain-mobilebar):not(.brain-scrim):not(.notes-rail):not(.nr-backdrop) {
        flex: 1 1 auto;
        width: 100%;
        max-width: 100%;
        min-width: 0;
        min-height: 0;
    }

    /* ── Fixed panels start below the bar ──
       A page's own off-canvas panel is position:fixed with top:0 and a
       page-local z-index (Calls' rail 5, Meetings' drawer 41). The bar is
       z-index 900 in the same stacking context, so those panels render
       *under* it — and their reopen handles sit in the top ~50px, which is
       exactly the band the bar occupies. Calls is the worst case: from
       681px the rail is already fixed, but the bar only appears at 900px,
       so across 681–900px the collapsed rail's toggle is unreachable.

       Offsetting rather than restacking keeps the bar's menu button live
       while a drawer is open. The sidebar drawer is excluded on purpose —
       it is the bar's own drawer and is meant to cover it.

       Calls' rail is handled in its own range block below: under 680px it
       turns into a bottom sheet (top:auto), and this offset would outrank
       that and stretch it back to full height. */
    .app-shell.has-mobile-nav .history-drawer {
        top: var(--mbar-total);
    }

    /* ── The drawer ── */
    .BRAIN-sidebar,
    .BRAIN-sidebar[data-collapsed="true"],
    .BRAIN-sidebar[data-collapsed="false"] {
        position: fixed;
        top: 0;
        bottom: 0;
        inset-inline-start: 0;
        z-index: 1200;
        width: min(86vw, 320px);
        min-width: 0;
        max-width: 320px;
        padding-top: var(--safe-t);
        padding-bottom: var(--safe-b);
        /* inset-inline-start flips to the right edge under RTL but the
           transform does not, so the offset has to carry --dir or the
           closed drawer parks ~64px inside the screen in Arabic.
           See the --dir block in i18n.css. */
        transform: translateX(calc(var(--dir, 1) * -102%));
        transition: transform var(--t-slow);
        border-inline-end: 1px solid var(--border-default);
    }
    body.brain-drawer-open .BRAIN-sidebar {
        transform: translateX(0);
        box-shadow: var(--shadow-lg);
    }

    /* The collapse rail is a desktop affordance. In the drawer every
       label must stay readable, so undo every collapsed-state rule. */
    .BRAIN-sidebar[data-collapsed="true"] .sd-logo img,
    .BRAIN-sidebar[data-collapsed="true"] .sb-wordmark,
    .BRAIN-sidebar[data-collapsed="true"] .sb-section-label,
    .BRAIN-sidebar[data-collapsed="true"] .sb-user-info,
    .BRAIN-sidebar[data-collapsed="true"] .sb-history-panel,
    .BRAIN-sidebar[data-collapsed="true"] .sb-nav-item > span:not(.sb-badge-live) {
        opacity: 1;
        max-width: none;
        max-height: none;
        pointer-events: auto;
    }
    .BRAIN-sidebar[data-collapsed="true"] .sb-section-label { padding: 8px 14px 3px; }
    .BRAIN-sidebar[data-collapsed="true"] .sb-nav-item      { padding: 6px 14px; justify-content: flex-start; }
    .BRAIN-sidebar[data-collapsed="true"] .sb-new-chat {
        width: auto; height: auto; padding: 7px 12px;
        justify-content: flex-start; border-radius: var(--r-md);
        margin-inline-start: 10px; margin-inline-end: 10px;
    }
    .BRAIN-sidebar[data-collapsed="true"] .sb-new-chat > span { max-width: 180px; opacity: 1; }
    .BRAIN-sidebar[data-collapsed="true"] .sb-badge-live     { display: inline-flex; }
    .BRAIN-sidebar[data-collapsed="true"] .sb-icon-btn {
        opacity: 1; max-width: none; pointer-events: auto;
    }
    .BRAIN-sidebar[data-collapsed="true"] .sb-upgrade-card,
    [data-collapsed="true"] #sb-upgrade-chip { display: flex !important; }

    /* The chevron now means "close the drawer", so point it at the edge the
       drawer retracts into — left in English, right in Arabic. scaleX(1) is
       the identity, so LTR renders exactly as the old rotate(0deg) did. */
    .BRAIN-sidebar .sb-collapse-btn svg { transform: scaleX(var(--dir, 1)) !important; }
    .sb-collapse-btn { width: 34px; height: 34px; }
    .sb-collapse-btn svg { width: 16px; height: 16px; }

    /* ── Comfortable touch targets inside the drawer ── */
    .sb-nav-item     { padding-block: 11px; font-size: var(--text-base); }
    .sb-nav-item svg { width: 18px; height: 18px; }
    .sb-new-chat     { padding-block: 11px; font-size: var(--text-base); }
    .sb-icon-btn     { width: 38px; height: 38px; }
    .sb-icon-btn svg { width: 17px; height: 17px; }
    .sb-tab-btn      { padding: 8px 13px; font-size: var(--text-sm); }
    .conversation-item,
    .sb-doc-item     { padding: 10px; }
    /* Row actions only appear on :hover, which a finger never triggers. */
    .conversation-menu-btn,
    .sb-doc-del      { opacity: 1; width: 30px; height: 30px; min-width: 30px; }
    .gallery-item-overlay { opacity: 1; }

    /* ── Forms ──
       Any control under 16px makes iOS Safari zoom the whole page on
       focus and never zoom back out. */
    input:not([type="checkbox"]):not([type="radio"]):not([type="range"]),
    select,
    textarea {
        font-size: 16px;
    }

    /* ── Perf: the decorative background is the single most expensive
       thing on the page. Large blurred orbs animating behind a
       backdrop-filter cost real frames on a phone GPU. Keep the static
       gradient, drop the motion and shrink the blur radius. ── */
    .bg-orb {
        animation: none;
        filter: blur(60px);
        opacity: 0.7;
    }
    .bg-orb-1 { width: 300px; height: 300px; }
    .bg-orb-2 { width: 220px; height: 220px; }
    .bg-orb-3 { display: none; }
    .neural-css { display: none; }

    /* ── Page footer ──
       Below 640px footer.css already hides the links and the wordmark,
       leaving 44px of logo-and-copyright at the bottom of an app screen
       that has none to spare. Drop it; the links live in .sb-legal
       inside the drawer instead. */
    .app-shell.has-mobile-nav .BRAIN-footer { display: none; }

    /* ── Chat: one title bar, not two ──
       The 54px mobile bar already shows the conversation name (it follows
       <title>, which chat.js rewrites per conversation), so #chat-header's
       own 52px title row repeats it — ~106px of chrome and the same text
       twice. Drop the duplicated label and let the header keep only its
       share / overflow actions, which have nowhere else to live. */
    .app-shell.has-mobile-nav .chat-header-title,
    .app-shell.has-mobile-nav .hdr-status-dot { display: none; }

    .app-shell.has-mobile-nav .chat-header {
        height: 44px;
        min-height: 44px;
    }
    .app-shell.has-mobile-nav .chat-header-inner { justify-content: flex-end; }

    .sb-legal {
        display: flex;
        align-items: center;
        justify-content: center;
        gap: var(--sp-2);
        padding: 10px 12px calc(10px + var(--safe-b));
        border-top: 1px solid var(--border-subtle);
    }
    .sb-legal a {
        font-size: var(--text-xs);
        color: var(--text-tertiary);
        padding: 2px 4px;
    }
    .sb-legal a:active   { color: var(--brand); }
    .sb-legal-dot        { color: var(--text-disabled); font-size: var(--text-xs); }

    /* ── Floating voice assistant ──
       On a page with a bottom-docked composer (chat), the bubble would
       otherwise sit on top of the Send button. mobile-nav.js publishes
       the composer's live height in --bottom-dock-h. */
    body.has-bottom-dock #BRAIN-voice-bubble {
        bottom: calc(var(--bottom-dock-h, 120px) + 10px);
    }

    /* ── Modals become sheets ── */
    .sb-modal {
        min-width: 0;
        width: min(420px, calc(100vw - 2 * var(--sp-4)));
        padding: var(--sp-5);
    }
    .sb-modal-actions .sb-btn { flex: 1; padding-block: 11px; }
    .sb-context-menu .sb-ctx-item { padding: 11px 13px; }
}

/* ── Calls' history rail: the tablet dead zone ──
   call.css makes the rail position:fixed/top:0 from 1100px down, and a
   bottom sheet from 680px down. Between those, the 54px bar covers the
   collapsed rail's reopen toggle (it sits at y≈18–52px), so on a 768px
   tablet there is no way to get the panel back. Bounded below at 681px
   so the bottom-sheet layout keeps its own top:auto. */
@media (min-width: 681px) and (max-width: 900px) {
    .app-shell.has-mobile-nav .history-rail { top: var(--mbar-total); }
}

/* ══════════════════════════════════════════════════════════════
   5 · PHONE — <= 600px
   ══════════════════════════════════════════════════════════════ */
@media (max-width: 600px) {

    .brain-mobilebar-title { font-size: var(--text-base); }

    /* Headers that were laid out as one wide row. */
    .page-header,
    .todo-header {
        flex-direction: column;
        align-items: stretch;
        gap: var(--sp-3);
    }
    .page-header-right,
    .todo-header-right {
        display: flex;
        flex-wrap: wrap;
        gap: var(--sp-2);
    }
    .page-header-right > *,
    .todo-header-right > * { flex: 1 1 auto; justify-content: center; }

    /* Primary/secondary buttons: 44px is the smallest reliably
       tappable target on a phone. */
    .btn-primary,
    .btn-secondary,
    .sb-btn { min-height: 44px; }

    /* Horizontal tab/filter strips scroll instead of wrapping into a
       ragged block that pushes the content below the fold. */
    .todo-tabs,
    .cal-provider-bar,
    .smartbar-modes,
    .provider-switch {
        overflow-x: auto;
        flex-wrap: nowrap;
        scrollbar-width: none;
        -webkit-overflow-scrolling: touch;
    }
    .todo-tabs::-webkit-scrollbar,
    .cal-provider-bar::-webkit-scrollbar,
    .smartbar-modes::-webkit-scrollbar,
    .provider-switch::-webkit-scrollbar { display: none; }
    .todo-tabs > *,
    .cal-provider-bar > * { flex-shrink: 0; }
}

/* ══════════════════════════════════════════════════════════════
   6 · SMALL PHONE — <= 380px
   ══════════════════════════════════════════════════════════════ */
@media (max-width: 380px) {
    .brain-mobilebar { gap: var(--sp-1); padding-inline: var(--sp-1); }
    .brain-mobilebar-logo { display: none; }
    /* max-width has to lift too, or the 320px cap from the 900px block
       makes the wider drawer a no-op. */
    .BRAIN-sidebar,
    .BRAIN-sidebar[data-collapsed="true"] { width: 90vw; max-width: 90vw; }
}

/* ══════════════════════════════════════════════════════════════
   7 · MOTION
   ══════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {
    .brain-scrim,
    .BRAIN-sidebar { transition: none; }
    .bg-orb { animation: none; }
}

/* Coarse pointers get no hover-reveal anywhere — on touch, :hover
   sticks after a tap and leaves controls stuck visible or invisible. */
@media (hover: none) {
    .conversation-menu-btn,
    .sb-doc-del,
    .gallery-item-overlay { opacity: 1; }
    .gallery-item:hover   { transform: none; }
}
