/* ============================================
   FIRST-RUN WELCOME BANNER
   ============================================
   Non-blocking banner shown to brand-new users
   over the demo team. Two primary CTAs plus a
   footer link:
     - Show me around    (kicks off coach-marks)
     - Set up my team    (Onboarding 3-step)
     - I'll explore on my own  (text link, dismiss)
   ============================================ */

.first-run-banner {
  /* `fixed` already establishes the containing block for the absolutely-pinned
     close button, which is deliberately a child of the BANNER's box rather than
     the centred .first-run-banner-inner: the inner is max-width:1200px, so on a
     wide desktop it leaves a gutter and an X pinned to it would sit ~40px further
     in than the same X on a phone. Pinning to the banner keeps the inset
     identical at every width. */
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 9000;
  background: linear-gradient(135deg, var(--primary-500, #14b8a6) 0%, var(--accent-500, #06b6d4) 100%);
  color: white;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
  transform: translateY(-100%);
  transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}

.first-run-banner.visible {
  transform: translateY(0);
}

/* Never cover an open dialog. The banner is a top-docked, dismissable strip at
   z-index:9000 — far above the modal layer (--z-modal:3000). On desktop the
   centred dialog and the top banner barely overlap, but on mobile the banner is
   ~250px tall and sits over the modal's header, so Settings / Dashboard / any
   modal looked like it "didn't open" while the first-run banner was visible
   (the dialog opened fine underneath, just hidden). A passive welcome strip must
   defer to a real dialog: hide it whenever any modal is active. :has() is already
   relied on elsewhere in the app's CSS. The board padding-top from
   .first-run-banner-active is harmless while a full-screen modal is up. */
body:has(.modal.active) .first-run-banner {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

/* CONSISTENT CLOSE ANCHOR (2026-07-30, user: "make this area have a consistent x
   for desktop and mobile"). The X used to be the 4th flex CHILD of the row, so its
   position was a by-product of whatever the row was doing: on desktop it landed
   inline after the CTAs, vertically centred; on mobile the row switched to
   column + align-items:stretch and the X dropped to the BOTTOM CENTRE, below the
   CTAs. Same control, two unrelated homes — and on mobile it read as a third
   button in the CTA stack rather than a dismiss affordance.

   Fix: take the X out of flow entirely and pin it to the BANNER's top-right
   corner at every breakpoint (see .first-run-banner-close; it is also a sibling
   of this row in the markup, not a child, so the centred max-width below can't
   push it inward on wide screens). The inner row then only lays out
   icon/text/actions, and reserves padding-right so nothing slides under it. */
.first-run-banner-inner {
  max-width: 1200px;
  margin: 0 auto;
  /* Right padding clears the absolutely-pinned close button (30px + 12px inset). */
  padding: 14px 52px 14px 20px;
  display: flex;
  align-items: center;
  gap: 16px;
}

.first-run-banner-icon {
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.18);
  border-radius: 50%;
  font-size: 18px;
  /* The brand tile has its own opaque white square (the favicon contract —
     see the tab-icon memory); clip it round so it sits in the circle like
     the glyph did, without a white box poking out of the corners. */
  overflow: hidden;
}

.first-run-banner-logo {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  display: block;
}

.first-run-banner-text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.first-run-banner-title {
  font-weight: 600;
  font-size: 15px;
  line-height: 1.3;
}

.first-run-banner-subtitle {
  font-size: 13px;
  opacity: 0.92;
  line-height: 1.4;
}

.first-run-banner-actions {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-shrink: 0;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.first-run-cta {
  appearance: none;
  border: none;
  cursor: pointer;
  padding: 8px 14px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 600;
  font-family: inherit;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  transition: all 0.15s ease;
  white-space: nowrap;
}

.first-run-cta-primary {
  background: white;
  color: var(--primary-700, #0f766e);
}

.first-run-cta-primary:hover {
  /* Tokenised 2026-08-05 — was a raw #f0fdfa (teal-50) literal, the only
     hardcoded brand colour left in this file. The fallback keeps the exact
     prior rendering if --primary-50 is ever unset. */
  background: var(--primary-50, #f0fdfa);
  transform: translateY(-1px);
}

.first-run-cta-secondary {
  background: rgba(255, 255, 255, 0.18);
  color: white;
  border: 1px solid rgba(255, 255, 255, 0.3);
}

.first-run-cta-secondary:hover {
  background: rgba(255, 255, 255, 0.28);
}

.first-run-link {
  appearance: none;
  border: none;
  background: transparent;
  color: white;
  text-decoration: underline;
  text-underline-offset: 3px;
  padding: 6px 0 0;
  margin-top: 4px;
  font: inherit;
  font-size: 0.875rem;
  cursor: pointer;
  opacity: 0.82;
  align-self: flex-start;
}

.first-run-link:hover {
  opacity: 1;
}

/* Pinned to the banner's top-right corner — the SAME anchor on every viewport
   (see the note on .first-run-banner-inner). Absolute so it can never be
   re-flowed by the row's direction/stretch changes at the mobile breakpoint. */
.first-run-banner-close {
  position: absolute;
  top: 12px;
  right: 12px;
  appearance: none;
  border: none;
  background: transparent;
  color: white;
  cursor: pointer;
  padding: 6px;
  border-radius: 50%;
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0.7;
  transition: opacity 0.15s ease, background 0.15s ease;
}

.first-run-banner-close:hover {
  opacity: 1;
  background: rgba(255, 255, 255, 0.15);
}

/* When banner is visible, push board content down so it isn't covered. */
body.first-run-banner-active {
  padding-top: 68px;
}

/* MOBILE (2026-07-30 optimisation pass, user: "optomise mobile layout if
   possible"). The old mobile banner was a 4-row vertical stack — stretched icon
   block, text, CTA rows, then a bottom-centred X — measuring 230-266px, roughly a
   third of a 390x844 phone viewport before the app's own header even started. It
   was also the direct cause of the 2026-07-27 menu-burial bug (the fixed chrome
   was offset by a stale 168px constant while the banner ran to 248px).

   The redesign keeps the icon INLINE beside the title on one compact header row,
   then puts the subtitle and the CTAs beneath it, which removes a whole row and
   ~70px of height. The X stays pinned top-right, matching desktop. */
@media (max-width: 720px) {
  .first-run-banner-inner {
    /* Two-column grid: a small fixed icon rail + the content column. The icon
       sits on the title's row rather than being stretched into a row of its own
       (the old `flex-direction:column; align-items:stretch` blew it up to full
       width and cost an entire row of vertical space). */
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: start;
    column-gap: 12px;
    row-gap: 8px;
    padding: 12px 48px 12px 14px;
  }

  /* Icon shrinks and aligns to the title's optical centre. */
  .first-run-banner-icon {
    width: 32px;
    height: 32px;
    font-size: 15px;
    margin-top: 1px;
  }

  /* Text column sits beside the icon; the actions span BOTH columns on the next
     row so the CTAs get the full width instead of being inset by the icon rail. */
  .first-run-banner-text {
    grid-column: 2;
  }

  .first-run-banner-actions {
    grid-column: 1 / -1;
    display: flex;
    flex-wrap: nowrap;
    gap: 8px;
  }

  /* Both CTAs share the row equally — they fit side-by-side down to ~360px with
     the tightened padding below, so this saves a second stacked row. */
  .first-run-cta {
    flex: 1 1 0;
    justify-content: center;
    min-width: 0;
    padding: 9px 10px;
  }

  /* Let a long label ellipsis rather than force the row to wrap or overflow. */
  .first-run-cta span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .first-run-banner-title {
    font-size: 14.5px;
  }

  .first-run-banner-subtitle {
    font-size: 12.5px;
  }

  /* Dismiss link tucks under the subtitle inside the text column — it stays a
     quiet text link rather than becoming a third full-width button. */
  .first-run-link {
    align-self: flex-start;
    margin-top: 2px;
    font-size: 0.8125rem;
  }

  /* NOTE: no .first-run-banner-close override here on purpose. It is pinned
     top-right by the base rule at every width — that consistency is the point. */

  /* Fallback only: js/ui/first-run.js measures the mounted banner and writes the
     real height into --first-run-banner-offset. Measured post-redesign at 168px
     (390-414px wide) and 185px (320-360px, where the subtitle takes a 4th line);
     was 230-266px before. Deliberately set to the WORST case rather than the
     typical one — undershooting is what buried the ⋮ menu under the z:9000 banner
     in 2026-07-27, whereas overshooting only leaves a little dead space for the
     one frame before the measurement lands. */
  body.first-run-banner-active {
    padding-top: 186px;
  }
}

body.dark-mode .first-run-banner {
  background: linear-gradient(135deg, var(--primary-700, #0f766e) 0%, #0e7490 100%);
}

/* The LEARNING CHOOSER block that used to sit here (.first-run-chooser-*, ~268
   lines incl. its own dark-mode variant) was deleted 2026-08-05 along with
   showLearningChooser() in js/ui/first-run.js. Its only caller returned early
   whenever PracticeMode.start existed, and practice-mode.js is an unconditional
   <script defer> — so the chooser was unreachable and never rendered for any
   user. See the note in first-run.js for why practice-first won outright. */

/* ============================================
   LOCAL-ONLY BANNER (signed-out save/share nudge)
   ============================================
   Shown to a signed-out visitor once they've added their own city locally —
   those edits live only in this browser until they sign in.

   REDESIGN (2026-07-16): re-skinned to match the app's LIGHT surface identity
   instead of the old foreign dark-slate slab. It is now a floating, rounded
   card (--radius-lg) docked to the bottom with a margin, on the app's teal-tint
   surface (--primary-50) with a teal left accent, slate text (--text-primary/
   -secondary) and the canonical teal→cyan CTA gradient + focus ring. This makes
   it read as part of FairlyRemote, not a system bar bolted on. Still BOTTOM-
   docked so it never collides with the top-docked first-run welcome.
   ============================================ */

.local-only-banner {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 8900; /* below first-run (9000) and modals, above the board */
  /* Transparent shell: the card itself (‑inner) carries the surface so it can
     float with a margin rather than spanning wall-to-wall like a system bar. */
  background: transparent;
  pointer-events: none; /* only the card catches clicks, not the dead gutter */
  transform: translateY(calc(100% + 24px));
  transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}

.local-only-banner.visible {
  transform: translateY(0);
}

/* Reserve board space so the fixed banner never OVERLAYS the timeline rows it
   describes — the board ends above it instead of being covered. The page scrolls
   at the document level with body full-height, so padding the body's bottom
   extends the scroll area by exactly the banner's footprint (card height + its
   bottom margin). Toggled by local-only-banner.js (mount adds the class), the
   same mechanism as body.first-run-banner-active at the top. */
body.local-only-banner-active {
  padding-bottom: 92px; /* ~63px card + 16px margin + breathing room */
}

/* Defer to any open dialog, same rationale as the first-run banner. */
body:has(.modal.active) .local-only-banner {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

.local-only-banner-inner {
  pointer-events: auto;
  max-width: 760px;
  margin: 0 auto 16px;
  padding: 12px 14px 12px 16px;
  display: flex;
  align-items: center;
  gap: 14px;
  /* App light surface + teal-tint, matching cards/popovers elsewhere. */
  background: var(--bg-primary, #ffffff);
  border: 1px solid var(--primary-200, #99f6e4);
  border-left: 3px solid var(--primary-500, #14b8a6);
  border-radius: var(--radius-lg, 16px);
  box-shadow:
    0 10px 30px rgba(15, 118, 110, 0.14),
    0 2px 8px rgba(15, 23, 42, 0.06);
}

.local-only-banner-icon {
  flex-shrink: 0;
  width: 34px;
  height: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--primary-50, #f0fdfa);
  border: 1px solid var(--primary-100, #ccfbf1);
  border-radius: var(--radius-full, 9999px);
  font-size: 15px;
  color: var(--primary-600, #0d9488);
}

.local-only-banner-text {
  flex: 1;
  min-width: 0;
  font-size: 13px;
  line-height: 1.45;
  color: var(--text-secondary, #475569);
}

.local-only-banner-cta {
  appearance: none;
  border: none;
  cursor: pointer;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 8px 14px;
  border-radius: var(--radius-sm, 8px);
  font-size: 13px;
  font-weight: 600;
  font-family: inherit;
  color: #ffffff;
  background: linear-gradient(135deg, var(--primary-500, #14b8a6) 0%, var(--accent-500, #06b6d4) 100%);
  box-shadow: 0 1px 2px rgba(13, 148, 136, 0.25);
  transition: filter 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
}

.local-only-banner-cta:hover {
  filter: brightness(1.05);
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(13, 148, 136, 0.3);
}

.local-only-banner-cta:focus-visible {
  outline: var(--focus-ring-width, 2px) solid var(--focus-ring, #2dd4bf);
  outline-offset: var(--focus-ring-offset, 2px);
}

.local-only-banner-close {
  appearance: none;
  border: none;
  cursor: pointer;
  flex-shrink: 0;
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm, 8px);
  color: var(--text-muted, #64748b);
  background: transparent;
  font-size: 15px;
  transition: color 0.15s ease, background 0.15s ease;
}

.local-only-banner-close:hover {
  color: var(--text-primary, #1e293b);
  background: var(--slate-100, #f1f5f9);
}

.local-only-banner-close:focus-visible {
  outline: var(--focus-ring-width, 2px) solid var(--focus-ring, #2dd4bf);
  outline-offset: var(--focus-ring-offset, 2px);
}

/* Mobile: full-bleed card that hugs the bottom, with the text stacked above the
   actions so the CTA never gets clipped. */
@media (max-width: 640px) {
  .local-only-banner-inner {
    max-width: none;
    margin: 0 10px 10px;
    flex-wrap: wrap;
    gap: 8px 12px;
    padding: 12px 12px 12px 14px;
  }
  .local-only-banner-text {
    flex-basis: 100%;
    order: 1;
  }
  .local-only-banner-icon { order: 0; }
  .local-only-banner-cta { order: 2; margin-left: auto; }
  .local-only-banner-close { order: 3; }

  /* Card is taller here (text wraps onto its own line above the actions), so
     reserve more bottom space to match. */
  body.local-only-banner-active {
    padding-bottom: 124px;
  }
}

/* Dark mode: keep it a light-on-dark CARD (elevated slate surface with a teal
   accent), not the near-black slab it used to be — so it still reads as an
   app card in the dark theme. */
body.dark-mode .local-only-banner-inner {
  background: var(--slate-800, #1e293b);
  border-color: var(--primary-800, #115e59);
  border-left-color: var(--primary-400, #2dd4bf);
  box-shadow:
    0 10px 30px rgba(0, 0, 0, 0.45),
    0 2px 8px rgba(0, 0, 0, 0.3);
}

body.dark-mode .local-only-banner-icon {
  background: rgba(20, 184, 166, 0.14);
  border-color: rgba(45, 212, 191, 0.3);
  color: var(--primary-300, #5eead4);
}

body.dark-mode .local-only-banner-text {
  color: var(--slate-300, #cbd5e1);
}

body.dark-mode .local-only-banner-close:hover {
  color: var(--slate-100, #f1f5f9);
  background: rgba(148, 163, 184, 0.16);
}
