/* ==========================================================================
   NetrAI — Mobile application layer
   --------------------------------------------------------------------------
   `css/layout/mobile.css` made the desktop site *survive* a phone: no overflow, no
   4px type, no unreachable controls. This file is a different job. It gives
   the phone its own shape.

   The complaint this answers is a real one — the old phone build was one
   narrow centred column, fourteen screens deep on the homepage and seventeen
   on pricing, because every desktop row simply became another stacked block.
   Nothing about it was decided by the fact that a phone is tall, narrow, held
   in one hand and driven by a thumb.

   So four things change:

     1. NAVIGATION MOVES TO THE THUMB. A fixed tab bar at the bottom, plus a
        "More" sheet. The top of a 6.5" phone is the hardest place on the
        device to reach; a menu button up there is a desktop habit.

     2. ROWS BECOME DECKS. Anything that was a grid of three-to-eight sibling
        cards turns into a horizontal snap rail with dots. A phone swipes far
        more comfortably than it scrolls past nine near-identical panels, and
        it cuts the homepage from ~14 screens to ~6.

     3. THE PAGE GOES EDGE TO EDGE. Rails bleed to both edges of the screen,
        so cards are cut by the screen rather than floating inside a gutter —
        that single detail is most of what makes an interface read as native.

     4. THE FIRST SCREEN IS A SCREEN. The hero is sized to the viewport with
        `dvh`, headline and live demo together, with a scroll cue.

   LOADING ORDER — this file must be LAST, after mobile.css and center.css,
   because it deliberately overrides both.

   SCOPING — everything is inside `html.m-app`, a class set by
   js/layout/mobile-app.js only on a narrow screen. Two consequences worth keeping:
   the desktop is provably untouched, and if the script fails the original
   mobile layout is still there, hamburger and all, rather than a page with no
   navigation at all.
   ========================================================================== */

@media (max-width: 860px) {
  html.m-app {
    /* One gutter value for the whole layer. Rails use it to line their first
       card up with the body text while still bleeding past both edges. */
    --m-gut: 18px;
    --m-tabs: 62px;         /* tab bar, before the safe-area inset */
    --m-top: 56px;          /* the shrunken header */
    --m-radius: 8px;
  }

  /* -----------------------------------------------------------------------
     1. Foundations
     ----------------------------------------------------------------------- */
  html.m-app body {
    /* Content has to clear the tab bar, including the home-indicator strip. */
    padding-bottom: calc(var(--m-tabs) + env(safe-area-inset-bottom, 0px));
  }

  html.m-app .container {
    padding-left: max(var(--m-gut), env(safe-area-inset-left, 0px));
    padding-right: max(var(--m-gut), env(safe-area-inset-right, 0px));
  }

  /* Sections at a phone's pace. mobile.css already cut these; this cuts them
     again, because a rail is a much shorter block than the stack it replaces
     and the old spacing left the page feeling gappy. */
  html.m-app section { padding: 56px 0; }
  html.m-app section.chapter { padding: 60px 0; }
  html.m-app .section-head { margin-bottom: 26px; }

  /* Type ramp. A phone headline can be proportionally larger than a desktop
     one — there is only ever one thing on screen, so it does not have to
     share the room with anything. */
  html.m-app h1 { font-size: clamp(2rem, 9.2vw, 2.75rem); line-height: 1.08; letter-spacing: -0.03em; }
  html.m-app h2 { font-size: clamp(1.7rem, 7.4vw, 2.2rem);  line-height: 1.12; letter-spacing: -0.025em; }
  html.m-app h3 { font-size: 1.12rem; line-height: 1.25; }
  html.m-app .lead { font-size: 1rem; line-height: 1.6; }
  html.m-app .eyebrow { font-size: 0.7rem; letter-spacing: 0.18em; }

  /* -----------------------------------------------------------------------
     2. Header — reduced to a logo and a search key
     -----------------------------------------------------------------------
     Everything that was in the top bar now lives in the tab bar or the More
     sheet, so the header's only remaining jobs are identity and search. */
  html.m-app .site-header {
    height: var(--m-top);
    padding-top: env(safe-area-inset-top, 0px);
    background: color-mix(in srgb, var(--void) 78%, transparent);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
    border-bottom: 1px solid var(--line);
  }
  html.m-app .nav {
    height: var(--m-top);
    display: flex;
    align-items: center;
    padding: 0 var(--m-gut);
    gap: 12px;
  }
  html.m-app .nav-links-wrapper,
  html.m-app .nav-toggle,
  html.m-app .nav-cta,
  html.m-app .nav-cta-btn { display: none !important; }

  html.m-app .nav-actions { margin-left: auto; display: flex; align-items: center; gap: 8px; }
  html.m-app .nav-search-btn {
    width: 40px; height: 40px;
    padding: 0;
    border-radius: 50%;
    display: grid; place-items: center;
  }
  html.m-app .nav-search-kbd { display: none; }
  html.m-app .logo-mark img { height: 26px; }

  /* -----------------------------------------------------------------------
     3. Bottom tab bar
     ----------------------------------------------------------------------- */
  .m-tabs {
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 9400;
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    align-items: stretch;
    height: calc(var(--m-tabs) + env(safe-area-inset-bottom, 0px));
    padding-bottom: env(safe-area-inset-bottom, 0px);
    background: color-mix(in srgb, var(--void) 86%, transparent);
    backdrop-filter: blur(22px) saturate(160%);
    -webkit-backdrop-filter: blur(22px) saturate(160%);
    border-top: 1px solid var(--line);
  }

  .m-tab {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    padding: 0 2px;
    color: var(--mist-dim);
    font-size: 0.65rem;
    letter-spacing: 0.01em;
    text-decoration: none;
    -webkit-tap-highlight-color: transparent;
    transition: color 0.2s ease;
  }
  .m-tab svg { width: 22px; height: 22px; stroke-width: 1.7; }
  .m-tab.is-active { color: var(--ink); }
  .m-tab.is-active svg { color: var(--accent); }

  /* The active pill is a lit bar above the icon rather than a filled tab, so
     the bar stays quiet against a dark page. */
  .m-tab.is-active::before {
    content: "";
    position: absolute;
    top: 0;
    width: 26px; height: 2px;
    border-radius: 0 0 3px 3px;
    background: var(--accent-fill);
    box-shadow: none;
  }
  .m-tab:active { color: var(--ink); }

  /* -----------------------------------------------------------------------
     4. "More" sheet
     ----------------------------------------------------------------------- */
  .m-sheet-scrim {
    position: fixed; inset: 0;
    z-index: 9450;
    background: rgba(0, 0, 0, 0.6);
    backdrop-filter: blur(3px);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s ease;
  }
  .m-sheet-scrim.is-open { opacity: 1; pointer-events: auto; }

  .m-sheet {
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 9460;
    padding: 10px var(--m-gut) calc(20px + env(safe-area-inset-bottom, 0px));
    border-radius: var(--radius) var(--radius) 0 0;
    background: var(--surface-2);
    border-top: 1px solid var(--line-strong);
    box-shadow: none;
    transform: translateY(101%);
    transition: transform 0.42s cubic-bezier(0.22, 1, 0.36, 1);
  }
  .m-sheet.is-open { transform: none; }

  /* js/layout/mobile-app.js drives the sheet's offset in pixels with a spring, so
     the CSS transition has to get out of the way — two things animating the
     same property is how a drag ends up fighting a tween. The rules above
     stay as the no-JS fallback: without this class the sheet still opens and
     closes on the class alone. */
  .m-sheet--fluid { transition: none; }

  .m-sheet-grip {
    width: 38px; height: 4px;
    border-radius: 999px;
    background: var(--line-strong);
    margin: 4px auto 16px;
  }
  .m-sheet-links { display: grid; gap: 6px; margin-bottom: 14px; }
  .m-sheet-links a {
    display: flex;
    align-items: center;
    gap: 14px;
    min-height: 52px;
    padding: 0 14px;
    border-radius: var(--radius);
    color: var(--ink);
    font-size: 1rem;
    text-decoration: none;
    background: var(--surface-canvas);
    border: 1px solid var(--line);
  }
  .m-sheet-links a svg { width: 20px; height: 20px; color: var(--mist); flex: none; }
  .m-sheet-links a.is-active { border-color: var(--accent); }
  .m-sheet-links a.is-active svg { color: var(--accent); }
  .m-sheet-links a:active { background: var(--surface-canvas); }
  .m-sheet .btn { width: 100%; justify-content: center; min-height: 52px; }

  /* -----------------------------------------------------------------------
     5. Floating widgets get out of the tab bar's way
     ----------------------------------------------------------------------- */
  html.m-app .back-to-top {
    right: var(--m-gut);
    bottom: calc(var(--m-tabs) + env(safe-area-inset-bottom, 0px) + 74px);
    width: 42px; height: 42px;
    z-index: 9300;
  }
  /* The site tour pins itself bottom-right at a z-index of 2147483000, which
     is above everything including the tab bar. Left alone its launcher lands
     exactly on the "More" tab. Everything it puts on screen is lifted clear. */
  html.m-app .aitg-launcher {
    bottom: calc(var(--m-tabs) + env(safe-area-inset-bottom, 0px) + 14px) !important;
    right: var(--m-gut) !important;
    width: 48px !important; height: 48px !important;
  }
  /* The launcher now lives in the header, so its bubble drops from the header
     too. Left at the bottom it covered the hero's buttons — the one thing on
     the first screen a visitor is meant to press. */
  html.m-app .aitg-bubble,
  html.m-app .aitg-dock {
    top: calc(var(--m-top) + env(safe-area-inset-top, 0px) + 10px) !important;
    bottom: auto !important;
    left: var(--m-gut) !important;
    right: var(--m-gut) !important;
    width: auto !important;
    max-width: none !important;
  }
  html.m-app .toast { bottom: calc(var(--m-tabs) + env(safe-area-inset-bottom, 0px) + 16px); }

  /* The old nav drawer is reparented to <body> and stays in the DOM as a
     full-screen fixed panel. With the hamburger gone it can never be opened,
     so it is removed from the page rather than left lying over the content. */
  html.m-app body:not(.nav-open) > .nav-links { display: none !important; }

  /* -----------------------------------------------------------------------
     6. Hero — one screen, not a scroll
     ----------------------------------------------------------------------- */
  html.m-app .hero {
    position: relative;
    /* "One screen" on a phone with a tab bar means the height between the
       header and the bar, not the whole viewport. Measuring against 100dvh
       alone put the hero's last 60px underneath the tab bar. */
    min-height: calc(100dvh - var(--m-top) - var(--m-tabs) - env(safe-area-inset-bottom, 0px));
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 20px;
    /* The header participates in normal flow, so the hero already starts
       below it. Adding its height here again pushed the demo off the fold. */
    padding: 18px 0 48px;
  }
  html.m-app .hero-inner { padding: 0 var(--m-gut); }
  html.m-app .hero h1 { text-wrap: balance; }
  /* The hero is a gap-based flex column here, so the margins mobile.css puts
     on these children are counted twice — once as a margin and once as the
     gap. Forty stray pixels is exactly enough to push the buttons under the
     tab bar, and it is also the amount the height measurement in
     js/layout/mobile-app.js cannot see. */
  html.m-app .hero-visual { padding: 0 var(--m-gut); margin-top: 0 !important; }

  /* The live dashboard is the proof; on a phone it should be as large as the
     remaining height allows rather than a postage stamp under the headline. */
  html.m-app .hero .video-frame { border-radius: var(--m-radius); }

  .m-cue {
    /* Absolute, so it sits in the hero's bottom padding instead of adding a
       fifth row to a layout that has to fit one screen exactly. */
    position: absolute;
    left: 0; right: 0; bottom: 12px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    transition: opacity 0.3s ease;
    font-size: 0.68rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--mist-dim);
  }
  .m-cue span { animation: mCue 2.2s ease-in-out infinite; }
  .m-cue svg { width: 16px; height: 16px; animation: mCue 2.2s ease-in-out infinite 0.1s; }
  @keyframes mCue {
    0%, 100% { opacity: 0.45; transform: translateY(0); }
    50%      { opacity: 1;    transform: translateY(3px); }
  }

  /* Page heroes on the inner pages get the same treatment at a smaller size —
     they are a title, not a screen. */
  html.m-app .page-hero { padding: calc(var(--m-top) + 44px) 0 20px; min-height: 0; }

  /* -----------------------------------------------------------------------
     7. Swipe rails
     -----------------------------------------------------------------------
     js/layout/mobile-app.js adds .m-rail to any grid of sibling cards. The bleed is
     done with `margin-inline: calc(50% - 50vw)` rather than a negative margin
     matching the container padding, so it stays correct no matter which of
     the four container-padding rules is in force at that width. */
  html.m-app .m-rail {
    display: flex !important;
    grid-template-columns: none !important;
    flex-wrap: nowrap;
    gap: 12px;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
    margin-inline: calc(50% - 50vw);
    padding-inline: max(var(--m-gut), env(safe-area-inset-left, 0px));
    padding-block: 4px 8px;
  }
  html.m-app .m-rail::-webkit-scrollbar { display: none; }

  html.m-app .m-rail > * {
    flex: 0 0 80%;
    max-width: 340px;
    scroll-snap-align: center;
    scroll-snap-stop: always;
    margin: 0 !important;
    /* Cards in a rail are all as tall as the tallest, so the deck does not
       jitter vertically as you swipe through it. */
    align-self: stretch;
  }
  /* A trailing spacer so the last card can centre itself. Without it the rail
     runs out of scroll and the final card sits pinned to the right edge. */
  html.m-app .m-rail::after {
    content: "";
    flex: 0 0 max(var(--m-gut), env(safe-area-inset-right, 0px));
  }

  /* Two-up for anything small enough that 80% would be silly. */
  html.m-app .m-rail.m-rail-sm > * { flex-basis: 62%; }

  /* Cards inside a rail: flatter, cheaper, and no hover lift to get stuck in. */
  html.m-app .m-rail > .card,
  html.m-app .m-rail > * {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    border-radius: var(--m-radius);
  }
  html.m-app .m-rail > .card { padding: 22px 20px; }
  html.m-app .m-rail > *:hover { transform: none !important; }

  /* Dots */
  .m-dots {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 7px;
    margin-top: 16px;
  }
  .m-dots i {
    width: 6px; height: 6px;
    border-radius: 999px;
    background: var(--line-strong);
    transition: width 0.3s cubic-bezier(0.22, 1, 0.36, 1), background 0.3s ease;
  }
  .m-dots i.is-on { width: 20px; background: var(--accent-fill); }

  /* -----------------------------------------------------------------------
     8. Reviews — one card at a time
     -----------------------------------------------------------------------
     The desktop version is a pinned horizontal rail driven by page scroll.
     That gesture does not exist on a phone, and the fallback stacked eight
     full-height testimonials into a 3,380px section. Here it is a plain deck
     you swipe, like everything else on the page. */
  html.m-app .reviews-chapter { height: auto !important; min-height: 0 !important; }
  html.m-app .reviews-pin,
  html.m-app .reviews-viewport { position: static !important; height: auto !important; overflow: visible !important; }
  html.m-app .reviews-track {
    display: flex !important;
    transform: none !important;
    width: auto !important;
    gap: 12px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    margin-inline: calc(50% - 50vw);
    padding-inline: max(var(--m-gut), env(safe-area-inset-left, 0px));
    padding-block: 4px 8px;
  }
  html.m-app .reviews-track::-webkit-scrollbar { display: none; }
  html.m-app .reviews-track > * {
    flex: 0 0 84%;
    max-width: 360px;
    scroll-snap-align: center;
    margin: 0 !important;
  }
  html.m-app .reviews-track::after {
    content: "";
    flex: 0 0 max(var(--m-gut), env(safe-area-inset-right, 0px));
  }

  /* -----------------------------------------------------------------------
     9. Demos section
     ----------------------------------------------------------------------- */
  html.m-app .demo-switch { margin-bottom: 18px; }
  html.m-app .demo-window { border-radius: var(--m-radius); }
  html.m-app .demo-try-chips { display: contents; }

  /* -----------------------------------------------------------------------
     10. Footer — the tab bar has taken over navigation, so the footer's link
         columns are duplicated furniture. Keep the brand, the CTA and the
         legal line; drop the rest.
     ----------------------------------------------------------------------- */
  html.m-app .footer-grid .footer-col:not(.footer-col-brand) { display: none; }
  html.m-app .footer-cta-giant { font-size: clamp(1.9rem, 8.4vw, 2.4rem); }
  html.m-app .site-footer { padding-bottom: 26px; }

  /* -----------------------------------------------------------------------
     11. Touch hygiene
     ----------------------------------------------------------------------- */
  html.m-app * { -webkit-tap-highlight-color: var(--fill-subtle); }
  html.m-app .card:hover,
  html.m-app .teaser-card:hover { transform: none; }
}

/* The tab bar and sheet are built for phones only; if the viewport grows past
   the breakpoint (rotation, a foldable opening) they get out of the way and
   the real nav comes back. */
@media (min-width: 861px) {
  .m-tabs, .m-sheet, .m-sheet-scrim { display: none !important; }
}

@media (prefers-reduced-motion: reduce) {
  .m-cue span, .m-cue svg { animation: none; }
  .m-sheet { transition: none; }
}

/* ==========================================================================
   Mobile application layer — part two
   --------------------------------------------------------------------------
   Everything above gave the phone its shape. This part fixes the two sections
   that were still costing a visitor most of the page: reviews and the pricing
   builder. Between them they were sixteen of the twenty-eight screens a phone
   visitor had to scroll through across the whole site.
   ========================================================================== */

@media (max-width: 860px) {

  /* -----------------------------------------------------------------------
     12. Reviews — the last piece of the pin
     -----------------------------------------------------------------------
     Section 8 unpinned the panel, but `.reviews-stage` is the element the
     scroll-driven version grows to 3,144px so the pinned panel has something
     to travel against. With the pin gone that height is just empty page. */
  html.m-app .reviews-stage { height: auto !important; min-height: 0 !important; }
  html.m-app .reviews-panel { padding: 22px 0; border-radius: var(--m-radius); }
  html.m-app .reviews-panel::before { display: none; }   /* one less blur layer */

  /* -----------------------------------------------------------------------
     13. Pricing builder — accordion
     -----------------------------------------------------------------------
     Ten categories × six or seven priced line items is 65 rows. On desktop
     that is a scannable menu you take in at a glance; on a phone it was a
     twelve-screen wall, and a visitor had to scroll past nine categories they
     did not want to reach the one they did.

     Collapsed, each category is a single 64px row that still tells you how
     many items you have picked inside it, so nothing is hidden — it is just
     closed. The first one opens by default so the pattern is obvious. */
  html.m-app .price-category { margin-bottom: 10px; }

  html.m-app .m-acc {
    border: 1px solid var(--line);
    border-radius: var(--m-radius);
    background: var(--surface-canvas);
    overflow: hidden;
    transition: border-color 0.25s ease;
  }
  html.m-app .m-acc.is-open { border-color: var(--line-strong); }

  html.m-app .m-acc > .price-category-head {
    margin: 0;
    padding: 14px 14px 14px 16px;
    min-height: 64px;
    gap: 10px;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  html.m-app .m-acc > .price-category-head h3 { font-size: 1rem; line-height: 1.25; }
  html.m-app .m-acc > .price-category-head .cat-icon { width: 34px; height: 34px; }
  html.m-app .m-acc > .price-category-head .cat-icon svg { width: 17px; height: 17px; }
  html.m-app .m-acc > .price-category-head .cat-icon-title { gap: 10px; min-width: 0; }

  /* Select-all is a real action inside a row that is otherwise a toggle, so
     it has to look like a control rather than a label. */
  html.m-app .m-acc .cat-selectall-btn {
    font-size: 0.72rem;
    padding: 7px 10px;
    white-space: nowrap;
  }
  html.m-app .m-acc:not(.is-open) .cat-selectall-btn { display: none; }

  /* How many of this category's items are in the cart. */
  .m-acc-count {
    flex: none;
    min-width: 22px;
    height: 22px;
    padding: 0 7px;
    border-radius: 999px;
    display: none;
    place-items: center;
    background: var(--accent-fill);
    color: #fff;
    font-size: 0.72rem;
    font-weight: 600;
  }
  .m-acc-count.is-on { display: grid; }

  .m-acc-chev {
    flex: none;
    width: 26px; height: 26px;
    display: grid; place-items: center;
    color: var(--mist-dim);
    transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
  }
  .m-acc-chev svg { width: 18px; height: 18px; }
  html.m-app .m-acc.is-open .m-acc-chev { transform: rotate(180deg); color: var(--accent); }

  /* `[hidden]` is a UA rule of `display: none`, and any author `display` wins
     over it — `.price-list` is a grid, so the attribute alone did nothing and
     the accordion collapsed to exactly the height it started at. */
  html.m-app .m-acc > .price-list[hidden],
  html.m-app .m-acc > .price-category-note[hidden] { display: none !important; }

  html.m-app .m-acc > .price-category-note { padding: 0 16px; margin: 0 0 12px; }
  html.m-app .m-acc > .price-list { padding: 0 12px 12px; gap: 8px; }
  html.m-app .m-acc .price-item { padding: 14px 12px; border-radius: var(--radius); }
  html.m-app .m-acc .price-item .item-desc { font-size: 0.78rem; }

  /* The aisle headings between groups of categories. */
  html.m-app .pricing-aisle-head { margin: 26px 0 12px; }
  html.m-app .pricing-aisle-head h2 { font-size: 1.15rem; letter-spacing: 0.02em; }
  html.m-app .pricing-aisle-head:first-child { margin-top: 0; }

  /* -----------------------------------------------------------------------
     14. FAQ — same treatment, and it already had the machinery
     ----------------------------------------------------------------------- */
  html.m-app .faq-question { min-height: 56px; padding: 14px 16px; font-size: 0.98rem; }
  html.m-app .faq-answer-inner { padding: 0 16px 16px; font-size: 0.92rem; }

  /* -----------------------------------------------------------------------
     15. The cart, on a phone, is a bar — not a column
     -----------------------------------------------------------------------
     `.cart-panel` is a 743px sidebar. Docked above the tab bar it becomes the
     running total you actually want while you are ticking boxes, and it opens
     to the full panel on tap. */
  html.m-app .cart-panel {
    position: static !important;
    width: auto !important;
    max-height: none !important;
    margin-top: 22px;
  }
}

/* ==========================================================================
   Mobile application layer — part three
   The pieces that make it read as an application rather than a page: an action
   on the first screen, a bar that says where you are, and a segmented control
   where the desktop had a row of cards.
   ========================================================================== */

@media (max-width: 860px) {

  /* -----------------------------------------------------------------------
     16. Hero actions
     ----------------------------------------------------------------------- */
  .m-hero-cta {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 10px;
    padding: 0 var(--m-gut);
  }
  .m-hero-cta .btn { min-height: 50px; justify-content: center; font-size: 0.95rem; }
  .m-hero-alt {
    border: 1px solid var(--line-strong);
    background: var(--surface-canvas);
    color: var(--ink);
    padding-inline: 18px;
  }

  /* Four rows now have to share one screen: headline, demo, buttons, and the
     hero's own padding. The demo gives back the 50px the buttons need — but
     by being *shorter*, not by being clipped. A `max-height` cut the panel
     through the middle of its own chip row, which looks like a rendering bug
     rather than a smaller demo. 470px is the height the small-phone
     breakpoint in mobile.css already uses, so the panel is laid out for it. */
  html.m-app .hero { padding: 12px 0 16px; gap: 16px; }
  /* A starting value only — js/layout/mobile-app.js measures the real leftover and
     writes the final height inline. See the note there. */
  html.m-app .hero .video-frame:has(.nd) { height: min(440px, 54dvh); }

  /* The cue would sit on top of the buttons; it has done its job either way
     once there is something tappable on screen. */
  html.m-app .hero .m-cue { display: none; }

  /* -----------------------------------------------------------------------
     17. Sticky chapter bar
     -----------------------------------------------------------------------
     Sits directly under the header and only appears once the hero is behind
     you. The hairline underneath doubles as a read-progress bar. */
  .m-chapter {
    position: fixed;
    top: calc(var(--m-top) + env(safe-area-inset-top, 0px));
    left: 0; right: 0;
    z-index: 9200;
    display: flex;
    align-items: center;
    height: 34px;
    padding: 0 var(--m-gut);
    background: color-mix(in srgb, var(--void) 82%, transparent);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border-bottom: 1px solid var(--line);
    transform: translateY(-100%);
    opacity: 0;
    transition: transform 0.32s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.25s ease;
    pointer-events: none;
  }
  .m-chapter.is-on { transform: none; opacity: 1; }

  .m-chapter-name {
    font-size: 0.72rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--mist);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .m-chapter-progress {
    position: absolute;
    left: 0; right: 0; bottom: -1px;
    height: 2px;
  }
  .m-chapter-progress i {
    display: block;
    height: 100%;
    width: 0;
    background: var(--gradient-iris);
  }

  /* -----------------------------------------------------------------------
     18. Demos — segmented control
     ----------------------------------------------------------------------- */
  html.m-app .m-seg {
    display: grid !important;
    grid-template-columns: repeat(3, 1fr);
    gap: 4px;
    padding: 4px;
    border-radius: var(--radius);
    background: var(--surface-canvas);
    border: 1px solid var(--line);
  }
  html.m-app .m-seg .demo-tab {
    padding: 10px 4px;
    border: 0;
    border-radius: var(--radius);
    background: transparent;
    align-items: center;
    gap: 6px;
    min-height: 58px;
  }
  html.m-app .m-seg .demo-tab::before { display: none; }
  html.m-app .m-seg .demo-tab[aria-selected="true"] {
    background: color-mix(in srgb, var(--demo-accent) 18%, var(--fill-hover));
  }
  html.m-app .m-seg .demo-tab-top { flex-direction: column; gap: 6px; }
  html.m-app .m-seg .demo-tab-dot { width: 20px; height: 20px; border-radius: 7px; }
  html.m-app .m-seg .demo-tab-name { font-size: 0.86rem; }
  html.m-app .m-seg .demo-tab-desc,
  html.m-app .m-seg .demo-tab-for { display: none; }

  /* The try-row reads better as its own scrollable line than as chips wrapped
     under a label that then wraps too. */
  html.m-app .demo-try { flex-direction: column; align-items: stretch; gap: 8px; }
  html.m-app .demo-try-chips {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    scrollbar-width: none;
    margin-inline: calc(50% - 50vw);
    padding-inline: var(--m-gut);
  }
  html.m-app .demo-try-chips::-webkit-scrollbar { display: none; }
  html.m-app .demo-chip { flex: none; }

  /* -----------------------------------------------------------------------
     19. Floating widgets — final clearances
     -----------------------------------------------------------------------
     The tour guide writes its position inline, so these have to out-specify
     an inline style; and its launcher glow reads as an overlap even when the
     box itself clears the bar, so it is lifted further than geometry needs. */
  /* Lifted out of the corner entirely and docked in the header — see the note
     in js/layout/mobile-app.js. Everything here is `!important` because the tour
     writes its own position inline. */
  html.m-app .aitg-launcher.m-aitg-inbar {
    position: static !important;
    inset: auto !important;
    /* Was 38px. The header row is 56px tall, so the floor fits with room to
       spare and the glyph inside is unchanged. */
    width: 44px !important;
    height: 44px !important;
    margin: 0 !important;
    box-shadow: none;
    transform: none !important;
    flex: none;
  }
  html.m-app .aitg-launcher.m-aitg-inbar::before,
  html.m-app .aitg-launcher.m-aitg-inbar::after { display: none !important; }

  /* Until it has been moved it must not sit under the tab bar. */
  html.m-app .aitg-launcher:not(.m-aitg-inbar) {
    bottom: calc(var(--m-tabs) + env(safe-area-inset-bottom, 0px) + 16px) !important;
  }
  /* Clear of the tab bar and of a hero action row sitting above it. */
  html.m-app .toast {
    bottom: calc(var(--m-tabs) + env(safe-area-inset-bottom, 0px) + 110px) !important;
  }
  html.m-app .back-to-top {
    bottom: calc(var(--m-tabs) + env(safe-area-inset-bottom, 0px) + 86px);
  }
}

/* ==========================================================================
   Mobile application layer — part four: last passes
   ========================================================================== */

@media (max-width: 860px) {

  /* -----------------------------------------------------------------------
     20. Tier selector — two up
     -----------------------------------------------------------------------
     Four tiers stacked is 320px of a phone screen spent on what is really one
     control. Two-by-two is the same information in half the height, and all
     four stay comparable at a glance, which is the whole point of the row. */
  html.m-app .tier-select-bar {
    display: grid !important;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
  }
  html.m-app .tier-btn { padding: 12px 10px; min-height: 62px; }
  html.m-app .tier-btn .tier-name { font-size: 0.95rem; }
  html.m-app .tier-btn .tier-sub { font-size: 0.72rem; }

  /* -----------------------------------------------------------------------
     21. Forms read left, not centre
     -----------------------------------------------------------------------
     center.css centres everything site-wide, which is right for a marketing
     page and wrong for a form: a centred label floating above a full-width
     field does not obviously belong to it, and the eye has to re-find the
     start of every line. */
  html.m-app .form-group label,
  html.m-app .form-group > span,
  html.m-app label.form-label { text-align: left; display: block; }
  html.m-app input, html.m-app textarea, html.m-app select { text-align: left; }
  /* 16px is the threshold below which iOS zooms the page on focus. */
  html.m-app input, html.m-app textarea, html.m-app select { font-size: 16px; }

  /* -----------------------------------------------------------------------
     22. Anything a rail did not catch still gets a phone-sized card
     ----------------------------------------------------------------------- */
  html.m-app .m-rail > .card { min-height: 100%; }
  html.m-app .m-dots:empty { display: none; }
}

@media (max-width: 860px) {
  /* -----------------------------------------------------------------------
     23. Touch-target and legibility sweep
     ----------------------------------------------------------------------- */

  /* iOS ships its own tab labels at 10-11px; 10.4 was under the 10.5 floor
     this site holds itself to, and on a 360px screen that is the difference
     between reading the label and recognising its shape. */
  .m-tab { font-size: 0.68rem; }
  .m-tab span { line-height: 1.1; }

  /* Inline links in body copy — a phone number, a "chat with us" — are a
     17px-tall target sitting in a sentence. The negative margin buys the
     padding back so the paragraph's line rhythm does not change. */
  html.m-app .card p > a,
  html.m-app .card p > .copy-btn,
  html.m-app .demo-open,
  html.m-app .card-link {
    display: inline-block;
    padding: 8px 2px;
    margin-block: -6px;
  }
}


/* ==========================================================================
   AUDIT FIXES — phone layer
   Added in response to the mobile audit. Kept as one block at the end so the
   overrides are readable in isolation and can be reverted together. Every
   rule below is inside the m-app breakpoint.
   ========================================================================== */

@media (max-width: 860px) {

  /* -----------------------------------------------------------------------
     A. Opaque chrome
     -----------------------------------------------------------------------
     The translucent recipe was tuned for a desktop bar floating over wide
     margins. On a phone the content column runs edge to edge underneath it,
     so 78–86% alpha meant body copy read straight through the tab labels and
     the header — on Pricing you could read two headlines at once.

     A phone has no margin for the material to read against, so it was
     costing legibility and buying nothing. The blur stays for the small
     amount of depth it gives at the edges; the fill goes opaque. */
  html.m-app .site-header {
    background: var(--surface-canvas);
  }
  html.m-app .m-tabs {
    background: var(--surface-canvas);
  }
  html.m-app .m-chapter {
    background: var(--surface-canvas);
  }

  /* The tab bar must sit above page furniture, including a footer that
     scrolls up underneath it. */
  html.m-app .m-tabs { z-index: 9400; }
  html.m-app .site-footer,
  html.m-app .site-finale { position: relative; z-index: 1; }

  /* -----------------------------------------------------------------------
     B. FAQ answers no longer leak a clipped half-line
     -----------------------------------------------------------------------
     The accordion collapses with `grid-template-rows: 0fr -> 1fr`, which
     works because the row's content is inside an `overflow: hidden` box that
     can shrink to nothing. Padding is NOT clipped by overflow, so putting
     padding on that box gives the collapsed row a floor equal to its own
     padding — 16px here, which is most of a line of text.

     pricing.css puts the padding on the `p` inside. These rules did not, so
     every collapsed FAQ showed the top of its first line. Measured collapsed
     height was 0px at 1200px and 16px at every mobile width. */
  html.m-app .faq-answer-inner { padding: 0; }
  html.m-app .faq-answer-inner p { padding: 0 16px 16px; font-size: 0.92rem; }

  /* -----------------------------------------------------------------------
     C. Touch targets
     -----------------------------------------------------------------------
     These were never enumerated in mobile.css's coarse-pointer block. Sizes
     are the measured ones, all under the 44px floor. */

  /* The theme toggle. mobile-app.js moves Appearance into the More sheet as
     a labelled row, and its comment says a 32px unlabelled glyph in the
     header "is a guess" — but both shipped. The sheet row is the one that
     can say what state it is in, so the header glyph goes. */
  html.m-app .site-header .theme-toggle { display: none; }

  html.m-app .nav-search-btn { min-width: 44px; min-height: 44px; }

  /* Footer social icons and the logo lockup. */
  html.m-app .footer-social a,
  html.m-app .social-links a,
  html.m-app .footer-bottom .logo,
  html.m-app .footer-logo-mark {
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }

  /* Demo suggestion chips and the dashboard's own chips sat at 38px tall. */
  html.m-app .demo-chip,
  html.m-app .nd-chip,
  html.m-app .nd-send { min-height: 44px; }
  html.m-app .nd-send { min-width: 44px; }

  /* Contact's WhatsApp and phone links were 34px tall — and the phone number
     is the single most likely tap on the whole page from a phone. */
  html.m-app .contact-link,
  html.m-app #contact-form-section + * a[href^="tel:"],
  html.m-app a[href^="tel:"],
  html.m-app a[href^="mailto:"],
  html.m-app a[href*="wa.me"] {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

  /* Work page "view all screens" was 21px tall. */
  html.m-app .screens-viewall { min-height: 44px; display: inline-flex; align-items: center; }

  /* The testimonial dots are the worst target on the site at 7x7, and
     reviews.css calls them "one dot per page, clickable" — so they are
     controls, not decoration. The dot stays 7px visually; the hit area grows
     around it with padding, and the negative margin keeps the row's spacing
     exactly as it was. */
  html.m-app .reviews-dot {
    /* 7px dot, 25x43 hit area. WCAG 2.5.8 (AA) asks for 24x24; 2.5.5 (AAA)
       asks for 44x44, which cannot be reached here without the eight targets
       overlapping each other — an overlapping hit area is worse than a small
       one, because the tap lands on the wrong dot rather than on nothing.
       The negative margin keeps the row's visual spacing unchanged. */
    padding: 18px 9px;
    margin: -18px -5px;
    background-clip: content-box;
    box-sizing: content-box;
  }
  html.m-app .reviews-dots { gap: 0; }

  /* -----------------------------------------------------------------------
     D. Type
     -----------------------------------------------------------------------
     --text-caption is 12px and the eyebrow renders at 11.2. It is the label
     that tells a visitor which chapter they are in, and unlike the tab bar
     labels it has no icon carrying the meaning. Tracking comes back a
     fraction so the line length is unchanged. */
  html.m-app .eyebrow {
    font-size: 12px;
    letter-spacing: 0.07em;
  }
  html.m-app .service-tag,
  html.m-app .work-tag,
  html.m-app .demo-live { font-size: 12px; }

  /* -----------------------------------------------------------------------
     E. Readability of card copy
     -----------------------------------------------------------------------
     Centred text has a ragged left edge, so the eye has to re-find the start
     of every line. On a wide desktop card that is a two-line paragraph and a
     stylistic choice; in a 390px column the same paragraph is five lines and
     the cost is real. Headings, eyebrows and single-line copy stay centred —
     the character of the design is in those, not in the body text. */
  html.m-app .card p,
  html.m-app .problem-card p,
  html.m-app .service-card p,
  html.m-app .value-card p,
  html.m-app .core-value p,
  html.m-app .faq-answer-inner p,
  html.m-app .ct-stage p,
  html.m-app .price-item .item-desc,
  html.m-app .checklist li {
    text-align: left;
    text-wrap: pretty;
  }

  /* -----------------------------------------------------------------------
     F. Sections must not run under the tab bar
     -----------------------------------------------------------------------
     body already reserves the bar's height, but individual viewport-sized
     sections measured against the full screen, so the industries orb was cut
     in half on a small phone. The expression already exists at line ~265;
     it just was not applied here. */
  html.m-app .industries-chapter,
  html.m-app .industry-stage,
  html.m-app .finale-stage {
    min-height: calc(100dvh - var(--m-top) - var(--m-tabs) - env(safe-area-inset-bottom, 0px));
  }

  /* -----------------------------------------------------------------------
     G. Back to top
     -----------------------------------------------------------------------
     Pinned at left:330 on a 390px screen, it landed inside the content
     column rather than beside it, and hit-testing its centre returned a
     different control underneath at three of five scroll positions on
     Pricing — the accordion chevron, a category header and the FAQ "+".

     On a phone the gesture already exists: a tap on the status bar. The
     button is removed rather than moved, which also gives the corner back
     to the tour launcher. */
  html.m-app .back-to-top { display: none !important; }
}


/* ==========================================================================
   AUDIT FIXES — the pricing cart on a phone
   --------------------------------------------------------------------------
   Two reported bugs, both reproduced:

   1. "When you add something to the cart, it comes behind the nav switcher."
      .cart-dock sat at bottom:12px with z-index 9000. The tab bar is 62px
      tall at z-index 9400. Measured: dock occupied y 766–832, tab bar 782–844
      — 50 of the dock's 66px were underneath a higher-stacked element. The
      dock rule predates the tab bar and never learned about it.

   2. "When I click on the cart there is no cart, it just blurs the screen."
      Section 15 above set `html.m-app .cart-panel { position: static
      !important }`, intending to dock the panel inline as a running-total
      bar. But the panel keeps `transform: translateY(100%)` from mobile.css,
      so as a static element it landed in the document flow at y=2358 — far
      off screen — while .cart-scrim (position: fixed, backdrop blur) opened
      correctly on top of everything. Blur, no cart. Exactly as described.

   The fix, per the brief: the cart opens as a popover anchored to the top
   right, under the header, sized to the space actually available.
   ========================================================================== */

@media (max-width: 860px) {

  /* ---- 1. The dock clears the tab bar ---------------------------------- */
  html.m-app .cart-dock {
    bottom: calc(var(--m-tabs) + env(safe-area-inset-bottom, 0px) + 12px);
    z-index: 9380;                       /* under the tab bar, over the page */
  }

  /* The two floating buttons stepped up by hard-coded amounts that also
     predate the tab bar. Back-to-top is gone on m-app; the launcher needs to
     clear both the bar and the dock. */
  html.m-app body.cart-dock-visible .aitg-launcher,
  html.m-app.cart-dock-visible .aitg-launcher {
    bottom: calc(var(--m-tabs) + env(safe-area-inset-bottom, 0px) + 90px) !important;
  }

  /* The builder has to clear the bar AND the dock, not just the dock. */
  html.m-app .pricing-builder {
    padding-bottom: calc(var(--m-tabs) + env(safe-area-inset-bottom, 0px) + 96px);
  }

  /* ---- 2. The panel becomes a top-right popover ------------------------ */
  /* Undo section 15's static docking. `position: fixed` has to beat the
     `!important` that rule uses, hence the matching !important here. */
  html.m-app .cart-panel {
    position: fixed !important;
    top: calc(var(--m-top) + env(safe-area-inset-top, 0px) + 8px) !important;
    right: max(10px, env(safe-area-inset-right, 0px)) !important;
    left: auto !important;
    bottom: auto !important;

    width: min(360px, calc(100vw - 20px)) !important;
    max-width: none !important;
    margin-top: 0 !important;

    /* Fits between the header and the tab bar, and scrolls inside itself if
       the build gets long. */
    height: auto !important;
    max-height: calc(100dvh - var(--m-top) - var(--m-tabs)
                     - env(safe-area-inset-top, 0px)
                     - env(safe-area-inset-bottom, 0px) - 24px) !important;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;

    z-index: 9440;                       /* above the tab bar and the scrim */

    padding: 20px 18px 22px;
    border: 1px solid var(--line);
    border-radius: 14px;
    background: var(--surface-white);
    box-shadow: 0 12px 40px -8px rgba(0, 0, 0, 0.28),
                0 2px 8px rgba(0, 0, 0, 0.10);

    /* Grows out of the corner it is anchored to rather than sliding in from
       an edge it no longer touches. */
    transform-origin: top right;
    transform: translateY(-8px) scale(0.94) !important;
    opacity: 0;
    visibility: hidden;
    transition: transform 260ms cubic-bezier(0.22, 1, 0.36, 1),
                opacity 200ms ease,
                visibility 260ms;
  }
  html.m-app .cart-panel.open {
    transform: none !important;
    opacity: 1;
    visibility: visible;
  }

  /* A popover is not a sheet: the drag handle has nothing to drag. */
  html.m-app .cart-drag-handle { display: none; }

  /* The scrim goes above the tab bar so the whole page dims, and loses the
     heavy blur — at this size the popover reads on its own and the blur was
     the only thing the visitor saw when the panel failed to appear. */
  html.m-app .cart-scrim {
    z-index: 9420;
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
    background: rgba(0, 0, 0, 0.34);
  }

  /* Close control, sized for a thumb and clear of the panel's own padding. */
  html.m-app .cart-close {
    top: 10px; right: 10px;
    width: 44px; height: 44px;
    font-size: 1.4rem;
    background: transparent;
    border-color: var(--line);
  }
  html.m-app .cart-header { margin-bottom: 14px; padding-right: 46px; }
  html.m-app .cart-header h3 { font-size: 1rem; }

  /* The list is the part that should scroll if anything does, but the panel
     now owns scrolling, so the inner cap is removed. */
  html.m-app .cart-items { max-height: none; overflow: visible; gap: 2px; }
  html.m-app .cart-actions { gap: 8px; }
  html.m-app .cart-actions .btn { width: 100%; min-height: 46px; justify-content: center; }
  html.m-app .cart-estimate-note { font-size: 12px; line-height: 1.45; }
}

/* Small phones: the popover becomes near-full-width but stays top-anchored,
   so it never collides with the tab bar or the dock. */
@media (max-width: 400px) {
  html.m-app .cart-panel {
    width: calc(100vw - 16px) !important;
    right: 8px !important;
  }
}


/* ==========================================================================
   AUDIT FIXES — remaining touch targets
   A second pass after measuring what the first one had actually reached.
   ========================================================================== */
@media (max-width: 860px) {

  /* mobile.css raises .aitg-ico/-btn/-stop/-cc to 44 via min-height, but the
     greeting buttons set their own padding and landed at 43. The launcher is
     handled where it is docked, above. */
  html.m-app .aitg-btn {
    min-height: 44px !important;
    display: inline-flex !important;
    align-items: center;
    justify-content: center;
  }

  /* Footer icon links measured 42x42 — the existing rule sized the box but
     these sit outside the selectors it used. */
  html.m-app .footer-bottom a,
  html.m-app .finale-baseline a,
  html.m-app .footer-social a,
  html.m-app .social-links a,
  html.m-app a[aria-label="Instagram"],
  html.m-app a[aria-label="X / Twitter"],
  html.m-app a[aria-label="LinkedIn"],
  html.m-app a[aria-label="WhatsApp"] {
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }

  /* Pricing's category rail chips were 41px wide. */
  html.m-app .cat-chip { min-width: 44px; }

  /* The embedded dashboard's own controls are part of a product mockup, but
     they are real buttons that really respond, so they get real targets. */
  html.m-app .nd-nav button,
  html.m-app .nd-composer input,
  html.m-app .nd-composer button { min-height: 44px; }
}
