/* ════════════════════════════════════════════════════════════════
   Phase 10.3 — Mobile design tokens
   ════════════════════════════════════════════════════════════════
   Companion to:
     docs/phase-10/mobile-approach.md
     docs/phase-10/mobile-design-system.md

   This file ships *only* tokens + a small set of opt-in utility
   classes. Existing components do NOT consume these — Phase 11+
   batches refactor pages to opt in. Loading this file on the
   current build is a no-op for desktop pages because every rule
   that paints is gated behind a (pointer: coarse) + (max-width)
   media query.

   Source of truth for naming + intent: tokens.md / foundations.md
   (web side) and docs/phase-10/mobile-design-system.md (mobile delta).

   Conventions
   -----------
   - All mobile-only custom properties are prefixed with one of:
       --m-*       generic mobile token
       --bp-*      breakpoint expression (string, used via custom
                   media queries when supported; documented for
                   humans)
       --touch-*   touch / pointer-target sizing
       --compose-* compose-sheet (camera) specific
       --skeleton-* loading-skeleton specific
   - Tokens declared on :root are *static values* that the rest of
     the file (and Phase 11 components) reference. They are safe to
     evaluate at load time even on desktop because they are not
     painted unless wrapped in a mobile media query.
   - Color tokens reuse the existing palette (--accent, --surface,
     etc.) from app.css. No new colors are introduced here.
   ════════════════════════════════════════════════════════════════ */

/* ── 1. Static tokens (always declared, only painted on mobile) ─ */
:root {

    /* Touch targets — pairs with app.css §8.4's existing coarse-pointer
       bump. WCAG 2.2 SC 2.5.5 (Large) recommends ≥44; Apple HIG floor
       is 44pt; Material's comfortable target is 48dp ≈ 48px.  */
    --touch-target-min:          44px;
    --touch-target-comfortable:  48px;
    --touch-target-spacing:      8px;

    /* Safe areas — env(...) values are 0 outside notched/foldable
       contexts, so these tokens stay safe to use on every browser. */
    --safe-area-top:     env(safe-area-inset-top, 0px);
    --safe-area-bottom:  env(safe-area-inset-bottom, 0px);
    --safe-area-left:    env(safe-area-inset-left, 0px);
    --safe-area-right:   env(safe-area-inset-right, 0px);

    /* Spacing extensions on top of the 8px scale (--space-*). */
    --space-thumb-margin: var(--space-2);   /* min bottom padding for scroll regions */
    --space-reach-band:   44vh;             /* bottom 44% = primary-action band */

    /* Mobile shell heights */
    --m-topbar-h:        56px;
    --m-bottomnav-h:     64px;
    --m-bottomnav-total: calc(var(--m-bottomnav-h) + var(--safe-area-bottom));

    /* Typography overrides (mobile only — see §3 of mobile-design-system.md).
       Inter remains the brand font; the system-first stack means iOS
       renders in SF Pro and Android in Roboto with zero network. */
    --m-font-family:
        -apple-system,
        BlinkMacSystemFont,
        "SF Pro Text",
        "Roboto",
        "Inter",
        system-ui,
        sans-serif;
    --m-text-sm:        0.9375rem;   /* 15px — iOS body floor */
    --m-line-height:    1.45;

    /* Skeleton loader — see §7 of mobile-design-system.md */
    --skeleton-bg:      color-mix(in srgb, var(--surface) 80%, var(--border));
    --skeleton-shimmer: color-mix(in srgb, var(--surface-alt) 70%, var(--accent-glow));
    --skeleton-duration: 1.4s;

    /* Offline / queue UX */
    --queue-chip-bg:        var(--warning-glow);
    --queue-chip-text:      var(--warning-text);
    --offline-banner-bg:    var(--info-glow);
    --offline-banner-text:  var(--info-text);

    /* Compose sheet (camera) tokens */
    --compose-shutter-size:    72px;
    --compose-shutter-ring:    4px;
    --compose-shutter-color:   var(--text);
    --compose-thumb-size:      var(--touch-target-min);
    --compose-switch-size:     var(--touch-target-min);
    --compose-toolbar-h:       96px;
    --compose-backdrop:        linear-gradient(
        to top,
        rgba(0, 0, 0, .65) 0%,
        rgba(0, 0, 0, .20) 70%,
        rgba(0, 0, 0, 0)   100%
    );

    /* Bottom-sheet (replaces hover popovers on coarse pointers) */
    --bottom-sheet-radius:   var(--radius-lg);
    --bottom-sheet-handle-w: 36px;
    --bottom-sheet-handle-h: 4px;
    --bottom-sheet-handle-c: color-mix(in srgb, var(--muted) 50%, transparent);

    /* Breakpoint *strings* — kept here for documentation/human use.
       CSS @media takes literal expressions, so we don't reference
       these variables in @media rules; they exist so a developer can
       `grep --bp-` to find the canonical breakpoint values. */
    --bp-mobile: "(max-width: 768px) and (pointer: coarse)";
    --bp-narrow: "(max-width: 480px)";
    --bp-tall:   "(min-height: 700px)";
    --bp-short:  "(max-height: 600px)";

    /* MD-T1: Fluid typography — these tokens live at :root so they evaluate
       on every page, not gated behind a media query. app.css consumes them
       via var(--text-fluid-h1, <fallback>) so the clamp is always available.
       Values from mobile-web-deep-audit-2026-05-18.md §6.1 #1 + §7. */
    --text-fluid-h1:   clamp(1.7rem, 7.5vw, 2.8rem);
    --text-fluid-h2:   clamp(1.35rem, 5.5vw, 2rem);
    --text-fluid-h3:   clamp(1.15rem, 4.5vw, 1.5rem);
    --text-fluid-auth: clamp(1.6rem, 6vw, 2.2rem);
    --text-fluid-body: clamp(0.9375rem, 1.4vw, 1rem);

    /* Pull-to-refresh opt-in flag. 0 = disabled, 1 = enabled (consumed
       by Phase 11.1 Feed page). */
    --mobile-allow-pull-refresh: 0;
}

/* ── 2. Mobile shell behavior (only on coarse-pointer narrow screens) ─ */
@media (max-width: 768px) and (pointer: coarse) {

    /* System-first typography. Phase 11.1 components can opt out by
       setting `font-family: inherit` on a parent. */
    html, body {
        font-family: var(--m-font-family);
        line-height: var(--m-line-height);
    }

    /* Ticket 02 — color-scheme is set on :root[data-theme="..."] in app.css,
       so form controls inherit the active theme's variant. The historical
       dark-only override at :root was removed here when light theme shipped;
       the inherited value carries through automatically. */

    /* Prevent text auto-zoom on rotate (iOS Safari). */
    html {
        -webkit-text-size-adjust: 100%;
    }

    /* Bump small body copy to 15px — Phase 8.4 size --text-sm is
       0.875rem (14px), below iOS HIG floor. Only nudge components
       that opt in via .m-body-sm. */
    .m-body-sm,
    .m-body-sm * {
        font-size: var(--m-text-sm);
    }
}

/* Narrow phone — single-column compose, tighter spacing. */
@media (max-width: 480px) {
    .m-narrow-stack > * + * {
        margin-top: var(--space-2);
    }
}

/* ── 3. Touch-target reinforcement (mobile-explicit, complements §8.4) ─ */
@media (max-width: 768px) and (pointer: coarse) {

    /* Primary CTAs explicitly hit Material's 48dp comfortable size. The
       existing app.css §8.4 rule sets 44×44; this opt-in class bumps
       buttons that act as a page's main action. Phase 11 components
       add `.m-cta` to such buttons. */
    .m-cta {
        min-height: var(--touch-target-comfortable);
        min-width:  var(--touch-target-comfortable);
        padding: var(--space-1-5) var(--space-3);
    }

    .m-cta + .m-cta {
        margin-top: var(--touch-target-spacing);
    }
}

/* ── 4. Bottom navigation (mobile shell) ────────────────────────── */
/* Component styling lives in app.css under "Frontend-handoff migration —
   MobileBottomNav (CSS prep)" — see the .mobile-bottom-nav / .mbn__item /
   .mbn__fab block there. This file only contributes the body-padding helper
   used by .m-with-bottomnav so page content clears the fixed bar. The
   visibility gate `(max-width: 48rem)` matches app.css's bar-visibility
   query so padding is reserved exactly when the bar is on screen. */
@media (max-width: 48rem) {
    .m-with-bottomnav {
        padding-bottom: var(--m-bottomnav-total);
    }

    /* Existing top navbar respects safe-area-top once a page opts in. */
    .m-safe-top {
        padding-top: calc(8px + env(safe-area-inset-top, 0px));
    }
}

@media (max-width: 48rem) and (orientation: landscape) and (max-height: 500px) {
    /* Landscape phones hide the bar (app.css) — drop the padding too. */
    .m-with-bottomnav { padding-bottom: 0; }
}

/* ── 5. Bottom-sheet (replaces hover popovers on coarse pointers) ── */
.bottom-sheet {
    /* Hidden by default; component logic toggles aria-hidden + class. */
    display: none;
}

/* MD-T3: activate on coarse-pointer narrow screens (phones) AND on any
   narrow window regardless of pointer type (narrow desktop browser,
   DevTools mobile emulation, audit harness). The two blocks share the
   same rule set so they stay in sync. */
@media (max-width: 768px) and (pointer: coarse) {
    .bottom-sheet {
        display: block;
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 40;
        background: var(--surface);
        border-top-left-radius: var(--bottom-sheet-radius);
        border-top-right-radius: var(--bottom-sheet-radius);
        padding: var(--space-2) var(--space-3)
                 calc(var(--space-3) + var(--safe-area-bottom));
        box-shadow: var(--shadow-lg);
        transform: translateY(100%);
        transition: transform var(--duration-slow) var(--easing-emphasis);
    }

    .bottom-sheet[aria-hidden="false"],
    .bottom-sheet.is-open {
        transform: translateY(0);
    }

    .bottom-sheet::before {
        content: "";
        display: block;
        width: var(--bottom-sheet-handle-w);
        height: var(--bottom-sheet-handle-h);
        border-radius: var(--radius-pill);
        background: var(--bottom-sheet-handle-c);
        margin: 0 auto var(--space-1-5);
    }

    @media (prefers-reduced-motion: reduce) {
        .bottom-sheet { transition: none; }
    }
}

/* Non-coarse narrow window fallback — exact same rules, pointer: fine
   (mouse/trackpad on a small window or DevTools emulation). */
@media (max-width: 768px) and (pointer: fine) {
    .bottom-sheet {
        display: block;
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 40;
        background: var(--surface);
        border-top-left-radius: var(--bottom-sheet-radius);
        border-top-right-radius: var(--bottom-sheet-radius);
        padding: var(--space-2) var(--space-3)
                 calc(var(--space-3) + var(--safe-area-bottom));
        box-shadow: var(--shadow-lg);
        transform: translateY(100%);
        transition: transform var(--duration-slow) var(--easing-emphasis);
    }

    .bottom-sheet[aria-hidden="false"],
    .bottom-sheet.is-open {
        transform: translateY(0);
    }

    .bottom-sheet::before {
        content: "";
        display: block;
        width: var(--bottom-sheet-handle-w);
        height: var(--bottom-sheet-handle-h);
        border-radius: var(--radius-pill);
        background: var(--bottom-sheet-handle-c);
        margin: 0 auto var(--space-1-5);
    }

    @media (prefers-reduced-motion: reduce) {
        .bottom-sheet { transition: none; }
    }
}

/* ── 6. Skeleton loader ─────────────────────────────────────────── */
.skeleton {
    background: var(--skeleton-bg);
    border-radius: var(--radius-sm);
    position: relative;
    overflow: hidden;
    color: transparent;
    user-select: none;
}

@media (prefers-reduced-motion: no-preference) {
    .skeleton::after {
        content: "";
        position: absolute;
        inset: 0;
        background: linear-gradient(
            90deg,
            transparent 0%,
            var(--skeleton-shimmer) 50%,
            transparent 100%
        );
        animation: m-skeleton-shimmer var(--skeleton-duration) ease-in-out infinite;
    }

    @keyframes m-skeleton-shimmer {
        0%   { transform: translateX(-100%); }
        100% { transform: translateX(100%); }
    }
}

/* ── 7. Compose sheet (camera) ──────────────────────────────────── */
.compose-sheet {
    display: none;
}

@media (max-width: 768px) and (pointer: coarse) {
    .compose-sheet {
        display: flex;
        flex-direction: column;
        position: fixed;
        inset: 0;
        z-index: 50;
        background: #000;
        color: var(--text);
        padding-top: var(--safe-area-top);
    }

    .compose-sheet__viewfinder {
        flex: 1;
        position: relative;
        background: #000;
        overflow: hidden;
    }

    .compose-sheet__topbar,
    .compose-sheet__toolbar {
        position: absolute;
        left: 0;
        right: 0;
        display: flex;
        align-items: center;
        padding: var(--space-2) var(--space-3);
        background: var(--compose-backdrop);
    }
    .compose-sheet__topbar    { top: 0;   justify-content: space-between; padding-top: calc(var(--space-2) + var(--safe-area-top)); }
    .compose-sheet__toolbar   { bottom: 0; min-height: var(--compose-toolbar-h); justify-content: space-between; padding-bottom: calc(var(--space-2) + var(--safe-area-bottom)); }

    .compose-sheet__shutter {
        width:  var(--compose-shutter-size);
        height: var(--compose-shutter-size);
        border-radius: 50%;
        background: var(--compose-shutter-color);
        border: var(--compose-shutter-ring) solid var(--compose-shutter-color);
        outline: 2px solid #000;
        box-shadow: 0 0 0 4px var(--text);
    }
    .compose-sheet__shutter:active { transform: scale(.95); }

    .compose-sheet__thumb,
    .compose-sheet__switch {
        width:  var(--touch-target-min);
        height: var(--touch-target-min);
        border-radius: var(--radius-sm);
        background: color-mix(in srgb, var(--surface) 60%, transparent);
        border: 1px solid var(--border);
        display: flex;
        align-items: center;
        justify-content: center;
    }
}

/* ── 8. Offline + queue chips ───────────────────────────────────── */
.m-queue-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--space-0-5);
    background: var(--queue-chip-bg);
    color: var(--queue-chip-text);
    border-radius: var(--radius-pill);
    padding: 2px var(--space-1);
    font-size: var(--text-xs);
    font-weight: 600;
    min-height: 24px;  /* WCAG floor preserved on all viewports */
}

.m-offline-banner {
    background: var(--offline-banner-bg);
    color: var(--offline-banner-text);
    text-align: center;
    padding: var(--space-1) var(--space-2);
    font-size: var(--text-sm);
    border-bottom: 1px solid var(--border);
}

/* ── 9. Outdoor / high-contrast mode ────────────────────────────── */
@media (prefers-contrast: more) {
    .m-cta,
    .mobile-bottom-nav__action {
        outline: 1px solid #fff;
        outline-offset: -1px;
    }
}

/* ── 10. Pull-to-refresh opt-in scope ───────────────────────────── */
/* Components opt in by adding .m-allow-pull-refresh on the scroll
   container; the host element gets `overscroll-behavior: contain`
   so the default browser pull behavior is suppressed elsewhere.   */
.m-allow-pull-refresh {
    overscroll-behavior-y: contain;
    --mobile-allow-pull-refresh: 1;
}

/* ── 11. Landscape-phone: bottom sheets become side sheets ──────────────
   At (orientation: landscape) and (max-height: 500px) a bottom sheet
   would be only ~150px tall — unusable. We convert to a left-anchored
   side sheet instead. The swipe gesture in caploo.bottom-sheet.js
   switches from swipe-down-to-dismiss to swipe-left-to-dismiss in
   the same orientation. */
@media (orientation: landscape) and (max-height: 500px) {
    .bottom-sheet {
        /* Reset the bottom-anchored position from §5. */
        inset: 0 auto 0 0;
        /* Full viewport height — svh is the tightest safe value (never
           counts the URL bar); fall back to vh for older engines. */
        height: 100svh;
        height: 100vh;
        width: min(90vw, 24rem);
        /* Left-anchored border radius — rounded on the right side only. */
        border-radius: 0 var(--bottom-sheet-radius) var(--bottom-sheet-radius) 0;
        /* Side-entry transform replaces the vertical one from §5. */
        transform: translateX(-100%);
        transition: transform var(--duration-slow) var(--easing-emphasis);
        /* Override the bottom padding from §5 that compensates for the
           safe-area-inset-bottom — no longer relevant on a side sheet. */
        padding: var(--space-3) var(--space-3) var(--space-3);
    }

    .bottom-sheet[aria-hidden="false"],
    .bottom-sheet.is-open {
        transform: translateX(0);
    }

    /* Hide drag handle — it implies vertical swipe which doesn't apply
       to a side sheet anchored on the left. */
    .bottom-sheet::before {
        display: none;
    }

    @media (prefers-reduced-motion: reduce) {
        .bottom-sheet { transition: none; }
    }
}

/* ════════════════════════════════════════════════════════════════
   End — mobile design tokens
   ════════════════════════════════════════════════════════════════ */
