/* ── MOBILE ────────────────────────────────────────────────────────────
   One place for everything the phone needs and the desktop must not see.

   Every rule in this file lives inside a max-width media query, so the
   desktop layout cannot be touched from here by accident. It loads last,
   after every other stylesheet, so it wins on specificity ties without
   needing !important for ordinary overrides.

   The rules are grouped by what they fix, and each group says what was
   wrong — a phone bug is rarely obvious from the selector alone.

   Breakpoints, and only these three:
     900px — the hamburger appears; the phone/tablet layout starts here.
     640px — one column; sheets replace panels.
     380px — the smallest phones still in use.
────────────────────────────────────────────────────────────────────── */

/* ══ 1. FOUNDATIONS ══════════════════════════════════════════════════ */

@media (max-width: 900px) {

  /* ── The iOS zoom ──
     Safari zooms the whole page in when you focus a field whose text is
     under 16px, and it never zooms back out. Every form on KULI was 14 or
     15px, so tapping any field — sign in, post a listing, the island
     search inside a dropdown — threw the layout sideways and left the
     renter pinch-zooming their way back. 16px is the entire fix; nothing
     else about the field changes. */
  .form-input,
  .form-select,
  .form-textarea,
  .kd-search input,
  .pr-val-input,
  input[type="text"],
  input[type="email"],
  input[type="tel"],
  input[type="url"],
  input[type="number"],
  input[type="search"],
  input[type="password"],
  input[type="date"],
  textarea,
  select {
    font-size: 16px;
  }

  /* A tap that lands three pixels off should still land. Anything the
     finger is meant to hit gets a real target; where the control has to
     stay small for the bar's sake, the target grows by padding and the
     drawn box stays the size it was. */
  .theme-toggle,
  .nav-right .theme-toggle,
  .nav-hamburger {
    min-width: 44px;
    min-height: 44px;
    height: 44px;
  }
  .nav-hamburger { padding: 6px 11px; gap: 5px; }

  /* The save disc on a card and the social marks in the footer are drawn
     small on purpose. Growing them would change the design, so the tap
     area is grown around them instead — an invisible box on the pseudo
     element, which the drawing never sees. Same trick the photo-thumb
     remove button already uses (css/pages.css). */
  /* .card-fav / .pcard-fav are already absolutely positioned, so they are
     their own containing block; only the footer marks need one. */
  .footer-socials a { position: relative; }
  .card-fav::after,
  .pcard-fav::after { content: ''; position: absolute; inset: -5px; }
  .footer-socials a::after { content: ''; position: absolute; inset: -5px -3px; }
  .pw-toggle::after { content: ''; position: absolute; inset: -9px; }
  .pr-clear { min-height: 40px; padding: 8px 10px; }

  /* A link inside a sentence cannot be 44px tall without pushing the
     sentence apart — but vertical padding on an inline box is painted and
     hit outside the line without changing the line's height at all, which
     is exactly the target this needs and none of the layout it doesn't. */
  .auth-link,
  .kauth-forgot,
  .kauth-foot a,
  .form-hint a,
  .report-link,
  .legal p a,
  .legal li a,
  .sup-block p a { padding-block: 9px; }

  /* Leaflet's own +/- are 30px squares out of the box, and its touch
     stylesheet says so at a specificity this has to match. */
  .leaflet-bar a,
  .leaflet-touch .leaflet-bar a,
  .mp-map .leaflet-bar a {
    width: 40px; height: 40px; line-height: 40px;
  }

  /* A secondary button is still a button somebody has to hit. */
  .btn-sm { min-height: 42px; }

  /* Momentum and containment on every sideways rail, so a horizontal
     flick never becomes a vertical one halfway through — and never hands
     the gesture on to the page behind it. */
  .filter-bar-inner,
  .nd-adopted,
  .mp-rail,
  .gallery-thumbs,
  .lb-thumbs {
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
  }
}

/* ── Stuck hover ──
   A touch screen has no pointer to leave, so :hover latches onto the last
   thing tapped and stays there — a card left lifted four pixels off the
   grid, a photo left zoomed in. Those states are decoration, so on a
   device with no hover they simply do not exist. */
@media (hover: none) {
  .listing-card:hover { transform: none; border-color: var(--hairline); }
  .listing-card:hover .card-img img,
  .listing-card:hover .card-img-placeholder { transform: none; }
  .card-fav:hover { transform: none; background: rgba(13,11,11,0.62); }
  .mp-prev:hover .mp-prev-img img { transform: none; }
  .gallery-cell:hover img { transform: none; }
  .kd-opt:hover { background: transparent; }
  .kd-opt.kd-selected:hover { background: rgba(126,123,120,0.22); }

  /* Pressing still has to answer. A tap that changes nothing on screen
     reads as a tap that missed. */
  .listing-card:active { border-color: var(--bronze); }
  .kd-opt:active { background: rgba(126,123,120,0.16); }
  .nav-mobile-menu a:active { background: rgba(126,123,120,0.16); }
}

/* ══ 2. THE HEADER AND THE MENU ══════════════════════════════════════ */

@media (max-width: 900px) {

  /* Room is the scarce thing in a 390px bar, so the gutters give some of
     it back to whatever is between them. */
  .navbar { padding: 0 16px; }

  /* ── The menu ──
     It used to be a dropdown: a panel hanging under the navbar, as tall
     as its own contents, with the page still showing above it (through a
     navbar that has no background of its own) and below it. Open, it read
     as a rendering fault rather than as a menu.

     It is now the screen. It starts at the top edge and the header's
     height is padding, so the mark, the theme toggle and the close cross
     stay exactly where they were and the bar never appears to change —
     but everything is the menu now, and what shows through the navbar's
     transparency is the menu, not the listings.

     Kept in the layout rather than display:none'd, so it can be seen to
     arrive instead of appearing. */
  .nav-mobile-menu {
    display: flex !important;
    top: 0; bottom: 0; left: 0; right: 0;
    height: auto;
    padding: calc(var(--nav-h) + 14px) 16px calc(20px + env(safe-area-inset-bottom, 0px));
    border-bottom: none;
    /* The blur was over a page that is no longer visible behind it. */
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    overflow-y: auto;
    overscroll-behavior: contain;
    gap: 0;
    z-index: 480;               /* under the navbar: the cross stays on top */
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transform: translateY(-10px);
    transition: opacity 0.24s var(--ease),
                transform 0.32s var(--expo-out),
                visibility 0.32s;
  }
  .nav-mobile-menu.open {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transform: none;
  }

  /* Fully opaque, in both themes. The panel used to be 98% over a page it
     only partly covered, where the 2% read as depth; covering the whole
     screen it reads as a listing photo showing through the menu. Doubled
     class name only to reach past the theme rule in variables.css, which
     is the one that set the 98%. */
  .nav-mobile-menu.nav-mobile-menu { background: var(--bg); }

  /* Full-width rows at a thumb's height, one per line. */
  .nav-mobile-menu a {
    display: flex;
    align-items: center;
    min-height: 52px;
    padding: 4px 12px;
    font-size: 17px;
    border-radius: 2px;
  }
  .nav-mobile-menu .nav-mobile-divider { margin: 14px 0 0; }

  /* The account row sits at the foot of the screen rather than directly
     under the last link — it is a different kind of thing, and the gap
     says so without a second rule. */
  .nav-mobile-bottom {
    margin-top: auto;
    padding-top: 18px;
    gap: 12px;
  }
  .nav-mobile-bottom .btn,
  .nav-mobile-bottom .btn-sm {
    min-height: 50px;
    font-size: 15px;
  }
  .nav-mobile-bottom.authed .nmb-user { padding: 2px 4px 8px; }

  /* While the menu is up, nothing else floats over it. */
  html.kuli-menu-open .mp-fab,
  html.kuli-menu-open .mobile-cta,
  html.kuli-menu-open .si-rail,
  html.kuli-menu-open #scroll-progress {
    opacity: 0;
    pointer-events: none;
  }

  /* Signed in, the avatar in the bar is a second account control beside
     the one already inside the menu. One of them is enough, and the menu
     is the one with room for a name. */
  .nav-right .nav-user-menu { display: none; }
}

/* ══ 3. THE FILTER BAR ═══════════════════════════════════════════════ */

@media (max-width: 900px) {

  /* ── The 30px filter bar ──
     `max-width: min(1240px, calc(100vw - 360px))` is the width the navbar
     gives this row on a laptop, and on a 390px phone it resolves to 30px:
     the whole filter row became a 30px window, centred, onto 750px of
     controls. That is the "Isla" sliver — an island field cropped to four
     letters with no way to reach any of the others.

     On a phone the row takes the full width and scrolls sideways, which
     is what it was always meant to do here. The gutter moves from the bar
     onto the row itself, so the first control starts on the page's margin
     and the last one can still scroll clear of the edge.

     Scoped through .filter-bar on purpose: the same row travels into the
     navbar (js/search-dock.js), and there it is a child of .nav-dock and
     must keep the navbar's spacing, not the page's. */
  .filter-bar { padding-left: 0; padding-right: 0; }
  .filter-bar .filter-bar-inner {
    max-width: none;
    width: auto;
    margin: 0;
    justify-content: flex-start;
    gap: 10px;
    padding: 2px 18px;
    scroll-padding-inline: 18px;
  }
  /* The chips under the row keep the gutter the bar just gave up. */
  .filter-bar .active-filters { padding: 0 18px; margin-top: 10px; }

  /* Every control in the row is a thumb target. */
  .filter-bar-inner .kd-trigger,
  .filter-bar-inner .filter-select,
  .filter-bar-inner .filter-toggle,
  .filter-bar-inner .sort-select,
  .filter-bar-inner .pr-btn,
  .filter-bar-inner .mp-trigger {
    height: 44px;
    min-height: 44px;
    font-size: 13.5px;
    padding-inline: 14px;
  }
  .afchip { min-height: 34px; padding: 6px 12px; }

  /* Docked in the navbar the row is the widest thing in the bar, so it
     takes every pixel the mark and the menu are not using. */
  .nav-dock { margin: 0 8px; }
  .nd-adopted { gap: 8px; }
}

/* ══ 4. THE HERO SEARCH ══════════════════════════════════════════════ */

@media (max-width: 900px) {
  /* Three stacked fields and a button, each one a full-width row. */
  .hs-field { min-height: 56px; }
  .hs-field .kd-trigger { font-size: 15px; }
  .hs-go { min-height: 50px; }
}

/* ══ 5. DROPDOWNS AND THE BUDGET PANEL ═══════════════════════════════ */

@media (max-width: 900px) {
  /* js/popover.js already pins these to the viewport and caps their
     height. What it cannot decide is how big a row has to be before it
     can be tapped reliably — that is here. */
  .kd-opt {
    display: flex;
    align-items: center;
    min-height: 46px;
    padding: 13px 14px;
    font-size: 15px;
  }
  .kd-group { padding: 14px 14px 6px; }
  .kd-list { padding: 6px; min-width: 200px; }
  .kd-big .kd-list { min-width: 250px; }
  .kd-search { padding: 10px; }
  .kd-search input { padding: 11px 12px; }

  /* The budget panel is the one dropdown with controls inside it, so it
     gets the room to be operated. */
  .pr-panel { padding: 22px 18px 20px; }
  .pr-vals { gap: 8px; margin-bottom: 22px; }
  .pr-val-box { padding: 12px 13px; }
  .pr-slider-wrap { height: 52px; }
  /* A 22px handle on glass is a handle you miss. */
  .pr-range::-webkit-slider-thumb { width: 26px; height: 26px; }
  .pr-range::-moz-range-thumb { width: 24px; height: 24px; }
  .pr-presets button { min-height: 38px; padding: 8px 13px; }
  .pr-clear { min-height: 40px; }
}

/* ══ 6. MAP PEEK — THE PHONE SHEET ═══════════════════════════════════ */

@media (max-width: 900px) {

  /* ── The head ──
     Title and note shared one baseline, which is right on a drawer 480px
     wide and wrong on a phone: both wrapped to two lines and interleaved,
     so "Where these homes are" and "Showing 2 of 3 homes on the map" read
     as one broken paragraph with a cross in it. Stacked, they are a title
     and its note again. */
  .mp-sheet .mp-head {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: start;
    gap: 2px 12px;
    padding: 20px 16px 12px;
  }
  .mp-sheet .mp-title { grid-column: 1; grid-row: 1; font-size: 18px; }
  .mp-sheet .mp-note  { grid-column: 1; grid-row: 2; font-size: 12px; line-height: 1.45; }
  .mp-sheet .mp-close {
    grid-column: 2; grid-row: 1 / span 2;
    align-self: center;
    width: 44px; height: 44px;
    border: 1px solid var(--hairline);
  }

  /* ── "N homes are outside the view" ──
     It is pinned to the bottom of the map's container, and on the sheet
     that container also holds the card rail — so the chip sat on top of
     the first card instead of on the map. --mp-rail-h is published by
     js/map-peek.js and is exactly how much of that bottom belongs to the
     rail. */
  .mp-sheet .mp-all {
    left: 12px; right: auto;
    bottom: calc(var(--mp-rail-h, 0px) + 12px);
    max-width: calc(100% - 24px);
    height: auto; min-height: 38px;
    padding: 8px 13px;
    text-align: left;
  }
  .mp-sheet .mp-all .mp-all-n { white-space: normal; }

  /* "Show homes in this area" clears the head and stays clear of the zoom
     controls on the right. */
  .mp-sheet .mp-area {
    top: 12px;
    height: auto; min-height: 40px;
    padding: 9px 16px;
    max-width: calc(100% - 96px);
  }

  /* The rail is the phone's marker preview, so it gets the width to be
     one. */
  .mp-sheet .mp-rail {
    gap: 8px;
    padding: 10px 12px calc(12px + env(safe-area-inset-bottom, 0px));
  }
  .mp-rcard { width: min(260px, 76vw); padding: 9px; }
  .mp-rcard-img { flex-basis: 66px; height: 66px; }

  /* The floating trigger clears the home indicator, and never sits under
     the listing page's contact bar. */
  .mp-fab {
    bottom: calc(16px + var(--mcta-h, 0px) + env(safe-area-inset-bottom, 0px));
    height: 48px;
    padding: 0 20px;
  }

  /* The empty state is a sentence, not a page. */
  .mp-empty { padding: 28px 24px; }
  .mp-empty-title { font-size: 18px; }
}

/* ══ 7. LISTING DETAIL ═══════════════════════════════════════════════ */

@media (max-width: 900px) {
  /* The contact bar is the one thing on this page that must never be
     covered, and it has to clear the phone's own home indicator. */
  .mobile-cta { padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px)); }

  /* Everything the bar is pinned over has to end above it. --mcta-h is set
     by listing-detail.html once the bar has a height, and is undefined
     everywhere else — so this is exactly 0 on every other page. */
  .detail-layout { padding-bottom: calc(28px + var(--mcta-h, 0px)); }
  .site-footer { margin-bottom: var(--mcta-h, 0px); }

  /* The lightbox on a phone: the photo takes the screen, and the controls
     sit on its edges rather than 40px inside them. */
  .lightbox {
    padding: 16px 12px calc(16px + env(safe-area-inset-bottom, 0px));
    gap: 10px;
  }
  .lightbox > img { max-width: 100vw; max-height: 62vh; }
  .lb-close { top: calc(12px + env(safe-area-inset-top, 0px)); right: 12px; }
  .lb-close, .lb-nav { width: 44px; height: 44px; }
  .lb-prev { left: 8px; }
  .lb-next { right: 8px; }

  .gallery-thumbs, .lb-thumbs { scroll-padding-inline: 8px; }
}

/* ══ 8. FORMS ════════════════════════════════════════════════════════ */

@media (max-width: 900px) {
  /* ── The pricing note ──
     `margin-top: -22px` was pulling this line up into the box above it:
     against that box's own 18px bottom margin it collapsed to -4px, so
     the sentence started four pixels ABOVE the border it was meant to sit
     under and touched it the whole way across. It is a note about the box
     above, so it stays close — but under it. */
  .price-manual-note { margin: 2px 0 28px; }

  /* Deposit and advance: the label takes its own line and the amounts sit
     under it. What was missing was room to breathe once the row became
     three stacked things instead of one. */
  .pay-row { padding: 14px 0 16px; }
  .pay-row-note { margin-top: 5px; }
  .pay-edit { min-height: 40px; margin-top: 2px; }

  /* A control at the end of a written line is still a control. */
  .kd-form .kd-trigger { min-height: 48px; }
  .seg button { min-height: 46px; }
  .form-textarea { min-height: 132px; }
}

/* ══ 9. OVERLAYS ═════════════════════════════════════════════════════ */

@media (max-width: 900px) {
  /* 100vh on a phone is the viewport with the address bar gone — which is
     not the viewport anyone is looking at, so a panel capped at it runs
     off the bottom until you scroll. dvh is the height that is actually
     there; the vh line stays first as the fallback. */
  .kw-modal {
    max-height: calc(100vh - 40px);
    max-height: calc(100dvh - 40px);
    border-radius: 3px;
    /* Reaching the end of this list must not hand the gesture on to the
       page behind it — the page is held, but iOS still rubber-bands it. */
    overscroll-behavior: contain;
  }
  .kw-overlay {
    align-items: flex-end;
    padding: 16px 14px calc(16px + env(safe-area-inset-bottom, 0px));
  }

  /* Every dismiss control on an overlay is a thumb target. */
  .kw-x,
  .lb-close,
  .mp-close,
  .kauth-x,
  .report-close { min-width: 44px; min-height: 44px; }

  /* Breadcrumbs are links people aim at, not a caption. */
  .breadcrumb a { display: inline-flex; align-items: center; min-height: 36px; }
}

/* ══ 10. FOOTER ══════════════════════════════════════════════════════ */

@media (max-width: 900px) {
  /* Footer links were 16px tall and six apart — a column of near-misses.
     The text is unchanged; only the box around it grows. */
  .footer-col a,
  .footer-links a {
    display: inline-flex;
    align-items: center;
    min-height: 40px;
  }
  .footer-links { gap: 20px; flex-wrap: wrap; }
}

/* ══ 11. NARROW PHONES ═══════════════════════════════════════════════ */

@media (max-width: 640px) {
  /* One thing per line, wherever a pair of controls was sharing one. */
  .nav-mobile-bottom:not(.authed) { flex-direction: column; }
  .nav-mobile-bottom:not(.authed) .btn { width: 100%; }

  /* "View All" beside a section heading is a link people aim at. */
  .link-all { display: inline-flex; align-items: center; min-height: 40px; }
}

@media (max-width: 380px) {
  .navbar { padding: 0 12px; }
  .filter-bar .filter-bar-inner { padding-inline: 14px; scroll-padding-inline: 14px; }
  .filter-bar .active-filters { padding: 0 14px; }
  .nav-mobile-menu { padding-left: 12px; padding-right: 12px; }
  .mp-rcard { width: 78vw; }
}
