/* ============================================================================
   MOMENTUM ON A PHONE
   ----------------------------------------------------------------------------
   ⛔⛔ EVERY RULE IN THIS FILE LIVES INSIDE @media (max-width: 820px).
   There is nothing outside it and nothing may ever be added outside it. That is
   the whole safety story: Zac asked for "way more mobile optimised ... should
   not touch anything on desktop", and a file that cannot express a desktop rule
   cannot break a desktop page.

   ⛔ IT IS LINKED LAST, AFTER EACH PAGE'S OWN <style> BLOCK.
   Media queries add no specificity, so a mobile override only wins because it
   comes later in the cascade. Keep it last in every <head> or the overrides
   silently stop working. Where a desktop rule is more specific than a bare
   class the override has to match it selector for selector - see the spine.

   WHAT WAS ACTUALLY WRONG (measured on the running app at a 390px viewport,
   not guessed):
     - every one of the 13 inner pages scrolled sideways by 312px, all from the
       same cause: nav.topnav is a non-wrapping flex row of 8 links, 534px wide,
       shoving the Lock button out to right:703px
     - the hub was worse. app.css:310 `.spine-layout.spine-has-search` is (0,2,0)
       and beat the (0,1,0) mobile collapse at app.css:229, so the grid computed
       to `260px 46px` and the ENTIRE CONTENT COLUMN OF THE HUB WAS 46 PIXELS
     - tap targets of 28-30px, and inputs under 16px, which make iOS Safari zoom
       the page on focus and never zoom back

   Paired with mobile.js, which is gated on the same 820px query.
   ============================================================================ */

@media (max-width: 820px) {

  /* ==========================================================================
     1. THE SHELL
     ========================================================================== */

  /* 40px of side padding is a tenth of a 390px screen. app.css:36 already drops
     it to 20 at 860; this takes it to 16 on the genuinely small ones. */
  .wrap { padding: 0 16px; }

  /* ⛔ 16px IS A FUNCTIONAL MINIMUM, NOT A TASTE. iOS Safari zooms the viewport
     in when a focused input is under 16px and gives you no way back out, which
     is why a rep tapping the resources search ended up on a page twice the
     width of their phone. Measured offenders: #doc-search at 15px, 5 inputs on
     library.html, 4 on design.html. */
  input[type='text'], input[type='search'], input[type='number'],
  input[type='email'], input[type='password'], input[type='tel'],
  input[type='date'], input[type='file'], select, textarea {
    font-size: 16px;
    min-height: 44px;
  }

  /* Comfortable thumb targets. 44px is the Apple HIG figure and the one the
     WCAG 2.2 target-size rule is built around. */
  .btn, .lockbtn { min-height: 44px; padding-left: 18px; padding-right: 18px; }
  .chip { min-height: 40px; display: inline-flex; align-items: center; }

  .page-head { padding: 12px 0 20px; }
  .page-title { font-size: 25px; }
  .page-sub { font-size: 13.5px; }
  .crumb { padding-top: 14px; }

  .panel { padding: 16px; border-radius: 10px; margin-bottom: 16px; }

  footer.foot .wrap { flex-direction: column; gap: 6px; }

  /* The gate is the first thing anyone sees, and on a 320px phone the box was
     wider than the screen. */
  #gate .box { width: 100%; max-width: none; padding: 26px 20px; }
  #gate input, #gate button { font-size: 16px; min-height: 46px; }


  /* ==========================================================================
     2. THE MENU - a drawer, because eight links will never fit on one line
     --------------------------------------------------------------------------
     nav.topnav is NOT rebuilt, cloned or moved. It is the same element app.js
     buildNav() wrote, restyled. That matters: buildNav has already dropped
     every link this login cannot reach, so a copy could offer a rep a page the
     server would 403, and aria-current="page" stays where it was put.
     mobile.js adds only the button, the scrim and the panel heading.
     ========================================================================== */

  .topbar .wrap { gap: 12px; }

  .m-navbtn {
    display: inline-flex; align-items: center; gap: 9px;
    min-height: 44px; padding: 0 14px;
    margin-left: auto;
    background: transparent;
    border: 1px solid rgba(255, 255, 255, 0.3);
    border-radius: 4px;
    color: var(--cream);
    font-family: 'Archivo', sans-serif; font-size: 13px; font-weight: 700;
    letter-spacing: 0.3px;
    cursor: pointer;
  }
  .m-navbtn-bars { display: flex; flex-direction: column; justify-content: center; gap: 3.5px; width: 16px; }
  .m-navbtn-bars i { display: block; height: 2px; background: currentColor; border-radius: 2px; }
  .m-navbtn-word { line-height: 1; }

  /* The panel itself. */
  nav.topnav {
    position: fixed; top: 0; right: 0; bottom: 0;
    z-index: 60;
    width: min(86vw, 330px);
    display: flex; flex-direction: column; align-items: stretch;
    gap: 0;
    padding: 0 0 max(18px, env(safe-area-inset-bottom));
    background: var(--charcoal-soft);
    border-left: 1px solid var(--hairline-dark);
    box-shadow: -18px 0 44px rgba(0, 0, 0, 0.34);
    font-size: 15px;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    transform: translateX(100%);
    transition: transform 0.24s ease;
    /* visibility, not display, so the slide-out is watchable and so the panel
       is out of the tab order while it is shut */
    visibility: hidden;
  }
  .m-navopen nav.topnav { transform: none; visibility: visible; }

  .m-navhead {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px;
    padding: 16px 8px 14px 20px;
    border-bottom: 1px solid var(--hairline-dark);
    margin-bottom: 6px;
  }
  .m-navhead-t {
    font-family: 'Archivo', sans-serif; font-size: 11px; font-weight: 800;
    letter-spacing: 1.4px; text-transform: uppercase; color: var(--ink-faint);
  }
  .m-navclose {
    width: 44px; height: 44px; flex: 0 0 auto;
    display: flex; align-items: center; justify-content: center;
    background: none; border: none; color: var(--cream); cursor: pointer;
  }
  .m-navclose svg { width: 19px; height: 19px; stroke: currentColor; stroke-width: 1.7; fill: none; }

  /* Full-width rows. `.topnav a` is (0,1,1); this is (0,2,1) and later, so it
     wins without an !important. */
  nav.topnav a {
    display: flex; align-items: center;
    min-height: 50px;
    padding: 0 20px;
    color: var(--cream);
    text-decoration: none;
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  }
  /* ⛔ app.css:99 marks the current page with a BOTTOM border, which in a
     vertical list reads as a divider rather than as "you are here". It has to
     be unset explicitly - a left bar alone would sit next to it. Desktop rule
     is (0,2,1), so this is (0,3,2) to be sure of winning. */
  nav.topnav a[aria-current='page'],
  .topnav a[aria-current='page'] {
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
    padding-bottom: 0;
    box-shadow: inset 3px 0 0 var(--rust);
    background: rgba(255, 255, 255, 0.045);
    color: #fff;
  }

  /* Lock is a destructive-ish action and belongs away from the links, at the
     bottom where a thumb rests, not inline as a ninth menu item. */
  nav.topnav .lockbtn {
    margin: 14px 20px 0;
    min-height: 46px;
    border-color: rgba(255, 255, 255, 0.3);
    color: var(--cream);
    border-radius: 4px;
  }

  .m-scrim {
    position: fixed; inset: 0; z-index: 55;
    display: block;
    background: rgba(10, 10, 10, 0.55);
    opacity: 0;
    transition: opacity 0.24s ease;
    -webkit-tap-highlight-color: transparent;
  }
  .m-navopen .m-scrim { opacity: 1; }
  /* ⛔ REQUIRED. An author `display:block` beats the user-agent
     `[hidden]{display:none}` no matter the specificity, so without this line
     the scrim would sit over the page permanently. Momentum has been bitten by
     exactly this before, with .news-nav-btn. */
  .m-scrim[hidden] { display: none; }

  /* Hold the page still behind the drawer. mobile.js banks the scroll offset
     into `top` and puts it back on close, because position:fixed alone would
     silently jump the page to the top. */
  body.m-locked {
    position: fixed;
    left: 0; right: 0;
    width: 100%;
    overflow: hidden;
  }

  @media (prefers-reduced-motion: reduce) {
    nav.topnav, .m-scrim { transition: none; }
  }


  /* ==========================================================================
     3. TABLES
     --------------------------------------------------------------------------
     A table cannot be reflowed by CSS without losing the shared column widths
     that make it a table, so mobile.js wraps any table that actually overflows
     in .m-scroll and the table itself is left completely alone.
     ========================================================================== */

  .m-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
    /* a hint that there is more to the right, without a scrollbar to point at */
    background:
      linear-gradient(to right, var(--paper) 30%, rgba(253, 252, 251, 0)) left center,
      linear-gradient(to left,  var(--paper) 30%, rgba(253, 252, 251, 0)) right center,
      linear-gradient(to right, rgba(0, 0, 0, 0.09), rgba(0, 0, 0, 0)) left center,
      linear-gradient(to left,  rgba(0, 0, 0, 0.09), rgba(0, 0, 0, 0)) right center;
    background-repeat: no-repeat;
    background-size: 34px 100%, 34px 100%, 12px 100%, 12px 100%;
    background-attachment: local, local, scroll, scroll;
  }
  .m-scroll:focus-visible { outline: 2px solid var(--rust); outline-offset: 2px; }
  /* Only tables that a max-content probe proved do not fit are wrapped, so by
     the time an element has .m-scroll the columns are genuinely wider than the
     phone. Letting them keep their natural width and scroll beats squashing
     "Distributor" into four characters a line. */
  .m-scroll > table { width: max-content; min-width: 100%; }
  .m-scroll th, .m-scroll td { white-space: nowrap; }


  /* ==========================================================================
     4. THE HUB
     --------------------------------------------------------------------------
     ⭐ THE HUB ALREADY HAD A MOBILE DESIGN. IT WAS JUST UNREACHABLE.
     app.css:245 turns the spine into a horizontal scroller at 900px, :271 makes
     its buttons into pills, :295 drops the month grid to one column, :259 the
     item grid, :249 the quick actions. All of it was written, commented, and
     never once ran, because ONE rule outranked the collapse that has to happen
     first:

       app.css:229  @media (max-width:900px){ .spine-layout{...:1fr} }   (0,1,0)
       app.css:310  .spine-layout.spine-has-search{...:260px 1fr}        (0,2,0)

     Media queries carry no specificity, so the two-class rule won everywhere
     and the hub stayed two columns on a phone: a 260px spine beside a content
     column that MEASURED 46 PIXELS WIDE. Every shelf, every month card and
     every price on the first page anybody opens was inside that 46px.

     So the whole of the hub's mobile layout is this one line. It is written
     with the same two classes to beat the same rule.
     ========================================================================== */

  .spine-layout.spine-has-search { grid-template-columns: 1fr; gap: 14px; }

  /* The search is the point of the hub on a phone, so it stops being a card in
     a rail and becomes the first thing under the banner, full width. */
  .spine-search {
    background: none; border: none; border-radius: 0; padding: 0;
    gap: 10px;
  }
  /* ⛔ app.css:323 sets 38px/13px for the narrow rail. On a phone a 13px input
     is under the 16px iOS zoom floor and 38px is under the 44px target. */
  .spine-search .search-row input { height: 48px; font-size: 16px; }
  .spine-search .search-btn { height: 48px; width: 52px; }

  /* The spine is now the horizontal strip app.css:245 always meant it to be.
     Edge to edge, so the row does not look like it ends at the padding, with
     the padding put back inside it. */
  .spine-search .spine {
    margin-left: -16px; margin-right: -16px;
    padding-left: 16px; padding-right: 16px;
    scroll-padding-left: 16px;
    scroll-snap-type: x proximity;
  }
  .spine-search .spine button { scroll-snap-align: start; min-height: 40px; }

  /* The banner is the top of the page, and app.css's clamp(200px, 30vw, 440px)
     bottoms out at its 200px FLOOR on a phone - a quarter of the screen spent
     before a single link, when the 30vw the clamp actually wants would be 108px.
     ⛔ THE RATIO IS MEASURED, NOT CHOSEN. All five files in Enia's Final Banners
     folder are 10833x3125, which is 3.47:1. 24/7 is a hair taller than that, so
     the artwork fits edge to edge with a little blurred surround top and bottom
     and never letterboxes at the sides. min-height keeps room for the wordmark
     and Lock, which are laid over this band and would otherwise sit on top of
     the artwork's own headline. A future banner of any other shape still works:
     that is what the blurred fill behind it is for. */
  .news-banner { height: auto; aspect-ratio: 24 / 7; min-height: 132px; max-height: 40vh; }
  /* Carousel arrows are a mouse affordance. The dots stay, and they are the
     touch target, so they get bigger rather than the arrows getting kept. */
  .news-nav-btn { display: none; }
  .news-dots { bottom: 10px; gap: 7px; }
  .news-dots button { width: 9px; height: 9px; }
  .news-dots button.active { width: 24px; }

  /* The wordmark and Lock sit ON the artwork. At 390px they were colliding with
     the picture's own headline, so the bar gets a scrim of its own. */
  .topbanner-bar { padding: 10px 0 20px; background: linear-gradient(rgba(0,0,0,0.45), rgba(0,0,0,0)); }

  /* Two up is right for a 390px screen and app.css:249 already says so. This
     just gives the tiles room to breathe once they are no longer in a 46px
     column, and lifts them to a proper touch target. */
  .quick-actions a { min-height: 62px; }

  .section { margin-bottom: 24px; }
  .month-grid { gap: 12px; }


  /* ==========================================================================
     5. THE PRICE SEARCH
     --------------------------------------------------------------------------
     "it is terrible if pricing is wrong. terrible" - so nothing here changes a
     number, a tier or a rounding. It only changes where the number sits.
     ========================================================================== */

  /* The row is `1fr auto` with an 18px gap. Inside .results at 390px there is
     about 246px to share, and .res .pr is white-space:nowrap, so the auto track
     claims the width of the longest unbreakable string ("DISTRIBUTOR" over a
     25px price) and the 1fr track - the product name and SKU - is what gives.
     Stacking is the honest fix: the name gets the full width, the price sits
     under it at full size rather than being squeezed. */
  .res { grid-template-columns: 1fr; gap: 8px; padding: 14px 16px; }
  .res .pr { text-align: left; }
  /* ⛔ the nowrap STAYS on the price itself. A wrapped "$1,234.56" is a
     misreadable price. It comes off only the container, so the label and the
     badges beneath it can flow. */
  .res .pr .priceblock { white-space: nowrap; }

  /* ⛔⛔ A NESTED SCROLLER INSIDE THE PAGE SCROLLER. On a phone this traps the
     flick: the inner list eats the gesture and the page behind it will not
     move, and 62vh of an 844px screen is a 523px window with the rest of the
     page dead below it. The page itself is the scroller on mobile. */
  .results { max-height: none; overflow-y: visible; }

  /* Right-aligned 23px chips hard against the screen edge. */
  .qchips { justify-content: flex-start; gap: 6px; }
  .qchips button { min-height: 38px; padding: 6px 12px; font-size: 12.5px; }

  /* a fixed 260px on a 358px-wide card, on the one badge whose whole job is to
     stop the eye before a units disagreement gets quoted */
  .src-badge.severe { max-width: none; }

  .tierbar .wrap { gap: 10px; }
  .tierseg { margin-left: 0; width: 100%; }
  .tierseg button { flex: 1; min-height: 42px; }


  /* ==========================================================================
     6. RESOURCES - the filter wall
     --------------------------------------------------------------------------
     ⛔⛔ MEASURED: the sticky .toolbar is 700-770px tall on a 390px screen.
     7 tab chips plus ~34 folder chips wrap to roughly 18 rows. It is
     position:sticky, top:0, opaque, so after ~290px of scroll it pins and is
     TALLER THAN THE PHONE - the entire screen becomes filter chips and the
     documents scroll underneath, permanently hidden. The page renders no
     documents at all.

     One row each, scrolling sideways. Same chips, same order, same behaviour,
     and the toolbar drops to about 150px.
     ========================================================================== */

  .toolbar .chips {
    flex-wrap: nowrap;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
    /* edge to edge, so a half-visible chip reads as "there is more this way" */
    margin-left: -16px; margin-right: -16px;
    padding: 2px 16px 6px;
  }
  .toolbar .chips::-webkit-scrollbar { height: 0; }
  .toolbar .chips .chip { flex: 0 0 auto; }
  .toolbar { padding: 10px 0 8px; }
  .search-field { margin-bottom: 10px; }

  /* ⛔ THE THIRD min-width:auto ON THIS PAGE SET, and it only shows at 320px.
     .doc is a grid item, so its automatic minimum is its own min-content: the
     42px thumb plus the widest unbreakable run in the title, the meta pills and
     the alternative-version pills. Measured 300px inside a 258px track on an
     iPhone SE. The card is what should give, not the page. */
  .doc-list > .doc { min-width: 0; }
  .doc-title, .doc-meta { overflow-wrap: anywhere; }


  /* ==========================================================================
     7. THE IMAGE LIBRARY
     --------------------------------------------------------------------------
     ⛔⛔ THE TILES ARE ANONYMOUS ON A TOUCH SCREEN. .tile-overlay carries the
     shoot name and its location, and it is drawn at opacity:0 behind
     `.tile:hover`. A phone has no hover, so it can never fire, and the library
     is a wall of unlabelled photographs. Everything else on this page is a
     nicety; this is the page not working.
     ========================================================================== */

  @media (hover: none) {
    .tile .tile-overlay { opacity: 1; }
    /* the shot-type pill sits bottom-left and app.css hides it on hover, which
       on touch now means it would sit under the permanent overlay */
    .tile .tile-shot { opacity: 0; }
  }
  /* a lighter gradient, because it is now permanent rather than a hover reveal */
  .tile-overlay { background: linear-gradient(180deg, rgba(19,19,19,0) 46%, rgba(19,19,19,0.78) 100%); }

  /* ⛔ (0,1,1) each, so these tie the page rules and win on source order. The
     generic `select` floor in section 1 is only (0,0,1) and would lose. */
  .filter-row select { font-size: 16px; min-height: 44px; }
  .search-field input { font-size: 16px; }
  .filter-row { gap: 8px; }
  .filter-row select { min-width: 0; flex: 1 1 46%; }

  /* the lightbox is full screen already - it just needs thumbable chrome */
  .lb-head { padding: 12px 16px; }
  .lb-body { padding: 0 16px 16px; }
  .lb-close { width: 44px; height: 44px; }
  .lb-strip { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 10px; }


  /* ==========================================================================
     8. THE CALCULATORS AND FREIGHT - the answer goes first
     --------------------------------------------------------------------------
     Both pages are a two column grid: form on the left, answer on the right.
     Collapsed to one column the answer lands UNDER the whole form, and the
     ArchiMat form is about 700px tall, so on a phone you fill it in and then
     have to scroll past everything you just typed to find out what it cost.
     `order` moves the answer above the form without touching the markup.
     ========================================================================== */

  /* ⛔ .work is ALREADY one column here - calculators.html:27 collapses it at
     880px. It is left as a grid rather than switched to flex, because the only
     thing actually needed is the order swap, and the grid keeps its own gap.
     ⛔⛔ min-width: 0 IS LOAD BEARING. A grid item defaults to min-width:auto,
     so .card.out refused to shrink below the natural width of the answer table
     inside it and the page measured 638px on a 360px screen. This is the same
     fix, for the same reason, as app.css:242 on the hub. */
  .work { gap: 14px; }
  .work > * { min-width: 0; }
  .work > .card.out { order: -1; }

  /* freight.html is the same shape with different names: .calc is the two
     column grid and .result is the dark total panel. Same min-width:0, and the
     total goes above the form for the same reason. */
  .calc { gap: 14px; }
  .calc > * { min-width: 0; }
  .calc > .result { order: -1; }
  .result { padding: 18px; }
  .total { font-size: 34px; }
  .qty-row { grid-template-columns: 1fr 96px; }

  /* the picker is a wall of 95px tiles before you reach anything */
  .picker { grid-template-columns: 1fr 1fr; gap: 8px; }
  .picker button { min-height: 56px; }
  .picker button s { display: none; }


  /* ==========================================================================
     9. MY HUBSPOT
     ========================================================================== */

  /* .hs-row is space-between with a nowrap right column and a nowrap,
     ellipsised title. The title is the only thing that identifies the row, and
     it is the only thing allowed to shrink, so it ellipsises to nothing. */
  .hs-row { flex-wrap: wrap; gap: 8px 12px; }
  .hs-row-main { flex: 1 1 100%; min-width: 0; }
  .hs-row-main b { white-space: normal; overflow: visible; text-overflow: clip; }
  .hs-row-right { flex: 0 0 auto; text-align: left; white-space: normal; }
  .hs-cards { grid-template-columns: 1fr 1fr; gap: 8px; }
  .hs-card-v { font-size: 24px; }
  .hs-tick, .hs-ico { width: 40px; height: 40px; }


  /* ==========================================================================
     10. THE REST
     ========================================================================== */

  /* ⛔ Every one of these ties or beats a page rule that sets a sub-16px font.
     They are listed one by one rather than forced with !important, because a
     blanket `input { font-size: 16px !important }` would also SHRINK the price
     search box, which is deliberately 17px. Sources: rates.html .rc-row inputs
     at 13.5px, admin #grid inputs at 13.5px and its .findrow at 15px, the tag
     generator's monospace textarea at 13px. */
  .rc-row input[data-key] { font-size: 16px; min-height: 44px; }
  #grid td input, #grid td select { font-size: 16px; min-height: 42px; }
  .findrow input { font-size: 16px; }
  textarea#input { font-size: 16px; }
  /* people.html's add-a-seat row, and the per-person view picker in the table */
  .addrow input, .addrow select { font-size: 16px; min-height: 44px; }
  select.viewpick { font-size: 16px; min-height: 40px; }
  /* the logo mat configurator's own field style, 13.5px on every control */
  .dz-field select, .dz-field input { font-size: 16px; height: 44px; }

  /* the design tool's canvas is a flex item whose automatic minimum size is its
     own max-width, so it cannot shrink and it takes the page with it */
  #dz-canvas, .dz-mat-row, .dz-grid { min-width: 0; max-width: 100%; }
  .dz-grid { display: flex; flex-direction: column; }

  /* ⛔ #gate is position:fixed inset:0 and centres its box. With the soft
     keyboard up there is less than 400px of room, the box is ~380-425px tall,
     and centred content with no scroll puts the Unlock button off screen with
     no way to reach it. Top aligned and scrollable instead. */
  #gate { align-items: flex-start; overflow-y: auto; padding: 20px 16px 40px; }
  #gate .box { margin-top: 6vh; }

  /* a work address is one unbreakable token and it is the whole point of these
     two lines - measured at 313px inside a 288px box on a 320px screen */
  #who b, .done p b { overflow-wrap: anywhere; }

}
