:root {
  /* Surflie Light Theme (Matches Reference) */
  --bg-dark: #ffffff;
  /* White background */
  --bg-gradient: linear-gradient(180deg, #ffffff 0%, #f1f5f9 100%);
  --accent-blue: #0077be;
  /* Ocean blue */
  --accent-teal: #131929;
  /* Navy as accent */

  --glass-bg: rgba(255, 255, 255, 0.7);
  --glass-border: rgba(19, 25, 41, 0.1);
  --glass-shine: rgba(255, 255, 255, 0.5);

  --text-primary: #131929;
  /* Navy Text */
  --text-secondary: #475569;

  --font-main: 'Rubik', sans-serif;
  /* Chunky rounded sans */

  --card-radius: 24px;
  --card-shadow: 0 10px 40px -10px rgba(19, 25, 41, 0.15);
}

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  font-family: var(--font-main);
  background: var(--bg-dark);
  /* Premium Ocean Palette - Surflie */
  background-image: var(--bg-gradient);
  background-attachment: fixed;
  color: var(--text-primary);
  min-height: 100vh;
  display: flex;
  justify-content: center;
  overflow-x: hidden;
}

.app-container {
  width: 100%;
  max-width: 1200px;
  /* Slim bottom: it counts against the hero/chart when fitDefaultView sizes
     the default view to the window */
  padding: 0 2rem 0.75rem 2rem;
  display: flex;
  flex-direction: column;
  gap: 0;
  /* No gap - unit toggle provides spacing */
  position: relative;
}

/* Lateral gradients removed in favor of wrapper overlays */

/* Header */
header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1rem 0 0.5rem;
  animation: fadeInDown 1s ease-out;
}

.brand {
  font-family: 'Rubik', sans-serif;
  font-size: 2.2rem;
  font-weight: 900;
  /* Black weight */
  font-style: italic;
  /* Italic to match Surfline */
  letter-spacing: -0.03em;
  color: #131929;
  cursor: pointer;
  /* Clicking the brand returns to the landing view */
  /* Solid Navy */
  text-transform: capitalize;
  /* "Surflie" not uppercase */
  display: flex;
  align-items: center;
  gap: 3px;
}

.brand img.alt-logo {
  height: 75px;
  padding-bottom: 5px;
}

.header-right {
  display: flex;
  align-items: center;
  gap: 1.5rem;
}

.date-display {
  font-size: 0.9rem;
  color: var(--text-secondary);
  font-weight: 500;
  text-align: right;
}

/* Unit Toggle Switch */
.unit-toggle-wrapper {
  display: flex;
  align-items: center;
  gap: 8px;
}

.unit-label {
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--text-secondary);
}

.wind-arrow-small {
  font-size: 0.6rem;
  display: inline-block;
  color: var(--text-secondary);
}

/* Daily Tide Chart */
.daily-tide-chart-container {
  margin: 0rem 1rem;
  width: calc(100% - 2rem);
}

.daily-tide-chart-header {
  font-weight: 600;
  background: rgba(255, 255, 255, 0.08);
  font-size: 0.75rem;
  text-transform: uppercase;
  padding: 1rem 0rem 0rem 0rem;
  margin-bottom: -0.5rem;
  color: var(--text-secondary);
  text-align: left;
}



.daily-tide-chart-svg {
  width: 100%;
  height: 90px;
  overflow: visible;
  position: relative;
  margin-bottom: 1rem;
}

.switch {
  position: relative;
  display: inline-block;
  width: 44px;
  height: 24px;
}

.switch input {
  opacity: 0;
  width: 0;
  height: 0;
}

.slider {
  position: absolute;
  cursor: pointer;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: var(--glass-border);
  border: 1px solid var(--glass-border);
  -webkit-transition: .4s;
  transition: .4s;
}

.slider:before {
  position: absolute;
  content: "";
  height: 16px;
  width: 16px;
  left: 3px;
  bottom: 3px;
  background-color: var(--text-secondary);
  -webkit-transition: .4s;
  transition: .4s;
}

/* Visibility Utilities */
.mobile-only {
  display: none !important;
}

.desktop-only {
  display: flex !important;
}

/* Controls Bar */
.controls-bar {
  display: flex;
  justify-content: flex-end;
  padding: 0;
  margin-bottom: 0.5rem;
}

/* Checked State (Imperial/FT) */
input:checked+.slider {
  background-color: rgba(56, 189, 248, 0.2);
  border-color: var(--accent-blue);
}

input:checked+.slider:before {
  -webkit-transform: translateX(20px);
  -ms-transform: translateX(20px);
  transform: translateX(20px);
  background-color: var(--accent-blue);
}

/* Rounded sliders */
.slider.round {
  border-radius: 34px;
}

.slider.round:before {
  border-radius: 50%;
}

/* Hero Section */
.hero {
  text-align: center;
  padding: 2rem 1rem;
  /* Reduced from 4rem */
  position: relative;
  /* Glass Card style for hero */
  background: var(--glass-bg);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid var(--glass-border);
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);
  animation: fadeInUp 0.8s ease-out 0.2s backwards;
}

.hero h1 {
  font-size: 4rem;
  font-weight: 800;
  margin-bottom: 0.5rem;
  letter-spacing: -0.03em;
  line-height: 1.1;
}

.hero p {
  color: var(--text-secondary);
  font-size: 1.2rem;
  max-width: 600px;
  margin: 0 auto;
}

.pulse-badge {
  display: inline-block;
  margin-bottom: 1rem;
  padding: 0.5rem 1rem;
  background: rgba(56, 189, 248, 0.1);
  color: var(--accent-blue);
  border-radius: 50px;
  font-size: 0.8rem;
  font-weight: 600;
  border: 1px solid rgba(56, 189, 248, 0.2);
  box-shadow: 0 0 15px rgba(56, 189, 248, 0.2);
}

/* Search Bar */
.search-container {
  margin-top: 2rem;
  position: relative;
  max-width: 2000px;
  margin-left: auto;
  margin-right: auto;
  display: flex;
  gap: 10px;
  z-index: 100;
  /* Ensure search results appear above other content */
}

.search-container input {
  width: 100%;
  padding: 1rem 1.5rem;
  border-radius: 50px;
  border: 1px solid var(--glass-border);
  background: rgba(255, 255, 255, 0.5);
  /* Semi-transparent white */
  color: var(--text-primary);
  /* Dark text */
  font-size: 1rem;
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  outline: none;
  transition: all 0.3s ease;
  font-weight: 500;
}

.search-container input:focus {
  background: rgba(255, 255, 255, 0.8);
  border-color: var(--accent-blue);
  box-shadow: 0 0 15px rgba(56, 189, 248, 0.2);
}

.search-container input::placeholder {
  color: var(--text-secondary);
  /* Visible placeholder */
}

.search-container button {
  background: var(--accent-blue);
  border: none;
  border-radius: 50%;
  /* Equal width/height + no flex shrink keeps these perfect circles */
  width: 50px;
  height: 50px;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: white;
  /* Icon color */
  transition: transform 0.3s ease;
}

.search-container button:hover {
  transform: scale(1.05);
}

/* Lives on <body> (app.js portals it out of the hero — its backdrop-filter
   creates a stacking context that would trap the panel under the chart
   controls) and is positioned under the input in JS. Highest z on the page
   so it unfolds in front of everything. */
.search-results {
  position: fixed;
  background: rgba(255, 255, 255, 0.97);
  border: 1px solid var(--glass-border);
  border-radius: 16px;
  overflow: hidden;
  display: none;
  z-index: 99999;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.15);
}

.search-result-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0.85rem 1rem;
  cursor: pointer;
  border-bottom: 1px solid rgba(0, 0, 0, 0.05);
  /* Light border */
  transition: background 0.2s;
  color: var(--text-primary);
  text-align: left;
}

/* Result-kind markers: map symbology — blue pin-dot = surf spot,
   ink dot = buoy — plus a small uppercase tag on the right */
.search-result-item .sri-dot {
  flex: 0 0 auto;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: 2px solid #fff;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.18);
}

.search-result-item .sri-dot--spot {
  background: #0078A8;
}

.search-result-item .sri-dot--buoy {
  background: #131929;
}

.search-result-item .sri-label {
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.search-result-item .sri-kind {
  flex: 0 0 auto;
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-secondary);
  background: rgba(0, 0, 0, 0.05);
  padding: 2px 7px;
  border-radius: 999px;
}

.search-result-item:hover {
  background: rgba(56, 189, 248, 0.1);
}

/* Forecast Wrapper & Horizontal Scroll */
.forecast-wrapper {
  position: relative;
  /* Breakout to full viewport width */
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  z-index: 5;
}

/* Lateral Fades - Absolute Positioned with Vertical Gradient Match */
.forecast-wrapper::before,
.forecast-wrapper::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  /* Dynamic width: fill margin, minimum 2rem */
  width: max(2rem, calc(50vw - 600px));
  z-index: 20;
  pointer-events: none;
  /* Match Page Background Vertical Gradient */
  background: linear-gradient(180deg, #ffffff 0%, #f1f5f9 100%);
  background-attachment: fixed;
  /* SYNC with viewport */
  background-size: cover;
}

.forecast-wrapper::before {
  left: 0;
  /* Mask fade from opaque (edge) to transparent (center) */
  -webkit-mask-image: linear-gradient(to right, black 0%, transparent 100%);
  mask-image: linear-gradient(to right, black 0%, transparent 100%);
}

.forecast-wrapper::after {
  right: 0;
  /* Mask fade from opaque (edge) to transparent (center) */
  -webkit-mask-image: linear-gradient(to left, black 0%, transparent 100%);
  mask-image: linear-gradient(to left, black 0%, transparent 100%);
}

.forecast-container {
  display: flex;
  overflow-x: auto;
  gap: 2rem;

  /* Align first card with hero - left padding counters wrapper's negative margin */
  /* Extra vertical padding to accommodate hover shadow */
  padding: 2rem max(2rem, calc(50vw - 600px + 2rem)) 3rem max(2rem, calc(50vw - 600px + 2rem));
  /* No top padding */

  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;

  /* Hide scrollbar completely for custom indicator */
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.forecast-container::-webkit-scrollbar {
  display: none;
}

/* Edge arrows for mice without horizontal scroll: invisible until the
   pointer is over the edge zone; touch devices never get them. */
.scroll-arrow {
  display: none;
}

@media (hover: hover) and (pointer: fine) {
  .scroll-arrow {
    display: flex;
    align-items: center;
    justify-content: center;
    position: absolute;
    top: 2rem;
    bottom: 3rem;
    width: max(6rem, calc(50vw - 600px));
    z-index: 21;
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.2s ease;
  }

  .scroll-arrow.left { left: 0; justify-content: flex-start; padding-left: 2.5rem; }
  .scroll-arrow.right { right: 0; justify-content: flex-end; padding-right: 2.5rem; }

  .scroll-arrow:hover,
  .scroll-arrow:focus-visible {
    opacity: 1;
  }

  .scroll-arrow.at-end {
    display: none;
  }

  .scroll-arrow span {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 140px;
    border-radius: 14px;
    background: rgba(255, 255, 255, 0.6);
    border: 1px solid #94a3b8;
    color: var(--text-primary);
    transition: background-color 0.2s ease;
  }

  .scroll-arrow:hover span {
    background: rgba(255, 255, 255, 0.75);
  }
}

/* Unfolded: each card keeps its own height — opening one hour's swell
   breakdown grows that card only, not (via the row's default stretch)
   every card beside it. */
.forecast-container:has(.forecast-card.expanded) {
  align-items: flex-start;
}

/* Custom Scroll Indicator */
.scroll-indicator {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 0rem 0 0.5rem 0;
  margin: -2rem 0 0 0;
  position: relative;
  z-index: 10;
}

.scroll-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background-color: rgba(19, 25, 41, 0.2);
  transition: background-color 0.3s ease, transform 0.3s ease;
}

.scroll-dot.active {
  background-color: rgba(19, 25, 41, 0.8);
  transform: scale(1.2);
}

.scroll-bar {
  width: 40px;
  height: 7px;
  border-radius: 6px;
  background-color: rgba(19, 25, 41, 0.2);
  transition: background-color 0.3s ease;
}

.scroll-bar.active {
  background-color: rgba(19, 25, 41, 0.8);
}

.forecast-card {
  /* Calculation: (100% width - (2 gaps * 2rem)) / 3 cards */
  flex: 0 0 calc((100% - 12rem) / 3);
  min-width: 350px;
  max-width: 400px;
  scroll-snap-align: center;

  background: var(--glass-bg);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border: 1px solid var(--glass-border);
  border-radius: var(--card-radius);
  padding: 1.5rem 1.5rem 0.5rem 1.5rem;
  transition: transform 0.3s ease, box-shadow 0.3s ease, border-color 0.3s ease;
  position: relative;
  overflow: hidden;
  animation: fadeInUp 0.8s ease-out 0.4s backwards;
  z-index: 1;
}

.forecast-card.expanded .daily-summary {
  display: none;
}

@media (min-width: 769px) {
  .forecast-card:hover {
    transform: translateY(-5px);
    box-shadow: 0 12px 30px rgba(0, 0, 0, 0.4);
    border-color: var(--glass-shine);
    z-index: 10;
  }
}

.forecast-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 100%;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.03) 0%, transparent 100%);
  pointer-events: none;
}

/* Forecast Content Layout */
.forecast-content {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 10px 0;
}

.metric-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 10px;
  padding-bottom: 6px;
}

.metric-row.main-row {
  border-bottom: 1px solid rgba(0, 0, 0, 0.05);
  padding-bottom: 12px;
}

.metric-group {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}

.metric-group.highlight .value {
  color: var(--accent-blue);
  font-weight: 800;
}

.metric-group .value {
  font-size: 1.2rem;
  font-weight: 700;
  color: var(--text-primary);
}

.metric-group .value.large {
  font-size: 2.5rem;
  line-height: 1;
}

.metric-group .value.small {
  font-size: 0.9rem;
}

.metric-group .unit {
  font-size: 0.8rem;
  color: var(--text-secondary);
  font-weight: 500;
}

.metric-group .label {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-secondary);
}

.direction-arrow {
  color: var(--accent-blue);
  display: flex;
  align-items: center;
  justify-content: center;
}

.direction-arrow.wind-arrow {
  color: var(--text-secondary);
  transform-origin: center;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 1rem;
  border-bottom: 1px solid var(--glass-border);
  padding-bottom: 0.75rem;
}

.day-label {
  font-size: 1.25rem;
  font-weight: 600;
  white-space: nowrap;
}

.quality-label {
  display: inline-block;
  min-width: 4.2rem;
  text-align: center;
  white-space: nowrap;
  font-size: 0.65rem;
  font-weight: 600;
  line-height: 0.85rem;
  color: white;
  /* Keeps white text legible on the lighter fills (yellow, orange, green). */
  text-shadow: 0 0 2px rgba(0, 0, 0, 0.35);
  /* 1px moved from bottom to top: the labels are all caps, so the font's
     descender space left the text sitting ~2px high. */
  padding: calc(0.25rem + 1px) 0.5rem calc(0.25rem - 1px);
  border-radius: 6px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

/* Long rating names ("Very poor", "Poor/fair", "Fair/good") get a slightly
   smaller font; the shared line-height and min-width keep every pill the
   same size so card headers line up. */
.quality-label--long {
  font-size: 0.55rem;
}

.date-label {
  color: var(--text-secondary);
  font-size: 0.9rem;
  white-space: nowrap;
}

.metric-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.5rem;
}

.metric {
  display: flex;
  flex-direction: column;
}

.metric-label {
  font-size: 0.8rem;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 0.25rem;
}

.metric-value {
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--text-primary);
  display: flex;
  align-items: center;
  gap: 0.5rem;
  transition: opacity 0.3s ease-in-out, transform 0.3s ease-in-out;
}

.metric-value.updating {
  opacity: 0.7;
  transform: scale(0.99);
}

.mini-hourly-plot {
  display: flex;
  align-items: flex-end;
  gap: 1px;
  /* Shorter than the label pill (22px) so the bars, growing from the
     bottom, sit centred on the pill and day name instead of low. */
  height: 16px;
  width: 60px;
  /* 60px when there's room; gives way first on narrow card headers so the
     day, label pill and date stay on one line. */
  min-width: 36px;
  flex-shrink: 1;
}

.mini-bar {
  flex: 1;
  border-radius: 1px;
  font-weight: 500;
  opacity: 0.8;
}

.expand-icon {
  font-size: 0.8rem;
  color: var(--text-secondary);
  opacity: 0.6;
  transition: transform 0.3s ease;
}

.forecast-card.expanded .expand-icon {
  transform: rotate(180deg);
}

.swell-arrow {
  display: inline-block;
  font-size: 1.2rem;
  color: var(--accent);
  transition: transform 0.3s ease;
}

.direction-text {
  font-size: 0.8rem;
  color: var(--text-secondary);
  font-weight: 400;
  margin-left: 0.2rem;
}

.metric-unit {
  font-size: 0.9rem;
  color: var(--text-secondary);
  font-weight: 400;
}

/* Hero Section */
.hero {
  flex: 0 0 auto;
  /* --hero-h / --hero-pad: app.js (fitDefaultView) shrinks the desktop hero
     so the folded default view fits a laptop window; 300px / 4rem when
     there's room. */
  min-height: var(--hero-h, 300px);
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  padding: var(--hero-pad, 4rem) 2rem;
  position: relative;
  border-radius: var(--card-radius);
  color: #131929;
  /* Dark text for visibility on map? Or keep white if map is dark? */
  overflow: hidden;
  /* Contain the map */
  /* Allow dropdown to extend beyond? No, map needs to be contained. If dropdown needs to extend, we might have issues. */
  /* Reverting overflow to visible caused issues with map z-index outside container. 
     But map needs to be background. 
     Wait, if overflow is visible, map might leak. 
     Let's keep overflow hidden for the map background. 
     But search results need to overflow. 
     Solution: map is absolute 100% width/height of hero. 
     If hero has overflow visible, map will stay within bounds if sized correctly, unless zoomed out? 
     Leaflet map container usually doesn't leak unless specified. 
     Let's use overflow: visible for search results, but borderRadius on map.
  */
  overflow: visible;
  box-shadow: var(--card-shadow);
  animation: fadeInUp 0.8s ease-out 0.2s backwards;
  z-index: 900;
}

/* Static Map Background */
#heroStaticMap {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  border-radius: var(--card-radius);
  opacity: 1;
  /* Fully opaque map */
  pointer-events: none;
  /* Disable interaction events handled by JS too, but this is good */
}

/* Content wrapper to sit above map */
.hero-content {
  position: relative;
  z-index: 2;
  width: 100%;
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: center;
  justify-items: center;
}

.hero h1 {
  color: white;
  /* Ensure title is white */
  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
  /* Slight shadow for readability */
  grid-column: 1 / 2;
  /* Left Column */
}

/* Specific positioning for search in large view */
.hero .search-container {
  grid-column: 2 / 3;
  /* Right half */
  width: 90%;
  max-width: 450px;
}

.hero-region {
  display: block;
  font-size: 1.2rem;
  font-weight: 400;
  color: white;
  margin-top: 0rem;
  opacity: 0.9;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
  /* Region follows H1 flow in grid item ?? 
     No, h1 is the grid item. The region is INSIDE h1 now (span).
     So it moves with h1. Perfect.
  */
}

/* Compact Hero State - Content adjustment */
@media (min-width: 769px) {
  .hero.compact .hero-content {
    display: flex;
    /* Override grid */
    flex-direction: row;
    justify-content: space-between;
    width: 100%;
  }

  .hero.compact .hero-region {
    text-align: left;
    margin-left: 2px;
  }

  /* Reset search container for compact flex */
  .hero.compact .search-container {
    grid-column: auto;
    width: auto;
    /* other props handled by existing .hero.compact .search-container rules below? 
         Yes, specificity is fine or I should check order.
         The existing media query rule for .hero.compact .search-container is at line 741 in original file.
         I am editing lines 734-758. 
         Wait, line 741 is "Compact Hero State - Desktop Only" block which follows.
         So those rules will cascade and apply. Good.
      */
  }
}

/* Compact Hero State - Desktop Only */
@media (min-width: 769px) {
  .hero.compact {
    min-height: auto;
    padding: 1.5rem 2rem;
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
    text-align: left;
    transition: all 0.4s ease;
  }

  .hero.compact h1 {
    font-size: 2rem;
    margin-bottom: 0;
    flex: 0 0 auto;
  }

  .hero.compact .search-container {
    margin-top: 0;
    max-width: 500px;
    flex: 1;
    margin-left: 2rem;
    /* Clear the absolutely-positioned favorite star (38px wide at right: 14px) */
    margin-right: 44px;
  }
}

/* ... existing hero styles ... */

.rating-badge {
  margin-top: 2rem;
  /* Increased spacing */
  text-align: center;
  padding: 0.75rem 1.5rem;
  border-radius: 12px;
  font-weight: 700;
  color: white;
  /* White text */
  /* background will be set inline by JS */
  font-size: 1rem;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

/* Animations */
@keyframes fadeInDown {
  from {
    opacity: 0;
    transform: translateY(-20px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(20px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* Mobile check */
@media (max-width: 768px) {

  /* Visibility Toggles */
  .mobile-only {
    display: flex !important;
  }

  .desktop-only {
    display: none !important;
  }

  /* Header Layout */
  header {
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
    padding-bottom: 0.5rem;
    /* Reduced padding */
  }

  .brand {
    font-size: 1.5rem;
    /* Smaller title */
  }

  .brand img,
  .brand img.alt-logo {
    height: 40px;
    /* Smaller logo, override alt specificity */
    padding-bottom: 0px;
    /* Remove alt padding if needed */
  }

  /* Right side: Toggle only now (Date hidden) */
  .header-right {
    width: auto;
    flex-direction: row;
    align-items: center;
  }

  /* Date is handled by desktop-only class */

  /* Hero Section */
  .hero {
    min-height: unset;
    /* Remove large min-height */
    height: auto;
    padding: 1rem 1rem 1rem 1rem;
    /* Reduced top padding */
    /* More top padding, tighter bottom */
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
  }

  /* Force stacked content on mobile */
  .hero .hero-content {
    display: flex;
    flex-direction: column;
    grid-template-columns: 1fr;
    /* Reset grid if it was grid */
    align-items: stretch;
    gap: 0.75rem;
    /* Increased space */
    /* Reduced gap strictly */
    width: 100%;
  }

  .hero h1 {
    grid-column: auto;
    /* Reset grid placement */
    /* Shrink-wrap the text rather than filling the row, so the box ends where
       the name does; max-width keeps long names off the favourite star. */
    width: auto;
    align-self: flex-start;
    /* Lane on the right for the star plus the spot dot between them; keep in
       step with HERO_TITLE_STAR_LANE in app.js */
    max-width: calc(100% - 76px);
    text-align: left;
    /* Starting size; fitHeroTitle() steps it down when the name is too long
       to fit on one line (the name only — .hero-region keeps its rem size). */
    font-size: 1.8rem;
    white-space: nowrap;
    margin-bottom: 0rem;
    /* No margin */
    line-height: 1.1;
    /* Tighter line height */
  }

  /* The region sits under the name, so it wraps on its own terms */
  .hero h1 .hero-region {
    white-space: normal;
  }

  .hero .search-container {
    grid-column: auto;
    /* Reset grid placement */
    width: 100%;
    margin-left: 0;
    margin-right: 0;
  }

  .search-container {
    margin-top: 0rem;
    /* Remove top margin */
  }

  /* Kill the double-tap-to-zoom gesture (Safari ignores user-scalable=no).
     'manipulation' keeps scrolling and normal taps, dropping only the
     double-tap zoom — so nothing rescales under the chart overlays. */
  body {
    touch-action: manipulation;
  }

  /* touch-action inherits, so hand the full gesture set back to Leaflet —
     the expanded map still needs pinch-zoom and double-tap of its own. */
  #surfMap,
  #surfMap * {
    touch-action: auto;
  }

  /* 16px exactly: iOS Safari zooms the page in on focus for any field
     smaller than that, and it ignores user-scalable=no. Keep every focusable
     text field here at 1rem. */
  .search-container input,
  .magic-link-form input {
    font-size: 1rem;
  }

  /* ...but the placeholder needs the old 0.85rem to fit on one line. Styling
     the placeholder alone keeps the input's own font at the 16px Safari
     checks, so there's still no focus zoom. */
  .search-container input::placeholder {
    font-size: 0.85rem;
  }

  .search-container input {
    /* 0.85rem sides rather than 1rem: at 360px the placeholder needs those
       last few pixels to sit on one line. */
    padding: 0.5rem 0.85rem;
    /* Reduced height */
  }

  .search-container button,
  .search-container .map-btn {
    width: 36px;
    height: 36px;
    padding: 8px;
    /* Adjustment for icon centering if needed */
  }

  .search-container button svg,
  .search-container .map-btn svg {
    width: 16px;
    height: 16px;
  }

  .app-container {
    padding: 0rem 0.8rem 0.8rem 0.8rem;
  }

  /* Mobile: Show 1 card fully */
  .forecast-card {
    flex: 0 0 100%;
    padding: 1.25rem;
  }

  .forecast-card .card-header {
    margin-bottom: 1rem;
    padding-bottom: 0.5rem;
  }

  .forecast-card .metric-row {
    padding-bottom: 0.75rem;
  }

  .forecast-card .metric-row.main-row {
    padding-bottom: 0.75rem;
  }

  .forecast-card .rating-badge {
    margin-top: 0.75rem;
    padding: 0.5rem 1rem;
    font-size: 0.9rem;
  }

  /* Fix lateral gradients on mobile - Adjust width for smaller screens */
  .forecast-wrapper::before,
  .forecast-wrapper::after {
    /* calc() might result in 0 or negative, max ensures visibility */
    /* But usually on mobile we want a fixed small width if the calc is crazy */
    /* The main rule handles it with max(2rem, ...), so this might be redundant unless we want a DIFFERENT max */
    width: 2rem;
  }

  /* Reset wrapper margins */
  .forecast-wrapper {
    margin-left: -1rem;
    margin-right: -1rem;
  }

  /* Reset container padding */
  .forecast-container {
    padding: 1rem 1rem;
    /* Balanced padding to match wrapper margin */
    gap: 1rem;
  }

  /* Increase scroll indicator distance on mobile */
  .scroll-indicator {
    margin-top: 0rem;
    padding: 0rem 0 0.5rem 0;
  }

  /* Headroom for the day labels, which sit at the top of each bar column.
     The Models/Buoys strip ends at 28px, and the highlight box starts below
     that — so the labels need to begin lower still or the box's top border
     would cut through them. */
  .chart-container {
    padding-top: 44px !important;
  }

  /* Make map twice as high as hero on mobile */
  /* Expand hero when map is active to push content down */
  .hero:has(.map-overlay.active) {
    min-height: 60vh;
    /* Approximately twice the normal hero height */
    transition: min-height 0.3s ease;
  }

  /* Hide other hero elements when map is active so only map is visible */
  .hero:has(.map-overlay.active)>*:not(.map-overlay) {
    display: none;
  }

  .map-overlay.active {
    height: 100%;
    /* Fill the expanded hero */
    bottom: 0;
    z-index: 50;
    /* Keep it below search results if needed, or just standard */
  }

}

/* Hourly Details */
.hourly-container {
  background: rgba(255, 255, 255, 0.05);
  border-radius: 8px;
  padding: 0;
  font-size: 0.9rem;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.1);
}

.hourly-header {
  display: grid;
  grid-template-columns: 3.5rem 6px 1.5fr 1fr;
  font-weight: 600;
  background: rgba(255, 255, 255, 0.08);
  font-size: 0.75rem;
  text-transform: uppercase;
}

.hourly-header span {
  padding: 0.5rem 0.4rem;
  border-right: 1px solid rgba(255, 255, 255, 0.1);
  text-align: center;
}

.hourly-header span:nth-child(2) {
  padding: 0;
  border-right: none;
}

.hourly-header span:last-child {
  border-right: none;
}

.hourly-row {
  display: grid;
  grid-template-columns: 3.5rem 6px 1.5fr 1fr;
  align-items: center;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  border-bottom: 1px solid rgba(0, 0, 0, 0.05);
}

.hourly-row:last-child {
  border-bottom: none;
}

/* Hourly rows with a swell-train breakdown expand on click */
.hourly-row.has-swells {
  cursor: pointer;
}

.hourly-row.swells-open {
  background: rgba(56, 189, 248, 0.06);
}

.hourly-swell-breakdown {
  border-bottom: 1px solid rgba(0, 0, 0, 0.05);
  background: rgba(56, 189, 248, 0.06);
  padding: 0.15rem 0 0.35rem;
  display: flex;
  align-items: flex-start;
}

/* Title sits in the time-column strip, level with the first train row */
.swell-breakdown-title {
  width: 4.4rem;
  flex: none;
  text-align: center;
  font-size: 0.65rem;
  text-transform: uppercase;
  color: var(--text-secondary);
  padding-top: 0.32rem;
}

/* Surfline-style train rows: height, period, arrow, compass + degrees in
   aligned columns beside the title. */
.swell-train-row {
  display: grid;
  grid-template-columns: 2.8rem 1.9rem 1.1rem auto;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.82rem;
  color: var(--text-secondary);
  padding: 0.18rem 0;
}

.swell-train-row .swell-train-h {
  color: var(--text-primary);
  text-align: right;
}

.swell-train-row .swell-arrow-small {
  justify-self: center;
}

.swell-train-row .swell-train-dir {
  white-space: nowrap;
}

.hourly-rating-bar {
  height: 60%;
  min-height: 1.2rem;
  border-radius: 4px;
  border-right: 1px solid rgba(255, 255, 255, 0.2) !important;
}

.hourly-row>div {
  padding: 0.5rem 0.4rem;
  border-right: 1px solid rgba(255, 255, 255, 0.1);
  display: flex;
  justify-content: center;
  align-items: center;
}

.hourly-row>div:nth-child(2) {
  padding: 0;
}

.hourly-row>div:last-child {
  border-right: none;
}

.hourly-time {
  font-weight: 500;
  font-size: 0.9rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.1rem;
}

.time-hour {
  font-size: 1rem;
  font-weight: 600;
}

.time-period {
  font-size: 0.7rem;
  opacity: 0.8;
}

.hourly-swell,
.hourly-wind {
  display: flex;
  gap: 0.6rem;
  align-items: center;
  font-size: 0.9rem;
  justify-content: center;
  width: 100%;
}

.hourly-swell {
  border-right: 1px solid rgba(0, 0, 0, 0.05) !important;
  padding-left: 0.8rem !important;
}

.swell-arrow-small,
.wind-arrow-small {
  display: inline-block;
  font-size: 1rem;
  opacity: 0.8;
}

.direction-indicator {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.15rem;
}

.direction-degrees {
  font-size: 0.75rem;
  font-weight: 500;
}

/* Zero-Height Container */
.forecast-gap-container {
  height: 0;
  width: 100%;
  position: relative;
  z-index: 950;
  /* Above chart/hero backgrounds if needed */
}

/* Forecast Days Counter */
.forecast-days-counter {
  position: absolute;
  top: 0.1rem;
  /* Nudged just below the chart so it clears the day-highlight box */
  right: 0.5rem;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text-secondary);
  animation: fadeInUp 0.8s ease-out 0.25s backwards;
  display: flex;
  align-items: center;
}

.forecast-days-counter::before {
  content: '+';
  margin-right: 0.25rem;
  font-weight: 700;
  color: var(--accent-blue);
}

/* --- Model comparison (hero/chart gap) --- */
/* Zero-height like .forecast-gap-container: floats content in the boundary
   between hero and wave chart without changing their spacing. */
.chart-gap-container {
  height: 0;
  width: 100%;
  position: relative;
  z-index: 960;
}

.model-compare-btn {
  position: absolute;
  /* Sits over the hero's bottom edge, clear of the chart area so the
     day-highlight box never slides underneath it. Left of the Buoys
     button, which owns the corner slot (right: 12px, below). */
  top: -38px;
  right: 88px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  padding: 0 12px;
  border-radius: 999px;
  border: 1px solid rgba(0, 0, 0, 0.15);
  background: rgba(255, 255, 255, 0.85);
  backdrop-filter: blur(4px);
  color: var(--text-secondary);
  font-family: inherit;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: background-color 0.2s, color 0.2s,
    top 0.65s cubic-bezier(0.22, 1, 0.36, 1),
    right 0.65s cubic-bezier(0.22, 1, 0.36, 1);
}

.model-compare-btn:hover {
  border-color: rgba(0, 0, 0, 0.3);
}

.model-compare-btn.active {
  background: #131929;
  border-color: #131929;
  color: #fff;
  /* Model view on: drop into the boundary strip, level with the legend */
  top: 6px;
}

.model-legend {
  position: absolute;
  /* In the hero/chart boundary strip: just below the hero, level with the
     active Models button, left of it (the legend only shows while the
     button sits in the strip) */
  top: 6px;
  right: 96px;
  display: none;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 4px 10px;
  max-width: calc(100% - 120px);
}

.model-legend.visible {
  display: flex;
}

.model-legend .legend-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 22px;
  padding: 0 8px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.85);
  backdrop-filter: blur(4px);
  font-size: 0.65rem;
  font-weight: 600;
  color: var(--text-secondary);
  white-space: nowrap;
  cursor: pointer;
  border: 1px solid transparent;
  transition: border-color 0.15s, background-color 0.15s, color 0.15s;
}

/* Hot = hovered directly, or its line is hovered in the plot */
.model-legend .legend-chip.legend-chip--hot {
  background: #fff;
  border-color: rgba(0, 0, 0, 0.35);
  color: var(--text-primary);
}

.model-legend .legend-chip i {
  width: 14px;
  height: 3px;
  border-radius: 2px;
  display: inline-block;
}

/* "N sources" label leading the legend. Only needed on mobile, where the
   chips collapse to bare swatches and nothing else says what they are. */
.model-legend .legend-count {
  display: none;
  align-items: center;
  height: 22px;
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--text-secondary);
  opacity: 0.75;
  white-space: nowrap;
  pointer-events: none;
}

/* Observed-driven nowcast: shown as points on the plot, so its legend
   swatch is a dot rather than a line, matching the buoy view's language. */
.model-legend .legend-chip--dot i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
}

/* Nearshore/Offshore segmented toggle — a pill of two connected segments,
   sitting in the boundary strip just left of the (active) Models button.
   Only shown while the model overlay is on, so it can share top: 6px. */
.model-filter {
  position: absolute;
  top: 6px;
  /* Clears the Models button (right: 124px, width ~68px) with an 8px gap:
     124 + 68 + 8 = 200. The models-mode legend rule then clears this
     toggle's ~152px width with the same gap it keeps from the button. */
  right: 200px;
  display: inline-flex;
  align-items: center;
  height: 22px;
  border-radius: 999px;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.85);
  backdrop-filter: blur(4px);
  border: 1px solid rgba(0, 0, 0, 0.15);
  z-index: 6;
  transition: right 0.65s cubic-bezier(0.22, 1, 0.36, 1);
}

.model-filter-btn {
  appearance: none;
  border: none;
  background: transparent;
  padding: 0 10px;
  height: 100%;
  font-family: inherit;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--text-secondary);
  cursor: pointer;
  transition: background-color 0.2s, color 0.2s;
}

.model-filter-btn + .model-filter-btn {
  border-left: 1px solid rgba(0, 0, 0, 0.15);
}

.model-filter-btn:hover {
  color: var(--text-primary);
}

/* Nearshore reads in the site's sky blue; Offshore in a deeper ocean blue,
   so the pressed side alone tells you which family is showing. */
.model-filter-btn[data-filter="nearshore"].active {
  background: #38bdf8;
  color: #fff;
}

.model-filter-btn[data-filter="offshore"].active {
  background: #0077be;   /* --accent-blue, a darker blue */
  color: #fff;
}

.model-overlay-svg {
  position: absolute;
  left: 0;
  top: 0;
  pointer-events: none;
  z-index: 3;
  transition: opacity 0.4s ease;
}

/* Stacked buoys view: each band's station name links to its own view —
   it grows a touch on hover (the number and distance stay put) */
.buoy-band-name {
  cursor: pointer;
  transition: font-size 0.15s ease;
}

.buoy-band-name:hover {
  font-size: 1.12em;
}

/* Discrete y-axis (model view only): height labels + short ticks hanging
   OUTSIDE the plot on both sides — in the app container's side padding,
   touching the plot edges. The plot keeps its full width; the section just
   lifts its overflow clipping while the axis is out there. Scrolled plot
   content still clips at the scroll container's edge, so it never reaches
   the labels. */
#waveChartSection {
  position: relative;
}

#waveChartSection.models-gutters {
  overflow: visible;
}

.chart-y-axis {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 36px;
  z-index: 6;
  pointer-events: none;
}

.chart-y-axis--left {
  right: 100%;
}

.chart-y-axis--right {
  left: 100%;
}

.chart-y-axis .y-tick {
  position: absolute;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  gap: 3px;
  font-size: 0.62rem;
  font-weight: 600;
  color: var(--text-secondary);
  white-space: nowrap;
}

.chart-y-axis--left .y-tick {
  right: 0;
}

.chart-y-axis--right .y-tick {
  left: 0;
}

/* Small screens: stretch the section out through the app container's own
   0.8rem side padding (hence the negative margins plus the matching width)
   and put the axis gutters in that reclaimed strip, so the labels sit nearer
   the screen edges. The gutters absorb the extra width, leaving the plot
   itself exactly where it sits without them. */
@media (max-width: 768px) {
  #waveChartSection.models-gutters {
    margin-left: -0.8rem;
    margin-right: -0.8rem;
    width: calc(100% + 1.6rem);
    /* Gutter trimmed ~7px from the 42.8px that left the plot untouched, so
       the plot grows halfway toward the labels without reaching them. */
    padding: 0 36px;
    overflow: hidden;
  }

  .chart-y-axis {
    width: 36px;
  }

  .chart-y-axis--left {
    right: auto;
    left: 0;
  }

  .chart-y-axis--right {
    left: auto;
    right: 0;
  }

  /* Sit toward the outer end of the gutter — closer to the screen edge than
     the plot, without crowding it. */
  .chart-y-axis--left .y-tick {
    right: auto;
    left: 8px;
  }

  .chart-y-axis--right .y-tick {
    left: auto;
    right: 8px;
  }

  /* Shorter tick: the label is what matters at this size */
  .chart-y-axis .y-tick i {
    width: 3px;
  }

  .chart-y-axis .y-tick {
    gap: 2px;
    font-size: 0.58rem;
  }
}

.chart-y-axis .y-tick i {
  display: block;
  width: 5px;
  height: 1px;
  background: currentColor;
  opacity: 0.6;
}

/* Model view replaces the bars: keep the wrappers (they define the time
   axis, date labels, and day-highlight geometry), hide only the bars.
   (ID-scoped: .chart-bar is declared three times further down and the last
   one would otherwise override the transition.) */
#waveChartContainer .chart-bar {
  transition: height 0.3s ease, background-color 0.2s, opacity 0.5s ease,
    transform 0.65s cubic-bezier(0.22, 1, 0.36, 1);
}

/* Bars fade in place: the model lines share their scale and baseline. */
#waveChartContainer.models-active .chart-bar {
  opacity: 0;
  pointer-events: none;
}

/* Model view: the chart grows a 24px strip at the BOTTOM (the box loses
   its top to the legend row, and gets it back below) and the date labels
   drop into it, under the plot floor. The plot itself keeps its exact box
   (taller container, equally taller bottom padding), so the shared y-scale
   lands on the same pixels as the bars. Inline top:0 on the labels is set
   in JS, hence the !important. */
#waveChartContainer {
  transition: height 0.65s cubic-bezier(0.22, 1, 0.36, 1),
    padding-bottom 0.65s cubic-bezier(0.22, 1, 0.36, 1);
}

#waveChartContainer.models-active {
  height: calc(var(--chart-h, 200px) + 24px);
  padding-bottom: 34px;
}

#waveChartContainer .axis-label {
  transition: top 0.65s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.4s ease;
}

#waveChartContainer.models-active .axis-label {
  top: calc(100% + 5px) !important;
}

/* The day-highlight box shrinks from its top edge while the legend occupies
   the boundary strip above it, moving with the same easing as the dates.
   left/width must be restated: this shorthand outranks the base
   .chart-highlight-overlay rule that provides the fluid horizontal glide. */
#waveChartContainer .chart-highlight-overlay {
  transition: left 0.3s ease, width 0.3s ease,
    top 0.65s cubic-bezier(0.22, 1, 0.36, 1);
}

#waveChartContainer.models-active .chart-highlight-overlay {
  /* Below the legend row (legend bottom = 6px top + 22px chip) */
  top: 32px;
}

/* Card unfolded (hero compacts): the button leaves the shrinking hero and
   drops into the hero/chart boundary strip, and the day-highlight box gives
   it room — same easing as everything else. */
.hero.compact+.chart-gap-container .model-compare-btn {
  top: 6px;
}

/* (No compact legend override: the legend only shows while a compare view
   is on, where the body.models-mode / body.buoys-mode rules place it.) */

.hero.compact~.chart-section #waveChartContainer .chart-highlight-overlay {
  top: 32px;
}

/* On small screens the hero bottom holds the search buttons — keep the
   model controls below the boundary instead (chart has 30px top padding) */
@media (max-width: 768px) {
  .model-compare-btn {
    top: 6px;
  }

  .model-legend {
    top: 6px;
  }

  /* Toggle shares the buttons' line, immediately left of Models: Models sits
     at right 124px with a ~68px width, plus an 8px gap = 200px. */
  .model-filter {
    top: 6px;
    right: 200px;
  }

  /* Buoys mode carries as many chips as models mode (observed + every
     model), so it gets the same full-width row under the strip rather than
     the narrow slot beside the buttons. */
  body.buoys-mode .model-legend#modelLegend {
    top: 34px;
    right: 12px;
    /* Flush with the app container's own 0.8rem padding — no extra inset,
       so the row starts as far left as the screen allows. */
    left: 0;
    max-width: none;
    justify-content: flex-start;
  }

  /* Models mode: the toggle now occupies the space left of the buttons, so
     the legend drops to its own line under the whole strip and lays out
     across the full width. Needs to out-specify the desktop models-mode rule
     further down the file, hence the doubled body selector. */
  body.models-mode .model-legend#modelLegend {
    top: 34px;
    right: 12px;
    /* Flush with the app container's own 0.8rem padding — no extra inset,
       so the row starts as far left as the screen allows. */
    left: 0;
    max-width: none;
    justify-content: flex-start;
  }

  /* The strip's contents are absolutely positioned, so the zero-height
     container lets the chart slide underneath them. In a compare view give
     it real height — the legend row height is measured into --legend-h by
     chart.js, since a wrapped legend is taller than a single row. */
  body.models-mode .chart-gap-container,
  body.buoys-mode .chart-gap-container {
    height: calc(34px + var(--legend-h, 22px) + 2px);
  }

  /* The top padding is headroom for the bar chart's day labels; the buoys
     view trims it (the legend already separates the plot from the strip).
     The models view keeps it: its lines share the bars' scale AND plot box,
     so a taller plot would shift every line off its bar. */
  body.buoys-mode .chart-container {
    padding-top: 8px !important;
  }

  /* Too little width for a full row of named chips: collapse them to their
     colour swatch alone. Tapping one pins that model (as on desktop) and
     that chip alone spells out its name. */
  body.models-mode .model-legend .legend-chip .legend-chip-name,
  body.buoys-mode .model-legend .legend-chip .legend-chip-name {
    display: none;
  }

  body.models-mode .model-legend .legend-chip,
  body.buoys-mode .model-legend .legend-chip {
    gap: 0;
    padding: 0 6px;
  }

  body.models-mode .model-legend .legend-chip.legend-chip--pinned .legend-chip-name,
  body.buoys-mode .model-legend .legend-chip.legend-chip--pinned .legend-chip-name {
    display: inline;
  }

  body.models-mode .model-legend .legend-chip.legend-chip--pinned,
  body.buoys-mode .model-legend .legend-chip.legend-chip--pinned {
    gap: 4px;
    padding: 0 8px;
  }

  /* Names are hidden here, so name the row instead */
  body.models-mode .model-legend .legend-count,
  body.buoys-mode .model-legend .legend-count {
    display: inline-flex;
  }

  /* Bars view: the Models/Buoys buttons sit in the strip at 6px + 22px tall,
     so start the box below them — the desktop 20px inset would run under the
     buttons whenever a mid-chart day is selected. */
  #waveChartContainer .chart-highlight-overlay,
  .hero.compact~.chart-section #waveChartContainer .chart-highlight-overlay {
    top: 34px;
  }

  /* Legend wraps to several rows on narrow screens: drop the highlight
     box further (higher-specificity twin keeps this winning when a card
     is unfolded at the same time) */
  #waveChartContainer.models-active .chart-highlight-overlay,
  .hero.compact~.chart-section #waveChartContainer.models-active .chart-highlight-overlay {
    top: 74px;
  }
}

/* Under ~380px the three controls no longer fit side by side at full size,
   so the toggle trims its padding rather than running off the left edge. */
@media (max-width: 380px) {
  .model-filter-btn {
    padding: 0 6px;
    font-size: 0.62rem;
  }
}

/* --- Buoy comparison view --- */

/* Owns the corner slot, right of the Models button (relabelled
   "Closest buoy" in JS whenever either compare view is on). */
.buoy-compare-btn {
  right: 12px;
}

/* Either compare view on: both buttons drop into the boundary strip —
   [legend][Models][Closest buoy] — so each view is one click from the
   other. The Models button slides further left so the corner button's
   wider "Closest buoy" label fits beside it. */
body.models-mode .model-compare-btn,
body.buoys-mode .model-compare-btn {
  top: 6px;
  right: 124px;
}

body.models-mode .buoy-compare-btn,
body.buoys-mode .buoy-compare-btn {
  right: 12px;
}

body.buoys-mode .model-legend {
  right: 202px;
  max-width: calc(100% - 214px);
}

/* Models mode: the Nearshore/Offshore toggle sits between the legend and the
   Models button, so the legend starts further left to clear it with a 12px
   gap: filter right 200px + its ~152px width + 12 = 364. */
body.models-mode .model-legend {
  right: 364px;
  max-width: calc(100% - 376px);
}

/* Station picked off the map or the search (not the spot's closest): the
   corner button hides and Models alone sits in the corner, pressed but
   inert — a state marker, not a control. */
body.buoy-solo .model-compare-btn {
  right: 12px;
  pointer-events: none;
}

body.buoy-solo .model-legend {
  right: 88px;
  max-width: calc(100% - 100px);
}

/* Map overlay open while a compare view is on: the site name
   (mapSiteNameContainer) owns the first line under the map — the buttons
   and legend step down a line so the two never overlap */
body.map-open.models-mode .model-compare-btn,
body.map-open.buoys-mode .model-compare-btn {
  top: 48px;
}

body.map-open.models-mode .model-legend,
body.map-open.buoys-mode .model-legend {
  top: 48px;
}

/* Filter follows the strip down when the map is open. */
body.map-open.models-mode .model-filter {
  top: 48px;
}

/* Buoy view hero: the h1 itself is re-filled by JS as
   "CDIP {id}" + buoy name in the .hero-region slot + a .buoy-hero-sub line
   ("the closest buoy to {spot}"). On desktop the sub line renders as the
   separate bottom-left #buoyHeroLabel instead; on small screens it stays
   inside the title block (the search bar owns the hero bottom there). */
.buoy-hero-label {
  display: none;
  position: absolute;
  left: 20px;
  bottom: 12px;
  z-index: 2;
  color: #fff;
  font-size: 0.9rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
  text-align: left;
}

body.buoys-mode .buoy-hero-label {
  display: block;
}

/* Stacked nearby-buoys view: the hero is a map of the spot and its
   stations — the big spot title steps aside (its space kept, so the search
   box doesn't move); the caption names the spot. */
body.buoys-stack #spotName {
  visibility: hidden;
}

/* In-title variant of the sub line: small-screen only */
.buoy-hero-sub {
  display: none;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: #fff;
  opacity: 0.9;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
}

@media (max-width: 768px) {
  body.buoys-mode .buoy-hero-label {
    display: none;
  }

  /* ...except the stacked view, whose title is gone: the caption takes
     its place at the top, and the hero grows so the map between caption
     and search box can show the spot and its stations */
  body.buoys-stack .buoy-hero-label {
    display: block;
    top: 16px;
    bottom: auto;
  }

  body.buoys-stack #spotName {
    display: none;
  }

  body.buoys-stack .hero {
    min-height: 230px;
    justify-content: flex-end;
  }

  .buoy-hero-sub {
    display: block;
  }
}

/* Buoy view has its own time axis (it reaches 3 days into the past, which the
   bars don't cover), so the bars, their day separators, date labels and the
   day-highlight box all stand down — the SVG carries its own separators and
   labels. The bar wrappers collapse to zero width so a single spacer element
   (sized in JS to the full 3-past + 15-forecast day span) defines the
   scrollWidth, letting the plot scroll like the bars/models views. */
#waveChartContainer.buoys-active {
  overflow-x: auto;
}

#waveChartContainer.buoys-active .chart-bar {
  opacity: 0;
  transform: translateY(26px);
  pointer-events: none;
}

#waveChartContainer.buoys-active .chart-bar-wrapper {
  min-width: 0 !important;
  width: 0 !important;
  flex: 0 0 0 !important;
  overflow: hidden;
  border-left-color: transparent !important;
}

#waveChartContainer.buoys-active .axis-label {
  opacity: 0;
}

/* !important: forecast-scroll syncing keeps setting display:block inline */
#waveChartContainer.buoys-active .chart-highlight-overlay {
  display: none !important;
}

/* --- Buoy mode (whole page): the forecast-day cards are replaced by the
   latest-observation cards, and the chart grows into the freed space. --- */
body.buoys-mode .forecast-wrapper,
body.buoys-mode .forecast-days-counter {
  display: none !important;
}

body.buoys-mode .chart-container {
  height: 320px;
  transition: height 0.4s ease;
}

/* Stacked nearby-buoys view: three station bands, each about as tall as the
   models view's plot, plus the shared date row */
body.buoys-mode.buoys-stack .chart-container {
  height: 520px;
}

/* Latest-observation cards (CDIP station-page style) */
.buoy-stats {
  width: 100%;
  max-width: 1100px;
  margin: 8px auto 24px;
  padding: 0 16px;
  animation: fadeInUp 0.5s ease-out;
}

.buoy-stats-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 4px 12px;
  margin-bottom: 10px;
}

.buoy-stats-title {
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--text-primary);
}

.buoy-stats-sub {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--text-secondary);
}

.buoy-stats-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
}

.buoy-stat-card {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 14px 16px;
  border-radius: 16px;
  background: #fff;
  border: 1px solid rgba(0, 0, 0, 0.08);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
}

.buoy-stat-label {
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--text-secondary);
}

.buoy-stat-value {
  font-size: 1.6rem;
  font-weight: 700;
  line-height: 1;
  color: var(--text-primary);
  display: flex;
  align-items: baseline;
  gap: 4px;
}

.buoy-stat-value .swell-arrow {
  font-size: 1rem;
  color: var(--accent-blue);
  display: inline-block;
}

.buoy-stat-unit {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text-secondary);
}

@media (max-width: 768px) {
  .buoy-stats-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  .buoy-stat-value {
    font-size: 1.35rem;
  }

  body.buoys-mode .chart-container {
    height: 260px;
  }

  body.buoys-mode.buoys-stack .chart-container {
    height: 480px;
  }
}

/* Wave Height Chart */
.chart-section {
  width: 100%;
  margin-top: 0;
  /* No space between hero and chart */
  margin-bottom: 0;
  /* No space between chart and forecast */
  background: transparent;
  overflow: hidden;
  animation: fadeInUp 0.8s ease-out 0.3s backwards;
}

.chart-container {
  display: flex;
  align-items: flex-end;
  justify-content: flex-start;
  /* Start from left to ensure first day is visible */
  height: 100%;
  /* Max height for bars */
  width: 100%;
  gap: 2px;
  overflow-x: auto;
  padding: 5px 5px 5px 5px;

  /* Hide scrollbar */
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.chart-container::-webkit-scrollbar {
  display: none;
}

.chart-bar-wrapper {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  height: 100%;
  min-width: 20px;
  /* Ensure readability */
  max-width: 60px;
  /* Prevent looking absurd on wide screens */
  position: relative;
  cursor: pointer;
}

.chart-bar {
  width: 100%;
  background: #38bdf8;
  /* Light blue base */
  border-radius: 2px 2px 0 0;
  transition: height 0.3s ease, background-color 0.2s, opacity 0.5s ease,
    transform 0.65s cubic-bezier(0.22, 1, 0.36, 1);
  position: relative;
}

.chart-bar:hover {
  background: var(--accent-blue);
}

.chart-bar.is-night {
  opacity: 0.5;
}

/* Tooltip/Label on top of bar */
.bar-label {
  position: absolute;
  top: -20px;
  font-size: 0.7rem;
  font-weight: 600;
  color: var(--text-primary);
  white-space: nowrap;
  opacity: 0;
  transition: opacity 0.2s;
  pointer-events: none;
}

.chart-bar-wrapper:hover .bar-label {
  opacity: 1;
}

/* Persistent labels for peaks */
.bar-label.peak {
  opacity: 1;
  font-weight: 700;
  top: -22px;
}

.chart-labels {
  display: flex;
  justify-content: space-between;
  margin-top: 5px;
  padding: 0 5px;
  border-top: 1px solid rgba(0, 0, 0, 0.05);
  padding-top: 5px;
}

.axis-label {
  font-size: 0.75rem;
  color: var(--text-secondary);
  text-transform: uppercase;
}

/* Mobile adjustments */
@media (max-width: 768px) {
  .chart-bar-wrapper {
    min-width: 15px;
    /* Wider bars to force scrolling on mobile */
    width: auto;
  }

  .forecast-days-counter {
    right: 1rem;
    font-size: 0.8rem;
  }
}


.chart-headers {
  display: flex;
  justify-content: flex-start;
  /* Items have width based on day proportion */
  padding: 0.75rem 0;
  border-bottom: 1px solid rgba(0, 0, 0, 0.05);
  width: 100%;
  /* Must match chart container scroll width? 
       Actually, chart-container scrolls independently.
       Headers should ideally scroll with it if they are wide.
       Better: Put headers INSIDE the scroll container or synced.
       For simple implementation: Headers are static? No, charts are long.
       User image shows headers fixed above specific days.
       
       Solution: Place headers absolute or relative INSIDE the scroll container 
       so they move with bars.
    */
  overflow: hidden;
  /* static header container? No, we will put day labels IN the chart container for simplicity */
  display: none;
  /* Hide top container if we move labels inside */
}

.chart-container {
  display: flex;
  align-items: flex-end;
  /* --chart-h: fitDefaultView's second lever after the hero (200px max) */
  height: var(--chart-h, 200px);
  width: 100%;
  /* Removed gap between days, using border separator instead */
  gap: 0;
  /* No gap, continuous bars */
  overflow-x: auto;
  position: relative;

  /* Hide scrollbar */
  scrollbar-width: none;
  -ms-overflow-style: none;

  /* Padding for labels */
  padding-top: 30px;
  padding-bottom: 10px;
}

.chart-container::-webkit-scrollbar {
  display: none;
}

/* Hover crosshair: thin vertical line following the cursor across the wave
   chart, with the hour it points at pinned above in the top label strip.
   Both scroll with the content (absolute inside the scroll container). */
.chart-crosshair {
  position: absolute;
  /* starts right below the hour label and runs nearly to the bottom */
  top: 40px;
  bottom: 8px;
  width: 1px;
  background: var(--text-secondary);
  opacity: 0;
  pointer-events: none;
  z-index: 6;
  transition: opacity 0.15s ease;
}

/* Models view (desktop): the hour label hugs the box top (32px, under the
   legend row); the line stops above the bottom date strip. */
#waveChartContainer.models-active .chart-crosshair {
  top: 52px;
  bottom: 34px;
}

#waveChartContainer.models-active .chart-crosshair-label {
  top: 36px;
}

/* Mobile keeps the legend outside the chart: base label position. */
@media (max-width: 768px) {
  #waveChartContainer.models-active .chart-crosshair {
    top: 40px;
  }

  #waveChartContainer.models-active .chart-crosshair-label {
    top: 24px;
  }
}

/* The buoys view builds its own crosshair off the chart's time scale (the
   bar wrappers it would otherwise measure are collapsed to zero width).
   The legend row sits level with the buttons here, so the hour label clears
   it and the line starts just below the label. */
#waveChartContainer.buoys-active .chart-crosshair-label {
  top: 30px;
}

#waveChartContainer.buoys-active .chart-crosshair {
  top: 46px;
}

.chart-crosshair.visible {
  opacity: 0.45;
}

.chart-crosshair-label {
  position: absolute;
  /* Just below the top border of the day-highlight box (top: 20px), above
     the date row (40-54px from the container top) */
  top: 24px;
  transform: translateX(-50%);
  /* Day-label typography, one point smaller (dates are 0.75rem = 12px) */
  font-size: 11px;
  font-weight: 700;
  white-space: nowrap;
  color: var(--text-secondary);
  /* bare text over bars of any shade — halo instead of a background box */
  text-shadow: 0 0 3px var(--bg-dark), 0 0 6px var(--bg-dark);
  opacity: 0;
  pointer-events: none;
  z-index: 7;
  transition: opacity 0.15s ease;
}

.chart-crosshair-label.visible {
  opacity: 1;
}

/* Background shading container - Absolute behind bars */
.chart-background {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  z-index: 0;
  pointer-events: none;
}

.chart-bg-slice {
  position: absolute;
  top: 0;
  height: 100%;
  /* width and left set by JS */
}

.bg-night {
  background-color: rgba(19, 25, 41, 0.08);
  /* Darker */
}

.bg-dawn,
.bg-dusk {
  background-color: rgba(19, 25, 41, 0.04);
  /* Slightly dark */
}

.bg-day {
  background-color: transparent;
}

/* Grid Lines */
.chart-grid-lines {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 0;
  pointer-events: none;
}

.grid-line {
  position: absolute;
  left: 0;
  right: 0;
  border-top: 1px dashed rgba(0, 0, 0, 0.05);
  /* Very subtle */
  width: 100%;
  /* Spans full scroll width? No, viewport. Use fixed position container? */
}

/* To keep grid static relative to viewport while bars scroll:
   Grid lines should be in a separate container OVER/UNDER the scroll view 
   that doesn't scroll. But chart-container handles scroll.
   So grid container should be outside chart-container or fixed?
   If grid is outside, it won't match potentially scaled content? 
   No, heights are fixed px/percent.
   Let's put grid-lines container effectively outside the scroll area but inside the section relative.
*/
.chart-grid-overlay {
  position: absolute;
  top: 30px;
  /* Below header padding */
  bottom: 0;
  left: 0;
  right: 0;
  pointer-events: none;
  z-index: 1;
}

.grid-line-label {
  position: absolute;
  right: 10px;
  font-size: 0.65rem;
  color: var(--text-secondary);
  background: rgba(255, 255, 255, 0.8);
  padding: 0 4px;
  border-radius: 4px;
  margin-top: -8px;
  /* Center on line */
}



.chart-bar {
  width: 90%;
  background: #38bdf8;
  border-radius: 2px 2px 0 0;
  transition: height 0.3s ease, background-color 0.2s;
  position: relative;
}

.chart-bar:hover {
  background: var(--accent-blue);
}

/* Header Labels inside chart */
.day-header-label {
  position: absolute;
  top: 5px;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--text-primary);
  text-align: center;
  width: 100px;
  /* distinct width */
  transform: translateX(-50%);
  z-index: 10;
}

.day-header-date {
  display: block;
  font-size: 0.7rem;
  color: var(--text-secondary);
  font-weight: 500;
}

.day-separator {
  position: absolute;
  top: 0;
  bottom: 0;
  border-left: 1px solid rgba(0, 0, 0, 0.1);
  z-index: 1;
  pointer-events: none;
}

/* Global Chart Tooltip */
.global-chart-tooltip {
  position: fixed;
  top: 0;
  left: 0;
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--text-primary);
  background: rgba(255, 255, 255, 0.95);
  padding: 6px 10px;
  border-radius: 8px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
  white-space: nowrap;
  pointer-events: none;
  z-index: 9999;
  /* Always on top */
  opacity: 0;
  transition: opacity 0.1s ease;
  transform: translate(-50%, -100%);
  /* Center horizontally, sit above anchor */
  margin-top: -10px;
  /* Gap from cursor/bar */
}

/* Show state */
.global-chart-tooltip.visible {
  opacity: 1;
}


/* Remove old headers logic if any */
.chart-headers {
  display: none;
}

.chart-labels {
  display: none;
}

.chart-container {
  flex: 1;
  width: 100%;
  overflow-x: auto;
  overflow-y: hidden;
  position: relative;
  /* Hide scrollbar */
  scrollbar-width: none;
  -ms-overflow-style: none;
  padding-top: 40px;
  /* Space for day headers inside */
}

.chart-container::-webkit-scrollbar {
  display: none;
}

.chart-content-wrapper {
  /* Set by JS: width, flex layout */
  margin: 0 auto;
  /* Center if smaller than viewport? */
}

.chart-bar {
  background-color: #38bdf8;
  /* Light blue */
  border-radius: 2px 2px 0 0;
  transition: background-color 0.2s;
  /* No border or complex styling */
}

.chart-bar:hover {
  background-color: var(--accent-blue);
}

/* Day Headers */
.day-header {
  position: absolute;
  top: -30px;
  /* Above bars, relative to wrapper content top? No, simplified. relative to wrapper bottom? */
  /* Since wrapper is height 100% and align-items: flex-end, top: 0 is top of container */
  /* Wait, wrapper is flex end. */
  top: 0;
  transform: translateX(-50%);
  text-align: center;
  color: var(--text-secondary);
  font-size: 0.8rem;
  line-height: 1.2;
}

.day-name {
  display: block;
  font-weight: 700;
  color: var(--text-primary);
}

.day-date {
  display: block;
  font-size: 0.7rem;
  font-weight: 400;
}

/* Peak Labels */
.peak-label {
  position: absolute;
  transform: translateX(-50%);
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--text-primary);
  white-space: nowrap;
  text-shadow: 0 1px 2px rgba(255, 255, 255, 0.8);
  /* No background box, just text on top of bar */
}

/* Daily Chart Styles */

.daily-chart-wrapper {
  display: flex;
  width: 100%;
  height: 100%;
  justify-content: space-between;
  /* distribute evenly */
  padding: 0 1rem;
  padding-bottom: 20px;
  /* Space for bars at bottom if needed */
}

.daily-col {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  /* Header at top, barContainer at bottom */
  align-items: center;
  height: 100%;
  position: relative;
  margin: 0 4px;
  /* Space between cols */
}

.daily-header {
  text-align: center;
  margin-top: 10px;
  z-index: 5;
}

.d-name {
  display: block;
  font-weight: 700;
  color: var(--text-primary);
  font-size: 0.9rem;
}

.d-date {
  display: block;
  font-size: 0.75rem;
  color: var(--text-secondary);
}

.daily-bar-container {
  width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: center;
  flex: 1;
  /* fills remaining height */
  padding-top: 40px;
  /* Space below header */
}

.daily-bar {
  width: 60%;
  /* Wider bars */
  max-width: 40px;
  background-color: #38bdf8;
  border-radius: 4px 4px 0 0;
  transition: height 0.3s ease, background-color 0.2s;
}

.daily-bar:hover {
  background-color: var(--accent-blue);
}

.daily-val-label {
  margin-bottom: 5px;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--text-primary);
}

/* Update App to support label class update */
/* We reused .daily-val-label, so we need to add logic in app.js or alias it */

/* Chart Day Grouping */
.chart-day-group {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  height: 100%;
  position: relative;
  /* Restore separator */
  border-left: 1px dashed rgba(0, 0, 0, 0.15);
  padding: 0;
  gap: 1px;
  /* Gap between bars inside the day */
  flex: 0 0 auto;
}

/* Remove border from the very first group to mimic 'index === 0' check not having it? 
   No, original code ADDED it for 'index === 0' too?
   Let's check code: "if (isNewDay || index === 0) { ... borderLeft ... }"
   Yes, original added it for the first one too.
   So we leave it on all groups.
*/

.chart-day-group .axis-label {
  position: absolute;
  top: 0;
  left: 6px;
  /* Match original: 6px */
  font-size: 0.75rem;
  font-weight: bold;
  color: var(--text-secondary);
  pointer-events: none;
  z-index: 5;
}

/* Ensure bars are positioned correctly */
.chart-day-group .chart-bar-wrapper {
  position: relative;
  border-left: none !important;
  /* Uniform width control if needed, but flex handles it */
}

.chart-highlight-overlay {
  position: absolute;
  /* Fallback only: app.js sets top/height from the measured plot area so the
     box spans the full day in every mode (bars, models, buoys). */
  top: 20px;
  bottom: 0px;
  border: 1px solid rgba(7, 7, 7, 0.492);
  background: transparent;
  /* No fill as requested */
  border-radius: 12px;
  pointer-events: none;
  transition: left 0.3s ease, width 0.3s ease, top 0.3s ease, height 0.3s ease;
  z-index: 50;
  display: none;
  box-shadow: none;
}

/* Map Feature Styles */

/* Map Button */
.map-btn {
  background: rgba(255, 255, 255, 0.2);
  border: 1px solid var(--glass-border);
  border-radius: 50%;
  width: 50px;
  height: 50px;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: var(--text-primary);
  transition: all 0.3s ease;
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}

.map-btn:hover {
  transform: scale(1.05);
  background: rgba(255, 255, 255, 0.4);
  color: var(--accent-blue);
}

/* Map Overlay Container */
.map-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: white;
  border-radius: var(--card-radius);
  z-index: 1000;
  /* Higher than search results */
  overflow: hidden;
  opacity: 0;
  visibility: hidden;
  transform: translateY(10px) scale(0.98);
  transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1);
  box-shadow: 0 20px 50px rgba(0, 0, 0, 0.2);
}

.map-overlay.active {
  opacity: 1;
  visibility: visible;
  transform: translateY(0) scale(1);
}

/* Desktop: the map as the hero extended down the window (app.js moves it
   under <body> and sets --map-top/left/right from the hero's box). The
   header stays visible; below it the page is covered by its own plain
   background, so nothing changes but the hero growing. */
@media (min-width: 769px) {
  .map-overlay.map-full {
    position: fixed;
    top: var(--map-top, 84px);
    left: var(--map-left, 24px);
    right: var(--map-right, 24px);
    bottom: 24px;
    z-index: 2000;
  }

  body.map-full-open {
    overflow: hidden;
  }

  /* Page background over everything under the header; a click on it closes
     the map (app.js) */
  body.map-full-open::before {
    content: '';
    position: fixed;
    top: var(--map-top, 84px);
    left: 0;
    right: 0;
    bottom: 0;
    background: var(--bg-dark);
    background-image: var(--bg-gradient);
    background-attachment: fixed;
    z-index: 1999;
    animation: mapBackdropIn 0.3s ease;
  }
}

@keyframes mapBackdropIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* Spot clusters: the pins' blue, count in the middle */
.spot-cluster {
  background: transparent;
}

.spot-cluster div {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: #0078A8;
  border: 2px solid white;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
  color: white;
  font-weight: 700;
  font-size: 0.85rem;
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
}

/* The actual Leaflet Map div */
#surfMap {
  width: 100%;
  height: 100%;
  z-index: 1;
}

/* Close Button */
.close-map-btn {
  position: absolute;
  top: 15px;
  right: 15px;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: white;
  border: 1px solid rgba(0, 0, 0, 0.1);
  font-size: 1.5rem;
  line-height: 1;
  color: var(--text-primary);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  z-index: 1001;
  /* Above map */
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  transition: all 0.2s ease;
}

.close-map-btn:hover {
  transform: scale(1.1);
  background: #f1f5f9;
}

/* Popup Styles overrides */
.leaflet-popup-content-wrapper {
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(10px);
  border-radius: 12px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
  padding: 0;
}

.leaflet-popup-content {
  margin: 12px 16px;
  line-height: 1.4;
  font-family: var(--font-main);
}

.popup-country {
  font-size: 0.75rem;
  text-transform: uppercase;
  color: var(--text-secondary);
  letter-spacing: 0.05em;
  margin-bottom: 2px;
}

.popup-name {
  font-size: 1rem;
  font-weight: 700;
  color: var(--text-primary);
  margin-bottom: 8px;
}

.custom-arrow-marker {
  background: transparent !important;
  border: none !important;
}

.popup-wrapper {
  min-width: 140px;
}

/* Map hover card title: always one line. app.js (fitCardTitle) shrinks the
   type to keep the card ~195px wide, widening it only for the longest
   names; the day rows' mini plots stretch to match. */
.spot-hover-card .popup-name {
  white-space: nowrap;
  font-size: 0.95rem;
  letter-spacing: -0.01em;
  margin: 0 0 6px !important;
}

/* Spot hover card on the full map (replaces the old click-popup): Leaflet
   tooltips default to nowrap single-line — open it up into a small card */
.leaflet-tooltip.spot-hover-card {
  white-space: normal;
  padding: 10px 12px;
  border-radius: 10px;
  border: none;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.18);
}

.popup-btn {
  display: inline-block;
  margin-bottom: 9px;
  background: var(--accent-blue);
  color: white;
  padding: 6px 12px;
  border-radius: 6px;
  font-size: 0.8rem;
  font-weight: 600;
  text-decoration: none;
  border: none;
  cursor: pointer;
  transition: background 0.2s;
}

.popup-btn:hover {
  background: #005a8e;
}

/* Compact Hero State fix for Map Button */
@media (min-width: 769px) {
  .hero.compact .search-container {
    padding-right: 0;
    /* Reset if needed */
  }

  /* Both buttons shrink together on compact so they stay matching circles */
  .hero.compact #mapBtn,
  .hero.compact #searchBtn {
    width: 44px;
    height: 44px;
  }
}

/* Map Attribution Minimal Style */
.leaflet-control-attribution {
  font-size: 8px !important;
  color: rgba(0, 0, 0, 0.4) !important;
  background: none !important;
  box-shadow: none !important;
  padding: 0 4px !important;
}

.leaflet-control-attribution a {
  color: rgba(0, 0, 0, 0.5) !important;
  text-decoration: none !important;
}

/* Map Site Name Container (visible when map expands) */
/* Map Site Name Container (visible when map expands) */
/* Map Site Name Container (visible when map expands) */
.map-site-name-container {
  display: block;
  text-align: left;
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--text-primary);
  /* No background/box style */
  background: transparent;
  padding: 0;
  border-radius: 0;
  box-shadow: none;

  margin: 0;
  margin-left: 2px;
  /* Slight alignment fix if needed */

  width: 100%;
  /* Full width to align left properly in container */
  max-width: 100%;
  position: relative;
  z-index: 950;

  opacity: 0;
  transform: translateY(-5px);
  transition: opacity 0.3s ease, transform 0.3s ease;
  pointer-events: none;

  height: 0;
  overflow: visible;
  /* Allow negative margins to not be clipped */
}

.map-site-name-container.active {
  opacity: 1;
  transform: translateY(0);
  height: auto;
  /* Super close to graph below */
  margin-top: 10px;
  margin-bottom: -10px;
  /* Pull graph up / pull text down closer */
  padding-bottom: 0px;
  pointer-events: auto;
}

.map-site-region {
  font-weight: 400;
  color: var(--text-secondary);
  font-size: 1.2rem;
  margin-left: 4px;
}
/* ---------------------------------------------------------------------------
   Account (auth.js): header button, dropdown panel, hero favorite star
   --------------------------------------------------------------------------- */
.account-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 1px solid var(--glass-border);
  background: var(--glass-bg);
  color: var(--text-primary);
  cursor: pointer;
  transition: background 0.2s;
}

.account-btn:hover {
  background: rgba(19, 25, 41, 0.06);
}

.account-panel {
  position: fixed;
  width: 330px;
  max-height: calc(100vh - 90px);
  overflow-y: auto;
  background: rgba(255, 255, 255, 0.97);
  border: 1px solid var(--glass-border);
  border-radius: 16px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.15);
  z-index: 99999;
  padding: 1rem;
}

.account-section {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.account-title {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-secondary);
}

.account-email {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding-bottom: 0.35rem;
  border-bottom: 1px solid rgba(0, 0, 0, 0.05);
}

.account-hint {
  font-size: 0.78rem;
  color: var(--text-secondary);
  line-height: 1.35;
}

.magic-link-form {
  display: flex;
  gap: 6px;
}

.magic-link-form input {
  flex: 1;
  min-width: 0;
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--glass-border);
  border-radius: 10px;
  font-family: var(--font-main);
  font-size: 0.85rem;
  color: var(--text-primary);
  background: #fff;
}

.magic-link-form button,
.account-action {
  padding: 0.55rem 0.9rem;
  border: none;
  border-radius: 10px;
  background: var(--accent-blue);
  color: #fff;
  font-family: var(--font-main);
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
  transition: opacity 0.2s;
}

/* In-app notice (limits etc.): glass card over a dimmed page */
.app-notice {
  position: fixed;
  inset: 0;
  z-index: 100000; /* above the account panel (99999) */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  background: rgba(19, 25, 41, 0.25);
  animation: mapBackdropIn 0.2s ease-out;
}

.app-notice-card {
  width: min(340px, 100%);
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  padding: 1.25rem;
  background: var(--glass-bg);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border: 1px solid var(--glass-border);
  border-radius: var(--card-radius);
  box-shadow: 0 12px 32px rgba(19, 25, 41, 0.18);
}

.app-notice-card .account-action {
  align-self: flex-end;
  min-width: 5rem;
}

/* All-sessions page: the notice overlay, but the card dressed like the
   account panel (near-opaque white, 16px radius, grouped content) */
.sessions-page-card {
  width: min(560px, 100%);
  max-height: 85vh;
  padding: 1rem;
  background: rgba(255, 255, 255, 0.97);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border-radius: 16px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.15);
}

.sessions-page-card .account-group {
  min-height: 0;
}

.sessions-page-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.sessions-page-list {
  overflow-y: auto;
  min-height: 0;
}

/* search (wide) + sort (narrow) on one line */
.sessions-page-tools {
  display: flex;
  gap: 6px;
}

.sessions-page-tools .sessions-search {
  flex: 1;
  min-width: 0;
}

.sessions-page-tools .sessions-sort {
  flex: 0 0 auto;
  width: 8.5rem;
}

.session-surf-mini .swell-arrow-small {
  display: inline-block;
  font-size: 0.6rem;
}

/* panel rows: date, then the surf summary filling the middle */
.account-session-list .account-session-when {
  flex: 0 1 auto;
}

.session-surf-mini {
  flex: 1;
  min-width: 0;
  font-size: 0.78rem;
  color: var(--text-secondary);
  white-space: nowrap;
}

.magic-link-form button:hover,
.account-action:hover {
  opacity: 0.85;
}

.account-signout {
  background: transparent;
  color: var(--text-secondary);
  border: 1px solid var(--glass-border);
}

.account-status {
  font-size: 0.78rem;
  color: var(--text-secondary);
  min-height: 1em;
}

/* Google requires its own mark on a white (or black) button — this one can't
   inherit the accent-blue .account-action fill. */
.account-google {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  width: 100%;
  background: #fff;
  color: #1f1f1f;
  border: 1px solid var(--glass-border);
}

.account-google .google-mark {
  flex: none;
}

.account-or {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 0.15rem 0;
  color: var(--text-secondary);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.account-or::before,
.account-or::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--glass-border);
}

.account-invite {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.3rem 0;
}

.account-invite-code {
  flex: 1;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.85rem;
  letter-spacing: 0.08em;
  color: var(--text-primary);
}

.account-invite-copy {
  padding: 0.25rem 0.55rem;
  border: 1px solid var(--glass-border);
  border-radius: 8px;
  background: transparent;
  color: var(--text-secondary);
  font-family: var(--font-main);
  font-size: 0.72rem;
  cursor: pointer;
}

.account-invite-copy:hover {
  color: var(--text-primary);
}

.account-favs {
  display: flex;
  flex-direction: column;
}

.account-fav {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0.25rem 0.4rem;
  border-radius: 8px;
  cursor: pointer;
  font-size: 0.85rem;
  transition: background 0.2s;
}

.account-fav:hover {
  background: rgba(0, 120, 168, 0.08);
}

.account-fav-name {
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.account-default-tag {
  flex: 0 0 auto;
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-secondary);
  background: rgba(0, 0, 0, 0.05);
  padding: 2px 7px;
  border-radius: 999px;
}

/* Favorite star: hero top-right corner */
.fav-star-btn {
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.35);
  background: rgba(19, 25, 41, 0.35);
  color: #fff;
  cursor: pointer;
  backdrop-filter: blur(4px);
  transition: background 0.2s, color 0.2s;
}

.fav-star-btn:hover {
  background: rgba(19, 25, 41, 0.55);
}

.fav-star-btn.active {
  color: #ffd166;
}

/* Favorites list kind markers: same symbology as search results */
.account-fav .fav-dot {
  flex: 0 0 auto;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: 2px solid #fff;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.18);
}

.account-fav .fav-dot--spot {
  background: #0078A8;
}

.account-fav .fav-dot--buoy {
  background: #131929;
}

/* Favorites: rating-coloured bar (like the cards' hourly rows) + surf box */
.account-fav .fav-bar {
  flex: 0 0 auto;
  width: 4px;
  height: 22px;
  border-radius: 2px;
  background: rgba(19, 25, 41, 0.15);
}

.account-fav .fav-bar--buoy {
  background: #131929;
}

/* name shrinks to fit so "default" sits right beside it; the box keeps right */
.account-fav .account-fav-name {
  flex: 0 1 auto;
}

.fav-conds {
  flex: 0 0 auto;
  margin-left: auto;
  padding: 2px 6px;
  border: 1px solid var(--glass-border);
  border-radius: 6px;
  background: #fff;
  font-size: 0.72rem;
  color: var(--text-secondary);
  white-space: nowrap;
}

/* remove-favorite ×: shown on row hover where there's a mouse, always on touch */
@media (hover: hover) {
  .account-fav .fav-del {
    opacity: 0;
    transition: opacity 0.15s ease;
  }

  .account-fav:hover .fav-del,
  .account-fav .fav-del:focus-visible {
    opacity: 1;
  }
}

.fav-conds .swell-arrow-small {
  display: inline-block;
  font-size: 0.6rem;
}

.account-error {
  color: #b3261e;
}

/* Alerts (swell alarms) in the account panel */
.account-alarm {
  padding: 0.45rem 0.4rem;
  border-radius: 8px;
  background: rgba(0, 0, 0, 0.03);
  margin-bottom: 4px;
}

.account-alarm.off .account-alarm-target,
.account-alarm.off .account-alarm-conds {
  opacity: 0.45;
}

.account-alarm-head {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* muted (already emailed): dashed, washed-out box until the window ends */
.account-alarm.muted {
  background: transparent;
  border: 1px dashed rgba(19, 25, 41, 0.2);
}

.account-alarm.muted .account-alarm-target,
.account-alarm.muted .account-alarm-conds {
  opacity: 0.5;
}

.account-alarm-muted {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 2px;
  font-size: 0.72rem;
  color: var(--text-secondary);
}

.alarm-unmute {
  padding: 0 6px;
  border: 1px solid var(--glass-border);
  border-radius: 6px;
  background: #fff;
  color: var(--accent-blue);
  font-size: 0.85rem;
  line-height: 1.3;
  cursor: pointer;
}

.alarm-unmute:hover {
  background: rgba(0, 120, 168, 0.08);
}

.account-alarm-target {
  flex: 1;
  min-width: 0;
  font-size: 0.85rem;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.alarm-toggle {
  flex: 0 0 auto;
  accent-color: var(--accent-blue);
  cursor: pointer;
}

.alarm-del {
  flex: 0 0 auto;
  border: none;
  background: none;
  color: var(--text-secondary);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  padding: 0 2px;
}

.alarm-del:hover {
  color: #b3261e;
}

.account-alarm-conds {
  font-size: 0.72rem;
  color: var(--text-secondary);
  line-height: 1.35;
  margin-top: 2px;
}

/* New-alert form */
.alarm-row {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.82rem;
  color: var(--text-primary);
}

/* direct child only: .alarm-bars spans inside the row must not match */
.alarm-row > span:first-child {
  flex: 0 0 68px;
}

.alarm-num {
  width: 62px;
  padding: 0.35rem 0.5rem;
  border: 1px solid var(--glass-border);
  border-radius: 8px;
  font-family: var(--font-main);
  font-size: 0.82rem;
  color: var(--text-primary);
  background: #fff;
}

/* Nearshore | Offshore side by side */
.alarm-models {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}

.alarm-model-col {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.alarm-model-group {
  margin-top: 4px;
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-secondary);
}

.alarm-model {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 0.8rem;
  cursor: pointer;
  padding: 2px 0;
}

.alarm-model.disabled {
  opacity: 0.4;
  cursor: default;
}

.alarm-model input {
  accent-color: var(--accent-blue);
}

.alarm-actions {
  display: flex;
  gap: 6px;
}

.account-action:disabled {
  opacity: 0.45;
  cursor: default;
}

.account-session-list {
  margin: 4px 0 8px;
}

.alarm-actions .account-action {
  flex: 1;
}

/* Direction control: heading + margin fields with a live compass preview */
.alarm-dir {
  display: flex;
  align-items: center;
  gap: 10px;
}

.alarm-dir-fields {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.dir-compass {
  flex: 0 0 auto;
  width: 68px;
  height: 68px;
  margin: 0 auto;
}

.dir-compass .dc-face {
  fill: rgba(0, 0, 0, 0.04);
  stroke: rgba(19, 25, 41, 0.15);
}

.dir-compass .dc-n {
  font-size: 10px;
  font-family: var(--font-main);
  fill: #94a3b8;
}

.dir-compass .dc-arc {
  fill: rgba(0, 119, 190, 0.3);
}

.dir-compass .dc-arrow line {
  stroke: #0077be;
}

.dir-compass .dc-arrow polygon {
  fill: #0077be;
}

/* Alarm rows open the edit form on click */
.account-alarm {
  cursor: pointer;
  transition: background 0.2s;
}

.account-alarm:hover {
  background: rgba(0, 120, 168, 0.08);
}

/* Condition rows: number + slider (+ bar meter for waves) stay in sync */
.alarm-cond {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.alarm-bars {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  height: 20px;
  padding: 0 2px;
}

.alarm-bars span {
  flex: 1;
  background: rgba(19, 25, 41, 0.1);
  border-radius: 1px;
  transition: background 0.15s;
}

.alarm-bars span.lit {
  background: var(--accent-blue);
}

.alarm-range {
  width: 100%;
  accent-color: var(--accent-blue);
  height: 18px;
  cursor: pointer;
}

/* Direction pair: the └ connector alone ties the margin to its heading —
   its horizontal end sits at the vertical center of the margin label */
.alarm-row-sub {
  position: relative;
  margin-left: 14px;
}

.alarm-row-sub::before {
  content: '';
  position: absolute;
  left: -11px;
  top: -9px;
  width: 5px;
  height: 23px;
  border-left: 1.5px solid rgba(19, 25, 41, 0.25);
  border-bottom: 1.5px solid rgba(19, 25, 41, 0.25);
  border-bottom-left-radius: 6px;
}

.alarm-row-sub > span:first-child {
  flex-basis: 54px;
}

.dir-compass {
  cursor: pointer;
  touch-action: none;
}

.dir-compass .dc-arrow {
  font-size: 17px;
  fill: #0077be;
  stroke: none;
  pointer-events: none;
  user-select: none;
}

/* Inline slider block at the right of each condition row */
.alarm-slide {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 1px;
}

.alarm-slide .alarm-bars {
  height: 17px;
  padding: 0 8px;
  gap: 2px;
}

.alarm-slide .alarm-range {
  width: 100%;
  height: 12px;
}

/* Session ratings: half-star widget + per-spot session log */
.star-row {
  display: inline-flex;
  gap: 2px;
  line-height: 1;
}

.star {
  position: relative;
  font-size: 20px;
  color: rgba(19, 25, 41, 0.15);
  user-select: none;
}

.star-fill {
  position: absolute;
  left: 0;
  top: 0;
  overflow: hidden;
  white-space: nowrap;
  color: #f5b301;
  pointer-events: none;
}

/* Session rating input: one colour box per quality label */
.quality-row {
  display: flex;
  gap: 3px;
  margin: 6px 0 10px;
}

.quality-box {
  flex: 1 1 0;
  min-width: 0;
  height: 26px;
  padding: 0;
  border: 0;
  border-radius: 6px;
  overflow: hidden;
  cursor: pointer;
  color: white;
  text-shadow: 0 0 2px rgba(0, 0, 0, 0.35);
  font-family: inherit;
  font-size: 0.65rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  white-space: nowrap;
  transition: flex-grow 0.25s ease, opacity 0.2s ease;
}

.quality-box span {
  opacity: 0;
  transition: opacity 0.2s ease;
}

.quality-box:hover,
.quality-box:focus-visible,
.quality-box.selected,
.quality-box.forecast {
  /* room for the longest name even with a hovered and a chosen box open */
  flex-grow: 3.5;
}

.quality-box:hover span,
.quality-box:focus-visible span,
.quality-box.selected span,
.quality-box.forecast span {
  opacity: 1;
}

/* Once one is chosen the others fade back; no outline needed */
.quality-row:has(.selected) .quality-box:not(.selected):not(:hover) {
  opacity: 0.45;
}

.account-session {
  padding: 0.45rem 0.4rem;
  border-radius: 8px;
  background: rgba(0, 0, 0, 0.03);
  margin-bottom: 4px;
  cursor: pointer;
  transition: background 0.2s;
}

.account-session:hover {
  background: rgba(0, 120, 168, 0.08);
}

.account-session-head {
  display: flex;
  align-items: center;
  gap: 8px;
}

.account-session-head .star-row .star {
  font-size: 17px;
}

.account-session-when {
  flex: 1;
  min-width: 0;
  font-size: 0.82rem;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.account-session-detail {
  margin-top: 4px;
}

.account-session-conds {
  font-size: 0.72rem;
  color: var(--text-secondary);
  line-height: 1.4;
}

.account-session-note {
  font-size: 0.76rem;
  color: var(--text-primary);
  font-style: italic;
  margin-top: 3px;
}

.session-select {
  flex: 1;
  padding: 0.4rem 0.5rem;
  border: 1px solid var(--glass-border);
  border-radius: 8px;
  font-family: var(--font-main);
  font-size: 0.82rem;
  color: var(--text-primary);
  background: #fff;
}

.session-note {
  width: 100%;
  padding: 0.5rem 0.6rem;
  border: 1px solid var(--glass-border);
  border-radius: 10px;
  font-family: var(--font-main);
  font-size: 0.8rem;
  color: var(--text-primary);
  resize: vertical;
  background: #fff;
}

/* Session snapshot rendered as a forecast-card hourly row + a tide cell.
   Sized down to fit the 280px panel: tighter gaps, shrinkable cells
   (min-width 0) so the tide column never spills past the panel edge. */
.session-cond-header {
  display: grid;
  grid-template-columns: 2.6rem 5px 1.6fr 1.2fr 2.8rem;
  margin-top: 6px;
  font-size: 0.58rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-secondary);
  text-align: center;
}

.session-cond-header span:last-child {
  text-align: right;
}

.session-cond-row {
  grid-template-columns: 2.6rem 5px 1.6fr 1.2fr 2.8rem;
  font-size: 0.72rem;
  border-top: none;
}

.session-cond-row > div {
  min-width: 0;
}

.session-cond-header.with-swells,
.session-cond-row.with-swells {
  grid-template-columns: 2.6rem 5px 1.3fr 1.6fr 1.1fr 2.8rem;
}

/* full-height dividers between every column, like the cards' surf|wind line */
.session-cond-row .hourly-swell,
.session-cond-row .session-swells,
.session-cond-row .hourly-wind {
  align-self: stretch;
}

.session-cond-row .session-swells,
.session-cond-row .hourly-wind {
  border-right: 1px solid rgba(0, 0, 0, 0.05);
}

.session-swells {
  justify-content: center;
  align-items: center;
}

/* degrees beside the arrow, not under it */
.session-cond-row .direction-indicator {
  flex-direction: row;
  gap: 0.2rem;
}

.session-swells {
  display: flex;
  flex-direction: column;
  gap: 1px;
  font-size: 0.66rem;
  color: var(--text-secondary);
  white-space: nowrap;
}

.session-swells .swell-arrow-small {
  display: inline-block;
  font-size: 0.55rem;
  margin-right: 1px;
}

.session-cond-row .hourly-swell,
.session-cond-row .hourly-wind {
  gap: 0.25rem;
  font-size: 0.72rem;
}

.session-cond-row .hourly-swell {
  padding-left: 0.2rem !important;
}

.session-cond-row .time-hour {
  font-size: 0.8rem;
}

.session-cond-row .direction-degrees {
  font-size: 0.68rem;
}

/* thin bar like the cards': kill the cell padding that fattened it */
.session-cond-row .hourly-rating-bar {
  padding: 0 !important;
  width: 5px;
  justify-self: center;
}

.session-tide {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 3px;
  color: var(--text-secondary);
  padding-right: 2px;
}

.session-tide-arrow {
  font-size: 0.6rem;
  color: var(--accent-blue);
}

/* Phone: the account panel centers and takes most of the viewport
   (!important beats the JS-set inline right from the desktop anchoring) */
@media (max-width: 768px) {
  .account-panel {
    left: 10px !important;
    right: 10px !important;
    width: auto;
    max-height: calc(100dvh - 100px);
  }
}

/* Email + unit preference on one panel row; small ghost default-view action */
.account-email-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-bottom: 0.35rem;
  border-bottom: 1px solid rgba(0, 0, 0, 0.05);
}

.account-email-row .account-email {
  flex: 1;
  min-width: 0;
  padding-bottom: 0;
  border-bottom: none;
}

.account-units {
  flex: 0 0 auto;
  transform: scale(0.82);
  transform-origin: right center;
}

.account-action-small {
  align-self: flex-start;
  padding: 0.3rem 0.65rem;
  border: 1px solid var(--glass-border);
  border-radius: 999px;
  background: transparent;
  color: var(--accent-blue);
  font-family: var(--font-main);
  font-size: 0.72rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.2s;
}

.account-action-small:hover {
  background: rgba(0, 120, 168, 0.08);
}

/* The account panel owns the unit toggle now; the header one stays in the
   DOM (app.js display logic routes through it) but out of sight */
header .unit-toggle-wrapper {
  display: none;
}

/* Boxed panel groups: Favorites / Alerts / Sessions each read as one unit */
.account-group {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  border: 1px solid var(--glass-border);
  border-radius: 12px;
  padding: 0.6rem 0.65rem;
  background: rgba(0, 0, 0, 0.015);
}

/* Buoy view: ring on the latest observation while it is under an hour old */
.obs-live-ring {
  stroke: #dc2626;
  transform-box: fill-box;
  transform-origin: center;
  /* linear: grows solid, then fades gradually from the moment it turns */
  animation: obsLivePulse 3s linear infinite;
}

@keyframes obsLivePulse {
  0%, 100% { opacity: 0.25; transform: scale(1); }
  15% { opacity: 1; transform: scale(1.15); }
  50% { opacity: 1; transform: scale(1.5); }
}

@media (prefers-reduced-motion: reduce) {
  .obs-live-ring { animation: none; }
}
