/* Mobile reference build of the multi-city planner — a self-contained,
   touch-first take on /worldtimebuddy-v2, deliberately kept separate from
   the desktop planner's CSS so this can be iterated on without touching
   production. Not linked from anywhere; reached only by its own URL. */

:root {
  --mtb-bg: #ffffff;
  --mtb-fg: #0f172a;
  --mtb-muted: #64748b;
  --mtb-border: #e2e8f0;
  --mtb-accent: #16a34a;
  --mtb-accent-bg: rgba(22, 163, 74, 0.16);
  --mtb-accent-bg-strong: rgba(22, 163, 74, 0.28);
  --mtb-radius: 16px;
}

* { box-sizing: border-box; }

/* Page-level reset/behavior below (the html,body rules) is scoped to
   html.mtb-standalone — set only by the standalone mobile page's own
   layout — so it never leaks into /time-zone-meeting-planner, which loads this
   stylesheet alongside the desktop planner's own. v3 wraps its mobile
   shell in the site's own header/footer (to read as part of the site
   rather than a full-screen app takeover), so that combined page is
   often taller than one viewport and needs to scroll normally — the
   opposite of the fixed, non-scrolling single "screen" the standalone
   page deliberately is. v3's layout sets html.v3-page instead, which
   intentionally gets none of this — see .mtb-app below for the one
   height/touch-action difference that still applies there. */
html.mtb-standalone,
html.mtb-standalone body {
  margin: 0;
  background: var(--mtb-bg);
  color: var(--mtb-fg);
  font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  -webkit-tap-highlight-color: transparent;
  /* Some browsers (notably iOS Safari) ignore user-scalable=no in the
     viewport meta tag for accessibility reasons and allow pinch/double-tap
     zoom anyway — once zoomed, the layout viewport really is wider than
     the screen until the user manually zooms back out, which reads
     exactly like a stray horizontal scroll. touch-action here is what
     actually gets respected: it stops double-tap-to-zoom at the CSS
     level regardless of what the meta tag says. */
  touch-action: manipulation;
  /* The only intentional horizontal scrolling lives inside .mtb-track and
     .mtb-date-tabs, and both already clip themselves. The page itself
     should never scroll on either axis — a safety net so a single pixel
     of stray overflow anywhere can't turn into a page-level scrollbar,
     on top of .mtb-app's own fixed 100dvh + overflow:hidden. */
  overflow: hidden;
}

button {
  font: inherit;
  color: inherit;
}

main {
  display: block;
}

/* ---- phone-frame preview — the standalone mobile page only (desktop
   convenience so it can be previewed without a real device). On v3, the
   desktop shell already shows the real desktop version above 900px, so
   its mobile shell should never get this decorative bezel mockup at any
   width — it always gets the real, full-bleed app instead (below). ---- */
@media (min-width: 560px) {
  html.mtb-standalone body {
    background: #0b1220;
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 32px 16px;
  }
  html.mtb-standalone .mtb-frame {
    width: 390px;
    height: 844px;
    border: 10px solid #111827;
    border-radius: 46px;
    overflow: hidden;
    box-shadow: 0 30px 70px rgba(0, 0, 0, 0.55);
    position: relative;
    /* Makes this the containing block for position:fixed descendants (like
       .mtb-add-city-btn and .mtb-overlay) too, not just position:absolute
       ones — otherwise "fixed" elements would escape the phone bezel
       mockup and float over the whole browser window instead of staying
       inside it. Real phones never hit this: this whole block only applies
       to the desktop preview convenience (>=560px), see the comment above. */
    transform: translateZ(0);
  }
  html.mtb-standalone .mtb-app { height: 100%; overflow: hidden; }
}
@media (max-width: 559px) {
  .mtb-frame { display: contents; }
  /* Fixed to exactly one screen, not min-height — a native app screen
     doesn't scroll as a whole; it's one fixed layout. Whatever doesn't
     fit is clipped rather than reachable via scroll (see the JS: vertical
     drags are intentionally inert now, there's nothing to scroll to).
     Scoped to the standalone page only — this rule used to apply
     unconditionally, which also clipped v3's mobile shell on any real
     phone (virtually all of them are ≤559px wide): once enough cities
     were added to overflow one screen, the extra rows (and the "Add
     city" button itself) were silently cut off instead of the page
     just growing taller and scrolling, which is what v3 wants (see the
     900px rule below). */
  html.mtb-standalone .mtb-app { height: 100dvh; overflow: hidden; }
}
/* v3's own shell-switch breakpoint (900px) is wider than the standalone
   page's own 559px cutoff above — this covers that gap so v3's mobile
   shell is never the phone-bezel mockup, right up to where the desktop
   shell takes over. Unlike the standalone page, .mtb-app is NOT forced to
   a fixed 100dvh here: v3 wraps this in the site's header/footer, so the
   card should size to its own content (like the desktop planner's own
   section does) and let the page scroll normally if the total is taller
   than one screen, rather than being its own fixed, clipped mini-screen. */
@media (max-width: 900px) {
  html.v3-page .mtb-frame { display: contents; }
}

.mtb-app {
  display: flex;
  flex-direction: column;
  background: var(--mtb-bg);
}
/* Standalone only: the JS drives horizontal panning itself
   (pan.locked === 'x' -> scrollX) and vertical drags are intentionally
   inert (there's nothing to scroll to — the page is one fixed screen) —
   touch-action other than 'none' here lets the browser start its own
   native vertical scroll the instant it sees ANY vertical component,
   often before that JS decision even runs, which produced a flicker/jump
   on the smallest vertical wobble. On v3, the page can legitimately be
   taller than one screen (header/footer above and below this card), so
   native vertical scroll needs to stay available here — see the matching
   condition in multi-city-planner-mobile.js (ALLOW_PAGE_SCROLL). */
html.mtb-standalone .mtb-app { touch-action: none; }

/* ---- top bar ---- */
.mtb-topbar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 14px 10px;
  border-bottom: 1px solid var(--mtb-border);
  flex: 0 0 auto;
}
/* v3 only — the site's own header (rendered above this card) already
   provides a way back, so the close button is redundant there. The
   standalone page has no header/nav at all, so it keeps this as its only
   way out. */
html.v3-page #mtbCloseBtn { display: none; }
.mtb-icon-btn {
  flex: 0 0 auto;
  width: 38px;
  height: 38px;
  border-radius: 999px;
  border: 1px solid var(--mtb-border);
  background: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.mtb-icon-btn:active { background: var(--mtb-accent-bg); }

.mtb-date-tabs {
  flex: 1 1 auto;
  display: flex;
  gap: 6px;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  padding: 2px;
}
.mtb-date-tabs::-webkit-scrollbar { display: none; }
.mtb-date-tab {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  min-width: 40px;
  padding: 4px 6px;
  border-radius: 12px;
  border: 1px solid transparent;
  background: transparent;
  cursor: pointer;
}
.mtb-date-tab span { font-size: 9px; font-weight: 700; text-transform: uppercase; color: var(--mtb-muted); }
.mtb-date-tab strong { font-size: 14px; font-weight: 700; }
.mtb-date-tab.is-weekend span, .mtb-date-tab.is-weekend strong { color: #dc2626; }
.mtb-date-tab.is-today strong { color: var(--mtb-accent); }
.mtb-date-tab.is-active { background: var(--mtb-fg); border-color: var(--mtb-fg); }
.mtb-date-tab.is-active span, .mtb-date-tab.is-active strong { color: #fff; }

/* ---- 24h / am-pm toggle — same segmented-control language as desktop's
   .planner-format-toggle, just sized for the topbar. ---- */
.mtb-format-toggle {
  flex: 0 0 auto;
  display: flex;
  border: 1px solid var(--mtb-border);
  border-radius: 8px;
  overflow: hidden;
}
.mtb-format-btn {
  border: 0;
  background: #fff;
  color: var(--mtb-muted);
  font-size: 10px;
  font-weight: 700;
  padding: 6px 8px;
  cursor: pointer;
  white-space: nowrap;
}
.mtb-format-btn + .mtb-format-btn { border-left: 1px solid var(--mtb-border); }
.mtb-format-btn.is-active { background: var(--mtb-fg); color: #fff; }

/* ---- hint ---- */
.mtb-hint {
  flex: 0 0 auto;
  font-size: 11.5px;
  color: var(--mtb-muted);
  text-align: center;
  padding: 8px 16px 0;
}
.mtb-hint.is-hidden { display: none; }

/* ---- board ---- */
.mtb-board {
  flex: 1 1 auto;
  /* Bottom padding reserves space for .mtb-add-city-btn, which is now
     position:fixed and floats over whatever's beneath it (its own height
     — roughly 40px — plus its 14px offset from the edge, plus the iOS home
     indicator safe area) so the last row isn't clipped behind the button. */
  padding: 10px 14px calc(12px + 40px + 14px + env(safe-area-inset-bottom));
  /* No scroll on either axis — a native app screen, not a scrollable page.
     Whatever doesn't fit is clipped; see the .mtb-app height:100dvh above
     and the JS, where vertical drags are now intentionally inert. */
  overflow: hidden;
}

/* ---- shared horizontal-pan viewport ----
   Every hour cell is a fixed 52px so it's actually tappable/legible on a
   phone; the day (24 * 52 = 1248px) is wider than the screen, so the
   timeline + every city row's track sit in their own clipped "viewport"
   (.mtb-hscroll) and share a single scroll offset (state.scrollX in the
   JS) applied as a transform to each's .mtb-hscroll-inner. They're kept
   in sync by JS, not by native per-element scrolling — see the pointer
   handling in multi-city-planner-mobile.js. */
.mtb-hscroll {
  position: relative;
  overflow: hidden;
  /* touch-action is set once, on .mtb-app — an ancestor's 'none' already
     wins over any descendant value, so this is just clipping/positioning. */
}
.mtb-hscroll-inner {
  /* relative (not absolute+top/left/bottom) on purpose — it stays in normal
     flow so its height comes from its own content (the cells' padding),
     instead of needing a hardcoded pixel height on .mtb-track to stretch
     against. It's still the positioning context for the highlight/handles.
     Its content (.mtb-track-cells) is wider than the viewport and simply
     overflows — .mtb-track's overflow-x:hidden is what clips it; translateX
     works the same regardless of this element's own declared width. */
  position: relative;
  will-change: transform;
}
.mtb-track-cells { display: flex; }

.mtb-band-duration {
  position: absolute;
  top: -20px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 10.5px;
  font-weight: 700;
  color: var(--mtb-accent);
  white-space: nowrap;
  background: #fff;
  padding: 0 4px;
  border-radius: 6px;
}
.mtb-band-handle {
  position: absolute;
  top: 50%;
  width: 22px;
  height: 34px;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  justify-content: center;
}
.mtb-band-handle::after {
  content: '';
  width: 6px;
  height: 22px;
  border-radius: 3px;
  background: var(--mtb-accent);
}
.mtb-band-handle-start { left: 0; }
.mtb-band-handle-end { left: 100%; }

/* ---- city rows ---- */
.mtb-rows { display: flex; flex-direction: column; gap: 14px; }
.mtb-row { border-bottom: 1px solid var(--mtb-border); padding-bottom: 12px; }
.mtb-row:last-child { border-bottom: none; padding-bottom: 0; }

.mtb-row-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
}
.mtb-pin-btn {
  flex: 0 0 auto;
  min-width: 38px;
  height: 30px;
  padding: 0 6px;
  border-radius: 8px;
  border: 1px solid var(--mtb-border);
  background: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 700;
  color: var(--mtb-muted);
  cursor: pointer;
}
.mtb-pin-btn.is-home { background: var(--mtb-fg); border-color: var(--mtb-fg); color: #fff; font-size: 14px; }

.mtb-row-info { flex: 1 1 auto; min-width: 0; }
.mtb-row-name-line { display: flex; align-items: baseline; gap: 3px; }
.mtb-row-name { font-size: 15px; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mtb-row-tz { font-size: 10px; font-weight: 700; color: var(--mtb-muted); }
.mtb-row-meta { font-size: 11px; color: var(--mtb-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.mtb-row-time { flex: 0 0 auto; text-align: right; max-width: 42%; }
.mtb-row-time-value { font-size: 13px; font-weight: 700; color: var(--mtb-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mtb-row-time-value.is-range { color: var(--mtb-accent); }

.mtb-row-remove {
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  border-radius: 999px;
  border: 1px solid var(--mtb-border);
  background: #fff;
  color: var(--mtb-muted);
  cursor: pointer;
}

.mtb-track {
  position: relative;
  border-radius: 8px;
  /* Real padding, not overflow:visible — the duration label + resize
     handles need room above/below the colored band. overflow:visible
     content still bleeds into .mtb-board's own scrollable-area
     calculation (it's not clipped by an intermediate box, so the nearest
     actual scroll container has to account for it), which was exactly
     the phantom vertical-scroll-per-row bug: it inflated .mtb-board's
     content height just enough to need scrolling. Giving this box real
     height via padding means that space is accounted for normally, and
     .mtb-hscroll's plain overflow:hidden (both axes) is enough. */
  padding: 28px 0 8px;
}
/* Same palette/shape language as the desktop planner's .planner-seg (see
   multi-city-planner.css) — same tier hex values, same collapsed 1px
   borders between cells, same rounded capsule at the very start/end of
   the 24h track, same dark day-boundary pill. Sized down for a phone. */
.mtb-track-cell {
  flex: 0 0 auto;
  position: relative;
  display: flex;
  /* Column, not row: in 12h mode the am/pm suffix stacks under the hour
     number (same as the desktop planner's .planner-seg), not beside it. */
  flex-direction: column;
  align-items: center;
  /* Centered, not left-aligned: a 1h selection's handles sit exactly at
     the cell's left/right edges, and a left-aligned label starting a few
     px in gets covered by the handle right there. Centered keeps the
     number clear of both edges regardless of selection width. */
  justify-content: center;
  gap: 1px;
  /* Top/bottom padding — not a height — is what gives the row its natural
     size, so it always exactly fits the label with nothing left to overflow. */
  padding: 10px 0;
  background: #f8fafc;
  border-right: 1px solid var(--mtb-border);
}
.mtb-track-cell:last-child { border-right: none; }
.mtb-track-cell:first-child { border-radius: 8px 0 0 8px; }
.mtb-track-cell:last-child { border-radius: 0 8px 8px 0; }
.mtb-track-cell.tier-night { background: #e2e8f0; }
.mtb-track-cell.tier-business { background: #e3ffe5; }
.mtb-track-cell.tier-evening { background: #ffedd5; }
.mtb-track-cell-label { font-size: 11px; font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums; color: var(--mtb-muted); }
.mtb-track-cell-suffix { font-size: 7px; font-weight: 700; line-height: 1; text-transform: lowercase; opacity: 0.75; color: var(--mtb-muted); }
.mtb-track-cell.tier-night .mtb-track-cell-label,
.mtb-track-cell.tier-night .mtb-track-cell-suffix { color: #64748b; }
.mtb-track-cell.tier-business .mtb-track-cell-label,
.mtb-track-cell.tier-business .mtb-track-cell-suffix { color: #4f8a58; }
.mtb-track-cell.tier-evening .mtb-track-cell-label,
.mtb-track-cell.tier-evening .mtb-track-cell-suffix { color: #b4682a; }

/* The dark "SEP 23" pill marking a new local day — same colors/shape as
   the desktop version's .planner-seg.is-day-boundary. */
.mtb-track-cell.is-day-break {
  background: #334155;
  border: 2px solid #64748b;
  border-radius: 12px 0 0 12px;
  z-index: 2;
}
.mtb-track-cell.is-day-end { border-radius: 0 12px 12px 0; }
.mtb-track-cell-daybreak { display: flex; flex-direction: column; align-items: center; gap: 1px; line-height: 1; }
.mtb-track-cell-daybreak-month { font-size: 7.5px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: rgba(255, 255, 255, 0.85); }
.mtb-track-cell-daybreak-day { font-size: 13px; font-weight: 800; color: #fff; }
.mtb-track-highlight {
  position: absolute;
  top: -6px;
  bottom: -6px;
  border-radius: 10px;
  background: var(--mtb-accent-bg-strong);
  border-left: 2px solid var(--mtb-accent);
  border-right: 2px solid var(--mtb-accent);
  touch-action: none; /* grabbable — dragging its body moves the selection instead of panning */
  cursor: grab;
  /* Higher than .mtb-track-cell.is-day-break's z-index:2 — otherwise the
     day-break pill (which needs its own stacking to sit above plain
     cells) paints over the selection/handles instead of the other way
     around whenever the selection lands on a day-break column. */
  z-index: 3;
}
.mtb-now-line {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 2px;
  background: #ef4444;
  pointer-events: none;
}

/* ---- add city floating button ----
   position:fixed (not a normal flex child) so it stays pinned to the
   bottom of the screen regardless of how tall .mtb-board's content gets —
   .mtb-board reserves matching bottom padding above so its last row is
   never clipped behind it. */
.mtb-add-city-btn {
  position: fixed;
  left: 14px;
  right: 14px;
  bottom: calc(14px + env(safe-area-inset-bottom));
  z-index: 40;
  padding: 12px;
  border-radius: 12px;
  border: 1px dashed var(--mtb-border);
  background: #fff;
  color: var(--mtb-muted);
  font-weight: 700;
  font-size: 13px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  cursor: pointer;
  box-shadow: 0 2px 10px rgba(15, 23, 42, 0.08);
  transition: opacity 0.15s ease, transform 0.15s ease;
}
.mtb-add-city-btn:active { background: #f8fafc; }
/* Set by JS (IntersectionObserver watching the site <footer>) — only
   reachable on v3, where the page can scroll past the card into the site
   footer; the standalone page has no <footer> at all, so this class is
   simply never added there. Without it, the fixed button would float on
   top of the footer's own content once scrolled into view. */
.mtb-add-city-btn.is-hidden {
  opacity: 0;
  transform: translateY(8px);
  pointer-events: none;
}
/* Set by JS (IntersectionObserver watching .v3-landing, v3 only) — once
   the landing content below the tool starts entering the viewport, the
   button stops floating over it and rejoins the normal document flow
   right where it already sits in the markup (end of .mtb-app, before
   .v3-landing) — so it scrolls away with the rest of the page instead of
   floating on top of the landing sections. */
.mtb-add-city-btn.is-docked {
  position: static;
  left: auto;
  right: auto;
  bottom: auto;
  margin: 40px 14px 14px;
  box-shadow: none;
}

/* ---- overlays / sheets ---- */
.mtb-overlay {
  position: absolute;
  inset: 0;
  background: rgba(15, 23, 42, 0.45);
  display: flex;
  align-items: flex-end;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease;
  z-index: 50;
}
@media (max-width: 559px) {
  .mtb-overlay { position: fixed; }
}
.mtb-overlay.is-open { opacity: 1; pointer-events: auto; }

.mtb-sheet {
  width: 100%;
  max-height: 78%;
  background: #fff;
  border-radius: 20px 20px 0 0;
  padding: 10px 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  transform: translateY(12px);
  transition: transform 0.15s ease;
}
.mtb-overlay.is-open .mtb-sheet { transform: translateY(0); }

.mtb-sheet-handle {
  width: 36px;
  height: 4px;
  border-radius: 999px;
  background: var(--mtb-border);
  margin: 0 auto;
}
.mtb-sheet-title { margin: 0; font-size: 14px; font-weight: 700; text-align: center; }

.mtb-sheet-head { display: flex; align-items: center; gap: 8px; }
.mtb-sheet-head input {
  flex: 1 1 auto;
  padding: 10px 12px;
  border-radius: 10px;
  border: 1px solid var(--mtb-border);
  font-size: 15px;
}
.mtb-sheet-close {
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  border-radius: 999px;
  border: 1px solid var(--mtb-border);
  background: #fff;
  font-size: 16px;
  cursor: pointer;
}

.mtb-search-results { overflow-y: auto; }
.mtb-search-item {
  width: 100%;
  text-align: left;
  padding: 10px 6px;
  border: none;
  border-bottom: 1px solid var(--mtb-border);
  background: transparent;
  cursor: pointer;
}
.mtb-search-item-label { display: block; font-size: 14px; font-weight: 600; }
.mtb-search-item-sub { display: block; font-size: 12px; color: var(--mtb-muted); }
.mtb-search-empty { padding: 14px 6px; color: var(--mtb-muted); font-size: 13px; }

.mtb-share-summary {
  margin: 0;
  font-size: 12.5px;
  color: var(--mtb-muted);
  white-space: pre-line;
  max-height: 120px;
  overflow-y: auto;
}
.mtb-share-actions { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; }
.mtb-share-action {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 12px 8px;
  border-radius: 12px;
  border: 1px solid var(--mtb-border);
  background: #fff;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
}
.mtb-share-action.is-primary { background: var(--mtb-fg); border-color: var(--mtb-fg); color: #fff; }
