/*
 * This is a manifest file that'll be compiled into application.css.
 *
 * With Propshaft, assets are served efficiently without preprocessing steps. You can still include
 * application-wide styles in this file, but keep in mind that CSS precedence will follow the standard
 * cascading order, meaning styles declared later in the document or manifest will override earlier ones,
 * depending on specificity.
 *
 * Consider organizing styles into separate files for maintainability.
 */

/* ── Design tokens ───────────────────────────────────────────────────────────
   Single source of truth for brand colours used across CSS and JS.
   In Tailwind templates use the matching utility (e.g. bg-green-600).
   In JS inline styles use: `var(--color-primary)`.                           */

:root {
  --color-primary: #16a34a; /* green-600 — submit buttons, active states */
  --color-secondary: #3b82f6; /* blue-500  — drawing, vertex handles        */
}

/* ── Drawer ─────────────────────────────────────────────────────────────────
   Auto-height: drawer grows to fit its content up to 50dvh so the map
   remains visible underneath. Height modes (tall/large/full) live in
   DrawerHelper and are applied via the drawer-size Stimulus controller.
   Snap positions (data-snap) set by DrawerController.
   transition:none during drag (data-dragging); JS only sets style.transform
   for live finger tracking, clearing it on dragEnd.                   */

.tinted-glass-surface {
  background: linear-gradient(
    180deg,
    rgba(236, 253, 245, 0.28) 0%,
    rgba(248, 250, 252, 0.82) 100%
  );
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
}

[data-controller="drawer"] {
  transition: transform 0.3s ease;
}
[data-controller="drawer"][data-dragging] {
  transition: none;
}
[data-controller="drawer"][data-snap="0"] {
  transform: translateY(0%);
}
[data-controller="drawer"][data-snap="1"],
[data-controller="drawer"]:has(turbo-frame:empty) {
  transform: translateY(100%);
  pointer-events: none;
}
[data-controller="drawer"][data-snap="2"] {
  transform: translateY(calc(100% - 4rem));
}
[data-controller="drawer"][data-snap="2"] .drawer-body {
  visibility: hidden;
  pointer-events: none;
}

@media (min-width: 1024px) {
  [data-controller="drawer"][data-snap="0"] {
    transform: translateX(0%);
  }
  [data-controller="drawer"][data-snap="1"],
  [data-controller="drawer"]:has(turbo-frame:empty) {
    transform: translateX(100%);
    pointer-events: none;
  }
  [data-controller="drawer"][data-snap="2"] {
    transform: translateX(0%);
  }
  [data-controller="drawer"][data-snap="2"] .drawer-body {
    visibility: visible;
    pointer-events: auto;
  }
}

/* ── Chat stream spinner ─────────────────────────────────────────────────────
   Show a spinner inside the assistant bubble while waiting for the first chunk.
   :empty stops matching the moment any text is appended, hiding it for free.  */

[id$="_stream_content"]:empty::after {
  content: "";
  display: inline-block;
  width: 14px;
  height: 14px;
  border: 2px solid #d1d5db;
  border-top-color: #6b7280;
  border-radius: 50%;
  animation: chat-spin 0.6s linear infinite;
  vertical-align: middle;
}

@keyframes chat-spin {
  to {
    transform: rotate(360deg);
  }
}

/* ── Typography ──────────────────────────────────────────────────────────────
   Balance headings to avoid awkward line breaks.
   Pretty-wrap body text to prevent orphaned words.                           */

h1,
h2,
h3,
h4,
h5,
h6 {
  text-wrap: balance;
}

p,
li,
label {
  text-wrap: pretty;
}

/* Font smoothing + base typography defaults now live in the Tailwind base
   layer (app/assets/tailwind/application.css, see DESIGN.md §3). */

/* ── Address suggestions dropdown animation ──────────────────────────────────
   Fade + slide in from slightly above. JS toggles `suggestions-hidden` class. */

.suggestions-list {
  transform-origin: top center;
  transition:
    opacity 150ms cubic-bezier(0.2, 0, 0, 1),
    transform 150ms cubic-bezier(0.2, 0, 0, 1),
    visibility 0ms 0ms;
  opacity: 1;
  transform: translateY(0) scale(1);
  visibility: visible;
}

.suggestions-list.suggestions-hidden {
  opacity: 0;
  transform: translateY(-4px) scale(0.98);
  visibility: hidden;
  pointer-events: none;
  transition:
    opacity 100ms cubic-bezier(0.2, 0, 0, 1),
    transform 100ms cubic-bezier(0.2, 0, 0, 1),
    visibility 0ms 100ms;
}

/* ── Layers panel animation ──────────────────────────────────────────────────
   Toggle visibility with a scale + opacity transition instead of hard show/hide.
   JS adds/removes the `layers-panel-hidden` class.                           */

.layers-panel {
  transform-origin: bottom right;
  transition:
    opacity 200ms cubic-bezier(0.2, 0, 0, 1),
    transform 200ms cubic-bezier(0.2, 0, 0, 1),
    visibility 0ms 0ms;
  opacity: 1;
  transform: scale(1);
  visibility: visible;
}

.layers-panel.layers-panel-hidden {
  opacity: 0;
  transform: scale(0.95);
  visibility: hidden;
  pointer-events: none;
  transition:
    opacity 150ms cubic-bezier(0.2, 0, 0, 1),
    transform 150ms cubic-bezier(0.2, 0, 0, 1),
    visibility 0ms 150ms;
}

/* ── Material Symbols ───────────────────────────────────────────────────────
   Constrain the icon span to a 1em × 1em box. While the Material Symbols font
   is loading, the span content (e.g. "arrow_back", "search") would otherwise
   render as wide text and overflow into adjacent layout. Clipping to the
   intrinsic glyph size avoids the visual jump when the font swaps in.        */

.material-symbols-outlined {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1em;
  height: 1em;
  overflow: hidden;
  line-height: 1;
  vertical-align: middle;
}

/* ── Map FAB (floating action button) ───────────────────────────────────────
   Unified style for all map overlay icon buttons: hamburger, layers, chat.   */

.map-fab {
  width: 40px;
  height: 40px;
  border-radius: 9999px;
  background: rgba(255, 255, 255, 0.82);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  box-shadow:
    0 2px 8px rgba(0, 0, 0, 0.15),
    0 0 0 1px rgba(255, 255, 255, 0.6) inset;
  border: none;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-ink);
  transition:
    background-color 120ms cubic-bezier(0.2, 0, 0, 1),
    transform 120ms cubic-bezier(0.2, 0, 0, 1);
  cursor: pointer;
}
.map-fab:hover {
  background: rgba(255, 255, 255, 0.95);
}
.map-fab:active {
  transform: scale(0.94);
}

/* ── Garden menu panel animation ─────────────────────────────────────────────
   Floating card that opens from the hamburger button (top-left origin).
   JS adds/removes garden-menu-panel-hidden.                                  */

.garden-menu-panel {
  transform-origin: top left;
  transition:
    opacity 120ms cubic-bezier(0.2, 0, 0, 1),
    transform 120ms cubic-bezier(0.2, 0, 0, 1),
    visibility 0ms 0ms;
  opacity: 1;
  transform: scale(1);
  visibility: visible;
  pointer-events: auto;
}

.garden-menu-panel.garden-menu-panel-hidden {
  opacity: 0;
  transform: scale(0.95);
  visibility: hidden;
  pointer-events: none;
  transition:
    opacity 120ms cubic-bezier(0.2, 0, 0, 1),
    transform 120ms cubic-bezier(0.2, 0, 0, 1),
    visibility 0ms 120ms;
}

/* ── Menu item ───────────────────────────────────────────────────────────────
   Icon + label row inside the garden menu floating card.                     */

.menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 10px 14px;
  min-height: 44px;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--color-ink);
  background: transparent;
  border: none;
  text-align: left;
  cursor: pointer;
  transition: background-color 100ms cubic-bezier(0.2, 0, 0, 1);
}
.menu-item:hover {
  background: rgba(255, 255, 255, 0.65);
}
.menu-item:active {
  background: rgba(0, 0, 0, 0.05);
}

.menu-item-icon {
  font-size: 20px;
  flex-shrink: 0;
  color: var(--color-muted);
}

/* The press-scale utility lives in app/assets/tailwind/application.css (the
   Tailwind-processed entry); @utility is ignored in this raw-served manifest.
   Its prefers-reduced-motion override lives below in the Reduced motion block. */

/* ── Form fields (see DESIGN.md §8) ──────────────────────────────────────────
   Text inputs, textareas, and selects are always a white surface — even on
   tinted panels — so a field always reads as editable. In @layer base so an
   explicit bg-* utility can still override it on the rare field that needs it. */
@layer base {
  input:where([type="text"], [type="email"], [type="password"], [type="search"], [type="url"], [type="tel"], [type="number"], [type="date"], :not([type])),
  textarea,
  select {
    background-color: var(--color-surface);
  }
}

/* ── Focus ring (see DESIGN.md §10) ──────────────────────────────────────────
   One consistent green, keyboard-only (focus-visible), with a 2px offset.
   Unlayered so it reliably wins over the UA default focus ring (which is what
   was showing through as blue) and Tailwind's layered preflight.              */
:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* ── Reduced motion (see DESIGN.md §7) ───────────────────────────────────────
   Honor prefers-reduced-motion: kill transitions/animations and the
   press-scale transform for users who opt out.                                */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .press-scale:active {
    transform: none;
  }
}

/* ── Chat markdown prose (see DESIGN.md §9) ──────────────────────────────────
   Scoped styling for assistant messages rendered from Commonmarker HTML, which
   ships unstyled. Uses the design tokens; numbers track the Tailwind scale.    */
.chat-prose {
  font-size: 0.875rem; /* text-sm */
  line-height: 1.625;  /* relaxed */
  color: var(--color-ink);
}
.chat-prose > :first-child {
  margin-top: 0;
}
.chat-prose > :last-child {
  margin-bottom: 0;
}
.chat-prose p {
  margin: 0.5rem 0;
}
.chat-prose h1,
.chat-prose h2,
.chat-prose h3,
.chat-prose h4 {
  font-weight: 600;
  color: var(--color-ink);
  line-height: 1.3;
  margin: 0.75rem 0 0.25rem;
}
.chat-prose h1,
.chat-prose h2 {
  font-size: 1rem; /* text-base */
}
.chat-prose h3,
.chat-prose h4 {
  font-size: 0.875rem; /* text-sm */
}
.chat-prose strong {
  font-weight: 600;
}
.chat-prose em {
  font-style: italic;
}
.chat-prose a {
  color: var(--color-accent);
  text-decoration: underline;
}
.chat-prose ul,
.chat-prose ol {
  margin: 0.5rem 0;
  padding-left: 1.25rem; /* pl-5 */
}
.chat-prose ul {
  list-style: disc;
}
.chat-prose ol {
  list-style: decimal;
}
.chat-prose li {
  margin: 0.125rem 0;
}
.chat-prose code {
  font-family: var(--font-mono);
  font-size: 0.9em;
  background: var(--color-divider);
  border-radius: 0.25rem;
  padding: 0.125rem 0.25rem; /* px-1 py-0.5 */
}
.chat-prose pre {
  font-family: var(--font-mono);
  background: var(--color-divider);
  border-radius: 0.75rem; /* rounded-xl */
  padding: 0.75rem; /* p-3 */
  overflow-x: auto;
  margin: 0.5rem 0;
}
.chat-prose pre code {
  background: transparent;
  padding: 0;
  font-size: 0.85em;
}
.chat-prose blockquote {
  border-left: 2px solid var(--color-edge);
  padding-left: 0.75rem; /* pl-3 */
  color: var(--color-muted);
  margin: 0.5rem 0;
}

button:hover,
input[type="submit"] {
  cursor: pointer;
}
button:disabled:hover,
input[type="submit"]:disabled:hover {
  cursor: default;
}

/* ── Polygon edit markers ─────────────────────────────────────────────────────
   Vertex and midpoint dots used by PolygonEditController as Mapbox marker
   elements. Styled here so the controller never needs inline JS styles.        */

.polygon-edit-vertex {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--color-secondary);
  border: 2.5px solid white;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
  cursor: grab;
  transition: background 0.15s;
}

.polygon-edit-vertex.is-selected {
  background: var(--color-primary);
}

.polygon-edit-midpoint {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: white;
  border: 2px solid #94a3b8;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
  cursor: pointer;
  opacity: 0.85;
}

/* ── Vertex popup ────────────────────────────────────────────────────────────
   Compact button-group popup shown when a zone vertex is selected in edit mode.
   Strips Mapbox's default padding and arrow colour to match app chrome.       */

.vertex-popup .mapboxgl-popup-content {
  padding: 0;
  border-radius: 10px;
  box-shadow:
    0 2px 8px rgba(0, 0, 0, 0.12),
    0 0 0 1px rgba(0, 0, 0, 0.06);
  overflow: hidden;
}

.vertex-popup .mapboxgl-popup-tip {
  border-top-color: white;
}

.vertex-popup-delete,
.vertex-popup-cancel {
  padding: 5px 10px;
  font-size: 12px;
  font-weight: 500;
  background: none;
  border: none;
  cursor: pointer;
}

.vertex-popup-delete {
  color: #ef4444;
  border-right: 1px solid rgba(0, 0, 0, 0.08);
}

.vertex-popup-delete:disabled {
  color: #fca5a5;
  cursor: not-allowed;
}

.vertex-popup-cancel {
  color: #374151;
}

/* ── Photo pin markers ────────────────────────────────────────────────────────
   Circular photo thumbnails rendered as Mapbox marker elements.
   MapController clones the photo-pin template and sets the img src.           */

.photo-pin {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 2px solid #fff;
  overflow: hidden;
  cursor: pointer;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35);
}

.photo-pin-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Placeholder shown when a photo has no GPS yet (grey circle, no image) */
.photo-pin--placeholder {
  background: #6b7280;
  cursor: grab;
}

.photo-pin--placeholder:active,
.photo-pin--placeholder.grabbing {
  cursor: grabbing;
}

/* When an existing photo marker is made draggable during move mode */
.photo-pin--draggable {
  cursor: grab;
}

.photo-pin--draggable.grabbing {
  cursor: grabbing;
}

/* ── Mapbox GeolocateControl — unified with .map-fab ─────────────────────────
   Override Mapbox defaults so the location button matches our FAB style.     */

.mapboxgl-ctrl-top-right .mapboxgl-ctrl-group {
  background: transparent;
  box-shadow: none;
  border: none;
}

.mapboxgl-ctrl-top-right .mapboxgl-ctrl-group button {
  width: 40px;
  height: 40px;
  border-radius: 9999px !important;
  background: rgba(255, 255, 255, 0.82) !important;
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  box-shadow:
    0 2px 8px rgba(0, 0, 0, 0.15),
    0 0 0 1px rgba(255, 255, 255, 0.6) inset !important;
  border: none !important;
  transition:
    background-color 120ms cubic-bezier(0.2, 0, 0, 1),
    transform 120ms cubic-bezier(0.2, 0, 0, 1);
}

.mapboxgl-ctrl-top-right .mapboxgl-ctrl-group button:hover {
  background: rgba(255, 255, 255, 0.95) !important;
}

.mapboxgl-ctrl-top-right .mapboxgl-ctrl-group button:active {
  transform: scale(0.94);
}

/* ── Photo viewer overlay ─────────────────────────────────────────────────────
   Full-screen image viewer for both garden and planting photos. A persistent
   wrapper (see shared/_photo_viewer_frame) fades + scales its content in;
   PhotoViewerController toggles the -hidden class. The image is object-contain
   so it never overflows the viewport on any device.                          */

.photo-viewer-overlay {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #0a0a0a;
  opacity: 1;
  transition: opacity 250ms cubic-bezier(0.2, 0, 0, 1);
}

.photo-viewer-overlay-hidden {
  opacity: 0;
  pointer-events: none;
}

.photo-viewer-img {
  position: relative;
  z-index: 10;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  /* Pure-white low-opacity outline reads as an edge, not dirt, on any photo. */
  outline: 1px solid rgba(255, 255, 255, 0.1);
  outline-offset: -1px;
  transition: transform 250ms cubic-bezier(0.2, 0, 0, 1);
}

.photo-viewer-overlay-hidden .photo-viewer-img {
  transform: scale(0.96) translateY(8px);
}

/* ── Photo viewer menu ────────────────────────────────────────────────────────
   Popover anchored under the viewer's hamburger (≡). PhotoMenuController toggles
   the `hidden` class on the panel; positioning is plain Tailwind on the markup. */

.photo-menu-item {
  display: block;
  width: 100%;
  padding: 0.625rem 1rem;
  font-size: 0.875rem;
  font-weight: 500;
  color: #374151;
  text-align: left;
  transition: background-color 150ms ease;
}

.photo-menu-item:hover {
  background: rgba(0, 0, 0, 0.05);
}

.photo-menu-item-danger {
  color: #dc2626;
}
