/* ==========================================================================
   Portal mobile foundation
   ==========================================================================

   The one place for cross-page phone behaviour: page rhythm, tap targets,
   the fixed-UI stack (chat launcher + bottom bars), and the table-to-card
   contract used by order lists. Page-specific phone rules stay in the sheet
   that owns the page (b2b_commerce.css for the B2B commerce screens, the
   ops_dashboard.html style block for the OPS dashboard).

   Desktop is deliberately untouched: every rule here lives inside a
   max-width media query, or defines a custom property that only mobile rules
   read. Nothing in this file changes a layout at >= 801px.

   BREAKPOINTS
   -----------
   Two edges, both already established in this repo:

       <= 800px    "fixed-UI edge". Matches the width at which
                   .mobile-cart-summary already replaces the desktop cart
                   sidebar in b2b_commerce.css. The chat launcher and every
                   bottom bar switch together here so a phone never shows a
                   desktop chat pill next to a mobile cart bar.

       <= 767.98px "card edge". Tailwind's `md` breakpoint, which these
                   templates already use for their md:* utilities. Wide data
                   tables become cards here, in step with the markup that
                   Tailwind is laying out around them.

   The B2B catalog is the exception: its cards switch at the fixed-UI edge
   instead, because its cart sidebar, its single-column grid and its chat
   launcher all already switch at 800px. See the phone block in
   ordering/css/b2b_commerce.css.

   Z-INDEX
   -------
   Deliberate order for everything that is fixed or sticky. Raise a layer by
   editing this list, never by inventing a local value.

       20  in-card popovers (.price-details)
       25  badge overflow panels
       28  page toolbars that stick under the site header
       30  site header
       40  bottom bars (.hmc-bottom-bar)
       45  chat launcher, drawer included: the drawer paints inside the
           launcher's stacking context, so this one value orders both
       50  page modals (order merge)
       90  image preview overlay

   BOTTOM BARS
   -----------
   A fixed bottom bar opts in with `.hmc-bottom-bar`. It then gets safe-area
   insets, the shared height, and the shared z-index for free, and the page
   automatically reserves matching bottom space so the bar never covers the
   last row of content. A bar that is not currently applicable carries
   `hidden`, and then costs neither space nor a chat offset.

   Whether any bar is currently on screen is published by
   static/js/portal-mobile.js as `data-hmc-bottom-bar` on <body>, because the
   page padding and the launcher offset both depend on it.

   RTL is handled with logical properties throughout.
   ========================================================================== */

:root {
    /* Safe areas. iOS reports 0px on non-notched devices, so these are safe
       to add unconditionally. */
    --hmc-safe-bottom: env(safe-area-inset-bottom, 0px);
    --hmc-safe-inline-start: env(safe-area-inset-left, 0px);
    --hmc-safe-inline-end: env(safe-area-inset-right, 0px);

    /* Designed height of a mobile bottom bar. The bar sets min-block-size
       from this, and the page reserves space from it, so the two cannot drift
       apart. Content inside a bar truncates rather than growing it. */
    --hmc-bottom-bar-height: 60px;
    --hmc-bottom-bar-gap: 10px;

    /* Compact circular chat launcher on phones. */
    --hmc-fab-size: 54px;
    --hmc-fab-gap: 14px;

    --hmc-z-bottom-bar: 40;
    --hmc-z-fab: 45;
}

/* ------------------------------------------------------- chat drawer shell */

/* Position lives here rather than on a style attribute so the phone rules
   below can move the drawer without !important. These are the values the
   launcher shipped with, so desktop is unchanged. The drawer paints inside
   the launcher's own stacking context and therefore needs no z-index of its
   own; the launcher's z-index is what orders it against the page. */
#chat-drawer {
    position: fixed;
    inset-inline-end: 1.25rem;
    inset-block-end: 4.5rem;
}

/* ============================================================ <= 800px ==== */

@media (max-width: 800px) {
    /* ------------------------------------------------------- page rhythm */

    /* The shell already carries 16px of inline padding, which is the target
       gutter. Only the vertical rhythm is desktop-sized, and the bottom needs
       to clear the floating launcher. */
    main[data-hmc-main="1"] {
        padding-block: 1.25rem;
        padding-bottom: calc(var(--hmc-safe-bottom) + var(--hmc-fab-size) + 1.75rem);
    }

    /* With a bottom bar on screen the page must clear the bar, the launcher
       sitting above it, and both gaps. */
    body[data-hmc-bottom-bar="1"] main[data-hmc-main="1"] {
        padding-bottom: calc(
            var(--hmc-safe-bottom) + var(--hmc-bottom-bar-gap) +
            var(--hmc-bottom-bar-height) + var(--hmc-fab-gap) +
            var(--hmc-fab-size) + 1rem
        );
    }

    /* --------------------------------------------------------- bottom bar */

    .hmc-bottom-bar {
        position: fixed;
        z-index: var(--hmc-z-bottom-bar);
        inset-inline: max(12px, var(--hmc-safe-inline-start)) max(12px, var(--hmc-safe-inline-end));
        inset-block-end: calc(var(--hmc-safe-bottom) + var(--hmc-bottom-bar-gap));
        display: flex;
        /* The insets decide the width. A bar that also carries a desktop
           `width` would otherwise over-constrain and ignore one inset. */
        inline-size: auto;
        margin-inline: 0;
        min-block-size: var(--hmc-bottom-bar-height);
        align-items: center;
        gap: 12px;
        padding: 8px 12px;
        border: 1px solid #cfdad3;
        border-radius: 14px;
        background: rgba(255, 255, 255, .97);
        box-shadow: 0 14px 36px rgba(32, 55, 42, .18);
        -webkit-backdrop-filter: blur(10px);
        backdrop-filter: blur(10px);
    }

    /* ----------------------------------------------------- chat launcher */

    /* A phone gets a compact circular action, not the desktop pill. The label
       is dropped visually but stays available to assistive technology through
       the button's aria-label. */
    #hmc-chat {
        inset-inline-end: max(14px, var(--hmc-safe-inline-end));
        inset-block-end: calc(var(--hmc-safe-bottom) + var(--hmc-fab-gap));
        inset-inline-start: auto;
        z-index: var(--hmc-z-fab);
    }

    /* Lifted clear of a bottom bar, so the two never overlap. */
    body[data-hmc-bottom-bar="1"] #hmc-chat {
        inset-block-end: calc(
            var(--hmc-safe-bottom) + var(--hmc-bottom-bar-gap) +
            var(--hmc-bottom-bar-height) + var(--hmc-fab-gap)
        );
    }

    #chat-fab {
        display: inline-grid;
        inline-size: var(--hmc-fab-size);
        block-size: var(--hmc-fab-size);
        place-items: center;
        padding: 0;
        font-size: 1.35rem;
        line-height: 1;
    }

    #chat-fab .hmc-chat-fab__label {
        position: absolute;
        inline-size: 1px;
        block-size: 1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }

    /* The drawer is a sheet on a phone: full usable width, anchored above the
       launcher, and internally scrollable so a long thread never pushes the
       composer off-screen. */
    #chat-drawer {
        inline-size: auto;
        max-inline-size: none;
        inset-inline: max(12px, var(--hmc-safe-inline-start)) max(12px, var(--hmc-safe-inline-end));
        inset-block-end: calc(
            var(--hmc-safe-bottom) + var(--hmc-fab-gap) +
            var(--hmc-fab-size) + 10px
        );
        max-block-size: min(72vh, 560px);
        overflow: auto;
        overscroll-behavior: contain;
    }

    body[data-hmc-bottom-bar="1"] #chat-drawer {
        inset-block-end: calc(
            var(--hmc-safe-bottom) + var(--hmc-bottom-bar-gap) +
            var(--hmc-bottom-bar-height) + var(--hmc-fab-gap) +
            var(--hmc-fab-size) + 10px
        );
    }

    /* --------------------------------------------------------- tap targets */

    /* 44px is the floor for anything a thumb has to hit. Buttons stop forcing
       one line so a translated label wraps instead of overflowing its box. */
    .btn,
    button.btn,
    a.btn,
    label.btn {
        min-block-size: 44px;
        white-space: normal;
    }

    .input,
    .select,
    .input-control,
    input.input-control,
    select.input-control {
        min-block-size: 44px;
    }

    /* A checkbox that selects a row is a primary control on a phone. */
    .hmc-tap-target {
        min-inline-size: 44px;
        min-block-size: 44px;
    }
}

/* ---------------------------------------------------------- card density */

@media (max-width: 560px) {
    .brand-card {
        padding: 16px;
        border-radius: 14px;
        margin-bottom: .9rem;
    }

    /* Hover lift is meaningless on touch and only causes repaint jitter. */
    .brand-card:hover {
        transform: none;
    }
}

/* ======================================================== <= 767.98px ==== */

/* Wide data tables become cards. The markup stays a single table: the same
   row, the same cells, the same ids and data-attributes, so row-level
   JavaScript and table semantics for assistive technology are unaffected.
   Only the visual box changes.

   A table opts in with `.hmc-card-table` and names each cell's role with a
   `hmc-cell-*` class, which the page's own sheet then places into a grid.
   This file supplies the shared card chrome; the grid areas are per-page,
   because the fields differ per page. */

@media (max-width: 767.98px) {
    .hmc-card-table,
    .hmc-card-table tbody,
    .hmc-card-table tr,
    .hmc-card-table td {
        display: block;
        inline-size: auto;
        max-inline-size: 100%;
    }

    /* Captions come from data-label on each cell, so the header row is
       redundant once stacked. It stays in the accessibility tree. */
    .hmc-card-table thead {
        position: absolute;
        inline-size: 1px;
        block-size: 1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }

    .hmc-card-table tbody tr {
        margin-block: 10px;
        padding: 12px 14px;
        border: 1px solid var(--border-soft, #e2eae6);
        border-radius: 14px;
        background: #fff;
        box-shadow: 0 2px 8px rgba(32, 55, 42, .06);
    }

    /* Zebra striping reads as an error once rows are separate cards. */
    .hmc-card-table tbody tr:nth-child(even),
    .hmc-card-table tbody tr:hover {
        background: #fff;
    }

    .hmc-card-table tbody td {
        padding: 0;
        border: 0;
        background: transparent;
        white-space: normal;
        text-align: start;
        min-inline-size: 0;
    }

    /* A cell that is empty in the data must not leave a gap in the card. */
    .hmc-card-table tbody td:empty {
        display: none;
    }

    /* Captions are opt-in per cell. Without this reset, a sheet that already
       stacks the table (style.css does for .brand-table) would caption every
       cell, including the ones this contract composes into a card header. */
    .hmc-card-table tbody td::before { content: none; }

    /* Captioned cells read as "label: value" on one line. */
    .hmc-card-table tbody td[data-label].hmc-cell-labelled::before {
        content: attr(data-label);
        display: block;
        color: var(--muted, #6b7280);
        font-size: .64rem;
        font-weight: 800;
        letter-spacing: .05em;
        text-transform: uppercase;
    }

    /* Long names, Arabic or Latin, wrap on word boundaries and never widen
       the card. Only an unbroken token longer than the card is broken. */
    .hmc-card-table .hmc-cell-title,
    .hmc-card-table .hmc-cell-name {
        word-break: normal;
        overflow-wrap: break-word;
        hyphens: none;
    }

    .hmc-card-table .empty-row td,
    .hmc-card-table tbody tr.empty-row {
        display: block;
        text-align: center;
    }
}

/* --------------------------------------------------- reduced motion */

@media (prefers-reduced-motion: reduce) {
    .hmc-bottom-bar {
        transition: none;
    }
}
