/* ============================================================================
   MOEDATECH — MOBILE BEHAVIOUR                                     2026-08-26
   Hosted, so changes here ship by deploying the asset host with NO Webflow
   publish. Loaded from ONE line in the site-wide head field, which replaced a
   5,600-character inlined block and gave that field its room back.

   A stylesheet link rather than JS-injected CSS on purpose: injected styles
   would let the old wrapped nav paint for a frame before being corrected.

   Two things live here:
     1. the mobile header sheet for the skinned pages (html.v4skin)
     2. the sideways-scroll hint, for every rail on every page
   ========================================================================= */

/* ==========================================================================
   1. SKINNED-PAGE MOBILE HEADER
   At 390px these pages drew a 130px double-decker bar: the skin wraps .v4nav
   to a second row at full width, and those four group labels went nowhere
   because .v4mm opens on hover and touch has none. This gives them the same
   66px bar and sheet that home-v4 has.
   ========================================================================== */
@media (max-width: 900px) {
  html.v4skin body :is(.v4bar,.v4mbar) {
    flex-wrap: nowrap;
    padding: 12px 18px;
    gap: 10px;
    min-height: 66px;
    align-items: center;
    position: relative;
    z-index: 70;                 /* stays above the sheet */
  }
  html.v4skin body :is(.v4bar,.v4mbar) > .v4bar-brand { margin-inline-end: auto; }
  /* header.hdr keeps its own brand class (only the .v4bar branch adds
     .v4bar-brand), and the bar's first child is the brand in BOTH shells -
     so this is what pushes the lang pill and the button to the far side. */
  html.v4skin body :is(.v4bar,.v4mbar) > *:first-child { margin-inline-end: auto; }
  /* the skin gives header.hdr an inline margin-inline-end:auto on the nav to
     centre it on desktop; hidden here, but the inline style would otherwise
     survive and eat the row */
  html.v4skin body :is(.v4bar,.v4mbar) > .v4nav { margin: 0; }
  html.v4skin body :is(.v4bar,.v4mbar) > .v4nav { display: none; }

  html.v4skin body .v4navbtn {
    display: inline-grid; place-items: center; flex: none;
    width: 36px; height: 36px; padding: 0;
    border: 1px solid var(--hairline); border-radius: var(--radius-pill);
    background: transparent; color: var(--ink); cursor: pointer;
    transition: border-color .15s ease;
  }
  html.v4skin body .v4navbtn:hover { border-color: var(--ink); }
  html.v4skin body .v4navbtn svg {
    width: 18px; height: 18px; fill: none; stroke: currentColor;
    stroke-width: 1.9; stroke-linecap: round;
  }
  html.v4nav-open.v4skin body .v4navbtn .v4nb-open { display: none; }
  html.v4skin body .v4navbtn .v4nb-shut { display: none; }
  html.v4nav-open.v4skin body .v4navbtn .v4nb-shut { display: block; }

  html.v4nav-open.v4skin body :is(.v4bar,.v4mbar) > .v4nav {
    display: flex; flex-direction: column; align-items: stretch; gap: 2px;
    /* flex-wrap:wrap is a desktop convenience on .v4nav and it SURVIVES the
       switch to column. Against the sheet's fixed height that made the four
       groups wrap into columns - measured at x=18, 374, 730, 1086 on a 390px
       screen, so three of the four sat off the side of the phone. This one
       line is what makes the sheet a single scrolling stack. */
    flex-wrap: nowrap; align-content: flex-start;
    position: fixed; inset: 66px 0 0 0; z-index: 60; margin: 0;
    padding: 16px 18px 32px;
    background: var(--bg); border-top: 1px solid var(--hairline);
    overflow-y: auto; -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
  }
  html.v4nav-open.v4skin body .v4nav-item { width: 100%; }
  html.v4nav-open.v4skin body .v4nav-top {
    width: 100%; justify-content: space-between;
    padding: .7rem .25rem; font-size: 1rem;
  }
  html.v4nav-open.v4skin body .v4nav-top:hover { background: transparent; }
  html.v4nav-open.v4skin body .v4nav-top svg { display: none; }

  html.v4nav-open.v4skin body .v4mm {
    /* display is the load-bearing one: the skin ships
       .v4mm:not([data-open]){display:none} at this width, so overriding
       position/opacity/visibility alone left every panel hidden and only the
       four group labels showing. */
    display: block;
    position: static; transform: none; opacity: 1; visibility: visible;
    pointer-events: auto; width: 100%; min-width: 0; max-width: none;
    padding: 0 0 10px 12px; background: transparent; border: 0;
    box-shadow: none; -webkit-backdrop-filter: none; backdrop-filter: none;
  }
  html.v4nav-open.v4skin body .v4mm-row { padding: .55rem 0; }
  html.v4nav-open.v4skin body .v4mm-feat { margin-top: .5rem; }

  html.v4nav-open, html.v4nav-open body { overflow: hidden; }
}
@media (min-width: 901px) { html.v4skin body .v4navbtn { display: none; } }


/* ==========================================================================
   2. SIDEWAYS-SCROLL HINT
   Every rail already cuts the next card at the edge - the peek - which says
   "there is more". It does not say how much, and on the long rails there are
   six to eleven screens of it. So a label says it in words and then gets out
   of the way the moment you scroll.

   The script adds .mh-hint only to rails that ACTUALLY overflow, so a short
   rail never gets a hint telling you to scroll something that cannot.
   ========================================================================== */
.mh-hint {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  /* inline-flex alone does NOT hug: every rail sits in a stretch container,
     which stretched the pill to the full column width (measured 33 -> 372 on
     a 390px screen) and turned a quiet label into a heavy bar. These three
     make it hug its own text under flex, grid and block parents alike, and
     sit at the reading start in both directions. */
  width: fit-content;
  max-width: 100%;
  align-self: start;
  justify-self: start;
  margin-top: 10px;
  padding: 6px 13px;
  border-radius: 999px;
  background: var(--bg-sunk, #e8dfd5);
  color: var(--ink-soft, #323232);
  font-family: var(--font, "Figtree", ui-sans-serif, system-ui, sans-serif);
  font-size: 12px;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  transition: opacity .3s ease;
}
.mh-hint svg {
  width: 14px; height: 14px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}
/* the arrow points the way the content continues, which flips with the script */
[dir="rtl"] .mh-hint svg { transform: scaleX(-1); }

/* retired: faded by the script, then taken out of the layout */
.mh-hint.mh-gone { opacity: 0; }
.mh-hint[hidden] { display: none; }

/* the hint is a mobile affordance; a mouse has a scrollbar and a trackpad */
@media (min-width: 901px) { .mh-hint { display: none; } }

/* a rail the keyboard can actually reach - none of them could before */
.mh-scroller:focus-visible {
  outline: 2px solid var(--cta, #e65d00);
  outline-offset: 3px;
  border-radius: 8px;
}

@media (prefers-reduced-motion: reduce) {
  .mh-hint { transition: none; }
}


/* ==========================================================================
   3. ARABIC FOUNDER QUOTE - MOVED OUT                            2026-08-26
   It used to live here. It does not any more, and the reason is worth
   keeping: the founder fix has two halves - the grid layout and the Arabic
   type size - and they were split across v4mobile.css and v4.css. Hisham's
   phone then picked up ONE of them: it had the newer v4.css, so the type was
   the corrected larger size, while its cached v4mobile.css still predated the
   grid rule. The result was the worst of both - the old two-column phone
   layout with the new bigger type crammed into a 110px column, which looked
   worse than the bug we started from.

   Both halves now live together at the end of v4.css. One fix, one file, so
   a stale copy of either can never show half of it.
   ========================================================================== */


/* ==========================================================================
   4. APP INSTALL BANNER                                          2026-09-01
   A pinned strip at the top of every mobile page sending visitors to the
   real store listing for their platform. Built by v4mobile.js, which also
   decides whether it should exist at all (platform, dismissal, width).

   THE SPACE IT OCCUPIES IS THE HARD PART, not the strip itself:

   `.floating-header` is `position: absolute; top: 0` (v4.css:122) - it FLOATS
   over the hero rather than sitting in the flow. So padding on <body> pushes
   the page down but leaves the header exactly where it was, sitting on top of
   the banner. Its `top` therefore has to be offset explicitly, and so does the
   `top` of both open nav sheets, which are `position: fixed; inset: 66px 0 0 0`
   and equally deaf to body padding.

   One custom property, --mt-appbar-h, drives all four. The script measures the
   real rendered height into it rather than anyone hard-coding 64px, because
   the strip is two lines of Arabic on some phones and one of Latin on others.
   ========================================================================== */

html.mt-appbar-on { --mt-appbar-h: 0px; }

/* the flow moves down... */
html.mt-appbar-on body { padding-top: var(--mt-appbar-h); }
/* ...the floating header MIGHT not, so it is offset only when measured to
   need it. On home-v4 it lives inside div.stage.stage-dark, which is
   position:relative and IN NORMAL FLOW - so the body padding already carries
   it, and adding our own `top` pushed it down TWICE (measured: banner ended at
   59, header rendered at 118, leaving a 59px hole). The script adds
   .mt-appbar-hdr only when the header did NOT move on its own, which is the
   case wherever it is a direct child of body and resolves against the ICB. */
html.mt-appbar-on.mt-appbar-hdr body .floating-header { top: var(--mt-appbar-h); }
/* ...and neither do the two open nav sheets. One extra class each, so these
   beat the `inset` shorthands in section 1 and in v4.css regardless of the
   order the two stylesheets happen to load in. */
html.mt-appbar-on.nav-open body .floating-header > .topnav,
html.mt-appbar-on.v4nav-open.v4skin body :is(.v4bar,.v4mbar) > .v4nav {
  top: calc(66px + var(--mt-appbar-h));
}

/* The space and the strip open together, on the same curve, so the banner
   appears to push the page down rather than land on a gap that was already
   waiting for it. --mt-appbar-h starts at 0 and the script sets the measured
   value one frame later, which is what gives these something to transition. */
html.mt-appbar-on body,
html.mt-appbar-on body .floating-header {
  transition: padding-top 280ms var(--ease-out, cubic-bezier(0.23, 1, 0.32, 1)),
              top 280ms var(--ease-out, cubic-bezier(0.23, 1, 0.32, 1));
}

/* ------------------------------------------------------------------ strip */
.mt-appbar {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  z-index: 90;                    /* over the header's 70 and the sheet's 60 */
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  /* standalone/home-screen only; 0 in normal Safari, so it costs nothing */
  padding-top: calc(10px + env(safe-area-inset-top, 0px));
  background: #101112;            /* --bg-dark, hard-coded: the skinned pages
                                     do not all load v4.css's :root */
  color: #fff;
  border-bottom: 1px solid rgba(255, 255, 255, 0.14);
  font-family: var(--font, "Figtree", ui-sans-serif, system-ui, -apple-system,
               "Segoe UI", Roboto, Helvetica, Arial, sans-serif);
  /* Entering, so ease-OUT: it moves at once and settles. The strip starts
     fully off the top edge - never scale(0), there is nothing to scale here,
     it simply has not arrived yet. */
  transform: translateY(-101%);   /* the extra 1% hides the border hairline */
  transition: transform 280ms var(--ease-out, cubic-bezier(0.23, 1, 0.32, 1));
  will-change: transform;
}
.mt-appbar[data-in] { transform: translateY(0); }

.mt-appbar-icon {
  flex: none;
  width: 38px; height: 38px;
  border-radius: 9px;             /* ~22% - the iOS squircle proportion */
  background: #fff;
  object-fit: cover;
}

.mt-appbar-copy { flex: 1 1 auto; min-width: 0; line-height: 1.25; }

.mt-appbar-title {
  display: block;
  font-size: 14px; font-weight: 600; color: #fff;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.mt-appbar-sub {
  display: -webkit-box;
  -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
  margin-top: 1px;
  font-size: 12.5px;
  color: rgba(255, 255, 255, 0.62);   /* --on-dark-muted */
}

/* the one filled thing in the strip, so it is unmistakably the action */
.mt-appbar-cta {
  flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 38px;
  padding: 0 15px;
  border-radius: 999px;
  background: #fff; color: #101112;
  font-size: 13.5px; font-weight: 600; text-decoration: none;
  white-space: nowrap;
  transition: transform 160ms var(--ease-out, cubic-bezier(0.23, 1, 0.32, 1));
}
/* press feedback: the strip has to feel like it heard the tap */
.mt-appbar-cta:active { transform: scale(0.97); }

.mt-appbar-x {
  flex: none;
  display: grid; place-items: center;
  /* 30px of ink, 44px of target - the tap area is padded out rather than
     drawn large, so dismissing never becomes the loudest thing in the bar */
  position: relative;            /* the ::after target is absolute to this */
  width: 30px; height: 30px;
  margin-inline-end: -7px;
  padding: 0;
  border: 0; background: transparent;
  color: rgba(255, 255, 255, 0.55);
  cursor: pointer;
  transition: transform 160ms var(--ease-out, cubic-bezier(0.23, 1, 0.32, 1)),
              color 160ms ease;
}
.mt-appbar-x::after {
  content: ""; position: absolute;
  top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 44px; height: 44px;      /* the real target, centred on the glyph */
}
.mt-appbar-x:active { transform: scale(0.9); color: #fff; }
.mt-appbar-x svg {
  width: 17px; height: 17px;
  fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round;
}

/* --------------------------------------------------------------- Arabic */
/* Site rule: when Arabic and Latin share a font-size the Arabic is already
   too small - Arabic ink sits smaller than Latin at the same px. Same x1.2
   correction the nav makes at 15 -> 17. Direction is inherited, and every
   offset above is logical, so RTL mirrors with no separate rules. */
html[lang="ar"] .mt-appbar-title { font-size: 16px; }
html[lang="ar"] .mt-appbar-sub   { font-size: 14px; }
html[lang="ar"] .mt-appbar-cta   { font-size: 15px; }

/* ----------------------------------------------------------- desktop off */
@media (min-width: 901px) {
  .mt-appbar { display: none; }
  html.mt-appbar-on { --mt-appbar-h: 0px !important; }
}

/* ------------------------------------------------------- reduced motion */
/* Fewer and gentler, not none: the strip still fades so it does not simply
   blink into existence, but nothing slides and the page does not move. */
@media (prefers-reduced-motion: reduce) {
  html.mt-appbar-on body,
  html.mt-appbar-on body .floating-header { transition: none; }
  .mt-appbar {
    transform: none; opacity: 0;
    transition: opacity 200ms ease;
  }
  .mt-appbar[data-in] { opacity: 1; }
  .mt-appbar-cta:active, .mt-appbar-x:active { transform: none; }
}

/* =============================================================================
   2026-09-14 — no focus frame around a whole scrolling rail
   A rail is full-bleed, so its focus ring showed only as two dark lines running
   the width of the page above and below the cards (reported from home-v4's
   Most rented strip). The site-wide :focus-visible rule in v4.css and the
   .mh-scroller rule above both drew it. The rail stays keyboard-reachable; the
   cards, size buttons and arrows inside keep their own focus rings.
   ========================================================================== */
html body .rail-viewport:focus-visible,
html body [data-rail]:focus-visible,
html body .mh-scroller:focus-visible,
html body .cmp-scroll:focus-visible {
  outline: none;
}


/* ==========================================================================
   2026-09-22  ·  THE OPEN MENU'S BAR SCROLLED AWAY, AND THE SKIN'S X WAS
   BURIED — the same two faults as home-v4, on every other page.

   Hisham, on a phone: "the close button keeps going with you when you are
   scrolling down, it ends up on top of one of the options"  and  "if I press
   one of the choices and open it again, there is no close button."

   MEASURED, /en/verification at 390px, menu open:
     - the X is drawn correctly (.v4nb-shut display:block, .v4nb-open none),
       but elementFromPoint at the button's centre returns `a.v4nav-top` —
       a link inside the sheet. Same cause as home-v4: the sheet is a CHILD
       of the bar, positioned with z-index 60, and the button beside it is
       static/auto, so the sheet paints over it. "No close button" is really
       "the close button cannot be touched".
     - the bar's controls run 67->103 while the sheet starts at 66, so they
       sit inside the sheet even before stacking is considered.
     - at scrollY 500 the button is at top -433: the bar is position:relative
       and simply scrolls off, while the sheet stays fixed. That is the
       button "going with you" and landing over the options.

   Fixes, applied to BOTH nav implementations:
     A. the bar's controls get their own z-index, above the sheet
     B. the sheet starts below the bar, measured into --mt-navsheet-top
     C. the bar is PINNED while the menu is open, so it cannot scroll away
   ========================================================================== */

@media (max-width: 900px) {

  /* C — pin the bar. html/body overflow:hidden is not enough on a phone:
     momentum scrolling still moves the page, and the bar went with it. */
  html.v4nav-open body :is(.v4bar, .v4mbar) {
    position: fixed !important;
    top: var(--mt-navbar-top, 0px) !important;
    inset-inline: 0 !important;
    z-index: 70 !important;
    background: var(--bg) !important;
  }

  /* A — the button sits above its own sheet (61 beats the sheet's 60) */
  html.v4nav-open body :is(.v4bar, .v4mbar) > .v4navbtn,
  html.v4nav-open body :is(.v4bar, .v4mbar) > *:not(.v4nav) {
    position: relative;
    z-index: 61;
  }

  /* B — and the sheet starts under the bar rather than behind it */
  html.v4nav-open body :is(.v4bar, .v4mbar) > .v4nav {
    top: var(--mt-navsheet-top, 66px) !important;
  }
}

/* home-v4's own bar needs C too — it is position:absolute, so it scrolled
   away exactly the same way. A and B for that nav are in v4.css, beside the
   rules they correct. */
@media (max-width: 60rem) {
  html.nav-open body .floating-header {
    position: fixed !important;
    top: var(--mt-navbar-top, 0px) !important;
    inset-inline: 0 !important;
  }
}

/* The bar is pinned at --mt-navbar-top (52px on a page carrying the National
   Day banner), so the strip ABOVE it still showed the page scrolling past —
   a sliver of the banner and the top of a card, floating over the menu.
   A pseudo-element paints that strip in the sheet's own colour: no layout
   change, no padding to collide with whatever the bar already sets. */
@media (max-width: 900px) {
  html.v4nav-open body :is(.v4bar, .v4mbar) { position: fixed; }
  html.v4nav-open body :is(.v4bar, .v4mbar)::before {
    content: ''; position: absolute; inset-inline: 0; bottom: 100%;
    height: var(--mt-navbar-top, 0px);
    background: var(--bg);
    pointer-events: none;
  }
}
@media (max-width: 60rem) {
  html.nav-open body .floating-header::before {
    content: ''; position: absolute; inset-inline: 0; bottom: 100%;
    height: var(--mt-navbar-top, 0px);
    background: var(--bg);
    pointer-events: none;
  }
}


/* ==========================================================================
   2026-09-22  ·  TOUCH TARGETS
   Measured across EN + AR at 390px. WCAG 2.2 "Target Size (Minimum)" asks
   for 24x24 CSS px; most of these were 15-23px tall because they are text
   links whose box is just the line height.

   WHAT IS DELIBERATELY NOT TOUCHED
   --------------------------------
   Links inside a sentence — `details.faq-q .faq-a p a` and the prose links
   in the docs pages. WCAG exempts targets "in a block of text", and padding
   a mid-sentence link makes the line leading lurch. They stay as they are.

   The approach is min-height + centring rather than padding wherever the
   element sits in a list, so the type does not move; padding would push
   every row down and grow the footer by a third.
   ========================================================================== */

@media (max-width: 900px) {

  /* --- the footer: 16 links a column at 15px tall, on every page --------- */
  html body .mtf-col ul li a,
  html body .mtf-contact a,
  html body .mtf-legal-row nav a {
    display: inline-flex;
    align-items: center;
    min-height: 28px;
  }

  /* --- the language toggle, on all four bars (44x23) -------------------- */
  html body :is(.v4bar, .v4mbar, .hdr, .floating-header) :is(.ctl-lang, .v4bar-lang, .mt-lang) {
    min-height: 36px;
  }

  /* --- home-v4's rate cards: "Rent this" 82x22, "All N sizes" 227x23 ---- */
  html body .rent-cta,
  html body .rent-more {
    display: inline-flex;
    align-items: center;
    min-height: 30px;
  }

  /* --- the supplier directory: category index + "See all" -------------- */
  html body .fc-idx a,
  html body .fc-showall {
    display: inline-flex;
    align-items: center;
    min-height: 28px;
  }

  /* --- the hero's slide dots were 10x10 --------------------------------
     The dot must STAY 10px — it is a mark, not a button, and growing it
     turns the progress row into a row of buttons. So the dot keeps its
     size and the FINGER gets a 28px square over it, which is what the
     ::after is for. 0.5rem gap between dots + 28px targets means the two
     hit areas touch but do not overlap. */
  html body .showreel-dots button { position: relative; }
  html body .showreel-dots button::after {
    content: '';
    position: absolute;
    top: 50%; left: 50%;
    width: 28px; height: 28px;
    transform: translate(-50%, -50%);
  }
}

/* Second pass, same day: three selectors missed.
   - `.mt-lang` is a DIV wrapping the anchor, so min-height landed on the
     wrapper and the <a> inside stayed 23px.
   - home-v4's own footer is `.util-cols` / `.util-socket`, not `.mtf-*`:
     that is the hand-written utility footer in embed 3, a different
     component from the hosted site footer. Seven 17px links and three
     20px ones. */
@media (max-width: 900px) {
  html body :is(.v4bar, .v4mbar, .hdr, .floating-header) :is(.ctl-lang, .v4bar-lang, .mt-lang) > a,
  html body :is(.v4bar, .v4mbar, .hdr, .floating-header) a:is(.ctl-lang, .v4bar-lang, .mt-lang) {
    display: inline-flex;
    align-items: center;
    min-height: 36px;
  }
  html body .util-cols ul li a,
  html body .util-socket > a {
    display: inline-flex;
    align-items: center;
    min-height: 28px;
  }
}

/* The dots sit 0.5rem apart, so 10px dot + 8px gap = 18px centre to centre.
   A 28px hit area over that OVERLAPS its neighbour by 10px — measured: a
   probe 11px left of one dot's centre lands on the dot before it. Enlarging
   the target without enlarging the spacing just moves the mis-tap around.
   So on a phone the gap opens to 16px (26px centre to centre) and the target
   matches it: they tile edge to edge with nothing between and nothing shared.
   The dot itself is still 10px. */
@media (max-width: 900px) {
  html body .showreel-dots { gap: 16px; }
  html body .showreel-dots button::after { width: 26px; height: 26px; }
}

/* The rate tables: 58 links at 17-18px, two per row across 29 rows, plus the
   three section headings. These are the page's main navigation — every one
   of them is "show me this machine" — so they matter more than the footer.
   Rows grow ~10px each on a phone, which a rate table can afford. */
@media (max-width: 900px) {
  html body table.eqt tbody tr th > a,
  html body table.eqt tbody tr td.k > a,
  html body .eqm-h h3 > a {
    display: inline-flex;
    align-items: center;
    min-height: 28px;
  }
}
/* ============================================================
   Mega menu: names only                          2026-09-23
   Hisham asked for the line under each row name to go, on
   every nav and both locales.

   Anchored on the ROW, so the featured card in each panel
   keeps its second line - that card is a CTA, not a menu row.

   Specificity, not !important: this file loads before v4.css
   and before the skin, so an equal-specificity rule would
   lose the tie.
   ============================================================ */
html body a.mm-row i,
html body a.v4mm-row .v4mm-s { display: none; }
