  /* Inter is now loaded via a parallel <link> in index.html <head> (was a
     render-blocking @import here that serialized behind styles.css). */

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

  :root {
    --bg-primary: #0b1426;
    --bg-card: #111d33;
    --bg-card-hover: #152540;
    --border: rgba(255,255,255,0.08);
    --accent: #4dabf7;
    --accent-dim: rgba(77,171,247,0.15);
    --text-primary: #e2e8f0;
    --text-secondary: rgba(255,255,255,0.55);
    --text-dim: rgba(255,255,255,0.3);
    --danger: #ff6b6b;
    --success: #51cf66;
    --warning: #ffd43b;
  }

  body {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
    background: var(--bg-primary);
    color: var(--text-primary);
    min-height: 100vh;
    -webkit-font-smoothing: antialiased;
    overflow-x: hidden;
  }

  /* === WINDY MAP BACKGROUND === */
  .windy-bg {
    position: fixed;
    top: 0; left: 0;
    width: 100%; height: 100%;
    z-index: 0;
    pointer-events: none;
    overflow: hidden;
  }
  .windy-bg iframe {
    width: calc(100% + 200px);
    height: calc(100% + 200px);
    margin: -100px;
    border: none;
    pointer-events: none;
    opacity: 1;
    filter: none;
  }

  /* Mobile-only: shift the Windy iframe rightward so the land sits closer
     to the middle of the viewport on small screens. Desktop stays unchanged.
     The iframe is widened to cover viewport edges after the shift. */
  @media (max-width: 768px) {
    .windy-bg iframe {
      width: calc(100% + 1060px);
      margin-left: -530px;
      transform: translateX(530px);
    }
  }

  .app {
    position: relative;
    z-index: 2;
    max-width: 640px;
    margin: 0 auto;
    padding: 16px 16px 80px;
  }

  /* === HEADER === */
  .header {
    position: relative;
    /* backdrop-filter below makes this a stacking context, which traps the
       station dropdown panel. Lift the header above page content (picker bar,
       widgets) so the open dropdown can overlay them; stays below modals (1000). */
    z-index: 500;
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 24px 16px;
    margin-bottom: 14px;
    background: rgba(11, 20, 38, 0.82);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid var(--border);
    border-radius: 12px;
  }
  .header h1 {
    font-size: 20px;
    font-weight: 700;
    letter-spacing: -0.5px;
  }
  .header h1 picture { display: block; }
  .header h1 span { color: var(--accent); }
  .logo-full {
    height: 120px;
    /* Explicit width (not auto) reserves the logo box BEFORE the image loads, so
       the header can't grow from ~49px to ~172px on load and shove the picker +
       widget stack + footer down. 120 × (654/240 aspect) = 327. */
    width: 327px;
    display: block;
  }
  .location-select {
    background: var(--bg-card);
    border: 1px solid var(--border);
    color: var(--text-primary);
    padding: 8px 12px;
    border-radius: 8px;
    font-family: inherit;
    font-size: 13px;
    cursor: pointer;
    outline: none;
  }
  .location-select:focus { border-color: var(--accent); }
  .location-select option { background: var(--bg-card); }

  .header-right {
    display: flex;
    align-items: center;
    gap: 8px;
    align-self: center;
    margin-right: 40px;
    margin-top: 20px;
  }

  .settings-btn {
    background: var(--bg-card);
    border: 1px solid var(--border);
    color: var(--text-secondary);
    width: 34px;
    height: 34px;
    border-radius: 8px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 13px;
    transition: border-color 0.15s, color 0.15s;
  }
  .settings-btn:hover { border-color: var(--accent); color: var(--accent); }
  /* Discovery nudge: an accent-blue dot on the gear icon when no Home
     Station has been picked. State-driven — body.needs-config is set/cleared
     in app.js based on loadHomeStation().stationId === null. Pulses gently
     so the eye picks it up; respects prefers-reduced-motion. */
  .settings-btn { position: relative; }
  body.needs-config .settings-btn::after {
    content: '';
    position: absolute;
    top: 5px;
    right: 5px;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--accent);
    box-shadow: 0 0 0 2px var(--bg-card);
    animation: needs-config-pulse 1.6s ease-in-out infinite;
  }
  body.needs-config .settings-btn:hover::after {
    box-shadow: 0 0 0 2px var(--bg-card-hover, var(--bg-card));
  }
  @keyframes needs-config-pulse {
    0%, 100% { opacity: 1;   transform: scale(1); }
    50%      { opacity: 0.35; transform: scale(0.8); }
  }
  @media (prefers-reduced-motion: reduce) {
    body.needs-config .settings-btn::after { animation: none; }
  }

  /* Stack the header below desktop width. The horizontal layout (logo + FB +
     gear + station picker) needs ~720px of content area; below that the picker
     clipped and the page scrolled sideways. Stacking at ≤768px covers all phones
     and small tablets; the ≤480 block below further refines for phones. */
  @media (max-width: 768px) {
    .header {
      flex-direction: column;
      align-items: center;
      gap: 12px;
    }
    .header-right {
      width: 100%;
      justify-content: center;
      margin-right: 0;
      margin-top: 0;
    }
    .location-select { flex: 1 1 auto; min-width: 0; max-width: 320px; }
  }

  /* === MOBILE HEADER === */
  @media (max-width: 480px) {
    .header {
      flex-direction: column;
      align-items: center;
      gap: 12px;
      padding: 14px 14px;
      /* Reserve the stacked header's loaded height (logo row + controls row) so it
         can't grow on load and push the picker + widget stack + footer down — the
         last remaining CLS source after the hero/picker/logo fixes. */
      min-height: 172px;
    }
    .logo-full { height: 90px; width: 245px; } /* 90 × (654/240) — reserve box pre-load */
    .header-right {
      width: 100%;
      justify-content: center;
      margin-right: 0;
      margin-top: 0;
    }
    .location-select {
      font-size: 16px; /* prevents iOS auto-zoom on tap */
      padding: 8px 10px;
      flex: 1;
    }
    .settings-btn { width: 40px; height: 40px; flex-shrink: 0; }
    /* Larger step button tap targets on mobile */
    .settings-step-btn { width: 40px; height: 38px; }
    .settings-step-val { line-height: 38px; }
    /* Shrink wind legend to save space */
    .wind-legend { padding: 6px 10px; gap: 7px; }
    .wind-legend-scale { width: 100px; }
    .wind-legend-source { display: none; }
  }

  /* === SETTINGS PANEL === */
  .settings-panel {
    display: none;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 16px;
    margin-bottom: 14px;
    box-shadow: 0 8px 24px rgba(0,0,0,0.4);
  }
  .settings-panel.open { display: block; }

  .settings-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 14px;
    font-size: 13px;
    font-weight: 600;
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.8px;
  }
  .settings-close {
    background: none;
    border: none;
    color: var(--text-dim);
    cursor: pointer;
    font-size: 14px;
    padding: 2px 4px;
  }
  .settings-close:hover { color: var(--text-primary); }

  .settings-section {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 10px 0;
    border-bottom: 1px solid var(--border);
  }
  .settings-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
  }
  .settings-label {
    font-size: 12px;
    font-weight: 600;
    color: var(--accent);
    text-transform: uppercase;
    letter-spacing: 0.6px;
    flex: 1;
  }
  /* Label as section lede — small breathing room before the help text. Applies
     when the label is a direct child of .settings-section (the post-2026-04-30
     layout where label sits above the help and control). Inside .settings-row
     (legacy inline placements that may still exist) it stays untouched. */
  .settings-section > .settings-label {
    margin-bottom: 4px;
  }
  .settings-help {
    font-size: 11px;
    color: var(--text-dim);
    line-height: 1.4;
  }
  /* Summary-above-control variant: a touch more breathing room and slightly
     warmer color so it reads as the section's lede, not as a trailing footnote. */
  .settings-help-top {
    color: var(--text-secondary);
    margin-bottom: 8px;
    line-height: 1.5;
  }
  .settings-help-top strong {
    color: var(--text-primary);
    font-weight: 600;
  }
  /* Chevron-tipped action rows used in the bug-report card (Email me / FB)
     and elsewhere we want an iOS-Settings-style "tap to go somewhere" affordance. */
  .settings-action-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-top: 12px;
  }
  .settings-action-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 12px;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: rgba(255,255,255,0.02);
    color: var(--text-primary);
    font-size: 13px;
    font-weight: 500;
    text-decoration: none;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s, color 0.15s;
    font-family: inherit;
    text-align: left;
    width: 100%;
  }
  .settings-action-row:hover {
    background: rgba(255,255,255,0.05);
    border-color: var(--accent);
    color: var(--accent);
  }
  .settings-action-icon {
    width: 22px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--accent);
    font-size: 14px;
  }
  .settings-action-text { flex: 1; }
  .settings-action-chev {
    color: var(--text-dim);
    font-size: 11px;
  }
  .settings-action-row:hover .settings-action-chev { color: var(--accent); }
  /* Pair group — wraps two related settings (Home Station + Offset at Home)
     in a single thin-bordered card with a shared header. Replaces the older
     "bar banner" pattern. The wrapper container provides the visual grouping;
     the sections inside drop their own bottom-borders to avoid double-rules. */
  .settings-pair-group {
    margin: 14px 0;
    padding: 14px 14px 8px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: rgba(255,255,255,0.015);
  }
  .settings-pair-header {
    margin-bottom: 6px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--border);
  }
  .settings-pair-title {
    font-size: 12px;
    font-weight: 700;
    color: var(--accent);
    text-transform: uppercase;
    letter-spacing: 0.7px;
    margin-bottom: 6px;
  }
  .settings-pair-body {
    font-size: 11.5px;
    color: var(--text-secondary);
    line-height: 1.5;
  }
  .settings-pair-body p { margin: 0; }
  .settings-pair-body p + p { margin-top: 6px; }
  .settings-pair-body strong {
    color: var(--text-primary);
    font-weight: 600;
  }
  .settings-pair-analogy {
    font-style: italic;
    color: var(--text-dim);
  }
  .settings-pair-analogy strong {
    color: var(--text-secondary);
    font-weight: 600;
  }
  /* Sections inside the pair group lose their own bottom-border so the only
     visible boundary is the wrapper card. A soft top-rule still divides one
     section from the next. */
  .settings-pair-group > .settings-section {
    border-bottom: none;
    padding: 10px 0 6px;
  }
  .settings-pair-group > .settings-section + .settings-section {
    border-top: 1px solid rgba(255,255,255,0.04);
    padding-top: 12px;
  }
  /* Help section — collapsible disclosures using native <details>. */
  .settings-section-help { padding-top: 14px; }
  .settings-section-help .settings-label { margin-bottom: 8px; }
  .help-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
  }
  .help-item {
    border: 1px solid var(--border);
    border-radius: 8px;
    background: rgba(255,255,255,0.02);
    overflow: hidden;
  }
  .help-item summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 12px;
    cursor: pointer;
    list-style: none;
    font-size: 13px;
    font-weight: 500;
    color: var(--text-primary);
    transition: background 0.15s;
  }
  .help-item summary::-webkit-details-marker { display: none; }
  .help-item summary::after {
    content: '';
    display: inline-block;
    width: 6px;
    height: 6px;
    border-right: 2px solid var(--text-dim);
    border-bottom: 2px solid var(--text-dim);
    transform: rotate(-45deg);
    transition: transform 0.2s;
    margin-right: 4px;
  }
  .help-item[open] summary::after { transform: rotate(45deg); margin-top: -4px; }
  .help-item summary:hover {
    background: rgba(255,255,255,0.04);
    color: var(--accent);
  }
  .help-item summary:hover::after { border-color: var(--accent); }
  .help-item-body {
    padding: 0 14px 12px;
    color: var(--text-secondary);
    font-size: 12px;
    line-height: 1.55;
  }
  .help-item-body strong { color: var(--text-primary); font-weight: 600; }
  .help-item-body p { margin: 8px 0 0; }
  .help-item-body p:first-child { margin-top: 0; }
  .settings-opts {
    display: flex;
    gap: 4px;
  }
  .settings-opt {
    background: transparent;
    border: 1px solid var(--border);
    color: var(--text-dim);
    padding: 5px 0;
    border-radius: 20px;
    font-family: inherit;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
    min-width: 54px;
    text-align: center;
  }
  .settings-opt.active {
    background: var(--accent-dim);
    border-color: var(--accent);
    color: var(--accent);
  }
  .settings-opt:hover:not(.active) { border-color: rgba(255,255,255,0.25); color: var(--text-secondary); }

  .settings-stepper {
    display: flex;
    align-items: center;
    gap: 0;
    border: 1px solid var(--border);
    border-radius: 20px;
    overflow: hidden;
  }
  .settings-step-btn {
    background: transparent;
    border: none;
    color: var(--text-secondary);
    font-size: 16px;
    font-weight: 400;
    width: 32px;
    height: 30px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s, color 0.15s;
    flex-shrink: 0;
  }
  .settings-step-btn:hover { background: var(--accent-dim); color: var(--accent); }
  .settings-step-val {
    font-size: 12px;
    font-weight: 600;
    color: var(--text-primary);
    min-width: 48px;
    text-align: center;
    border-left: 1px solid var(--border);
    border-right: 1px solid var(--border);
    padding: 0 4px;
    line-height: 30px;
  }

  .settings-section-widgets { gap: 8px; }
  .settings-section-widgets .settings-label { margin-bottom: 2px; }
  #settingsWidgetList {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
  }

  .widget-picker-hidden { display: none !important; }

  .settings-section-reset { padding: 10px 0 2px; border-bottom: 1px solid var(--border); }
  .settings-reset-btn {
    background: transparent;
    border: 1px solid var(--danger);
    color: var(--danger);
    padding: 5px 14px;
    border-radius: 20px;
    font-family: inherit;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
  }
  .settings-reset-btn:hover {
    background: var(--danger);
    color: var(--bg-primary);
    border-color: var(--danger);
  }
  /* "Check for updates" — accent (non-destructive), distinct from the red Reset. */
  .settings-update-btn {
    background: transparent;
    border: 1px solid var(--accent);
    color: var(--accent);
    padding: 5px 14px;
    border-radius: 20px;
    font-family: inherit;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
  }
  .settings-update-btn:hover {
    background: var(--accent);
    color: var(--bg-primary);
    border-color: var(--accent);
  }
  .settings-update-status {
    margin-left: 10px;
    font-size: 12px;
    color: var(--text-secondary);
  }

  /* Notifications settings — status line + per-alert sub-options */
  .notif-perm-status:empty { display: none; }
  .notif-perm-status.is-error   { color: var(--danger); }
  .notif-perm-status.is-success { color: var(--success); }
  .notif-perm-status.is-warning { color: var(--warning); }
  /* Sub-options dimmed + non-interactive when master is off or permission unusable */
  .notif-suboptions.is-disabled { opacity: 0.45; pointer-events: none; }

  /* === WIDGET PICKER BAR === */
  /* Holds only the centered "Show/Hide all" control now (per-widget pills moved to
     Settings). The flanking hairlines (::before/::after) turn the lone toggle into
     an intentional divider between the header and the widget stack, and let the
     Windy background show through. */
  .widget-picker {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 2px 6px 12px;
    /* One control row — reserved so the JS-injected toggle doesn't shift the
       widget stack + footer when it mounts (the hairlines exist pre-JS). */
    min-height: 36px;
  }
  .widget-picker::before,
  .widget-picker::after {
    content: '';
    flex: 1 1 0;
    height: 1px;
    /* Solid next to the toggle, fading out toward the screen edges. */
    background: linear-gradient(to left, var(--border), transparent);
  }
  .widget-picker::after {
    background: linear-gradient(to right, var(--border), transparent);
  }

  .picker-btn {
    display: flex;
    align-items: center;
    gap: 5px;
    background: var(--bg-card);
    border: 1px solid var(--accent);
    color: var(--accent);
    padding: 5px 12px;
    border-radius: 20px;
    font-family: inherit;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.4px;
    cursor: pointer;
    white-space: nowrap;
    transition: background 0.15s, color 0.15s, opacity 0.15s;
  }
  .picker-btn i { font-size: 10px; }
  .picker-btn.off {
    background: transparent;
    border-color: rgba(255,255,255,0.15);
    color: var(--text-dim);
  }
  /* Keep off pills visible (grayed) in the picker bar so a hidden widget can be
     re-shown with one tap. Picker bar itself is hidden via SETTINGS.showPicker. */
  .picker-btn:hover { opacity: 0.8; }

  /* The lone "Show/Hide all" control: a quiet frosted chip (not the loud accent
     pill) so it reads as a calm divider focal point rather than a call-to-action. */
  .picker-btn-toggle-all {
    flex: 0 0 auto;
    background: rgba(11, 20, 38, 0.55);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    border-color: rgba(255, 255, 255, 0.18);
    color: var(--text-secondary);
    letter-spacing: 0.5px;
  }
  .picker-btn-toggle-all:hover {
    opacity: 1;
    color: var(--accent);
    border-color: var(--accent);
  }
  /* When everything is hidden the Windy map fills the screen — keep the toggle
     legible over it (the generic .picker-btn.off goes transparent/dim, which
     would vanish against the map). */
  .picker-btn-toggle-all.off {
    background: rgba(11, 20, 38, 0.6);
    border-color: var(--accent);
    color: var(--accent);
  }

  /* === DRAG GRIP === */
  .drag-grip {
    padding: 2px 0 2px 8px;
    color: var(--text-dim);
    cursor: grab;
    opacity: 0;
    transition: opacity 0.15s;
    font-size: 12px;
  }
  .widget-header:hover .drag-grip { opacity: 1; }
  .drag-grip:active { cursor: grabbing; }

  /* === WIDGET HIDDEN (soft, picker bar) === */
  .widget-hidden {
    display: none !important;
  }

  /* === WIDGET DISABLED (hard, settings) === */
  /* Disabled widgets are removed from the picker bar entirely and hidden
     from the page. Render/fetch paths short-circuit on isWidgetDisabled(). */
  .widget-disabled {
    display: none !important;
  }

  /* === SORTABLEJS STATES === */
  .sortable-ghost {
    opacity: 0.3;
    border: 1px dashed var(--accent);
  }
  .sortable-chosen {
    box-shadow: 0 8px 32px rgba(0,0,0,0.4);
  }

  /* === WIDGET === */
  .widget {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 12px;
    margin-bottom: 12px;
    overflow: hidden;
  }
  .widget-header {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    padding: 14px 16px;
    border-bottom: 1px solid var(--border);
    font-size: 13px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.8px;
    color: var(--text-secondary);
  }
  /* Day-toggle headers (tide/wind) widen when switched to "Tomorrow" (longer
     label + "Predicted" badge). On narrow phones that overflowed the row, and
     since .widget has overflow:hidden the toggle button got clipped off-screen
     (had to rotate to landscape to reach it). flex-wrap lets the controls drop
     to a second line instead of clipping; keep them from shrinking so they stay
     legible and tappable. Desktop is unchanged — wrapping only kicks in when the
     row can't fit on one line. */
  .widget-header .badge,
  .widget-header .tide-day-btn,
  .widget-header .widget-help-btn,
  .widget-header .drag-grip { flex-shrink: 0; }
  .widget-header > i { color: var(--accent); font-size: 14px; }
  .widget-header .badge {
    margin-left: auto;
    margin-right: 0;
    font-size: 10px;
    padding: 2px 8px;
    border-radius: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
  }
  .badge-live { background: rgba(81,207,102,0.15); color: var(--success); }
  .badge-warn { background: rgba(255,107,107,0.15); color: var(--danger); }
  .badge-info { background: var(--accent-dim); color: var(--accent); }
  /* Offshore header badge is source/freshness only (no go/no-go verdict). Amber
     ring flags thin/stale buoy data, not a safety verdict. */
  .badge-info.offshore-badge-stale { box-shadow: inset 0 0 0 1px rgba(255,212,59,0.45); }
  .tide-day-btn {
    background: none;
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: 6px;
    color: rgba(255,255,255,0.45);
    font-size: 10px;
    font-weight: 600;
    padding: 2px 7px;
    cursor: pointer;
    letter-spacing: 0.3px;
    transition: color 0.15s, border-color 0.15s;
  }
  .tide-day-btn:hover { color: var(--accent); border-color: var(--accent); }
  .widget-body { padding: 16px; }
  /* Async renderers replace their loading state in-place. Isolating each widget
     keeps a late chart/report from invalidating layout for the whole stack, and
     overflow anchoring no longer magnifies a small internal resize into a page
     jump while the user is scrolling. */
  #widgetStack > .widget {
    contain: layout paint;
    overflow-anchor: none;
  }

  /* === CLS RESERVATIONS (mobile) ===
     Data-driven widget bodies start as a one-line spinner, then expand when
     their async fetch lands. A mobile user scrolling down during the staggered
     loads sees those expansions shove content — the main-content CLS regression
     (#main, #widgetStack > section.widget). Reserve each body's typical loaded
     height (measured at 390px, default station) so the spinner→content swap
     doesn't grow the page. Mobile-only: tablet+ uses different layouts
     (e.g. offshore goes multi-column) where these heights would over-reserve. */
  @media (max-width: 699px) {
    .widget[data-widget-id="tide-chart"] .widget-body   { min-height: 330px; }
    .widget[data-widget-id="live-radar"] .widget-body  { min-height: 430px; }
    .widget[data-widget-id="wind-chart"] .widget-body  { min-height: 360px; }
    .surge-trend-body                                  { min-height: 360px; }
    .widget[data-widget-id="launch-window"] .widget-body { min-height: 130px; }
    .widget[data-widget-id="bite-windows"]  .widget-body { min-height: 330px; }
    .widget[data-widget-id="tide-schedule"] .widget-body { min-height: 360px; }
    #offshoreBody                                      { min-height: 700px; }
    .widget[data-widget-id="flood-tides"]   .widget-body { min-height: 180px; }
    #tropicalBody                                      { min-height: 80px; }
    /* Marine <pre> is capped at max-height 340; reserve the lower bound so the
       LOADING… line doesn't grow into the full forecast. */
    .marine-forecast-text                              { min-height: 300px; }
  }

  /* === HERO: Current Tide === */
  .tide-hero {
    text-align: center;
    padding: 24px 16px 20px;
    /* Reserve the loaded height so the spinner -> tide-grid swap doesn't grow the
       hero and shove every widget + the footer down (a top CLS source). Matches
       the real loaded height (~190px: grid + surge pill + padding) so the reserve
       fully prevents CLS without leaving an empty gap below the surge pill. */
    min-height: 190px;
  }
  /* 3×3 grid — columns: height | arrow | next-tide. Rows: top-label / big / bottom-label.
     Each row is shared across columns so the big elements (2.7, arrow, 4:40) sit on a
     common horizontal line. */
  .tide-hero-grid {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    grid-template-rows: auto auto auto;
    align-items: center;
    justify-items: center;
    column-gap: 16px;
    row-gap: 4px;
  }
  .tide-hero-top-slot {
    min-height: 14px;
    line-height: 1;
  }
  .tide-hero-dir {
    display: block;
    line-height: 0;
  }
  .tide-hero-dir i {
    font-size: 80px;
    line-height: 1;
    color: var(--accent);
  }
  .tide-hero-dir-label {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.12em;
    color: var(--accent);
  }
  .tide-hero-next-label {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.12em;
    color: var(--text-dim);
  }
  .tide-hero-next-time {
    line-height: 1;
    color: var(--text);
    white-space: nowrap;
  }
  .tide-hero-next-main {
    font-size: 64px;
    font-weight: 900;
    letter-spacing: -3px;
  }
  .tide-hero-next-suffix {
    font-size: 14px;
    font-weight: 400;
    color: var(--text-dim);
    margin-left: 4px;
    vertical-align: 0.4em;
    letter-spacing: 0.04em;
  }
  .tide-hero-next-height {
    font-size: 13px;
    color: var(--text-dim);
  }
  .tide-hero-height {
    font-size: 64px;
    font-weight: 900;
    letter-spacing: -3px;
    line-height: 1;
  }
  .tide-hero-unit {
    font-size: 14px;
    color: var(--text-dim);
    font-weight: 400;
  }
  .hero-station { font-weight: 400; color: var(--text-dim); }
  /* Mobile overrides MUST come after all base rules above — same-specificity
     source order determines which wins when the media query matches. */
  @media (max-width: 480px) {
    .tide-hero-grid { column-gap: 8px; }
    .tide-hero-dir i { font-size: 52px; }
    .tide-hero-height { font-size: 36px; letter-spacing: -2px; }
    .tide-hero-next-main { font-size: 36px; letter-spacing: -2px; }
    .tide-hero-next-suffix { font-size: 11px; vertical-align: 0.3em; }
  }

  /* === SURGE INDICATOR === */
  .surge-indicator {
    font-size: 12px;
    font-weight: 600;
    margin-top: 6px;
    padding: 3px 10px;
    border-radius: 8px;
    display: inline-block;
  }
  .surge-positive {
    color: #4dabf7;
    background: rgba(77, 171, 247, 0.12);
  }
  .surge-negative {
    color: #ff922b;
    background: rgba(255, 146, 43, 0.12);
  }

  /* === SURGE TREND WIDGET === */
  .surge-trend-body {
    padding: 14px 16px 12px;
  }
  .surge-summary {
    margin: 0 0 6px;
    font-size: 14px;
    font-weight: 600;
    color: var(--text);
    line-height: 1.4;
  }
  .surge-summary .surge-arrow-up { color: #51cf66; margin-right: 4px; }
  .surge-summary .surge-arrow-down { color: #ff922b; margin-right: 4px; }
  .surge-summary .surge-arrow-flat { color: rgba(255,255,255,0.55); margin-right: 4px; }
  .surge-summary .surge-gauge {
    margin-left: 8px;
    font-size: 12px;
    font-weight: 500;
    color: rgba(255,255,255,0.55);
  }
  .surge-projection {
    margin: 0 0 10px;
    font-size: 12px;
    color: rgba(255,255,255,0.65);
    line-height: 1.4;
  }
  .surge-chart-container {
    height: 200px;
    padding: 6px 0 8px;
  }
  .surge-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    font-size: 11px;
    color: rgba(255,255,255,0.7);
    margin: 8px 0 4px;
    padding: 0;
  }
  .surge-legend-item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
  }
  .surge-legend-swatch {
    width: 14px;
    height: 2px;
    border-radius: 1px;
    display: inline-block;
  }
  .surge-legend-swatch.swatch-live { background: #51cf66; height: 2px; }
  .surge-legend-swatch.swatch-tide-predicted { background: #4dabf7; height: 2px; }
  .surge-legend-swatch.swatch-tide-observed {
    height: 1px;
    background: linear-gradient(to right,
      rgba(81, 207, 102, 0.55) 0px, rgba(81, 207, 102, 0.55) 3px,
      transparent 3px, transparent 6px,
      rgba(81, 207, 102, 0.55) 6px, rgba(81, 207, 102, 0.55) 9px,
      transparent 9px, transparent 12px,
      rgba(81, 207, 102, 0.55) 12px, rgba(81, 207, 102, 0.55) 14px);
  }
  /* Tide Chart legend — same look as surge-legend but appears in a different
     widget, so it gets its own padding context. Hidden until the user enables
     the "Show on Tide Curve" overlay. `:not([hidden])` so the HTML hidden
     attribute actually wins over the display:flex rule. */
  .tide-chart-legend:not([hidden]) {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    font-size: 11px;
    color: rgba(255,255,255,0.7);
    padding: 0 16px 12px;
  }
  /* P6: quiet interpolated-curve disclosure for hi/lo-only stations. Unobtrusive
     muted caption; takes no space when hidden (the [hidden] attribute wins). */
  .tide-curve-note {
    font-size: 11px;
    font-style: italic;
    color: rgba(255,255,255,0.55);
    padding: 0 16px 12px;
    line-height: 1.4;
  }
  .surge-legend-swatch.swatch-forecast-history { background: #fab005; height: 2px; }
  .surge-legend-swatch.swatch-forecast {
    background: linear-gradient(to right,
      #51cf66 0px, #51cf66 4px, transparent 4px, transparent 8px,
      #51cf66 8px, #51cf66 12px);
    opacity: 0.75;
  }
  .surge-source {
    font-size: 11px;
    color: rgba(255,255,255,0.45);
    line-height: 1.5;
    margin-top: 8px;
  }
  .surge-switch-cta:not([hidden]) {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: 10px;
    padding: 8px 12px;
    border-radius: 8px;
    background: rgba(77, 171, 247, 0.10);
    border: 1px solid rgba(77, 171, 247, 0.25);
    font-size: 12px;
    color: rgba(255,255,255,0.85);
  }
  .surge-switch-cta > i { color: #4dabf7; font-size: 13px; }
  .surge-switch-btn {
    margin-left: auto;
    background: rgba(77, 171, 247, 0.18);
    border: 1px solid rgba(77, 171, 247, 0.4);
    color: #4dabf7;
    padding: 4px 10px;
    border-radius: 6px;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
  }
  .surge-switch-btn:hover { background: rgba(77, 171, 247, 0.25); }
  .surge-overlay-toggle {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 12px;
    padding: 10px 12px;
    border-top: 1px solid var(--border);
    font-size: 12px;
    color: rgba(255,255,255,0.75);
    cursor: pointer;
    user-select: none;
  }
  .surge-overlay-toggle input[type="checkbox"] {
    accent-color: #51cf66;
    width: 14px;
    height: 14px;
    margin: 0;
  }
  /* Badge color variants on the surge widget header. badge-info is the
     default; positive/negative override when current surge is non-trivial. */
  #surgeBadge.surge-badge-positive {
    background: rgba(81,207,102,0.18);
    color: #51cf66;
  }
  #surgeBadge.surge-badge-negative {
    background: rgba(255,146,43,0.18);
    color: #ff922b;
  }
  /* Inline surge tag on the hero "NEXT HIGH" block — small, lighter weight,
     color-tinted by sign. Lives below the height number and inherits the
     parent's spacing. */
  .next-surge-tag {
    display: inline-block;
    margin-left: 4px;
    font-size: 11px;
    font-weight: 500;
    color: #51cf66;
    letter-spacing: 0.2px;
  }

  /* Surge tags on Flood Tides events. Hero block uses .flood-hero-surge as a
     full sub-line beside "+X ft over flood line"; calendar chips use the
     smaller .flood-event-surge-tag inline next to the predicted height + grade.
     Single color for both — sign in the text communicates direction. */
  .flood-hero-surge {
    color: #51cf66;
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.2px;
  }
  .flood-event-surge-tag {
    color: #51cf66;
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.2px;
  }

  /* Mobile defensive overrides for the bug-squash bundle: tighter padding so
     the new components (pair card, action rows) don't crowd the content area
     on narrow phones, and bumped tap targets for the chevron-style action
     rows so they meet ~44px touch-target guidance. */
  @media (max-width: 480px) {
    .settings-pair-group {
      padding: 12px 10px 6px;
    }
    .settings-pair-header {
      padding-bottom: 10px;
    }
    .settings-pair-title {
      font-size: 11px;
      letter-spacing: 0.5px;
    }
    .settings-pair-body { font-size: 11px; }
    .settings-action-row {
      padding: 12px 12px;
    }
    /* Gear-dot sits on a 40px mobile button (vs 34px desktop). Recenter the
       dot slightly inward so the box-shadow ring reads cleanly on the larger
       button. */
    body.needs-config .settings-btn::after {
      top: 7px;
      right: 7px;
    }
    /* FAQ summary tap target */
    .help-item summary { padding: 12px 12px; }
  }

  /* === CONDITIONS BAR === */
  .conditions-bar {
    display: flex;
    justify-content: space-around;
    padding: 12px 16px;
    border-top: 1px solid var(--border);
  }
  .cond-item { text-align: center; }
  .cond-label { font-size: 11px; color: rgba(255,255,255,0.7); text-transform: uppercase; letter-spacing: 0.5px; }
  .cond-label i { font-size: 11px; margin-right: 2px; }
  .cond-value { font-size: 15px; font-weight: 600; margin-top: 2px; }

  /* === TIDE CHART === */
  .chart-container {
    padding: 12px 16px 16px;
    height: 200px;
    position: relative;
  }

  /* === LAUNCH WINDOWS (multi) === */
  .lw-list { display: flex; flex-direction: column; gap: 8px; }
  .lw-add-row {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 10px 12px;
    border: 1px dashed var(--border);
    border-radius: 10px;
    background: transparent;
    color: var(--text-dim);
    font-size: 12px;
    font-weight: 500;
    cursor: pointer;
    transition: color 0.15s, border-color 0.15s, background 0.15s;
  }
  .lw-add-row:hover {
    color: var(--accent);
    border-color: var(--accent-dim);
    background: rgba(77,171,247,0.04);
  }
  .lw-add-row i { font-size: 10px; }
  .lw-add-row[hidden] { display: none; }
  .lw-row {
    border-radius: 10px;
    background: rgba(255,255,255,0.02);
    overflow: hidden;
    transition: background 0.15s;
  }
  .lw-row-head {
    display: grid;
    grid-template-columns: 36px 1fr auto 18px;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    cursor: pointer;
    user-select: none;
  }
  .lw-row-head:hover { background: rgba(255,255,255,0.03); }
  .lw-icon {
    width: 36px; height: 36px;
    border-radius: 9px;
    display: flex; align-items: center; justify-content: center;
    font-size: 15px;
    /* Per-launch accent color set via --lw-accent / --lw-accent-bg custom
       properties on the .lw-row element. Safe/closed state is conveyed by
       the status word, not the icon — icon communicates launch identity
       so it can be matched against the chart overlay line of the same color. */
    background: var(--lw-accent-bg, rgba(255,255,255,0.05));
    color: var(--lw-accent, var(--text-secondary));
  }
  .lw-main { min-width: 0; }
  .lw-name { font-size: 14px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .lw-line { font-size: 11.5px; color: var(--text-dim); margin-top: 1px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }
  .lw-primary { color: var(--text-primary); font-weight: 600; font-size: 12.5px; }
  .lw-status { text-align: right; }
  .lw-status-word { font-size: 13px; font-weight: 600; }
  .lw-row.safe   .lw-status-word { color: var(--success); }
  .lw-row.closed .lw-status-word { color: var(--danger); }
  .lw-row.safe .lw-status-word.urgent { color: var(--warning); }
  .lw-status-sub { font-size: 11px; color: var(--text-dim); margin-top: 1px; }
  .lw-chevron {
    border: none; background: transparent; color: var(--text-dim);
    font-size: 10px; cursor: pointer; padding: 0;
    transition: transform 0.2s;
  }
  .lw-row.expanded .lw-chevron { transform: rotate(180deg); }
  .lw-row-body {
    padding: 4px 12px 12px;
    border-top: 1px solid var(--border);
    margin-top: 2px;
    display: flex;
    flex-direction: column;
    gap: 10px;
  }
  .lw-section-label {
    font-size: 9px;
    color: var(--text-dim);
    text-transform: uppercase;
    letter-spacing: 0.6px;
    margin-top: 10px;
    display: block;
  }
  /* Trip plan hero */
  .lw-trip {
    background: rgba(77,171,247,0.06);
    border: 1px solid var(--accent-dim);
    border-radius: 8px;
    padding: 10px 12px;
  }
  .lw-trip .lw-section-label { margin-top: 0; color: var(--accent); }
  .lw-trip-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    font-size: 13px;
    margin-top: 6px;
    font-variant-numeric: tabular-nums;
  }
  .lw-trip-row span { color: var(--text-secondary); }
  .lw-trip-row b { color: var(--text-primary); font-weight: 700; font-size: 14px; }
  .lw-trip-allday { font-size: 13px; font-weight: 600; color: var(--success); margin-top: 6px; }
  .lw-trip-note { font-size: 10.5px; color: var(--text-dim); margin-top: 8px; font-style: italic; }
  /* Tomorrow timeline */
  .lw-timeline { display: flex; flex-direction: column; gap: 2px; }
  .lw-timeline .lw-section-label { margin-top: 0; margin-bottom: 4px; }
  .lw-seg {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    font-size: 12px;
    padding: 5px 10px;
    border-radius: 6px;
    font-variant-numeric: tabular-nums;
  }
  .lw-seg-safe   { background: rgba(81,207,102,0.08);  color: var(--success); }
  .lw-seg-unsafe { background: rgba(255,107,107,0.06); color: var(--danger); }
  .lw-seg-name   { font-weight: 600; font-size: 11px; text-transform: uppercase; letter-spacing: 0.4px; }
  .lw-seg-range  { color: var(--text-primary); font-weight: 500; }
  .lw-seg-trip {
    outline: 1px solid var(--accent);
    background: rgba(81,207,102,0.14);
  }
  .lw-seg-trip-tag {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 6px;
    font-size: 9px;
    font-style: normal;
    font-weight: 700;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    background: var(--accent);
    color: #0f1419;
    border-radius: 4px;
  }
  .lw-seg-past {
    opacity: 0.45;
  }
  .lw-seg-past .lw-seg-range { text-decoration: line-through; }
  .lw-seg-past-tag {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 6px;
    font-size: 9px;
    font-style: normal;
    font-weight: 700;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    background: rgba(255,255,255,0.08);
    color: var(--text-dim);
    border-radius: 4px;
  }
  /* Per-launch station selector */
  .lw-name-row {
    display: flex;
    align-items: baseline;
    gap: 6px;
    min-width: 0;
  }
  .lw-name-station {
    font-size: 11.5px;
    color: var(--text-dim);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .lw-station-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 2px 0;
  }
  .lw-station-label {
    font-size: 9px;
    color: var(--text-dim);
    text-transform: uppercase;
    letter-spacing: 0.6px;
    flex-shrink: 0;
  }
  .lw-station-select {
    flex: 1;
    min-width: 0;
    padding: 6px 8px;
    background: rgba(255,255,255,0.04);
    border: 1px solid var(--border);
    color: var(--text-primary);
    border-radius: 6px;
    font-size: 12.5px;
    font-family: inherit;
  }
  .lw-toggle-disabled {
    opacity: 0.45;
    cursor: not-allowed;
  }
  .lw-toggle-disabled input { cursor: not-allowed; }
  .lw-toggle-hint {
    font-size: 10.5px;
    color: var(--text-dim);
    font-style: italic;
    margin-top: 4px;
    padding-left: 4px;
    line-height: 1.35;
  }
  .lw-partial-note {
    font-size: 10.5px;
    color: var(--text-dim);
    font-style: italic;
    margin-top: 6px;
    padding-left: 10px;
  }
  /* Now block */
  .lw-now {
    display: flex;
    flex-direction: column;
    gap: 2px;
  }
  .lw-now .lw-section-label { margin-top: 0; }
  .lw-now-detail { font-size: 12px; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
  .lw-windows {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 10px;
  }
  .lw-pill {
    flex: 1 1 auto;
    min-width: 0;
    padding: 6px 10px;
    background: rgba(255,255,255,0.03);
    border-radius: 6px;
    font-size: 12px;
  }
  .lw-pill-label { font-size: 9px; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.5px; }
  .lw-pill-value { font-weight: 600; margin-top: 2px; font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .lw-pill.good  .lw-pill-value { color: var(--success); }
  .lw-pill.warn  .lw-pill-value { color: var(--warning); }
  .lw-row-actions {
    display: flex;
    gap: 8px;
    justify-content: space-between;
    align-items: flex-start;
    margin-top: 10px;
  }
  .lw-toggles {
    display: flex;
    flex-direction: column;
    gap: 4px;
  }
  .lw-action-buttons {
    display: flex;
    gap: 8px;
  }
  .lw-row-actions button {
    background: transparent;
    border: 1px solid var(--border);
    color: var(--text-secondary);
    font-size: 11px;
    padding: 4px 10px;
    border-radius: 6px;
    cursor: pointer;
  }
  .lw-row-actions button:hover { background: rgba(255,255,255,0.05); color: var(--text-primary); }
  .lw-row-actions .lw-delete:hover { border-color: var(--danger); color: var(--danger); }
  .lw-toggle {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 11px;
    color: var(--text-secondary);
    cursor: pointer;
    user-select: none;
  }
  .lw-toggle input[type="checkbox"] {
    appearance: none;
    -webkit-appearance: none;
    width: 14px;
    height: 14px;
    border: 1.5px solid var(--border);
    border-radius: 3px;
    background: rgba(0,0,0,0.2);
    cursor: pointer;
    position: relative;
    margin: 0;
    transition: border-color 0.15s, background 0.15s;
  }
  .lw-toggle input[type="checkbox"]:hover { border-color: #ffa94d; }
  .lw-toggle input[type="checkbox"]:checked {
    background: #ffa94d;
    border-color: #ffa94d;
  }
  .lw-toggle input[type="checkbox"]:checked::after {
    content: '';
    position: absolute;
    left: 3px;
    top: 0;
    width: 4px;
    height: 8px;
    border: solid #071124;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
  }
  .lw-toggle:hover { color: var(--text-primary); }
  /* Inline name edit affordance */
  .lw-name {
    cursor: text;
    border-radius: 4px;
    padding: 0 2px;
    transition: background 0.15s, box-shadow 0.15s;
  }
  .lw-name:hover {
    background: rgba(255,255,255,0.04);
    box-shadow: inset 0 -1px 0 var(--text-dim);
  }
  .lw-name.lw-name-editing {
    background: rgba(77,171,247,0.08);
    box-shadow: inset 0 -1px 0 var(--accent);
    outline: none;
    cursor: text;
  }
  /* Inline depth stepper on row head */
  .lw-depth-mini {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-top: 2px;
    font-variant-numeric: tabular-nums;
  }
  .lw-depth-mini button {
    width: 18px; height: 18px;
    border-radius: 50%;
    background: rgba(255,255,255,0.06);
    border: none;
    color: var(--text-secondary);
    cursor: pointer;
    font-size: 11px;
    line-height: 1;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s, color 0.15s;
  }
  .lw-depth-mini button:hover { background: var(--accent-dim); color: var(--accent); }
  .lw-depth-val {
    min-width: 38px;
    text-align: center;
    font-size: 11px;
    color: var(--text-primary);
    font-weight: 600;
  }

  /* Mobile restack: at narrow viewports the 4-column grid (icon | main | status | chevron)
     truncates the launch name, station, and primary line because the status column
     (word + depth stepper) is unbounded. Drop to 3 columns; status drops to its own
     row beneath main, so name/station and primary line get the full middle width. */
  @media (max-width: 480px) {
    .lw-row-head {
      grid-template-columns: 36px 1fr 18px;
      grid-template-areas:
        "icon main    chevron"
        "icon status  chevron";
      row-gap: 4px;
    }
    .lw-icon    { grid-area: icon; }
    .lw-main    { grid-area: main; }
    .lw-status  { grid-area: status;
      display: flex;
      align-items: center;
      justify-content: space-between;
      text-align: left;
      gap: 10px;
    }
    .lw-chevron { grid-area: chevron; align-self: center; }
    .lw-depth-mini { margin-top: 0; }
  }

  /* Station Fine-Tune stepper in Settings — mirrors .lw-depth-mini but
     sized for the settings panel context (bigger tap targets, bigger value). */
  .settings-section-offset .settings-sublabel {
    font-size: 11px;
    color: var(--text-secondary);
    margin-top: 2px;
  }
  .settings-home-select {
    appearance: none;
    -webkit-appearance: none;
    background: rgba(255,255,255,0.06);
    border: 1px solid rgba(255,255,255,0.1);
    color: var(--text-primary);
    font-size: 13px;
    padding: 6px 10px;
    border-radius: 8px;
    min-width: 180px;
    cursor: pointer;
  }
  .settings-home-select:focus { outline: none; border-color: var(--accent); }
  .offset-stepper {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    font-variant-numeric: tabular-nums;
  }
  .offset-stepper button {
    width: 30px; height: 30px;
    border-radius: 50%;
    background: rgba(255,255,255,0.06);
    border: 1px solid rgba(255,255,255,0.1);
    color: var(--text-primary);
    cursor: pointer;
    font-size: 16px;
    line-height: 1;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
  }
  .offset-stepper button:hover { background: var(--accent-dim); color: var(--accent); border-color: var(--accent); }
  .offset-stepper button:active { transform: scale(0.95); }
  .offset-stepper button:disabled,
  .offset-stepper button[aria-disabled="true"] {
    opacity: 0.35;
    cursor: not-allowed;
    transform: none;
    background: rgba(255,255,255,0.04);
    border-color: rgba(255,255,255,0.08);
    color: var(--text-secondary);
  }
  .offset-stepper button:disabled:hover,
  .offset-stepper button[aria-disabled="true"]:hover {
    background: rgba(255,255,255,0.04);
    color: var(--text-secondary);
    border-color: rgba(255,255,255,0.08);
  }
  .settings-section-offset.offset-disabled .offset-val {
    opacity: 0.5;
  }
  .offset-val {
    min-width: 70px;
    text-align: center;
    font-size: 14px;
    color: var(--text-primary);
    font-weight: 600;
  }

  /* === TIDE TABLE === */
  .tide-table {
    width: 100%;
    border-collapse: collapse;
  }
  .tide-table th {
    font-size: 10px;
    color: var(--text-dim);
    text-transform: uppercase;
    letter-spacing: 0.8px;
    text-align: left;
    padding: 0 0 10px;
    font-weight: 500;
  }
  .tide-table th:last-child { text-align: right; }
  .tide-table td {
    padding: 8px 0;
    border-top: 1px solid rgba(255,255,255,0.04);
    font-size: 13px;
  }
  .tide-table td:last-child { text-align: right; font-weight: 600; }
  .tide-dot {
    display: inline-block;
    width: 6px; height: 6px;
    border-radius: 50%;
    margin-right: 6px;
    vertical-align: middle;
  }
  .tide-dot.high { background: var(--accent); }
  .tide-dot.low { background: var(--warning); }
  /* Today's rows render green and slightly highlighted to distinguish them
     from future days at a glance. Applied to the <td>s so the row cells share
     a tinted background regardless of <tr> background-inheritance quirks.
     The left-accent marker uses inset box-shadow instead of border-left so
     today rows don't have a different width than tomorrow rows. */
  .tide-table tr.today td {
    color: var(--success);
    background: rgba(81, 207, 102, 0.08);
    font-weight: 600;
  }
  .tide-table tr.today td:first-child {
    box-shadow: inset 3px 0 0 var(--success);
    padding-left: 9px;
  }
  .tide-table tr.tomorrow td { color: var(--text-secondary); }
  /* Collapsed schedule: hide everything but today's events until expanded. */
  .tide-table.tide-table-collapsed tr.tide-row-extra { display: none; }

  .tide-schedule-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    margin-top: 8px;
    padding: 10px;
    background: rgba(255, 255, 255, 0.03);
    border: 1px solid var(--border);
    border-radius: 8px;
    color: var(--text-secondary);
    font: inherit;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: border-color 0.15s, color 0.15s, background 0.15s;
  }
  .tide-schedule-toggle:hover { border-color: var(--accent); color: var(--accent); }
  .tide-schedule-toggle-chev { font-size: 11px; transition: transform 0.2s ease; }
  .tide-schedule-toggle.expanded .tide-schedule-toggle-chev { transform: rotate(180deg); }

  /* === FLOOD TIDE WIDGET === */

  /* Meta bar */
  .flood-meta {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 11px;
    color: var(--text-dim);
    margin-bottom: 12px;
  }
  .flood-threshold-label { opacity: 0.7; }
  .flood-season-badge {
    background: rgba(255, 160, 0, 0.15);
    color: #ffa000;
    border-radius: 10px;
    padding: 1px 7px;
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.4px;
  }
  .flood-spring-next {
    opacity: 0.75;
    font-size: 11px;
  }

  /* Hero: Best Next */
  .flood-hero {
    background: rgba(77,171,247,0.07);
    border: 1px solid rgba(77,171,247,0.15);
    border-radius: 10px;
    padding: 12px 14px;
    margin-bottom: 14px;
  }
  .flood-hero-label {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 1px;
    text-transform: uppercase;
    color: var(--accent);
    opacity: 0.8;
    margin-bottom: 6px;
  }
  .flood-hero-main {
    display: flex;
    align-items: baseline;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 6px;
  }
  .flood-hero-date { font-size: 15px; font-weight: 600; color: var(--text); }
  .flood-hero-time { font-size: 14px; color: var(--text-dim); }
  .flood-hero-height { font-size: 14px; font-weight: 700; color: var(--accent); }
  .flood-hero-sub {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
  }
  .flood-hero-above { font-size: 12px; color: var(--text-dim); }
  .flood-hero-timing { font-size: 12px; color: var(--text-dim); }

  /* Signal pills (shared between hero and chips) */
  .flood-signal {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 10px;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.4px;
  }
  .flood-prime        { background: rgba(77,171,247,0.18); color: var(--accent); }
  .flood-good         { background: rgba(81,207,102,0.18); color: var(--success); }
  .flood-marginal     { background: rgba(255,255,255,0.07); color: var(--text-dim); }
  .flood-night-surge  { background: rgba(255,196,0,0.18);  color: #ffd060; }

  /* 30-day calendar — only flood tide days, auto-wrap */
  .flood-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
    gap: 5px;
  }
  .flood-day {
    position: relative;
    background: rgba(255,255,255,0.03);
    border: 1px solid rgba(255,255,255,0.06);
    border-radius: 8px;
    padding: 6px 4px;
    min-height: 70px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0; /* grid items default to min-width:auto — allow shrink below content width */
  }
  .flood-day-active {
    border-color: rgba(77,171,247,0.2);
    background: rgba(77,171,247,0.04);
  }
  .flood-day-label {
    font-size: 10px;
    font-weight: 600;
    color: var(--text-dim);
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  /* Chips inside day cards */
  .flood-chip {
    border-radius: 5px;
    padding: 3px 4px;
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
    overflow: hidden; /* hard containment — content can never spill past the rounded box */
  }
  .flood-chip-prime         { background: rgba(77,171,247,0.12); }
  .flood-chip-good          { background: rgba(81,207,102,0.12); }
  .flood-chip-marginal      { background: rgba(255,255,255,0.05); }
  /* NIGHT SURGE — surge-driven flood that peaks at night. Shown distinctly
     so the user reads it as a "flood will happen, just at night" alert
     rather than a fly-fishing window. Amber accent, slightly darker bg. */
  .flood-chip-night-surge   { background: rgba(255, 196, 0, 0.10); }
  .flood-chip-time {
    font-size: 10px;
    font-weight: 600;
    color: var(--text);
    white-space: nowrap;
  }
  .flood-chip-detail {
    font-size: 10px;
    color: var(--text-dim);
  }
  /* Stars + grade get a dedicated second line: inside an 80px-min day card the
     one-line form ("5.4 ft ★★ GOOD") overflows at common widths, and longer
     grades (MARGINAL) are worse. Two lines fit at every grid width. */
  .flood-chip-sig { opacity: 0.8; display: block; }

  /* Empty / mobile */
  .flood-empty { text-align: center; color: var(--text-dim); font-size: 13px; padding: 20px 0; }

  @media (max-width: 480px) {
    .flood-grid { grid-template-columns: repeat(3, 1fr); }
  }

  /* Per-card calendar export button */
  .flood-day-cal {
    position: absolute;
    top: 2px;
    right: 2px;
    width: 22px;
    height: 22px;
    border: none;
    background: rgba(77,171,247,0.1);
    border-radius: 50%;
    color: rgba(77,171,247,0.5);
    cursor: pointer;
    font-size: 9px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    transition: background 0.15s, color 0.15s;
  }
  .flood-day-cal:hover, .flood-day-cal:active {
    background: rgba(77,171,247,0.25);
    color: var(--accent);
  }

  /* Daytime highlight — good or prime flood during daylight hours */
  .flood-day-highlight {
    border-color: rgba(255, 196, 0, 0.5);
    background: rgba(255, 196, 0, 0.07);
    box-shadow: 0 0 10px rgba(255, 196, 0, 0.09);
  }

  .flood-day-sun {
    position: absolute;
    top: 3px;
    left: 5px;
    font-size: 9px;
    color: rgba(255, 196, 0, 0.8);
  }

  /* Reference-station attribution ("Tide data from Mayport") */
  .flood-source-label {
    background: rgba(255, 255, 255, 0.06);
    color: var(--text-dim);
    border-radius: 10px;
    padding: 1px 7px;
    font-size: 10px;
    font-weight: 600;
  }
  .flood-source-label i { margin-right: 4px; opacity: 0.6; }

  /* Off-season badge */
  .flood-season-badge.flood-season-off {
    background: rgba(255, 255, 255, 0.05);
    color: var(--text-dim);
  }

  /* Hero stars + grade pill */
  .flood-hero-stars {
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 1.5px;
    margin-bottom: 6px;
  }
  .flood-hero-stars.flood-prime    { color: var(--accent); background: transparent; padding: 0; }
  .flood-hero-stars.flood-good     { color: var(--success); background: transparent; padding: 0; }
  .flood-hero-stars.flood-marginal { color: var(--text-dim); background: transparent; padding: 0; }

  /* Hero sub-line extras */
  .flood-hero-moon    { font-size: 12px; color: var(--text-dim); }
  .flood-hero-wind    { font-size: 12px; color: var(--text-dim); }
  .flood-hero-sunset  { font-size: 12px; color: rgba(255, 196, 0, 0.85); }
  .flood-hero-warning {
    margin-top: 8px;
    padding: 6px 8px;
    background: rgba(255, 160, 0, 0.08);
    border-left: 2px solid rgba(255, 160, 0, 0.6);
    border-radius: 3px;
    color: #ffa000;
    font-size: 11px;
  }

  /* Empty state with reason */
  .flood-empty-headline {
    font-size: 14px;
    font-weight: 600;
    color: var(--text);
    margin-bottom: 6px;
  }
  .flood-empty-reason { font-size: 12px; color: var(--text-dim); }

  /* Day-container grade tints */
  .flood-prime-day {
    border-color: rgba(77,171,247,0.45) !important;
    background: rgba(77,171,247,0.08) !important;
    box-shadow: 0 0 10px rgba(77,171,247,0.15);
  }
  .flood-good-day {
    border-color: rgba(81,207,102,0.35) !important;
    background: rgba(81,207,102,0.06) !important;
  }
  .flood-marginal-day {
    border-color: rgba(255,255,255,0.1) !important;
    background: rgba(255,255,255,0.03) !important;
  }

  /* Grade-specific chip fills */
  .flood-chip.flood-prime        { background: rgba(77,171,247,0.15); color: var(--accent); }
  .flood-chip.flood-good         { background: rgba(81,207,102,0.15); color: var(--success); }
  .flood-chip.flood-marginal     { background: rgba(255,255,255,0.05); color: var(--text-dim); }
  .flood-chip.flood-night-surge  { background: rgba(255,196,0,0.12);  color: #ffd060; }

  /* Per-row tags inside .flood-chip — surge contribution, Wind TBD, etc.
     Each tag wraps onto its own line so a chip with a long surge tag doesn't
     overflow the narrow grid column. */
  .flood-chip-tag {
    display: block;
    font-size: 9px;
    font-weight: 600;
    letter-spacing: 0.2px;
    line-height: 1.3;
    margin-top: 1px;
  }

  /* Surge contribution tag inside chips — green to match the hero surge tag
     and the surge-trend widget's positive-surge convention. */
  .flood-chip-tag.flood-event-surge-tag {
    color: #51cf66;
  }

  /* "Wind TBD" pill on cards beyond NWS 48h hourly horizon. Used both in
     legacy inline form and the new per-row .flood-chip-tag form. */
  .flood-chip-tbd {
    background: rgba(255, 160, 0, 0.12);
    color: #ffa000;
    font-weight: 700;
    letter-spacing: 0.3px;
  }
  /* Inline (legacy) form */
  .flood-chip-tbd:not(.flood-chip-tag) {
    display: inline-block;
    margin-left: 4px;
    padding: 0 5px;
    border-radius: 3px;
    font-size: 9px;
    opacity: 0.85;
  }
  /* Per-row form */
  .flood-chip-tag.flood-chip-tbd {
    padding: 0 4px;
    border-radius: 3px;
    align-self: flex-start;
  }

  /* === OFFSHORE 70NM WIDGET === */
  .offshore-loading {
    text-align: center;
    color: var(--text-dim);
    font-size: 13px;
    padding: 20px 0;
  }
  .offshore-loading i { margin-right: 6px; }

  .offshore-header {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 12px;
    font-size: 12px;
    color: var(--text-dim);
  }
  .offshore-date { font-weight: 600; color: var(--text-secondary); }
  .offshore-moon { opacity: 0.8; }
  .offshore-solunar {
    color: rgba(255,215,0,0.8);
    font-weight: 600;
    font-size: 11px;
  }

  .offshore-columns {
    display: grid;
    /* Mayport · St. Augustine · Offshore Buoy — three balanced columns. */
    grid-template-columns: repeat(3, 1fr);
    gap: 12px;
    margin-bottom: 14px;
    align-items: stretch; /* all three cards equalize to the tallest — even columns, no ragged gap */
  }
  @media (max-width: 560px) {
    .offshore-columns { grid-template-columns: 1fr; }
  }

  .offshore-col {
    background: rgba(255,255,255,0.035);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 12px;
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.03);
  }
  .offshore-col-title {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.8px;
    color: var(--accent);
    margin-bottom: 10px;
    padding-bottom: 6px;
    border-bottom: 1px solid rgba(77,171,247,0.15);
  }
  .offshore-col-subtitle {
    font-size: 10px;
    color: var(--text-dim);
    line-height: 1.35;
    margin-top: -4px;
    margin-bottom: 10px;
    font-style: italic;
  }

  .offshore-inlet-label {
    font-size: 11px;
    font-weight: 600;
    color: var(--text-secondary);
    margin-bottom: 6px;
  }

  .offshore-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 4px 0;
    font-size: 12px;
    line-height: 1.5;
    border-bottom: 1px dashed rgba(255,255,255,0.04);
  }
  .offshore-row:last-child { border-bottom: none; }
  .offshore-row-label {
    color: var(--text-dim);
    display: inline-flex;
    align-items: center;
    gap: 2px;
  }
  .offshore-row-icon {
    font-size: 10px;
    width: 14px;
    text-align: center;
    color: var(--accent);
    opacity: 0.7;
  }
  .offshore-row-val {
    color: var(--text-primary);
    font-weight: 600;
    text-align: right;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    line-height: 1.25;
  }
  .offshore-row-source {
    display: block;
    font-weight: 400;
    font-size: 9px;
    color: var(--text-dim);
    opacity: 0.7;
    letter-spacing: 0.3px;
    margin-top: 1px;
  }
  .offshore-warn-text { color: #ff922b; }

  .offshore-inlet-warn {
    margin-top: 6px;
    padding: 5px 8px;
    background: rgba(255,146,43,0.1);
    border-radius: 6px;
    font-size: 11px;
    color: #ff922b;
    font-weight: 500;
  }
  .offshore-inlet-warn i { margin-right: 4px; }

  .offshore-no-data {
    text-align: center;
    color: var(--text-dim);
    font-size: 12px;
    padding: 12px 0;
  }
  .offshore-no-data-expired {
    color: var(--danger);
    font-weight: 600;
    background: rgba(255,107,107,0.08);
    border: 1px solid rgba(255,107,107,0.25);
    border-radius: 6px;
    padding: 10px 12px;
    line-height: 1.4;
  }
  .offshore-no-data-expired i { margin-right: 6px; }

  /* NOTE: the GO/CAUTION/NO-GO decision hero (`.offshore-decision`,
     `.offshore-go-badge`, `.offshore-go/-caution/-nogo`) was removed — the
     offshore brief describes conditions and defers to NWS marine guidance,
     it no longer renders a go/no-go verdict. */

  .offshore-steepness {
    font-size: 11px;
    font-weight: 600;
    margin: 0 auto 6px;
    padding: 2px 10px;
    border-radius: 10px;
    display: block;
    width: fit-content;
  }
  .offshore-sig-green { background: rgba(81,207,102,0.12); color: var(--success); }
  .offshore-sig-yellow { background: rgba(255,212,59,0.12); color: var(--warning); }
  .offshore-sig-red { background: rgba(255,107,107,0.12); color: var(--danger); }

  .offshore-steepness-caption {
    font-size: 10px;
    color: var(--text-dim);
    margin-top: 2px;
    margin-bottom: 4px;
    line-height: 1.4;
    font-style: italic;
  }

  /* Sea-state headline — the SE "what's the ride" word above the GO badge. */
  .offshore-seastate {
    font-size: 21px;
    font-weight: 800;
    letter-spacing: 2px;
    text-transform: uppercase;
    margin-bottom: 8px;
    line-height: 1;
    color: var(--text-primary);
  }
  .offshore-seastate-slick,
  .offshore-seastate-fishable { color: var(--success); }
  .offshore-seastate-rolling  { color: var(--accent); }
  .offshore-seastate-sloppy   { color: var(--warning); }
  .offshore-seastate-sporty   { color: #f0a93e; }
  .offshore-seastate-snotty,
  .offshore-seastate-victory-at-sea { color: var(--danger); }
  /* The storm egg — biggest warning the widget can throw. */
  .offshore-seastate-storm {
    color: #ff5b5b;
    font-size: 17px;
    letter-spacing: 1px;
    text-shadow: 0 1px 8px rgba(255,91,91,0.35);
  }

  /* St. Augustine buoy highlight chip — makes the wave source unmistakable. */
  .offshore-buoy-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 10.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--accent);
    background: var(--accent-dim);
    border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
    border-radius: 999px;
    padding: 3px 10px;
    margin-bottom: 10px;
  }
  .offshore-buoy-chip i { font-size: 10px; }
  .offshore-buoy-chip-id { color: var(--text-dim); font-weight: 600; letter-spacing: 0; }

  /* Two stacked inlet columns (Mayport + St. Augustine) in the inlet panel. */
  .offshore-inlet-block + .offshore-inlet-block {
    margin-top: 14px;
    padding-top: 12px;
    border-top: 1px solid var(--border);
  }

  /* Wave history + forecast chart. */
  .offshore-history {
    margin-top: 16px;
    padding-top: 14px;
    border-top: 1px solid var(--border);
  }
  .offshore-history-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 8px;
    gap: 8px;
  }
  .offshore-history-title {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-secondary);
  }
  /* Self-contained 1wk/2wk segment (the .jt-seg styles are scoped to settings). */
  .offshore-hist-toggle {
    display: inline-flex;
    gap: 3px;
    padding: 3px;
    background: rgba(255, 255, 255, 0.06);
    border-radius: 9px;
    flex-shrink: 0;
  }
  .offshore-hist-toggle .offshore-hist-range {
    border: none;
    background: transparent;
    color: var(--text-secondary);
    font: inherit;
    font-size: 11px;
    font-weight: 600;
    padding: 3px 9px;
    border-radius: 6px;
    cursor: pointer;
  }
  .offshore-hist-toggle .offshore-hist-range.active {
    background: var(--accent);
    color: var(--bg-primary);
    font-weight: 700;
  }
  .offshore-history-container {
    position: relative;
    height: 160px;
  }
  .offshore-history-legend {
    display: flex;
    gap: 16px;
    justify-content: center;
    margin-top: 8px;
    font-size: 11px;
    color: var(--text-dim);
  }
  .offshore-hist-leg { display: inline-flex; align-items: center; gap: 6px; }
  .offshore-hist-swatch {
    width: 16px;
    border-top: 2px solid var(--accent);
    display: inline-block;
  }
  .offshore-hist-swatch.fc { border-top-style: dashed; border-top-color: #ffa94d; }

  /* Offshore GFS forecast — Windfinder-style table adapted for mobile: day
     buttons pick the day; that day shows across ~4 time columns with wind / sky /
     temp / pressure / wave rows down the side. Dark theme, fits a phone width. */
  .offshore-forecast { margin-top: 16px; }
  .offshore-forecast-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    margin-bottom: 8px;
  }
  .offshore-forecast-title {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.8px;
    color: var(--accent);
  }
  .offshore-forecast-src {
    font-size: 9px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--text-dim);
  }
  /* Day selector buttons */
  .offshore-fc-days {
    display: flex;
    gap: 6px;
    margin-bottom: 10px;
  }
  .offshore-fc-daybtn {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1px;
    padding: 6px 4px;
    background: rgba(255,255,255,0.035);
    border: 1px solid var(--border);
    border-radius: 8px;
    color: var(--text-secondary);
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s;
  }
  .offshore-fc-daybtn:hover { background: rgba(255,255,255,0.06); }
  .offshore-fc-daybtn.active {
    background: rgba(77,171,247,0.15);
    border-color: var(--accent);
    color: var(--text-primary);
  }
  .offshore-fc-daybtn-wd { font-size: 11px; font-weight: 700; }
  .offshore-fc-daybtn-md { font-size: 9px; color: var(--text-dim); }
  /* Standalone storm-likely marker (a discrete hazard, NOT a quality rating —
     uncolored, no pill background). */
  .offshore-fc-daybtn-storm { font-size: 11px; line-height: 1; margin-top: 2px; }

  /* Forecast grid (one day) — columns set inline by JS (auto + one per slot).
     Scrolls horizontally (the "slider") when there are more time columns than
     fit; the row-label column stays pinned on the left. */
  .offshore-forecast-table {
    display: grid;
    column-gap: 2px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
  .offshore-fcg-cell {
    padding: 5px 4px;
    font-size: 11px;
    text-align: center;
    color: var(--text-secondary);
    border-bottom: 1px dashed rgba(255,255,255,0.05);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .offshore-fcg-rowlabel {
    position: sticky;
    left: 0;
    z-index: 1;
    background: var(--bg-card);
    text-align: left;
    padding-right: 6px;
    font-size: 9px;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    color: var(--text-dim);
  }
  .offshore-fcg-head {
    font-weight: 700;
    color: var(--accent);
    border-bottom: 1px solid rgba(77,171,247,0.15);
    padding-bottom: 6px;
  }
  .offshore-fcg-corner { border-bottom: 1px solid rgba(77,171,247,0.15); }
  .offshore-fcg-val { font-variant-numeric: tabular-nums; }
  .offshore-fcg-dircell {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1px;
    line-height: 1.1;
  }
  .offshore-fcg-arrow { font-size: 9px; color: var(--accent); }
  .offshore-fcg-skycell {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1px;
    line-height: 1.1;
  }
  .offshore-fcg-sky { font-size: 12px; color: var(--text-secondary); }
  .offshore-fcg-rain { font-size: 8px; color: var(--accent); }
  .offshore-fcg-ht { color: var(--text-primary); font-weight: 600; }
  .offshore-fcg-note {
    grid-column: 1 / -1;
    text-align: left;
    border-bottom: none;
    margin-top: 8px;
    font-size: 9px;
    font-style: italic;
    line-height: 1.35;
    color: var(--text-dim);
    opacity: 0.8;
    white-space: normal;
  }

  /* ── Windfinder-style redesign ── */
  .offshore-fcg-dironly { display: flex; align-items: center; justify-content: center; }
  .offshore-fcg-fill {
    color: #fff;
    font-weight: 700;
    border-radius: 3px;
    text-shadow: 0 1px 1px rgba(0,0,0,0.35);
  }
  .offshore-fcg-tideh { color: #51cf66; font-size: 12px; }   /* high tide */
  .offshore-fcg-tidel { color: #4dabf7; font-size: 12px; }   /* low tide */
  /* Demoted nearshore buoy trend line */
  .offshore-buoy-trend {
    font-size: 11px;
    color: var(--text-secondary);
    margin: 2px 0 8px;
    line-height: 1.4;
  }
  .offshore-buoy-trend strong { color: var(--text-primary); }
  .offshore-buoy-trend-note { color: var(--text-dim); font-size: 10px; }

  .offshore-reason {
    font-size: 12px;
    color: var(--text-secondary);
    margin-top: 4px;
    line-height: 1.5;
  }

  .offshore-day-label {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--text-dim);
    margin-top: 8px;
    margin-bottom: 2px;
    padding-top: 6px;
    border-top: 1px solid var(--border);
  }
  .offshore-day-label:first-of-type {
    margin-top: 4px;
    border-top: none;
    padding-top: 0;
  }

  .offshore-partial-tag {
    display: inline-block;
    font-size: 10px;
    font-weight: 600;
    color: var(--warning);
    background: rgba(255,212,59,0.1);
    border: 1px solid rgba(255,212,59,0.25);
    border-radius: 4px;
    padding: 2px 8px;
    margin-top: 8px;
  }

  .offshore-tomorrow-note {
    font-size: 10px;
    color: var(--text-dim);
    opacity: 0.8;
    margin-top: 6px;
    font-style: italic;
    line-height: 1.4;
  }

  .offshore-freshness {
    margin-top: 8px;
    padding-top: 6px;
    border-top: 1px solid var(--border);
    text-align: center;
  }
  .offshore-freshness-line {
    font-size: 10px;
    color: var(--text-dim);
    opacity: 0.7;
    line-height: 1.6;
  }

  .offshore-disclaimer {
    margin-top: 10px;
    font-size: 10px;
    color: var(--text-dim);
    opacity: 0.7;
    text-align: center;
    font-style: italic;
    line-height: 1.4;
  }

  /* === MARINE FORECAST === */
  .marine-radio-btn {
    background: none;
    border: 1px solid rgba(100, 200, 100, 0.35);
    border-radius: 12px;
    color: #c8e6c9;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 2px 8px;
    cursor: pointer;
    font-size: 10px;
    margin-left: 6px;
    transition: background 0.2s, border-color 0.2s;
    flex-shrink: 0;
    white-space: nowrap;
  }
  .marine-radio-label {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.3px;
    text-transform: uppercase;
  }
  .marine-radio-btn:hover {
    background: rgba(100, 200, 100, 0.15);
    border-color: rgba(100, 200, 100, 0.7);
  }
  .marine-radio-btn.playing {
    background: rgba(100, 200, 100, 0.2);
    border-color: #81c784;
    box-shadow: 0 0 8px rgba(100, 220, 100, 0.4);
  }

  .marine-forecast-text {
    font-family: 'Courier New', Courier, monospace;
    font-size: 11px;
    line-height: 1.6;
    color: #c8e6c9;
    background: rgba(0, 20, 0, 0.55);
    border: 1px solid rgba(100, 200, 100, 0.2);
    border-radius: 6px;
    padding: 12px;
    white-space: pre-wrap;
    word-break: break-word;
    margin: 0;
    max-height: 340px;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: rgba(100,200,100,0.3) transparent;
    text-shadow: 0 0 6px rgba(100, 220, 100, 0.4);
  }
  /* Cooperative-scroll hint — flashes when a single finger tries to scroll the
     forecast box, telling the user to use two fingers (the page scrolls past
     otherwise). Interaction-driven, so it never counts toward CLS. */
  .marine-scroll-hint {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    padding: 7px 14px;
    border-radius: 18px;
    background: rgba(0, 20, 0, 0.82);
    border: 1px solid rgba(100, 200, 100, 0.35);
    color: #c8e6c9;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.3px;
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.18s ease;
    z-index: 3;
  }
  .marine-scroll-hint.show { opacity: 1; }

  /* === LIVE RADAR === */
  .widget[data-widget-id="live-radar"] { overflow: hidden; }
  .radar-body {
    padding: 0;
    position: relative;
  }
  .radar-map {
    width: 100%;
    height: 400px;
    overflow: hidden;
    background: #050a14;
  }

  /* Banner footer for the NEXRAD reflectivity scale.
     Sits below the map, above the widget's bottom edge. Slightly more visual
     weight than the previous slim strip — has a small title row, the gradient
     bar, and tick labels arranged like a navigation chart legend. */
  .radar-scale-banner {
    background: linear-gradient(180deg, rgba(11,20,38,0.55), rgba(11,20,38,0.95));
    padding: 8px 14px 9px;
    border-top: 1px solid rgba(255, 255, 255, 0.06);
  }
  .radar-key {
    display: flex;
    gap: 16px;
    margin-bottom: 6px;
    font-size: 9px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-secondary);
  }
  .radar-key-item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
  }
  .radar-key-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    display: inline-block;
    flex-shrink: 0;
  }
  .radar-key-dot-kjax {
    background: #ffd43b;
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.85);
  }
  .radar-key-dot-station {
    background: #4dabf7;
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.6);
  }
  .radar-scale-banner-title {
    font-size: 9px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.14em;
    color: var(--text-secondary);
    margin-bottom: 5px;
    display: flex;
    justify-content: space-between;
    align-items: baseline;
  }
  .radar-scale-banner-title .radar-scale-unit {
    color: var(--text-dim);
    font-weight: 600;
  }
  .radar-scale-banner .radar-scale-bar {
    height: 9px;
    border-radius: 2px;
    background: linear-gradient(
      to right,
      #04E9E7 0%,
      #019FF4 10%,
      #02FD02 25%,
      #FDF802 45%,
      #FD9500 60%,
      #FD0000 75%,
      #F800FD 90%,
      #FDFDFD 100%
    );
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.3);
  }
  .radar-scale-banner .radar-scale-ticks {
    display: flex;
    justify-content: space-between;
    margin-top: 3px;
    font-size: 9px;
    font-weight: 600;
    color: var(--text-secondary);
    letter-spacing: 0.04em;
  }
  .radar-map .maplibregl-canvas {
    outline: none;
  }
  .radar-map .maplibregl-ctrl-top-right {
    top: 8px;
    right: 8px;
  }
  .radar-map .maplibregl-ctrl-group {
    background: rgba(11, 20, 38, 0.85);
    border: 1px solid rgba(255, 255, 255, 0.08);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
  }
  .radar-map .maplibregl-ctrl-group button {
    background-color: transparent;
  }
  .radar-map .maplibregl-ctrl-group button + button {
    border-top: 1px solid rgba(255, 255, 255, 0.08);
  }
  .radar-map .maplibregl-ctrl-group button span.maplibregl-ctrl-icon {
    filter: invert(0.85);
  }

  .radar-controls {
    position: absolute;
    left: 10px;
    bottom: 10px;
    display: flex;
    align-items: center;
    gap: 8px;
    z-index: 2;
  }
  .radar-icon-btn {
    /* 44×44 meets the iOS Human Interface Guideline minimum touch target.
       Lighter slate fill + brighter border + outer ring so the button stays
       visible whether the basemap underneath is near-black ocean or
       brighter coastal tile colors. */
    width: 44px;
    height: 44px;
    border-radius: 50%;
    border: 1.5px solid rgba(255, 255, 255, 0.45);
    background: rgba(40, 55, 85, 0.92);
    color: var(--text-primary);
    cursor: pointer;
    font-size: 14px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-shadow:
      0 0 0 2px rgba(0, 0, 0, 0.5),
      0 2px 10px rgba(0, 0, 0, 0.7);
    transition: background 0.15s, color 0.15s, border-color 0.15s;
  }
  .radar-icon-btn:hover {
    background: rgba(60, 80, 120, 0.95);
    border-color: var(--accent);
    color: var(--accent);
  }
  .radar-icon-btn:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
  }
  .radar-icon-btn:disabled { cursor: default; opacity: 0.7; }
  /* Speed control — pill (not circle) since it carries a text label. Shares the
     icon button's slate fill / ring so it reads as part of the control cluster. */
  .radar-speed-btn {
    height: 44px;
    padding: 0 13px;
    border-radius: 22px;
    border: 1.5px solid rgba(255, 255, 255, 0.45);
    background: rgba(40, 55, 85, 0.92);
    color: var(--text-primary);
    cursor: pointer;
    font: inherit;
    font-size: 13px;
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    box-shadow:
      0 0 0 2px rgba(0, 0, 0, 0.5),
      0 2px 10px rgba(0, 0, 0, 0.7);
    transition: background 0.15s, color 0.15s, border-color 0.15s;
  }
  .radar-speed-btn:hover { background: rgba(60, 80, 120, 0.95); border-color: var(--accent); color: var(--accent); }
  .radar-speed-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
  .radar-speed-btn i { font-size: 12px; opacity: 0.85; }
  .radar-icon-spin { animation: radar-spin 0.8s linear infinite; }
  @keyframes radar-spin { to { transform: rotate(360deg); } }
  .radar-frame-time {
    background: rgba(11, 20, 38, 0.75);
    color: var(--text-secondary);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.04em;
    padding: 4px 8px;
    border-radius: 10px;
    min-height: 22px;
    display: inline-flex;
    align-items: center;
  }
  .radar-frame-time:empty {
    display: none;
  }

  .radar-attribution {
    position: absolute;
    right: 8px;
    bottom: 8px;
    font-size: 10px;
    color: var(--text-dim);
    background: rgba(11, 20, 38, 0.6);
    padding: 2px 6px;
    border-radius: 4px;
    z-index: 2;
  }
  .radar-attribution a {
    color: var(--text-dim);
    text-decoration: underline;
  }
  .radar-attribution a:hover { color: var(--accent); }

  .radar-error-overlay {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    background: rgba(11, 20, 38, 0.85);
    color: var(--text-secondary);
    font-size: 13px;
    z-index: 3;
    border-radius: 0 0 12px 12px;
  }
  .radar-error-overlay i {
    font-size: 24px;
    color: var(--text-dim);
  }
  .radar-error-overlay[hidden] {
    display: none;
  }
  .radar-kjax-label {
    color: rgba(255, 255, 255, 0.75);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-shadow: 0 0 3px rgba(0, 0, 0, 0.9), 0 0 6px rgba(0, 0, 0, 0.7);
    pointer-events: none;
    white-space: nowrap;
  }

  /* === TROPICAL OUTLOOK === */
  .tropical-clear {
    color: var(--text-dim);
    font-size: 13px;
    text-align: center;
    padding: 8px 0;
  }
  .tropical-storm-card {
    background: rgba(255,255,255,0.03);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 12px;
    margin-bottom: 10px;
  }
  .tropical-storm-card:last-child { margin-bottom: 0; }
  .tropical-storm-card.tropical-approaching {
    border-color: rgba(255,146,43,0.4);
    background: rgba(255,146,43,0.06);
  }
  .tropical-storm-card.tropical-imminent {
    border-color: rgba(255,107,107,0.5);
    background: rgba(255,107,107,0.08);
  }
  .tropical-storm-name {
    font-size: 16px;
    font-weight: 700;
    color: var(--text-primary);
    margin-bottom: 4px;
  }
  .tropical-storm-cat {
    font-size: 12px;
    color: var(--text-secondary);
    margin-bottom: 6px;
  }
  .tropical-storm-dist {
    font-size: 13px;
    color: var(--text-primary);
    margin-bottom: 4px;
  }
  .tropical-distance-pill {
    display: inline-block;
    font-size: 11px;
    font-weight: 600;
    padding: 2px 8px;
    border-radius: 10px;
  }
  .tropical-pill-far {
    background: var(--accent-dim);
    color: var(--accent);
  }
  .tropical-pill-approaching {
    background: rgba(255,146,43,0.15);
    color: #ff922b;
  }
  .tropical-pill-imminent {
    background: rgba(255,107,107,0.15);
    color: var(--danger);
  }
  .tropical-storm-move, .tropical-storm-meta {
    font-size: 12px;
    color: var(--text-dim);
    margin-bottom: 2px;
  }
  .tropical-trip-note {
    margin-top: 8px;
    padding: 8px 10px;
    background: rgba(255,146,43,0.1);
    border-radius: 6px;
    font-size: 12px;
    color: #ff922b;
    font-weight: 500;
  }
  .tropical-trip-note i { margin-right: 4px; }
  .tropical-nhc-link {
    display: inline-block;
    margin-top: 6px;
    font-size: 11px;
    color: var(--accent);
    text-decoration: none;
    opacity: 0.8;
  }
  .tropical-nhc-link:hover { opacity: 1; text-decoration: underline; }
  .tropical-nhc-link i { margin-right: 3px; font-size: 10px; }
  .tropical-footnote {
    color: var(--text-dim);
    font-size: 11px;
    margin-top: 4px;
  }
  /* Watch/Warning banner — most actionable line when our coast is under a W/W */
  .tropical-ww-banner {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 9px 11px;
    border-radius: 8px;
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.2px;
    margin-bottom: 10px;
  }
  .tropical-ww-banner i { font-size: 13px; }
  .tropical-ww-ts {
    background: rgba(255,146,43,0.16);
    color: #ffb066;
    border: 1px solid rgba(255,146,43,0.45);
  }
  .tropical-ww-hurricane {
    background: rgba(255,107,107,0.16);
    color: #ff8a8a;
    border: 1px solid rgba(255,107,107,0.5);
  }
  /* The localized "what it means for Jacksonville" line */
  .tropical-impact {
    margin-top: 8px;
    padding: 8px 10px;
    background: rgba(56,189,248,0.08);
    border-left: 3px solid var(--accent);
    border-radius: 4px;
    font-size: 12.5px;
    line-height: 1.45;
    color: var(--text-primary);
  }
  /* NHC official cone image — framed on a white mat so the bright NOAA graphic reads well */
  .tropical-cone {
    margin-top: 4px;
    border: 1px solid var(--border);
    border-radius: 8px;
    overflow: hidden;
  }
  .tropical-cone-img {
    display: block;
    width: 100%;
    height: auto;
    background: #fff; /* white mat behind the bright NHC/GOES graphic */
  }
  .tropical-cone-cap {
    font-size: 10px;
    color: var(--text-dim);
    text-align: center;
    padding: 5px 0;
    background: rgba(255,255,255,0.04); /* dark strip on the widget — caption stays legible */
  }
  .tropical-cone-missing {
    background: rgba(255,255,255,0.03);
    color: var(--text-dim);
    font-size: 12px;
    text-align: center;
    padding: 22px 12px;
    border-style: dashed;
  }
  .tropical-storm-secondary { opacity: 0.9; }
  .tropical-storm-secondary .tropical-storm-name { font-size: 14px; }
  /* View selector pills — flip between My Area / Outlook / Satellite */
  .tropical-tabs {
    display: flex;
    gap: 6px;
    margin-bottom: 12px;
    flex-wrap: wrap;
  }
  .tropical-tab {
    flex: 1 1 0;
    min-width: 72px;
    padding: 7px 10px;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-secondary);
    background: rgba(255,255,255,0.04);
    border: 1px solid var(--border);
    border-radius: 999px;
    cursor: pointer;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
  }
  .tropical-tab:hover { color: var(--text-primary); background: rgba(255,255,255,0.07); }
  .tropical-tab-active {
    color: var(--accent);
    background: var(--accent-dim);
    border-color: var(--accent);
  }
  .tropical-view { min-height: 36px; }
  /* Always-on "tropical vitals" in My Area — early indicators even when quiet */
  .tropical-vitals {
    margin-top: 10px;
    border: 1px solid var(--border);
    border-radius: 8px;
    overflow: hidden;
  }
  .tropical-vital {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px;
    padding: 8px 11px;
    font-size: 12.5px;
  }
  .tropical-vital + .tropical-vital { border-top: 1px solid var(--border); }
  .tropical-vital-label { color: var(--text-secondary); }
  .tropical-vital-val {
    color: var(--text-primary);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
  }
  .tropical-vital-warn { color: #ff922b; }       /* falling barometer — worth watching */
  .tropical-vital-watch { color: var(--accent); } /* NHC is watching an area */
  /* Tiny barometric-pressure sparkline that sits between the mb value and the
     trend word in the Barometer row. Subtle, vertically centered, fixed size. */
  .pressure-spark {
    display: inline-block;
    vertical-align: middle;
    margin: 0 6px;
    opacity: 0.9;
  }

  /* === LOADING STATE === */
  .loading {
    text-align: center;
    padding: 40px;
    color: var(--text-dim);
    font-size: 13px;
  }
  .loading i { font-size: 20px; margin-bottom: 8px; display: block; }

  /* === ADVISORY BUBBLES === */
  .advisories {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-bottom: 14px;
  }
  .advisories:empty { display: none; }
  .advisory-bubble {
    position: relative;
    background: rgba(11, 20, 38, 0.9);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border-radius: 12px;
    padding: 10px 36px 10px 14px;
    border-left: 3px solid var(--warning);
    animation: advisorySlide 0.4s ease-out;
  }
  .advisory-dismiss {
    position: absolute;
    top: 6px;
    right: 6px;
    width: 26px;
    height: 26px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: none;
    color: var(--text-dim);
    font-size: 12px;
    cursor: pointer;
    border-radius: 6px;
    transition: color 0.15s, background 0.15s;
  }
  .advisory-dismiss:hover { color: var(--text-primary); background: rgba(255,255,255,0.06); }
  .advisory-bubble.severity-Extreme,
  .advisory-bubble.severity-Severe {
    border-left-color: var(--danger);
  }
  .advisory-bubble.severity-Moderate {
    border-left-color: #ff922b;
  }
  .advisory-bubble.severity-Minor {
    border-left-color: var(--warning);
  }
  @keyframes advisorySlide {
    from { opacity: 0; transform: translateX(20px); }
    to { opacity: 1; transform: translateX(0); }
  }
  .advisory-event {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    margin-bottom: 4px;
    display: flex;
    align-items: center;
    gap: 6px;
  }
  .severity-tag {
    font-size: 10px;
    font-weight: 600;
    padding: 1px 5px;
    border-radius: 4px;
    margin-left: auto;
    text-transform: uppercase;
    letter-spacing: 0.5px;
  }
  .severity-Extreme .severity-tag,
  .severity-Severe .severity-tag { background: rgba(255,107,107,0.2); color: var(--danger); }
  .severity-Moderate .severity-tag { background: rgba(255,146,43,0.2); color: #ff922b; }
  .severity-Minor .severity-tag { background: rgba(255,212,59,0.2); color: var(--warning); }
  .advisory-desc {
    font-size: 11px;
    line-height: 1.5;
    color: var(--text-secondary);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    cursor: pointer;
    transition: all 0.3s ease;
  }
  .advisory-desc.expanded {
    display: block;
    -webkit-line-clamp: unset;
  }
  .advisory-more {
    font-size: 10px;
    color: var(--accent);
    cursor: pointer;
    margin-top: 4px;
    font-weight: 500;
  }
  .advisory-expires {
    font-size: 10px;
    color: var(--text-dim);
    margin-top: 6px;
  }

  /* === WIND LEGEND BAR === */
  .wind-legend {
    position: fixed;
    bottom: 12px;
    left: 12px;
    z-index: 3;
    background: rgba(11, 20, 38, 0.85);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border: 1px solid rgba(255,255,255,0.1);
    border-radius: 10px;
    padding: 8px 14px;
    display: flex;
    align-items: center;
    gap: 10px;
  }
  .wind-legend-live {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--success);
    flex-shrink: 0;
  }
  .live-dot {
    width: 6px; height: 6px;
    border-radius: 50%;
    background: var(--success);
    animation: livePulse 2s ease-in-out infinite;
  }
  @keyframes livePulse {
    0%, 100% { opacity: 1; box-shadow: 0 0 4px var(--success); }
    50% { opacity: 0.4; box-shadow: none; }
  }
  .wind-legend-unit {
    font-size: 10px;
    color: var(--accent);
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 2px;
    flex-shrink: 0;
  }
  .wind-legend-scale {
    display: flex;
    flex-direction: column;
    gap: 1px;
    width: 140px;
  }
  .wind-legend-bar {
    height: 6px;
    border-radius: 3px;
    /* Windy wind speed palette */
    background: linear-gradient(to right,
      #3288bd,
      #66c2a5,
      #abdda4,
      #e6f598,
      #fee08b,
      #fdae61,
      #f46d43,
      #d53e4f,
      #9e0142
    );
  }
  .wind-legend-ticks {
    display: flex;
    justify-content: space-between;
  }
  .wind-legend-tick {
    font-size: 10px;
    color: var(--text-dim);
  }
  .wind-legend-source {
    font-size: 10px;
    color: var(--text-dim);
    flex-shrink: 0;
  }

  /* === WIND FORECAST CHART === */
  .wind-chart-container { height: 180px; }
  .wind-sol-major { color: rgba(255,215,0,0.8); }
  .wind-sol-minor { color: rgba(180,180,255,0.65); }
  .wind-legend-key {
    display: flex;
    gap: 12px;
    padding: 4px 16px 12px;
    flex-wrap: wrap;
  }
  .wind-legend-key-item {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: 11px;
    color: var(--text-secondary);
  }
  .wind-legend-key-dot {
    width: 10px;
    height: 10px;
    border-radius: 2px;
    flex-shrink: 0;
  }
  /* Live observed wind + forecast source — quiet caption under the legend. */
  .wind-chart-source {
    padding: 0 16px 14px;
    font-size: 11px;
    line-height: 1.4;
    letter-spacing: 0.2px;
    color: var(--text-secondary);
  }
  .wind-chart-source:empty { display: none; }

  /* === RESPONSIVE — Tablet+ === */
  @media (min-width: 700px) {
    .app { max-width: 720px; }
  }

/* === TAP-TO-FORECAST POPOVER === */
.forecast-popover {
  position: fixed;
  z-index: 9999;
  background: #1a2a44;
  border: 1px solid rgba(77,171,247,0.3);
  border-radius: 10px;
  padding: 10px 14px;
  min-width: 160px;
  box-shadow: 0 4px 20px rgba(0,0,0,0.5);
  pointer-events: none;
  animation: fp-in 0.12s ease;
}
@keyframes fp-in {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}
.fp-time {
  font-size: 12px;
  font-weight: 700;
  color: #4dabf7;
  margin-bottom: 6px;
  letter-spacing: 0.3px;
}
.fp-row {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  font-size: 12px;
  line-height: 1.7;
}
.fp-label { color: rgba(255,255,255,0.35); }
.fp-val   { color: #e2e8f0; font-weight: 600; text-align: right; }
.fp-sky   { font-weight: 400; color: rgba(255,255,255,0.7); max-width: 110px; text-align: right; }

/* === WIDGET HELP POPOVERS === */
.widget-help-btn {
  background: none;
  border: none;
  color: rgba(255,255,255,0.2);
  font-size: 13px;
  cursor: pointer;
  padding: 2px 4px;
  margin-left: auto;
  transition: color 0.15s;
}
.widget-help-btn:hover { color: rgba(255,255,255,0.4); }
.widget-help-popover {
  position: fixed;
  z-index: 9999;
  background: #1a2a44;
  border: 1px solid rgba(77,171,247,0.3);
  border-radius: 10px;
  padding: 12px 16px;
  max-width: 320px;
  box-shadow: 0 4px 20px rgba(0,0,0,0.5);
  animation: fp-in 0.12s ease;
}
.widget-help-text {
  font-size: 12px;
  line-height: 1.55;
  color: rgba(255,255,255,0.8);
}
.widget-help-text p {
  margin: 0 0 10px 0;
}
.widget-help-text p:last-child {
  margin-bottom: 0;
}

/* ============================================================
   Settings notice — developer contact callout at top of settings
   ============================================================ */
.settings-notice {
  margin: 0 16px 14px 16px;
  padding: 14px 16px;
  background: linear-gradient(135deg, rgba(77,171,247,0.18), rgba(77,171,247,0.06));
  border: 1px solid rgba(77,171,247,0.35);
  border-left: 4px solid var(--accent);
  border-radius: 8px;
}
.settings-notice-title {
  font: 700 14px/1.3 'Inter', -apple-system, sans-serif;
  color: var(--accent);
  margin-bottom: 8px;
  display: flex;
  align-items: center;
  gap: 8px;
}
.settings-notice-body {
  font: 400 13px/1.5 'Inter', -apple-system, sans-serif;
  color: var(--text-primary);
}
.settings-notice-body strong {
  color: var(--accent);
  font-weight: 600;
}

.settings-install-actions {
  display: flex;
  gap: 8px;
  margin-top: 10px;
}
.settings-install-btn,
.settings-install-dismiss {
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  padding: 6px 14px;
  border-radius: 20px;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.settings-install-btn {
  background: var(--accent);
  border: 1px solid var(--accent);
  color: #0b1426;
}
.settings-install-btn:hover { background: #6bbaff; border-color: #6bbaff; }
.settings-install-dismiss {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-dim);
}
.settings-install-dismiss:hover { border-color: rgba(255,255,255,0.25); color: var(--text-secondary); }
.settings-install-ios {
  margin-top: 10px;
  font: 400 12px/1.5 'Inter', -apple-system, sans-serif;
  color: var(--text-secondary);
}
.settings-install-ios strong { color: var(--text-primary); font-weight: 600; }
.settings-install-ios i { color: var(--accent); margin: 0 2px; }

/* ============================================================
   PWA install banner (top of page, sticky)
   ============================================================ */
.pwa-banner {
  position: sticky;
  top: max(8px, env(safe-area-inset-top));
  margin: 8px 12px 0;
  z-index: 200;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 999px;
  box-shadow: 0 4px 14px rgba(0,0,0,0.35);
  padding: 10px 20px;
}
.pwa-banner-main {
  display: flex;
  align-items: center;
  gap: 10px;
  max-width: 1100px;
  margin: 0 auto;
}
.pwa-banner-icon {
  color: var(--accent);
  font-size: 16px;
  flex-shrink: 0;
}
.pwa-banner-text {
  flex: 1;
  font: 600 13px/1.3 'Inter', -apple-system, sans-serif;
  color: var(--text-primary);
  min-width: 0;
}
.pwa-banner-action {
  font-family: inherit;
  font-size: 13px;
  font-weight: 700;
  padding: 8px 16px;
  min-height: 36px;
  border-radius: 20px;
  background: var(--accent);
  border: 1px solid var(--accent);
  color: #0b1426;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
  flex-shrink: 0;
}
.pwa-banner-action:hover { background: #6bbaff; border-color: #6bbaff; }
.pwa-banner-close {
  font-family: inherit;
  font-size: 22px;
  line-height: 1;
  width: 36px;
  height: 36px;
  padding: 0;
  border-radius: 50%;
  background: transparent;
  border: none;
  color: var(--text-secondary);
  cursor: pointer;
  transition: color 0.15s, background 0.15s;
  flex-shrink: 0;
}
.pwa-banner-close:hover { color: var(--text-primary); background: rgba(255,255,255,0.08); }
.pwa-banner-ios {
  max-width: 1100px;
  margin: 8px auto 0;
  padding: 8px 10px;
  border-radius: 6px;
  background: rgba(77,171,247,0.08);
  font: 400 12px/1.4 'Inter', -apple-system, sans-serif;
  color: var(--text-secondary);
}
.pwa-banner-ios strong { color: var(--text-primary); font-weight: 600; }
.pwa-banner-ios i { color: var(--accent); margin: 0 2px; }

/* ============================================================
   Contact pill + modal
   ============================================================ */
/* Facebook button anchored to the bottom-right of the header card. Absolute
   positioning so it sits inside the header's rounded box without affecting
   the logo/settings flex row. Styled to match .settings-btn so the two
   share a visual vocabulary despite being separately positioned. */
.header-fb-btn {
  position: absolute;
  /* Anchored to the top-right corner of the header card so it stays
     clear of the station selector regardless of desktop/mobile layout.
     On mobile the header stacks vertically (logo on top, selector row
     below); putting FB at top-right puts it in the logo's unused
     corner without competing for tap space with the selector. */
  top: 10px;
  right: 10px;
  z-index: 2;
  background: var(--bg-card);
  border: 1px solid var(--border);
  color: #4dabf7;
  width: 32px;
  height: 32px;
  border-radius: 8px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
  transition: border-color 0.15s, color 0.15s;
}
.header-fb-btn:hover { border-color: var(--accent); color: #6bbaff; }
.header-fb-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.header-fb-btn svg { display: block; }

.contact-pill {
  position: fixed;
  right: 16px;
  bottom: 16px;
  z-index: 900;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  border-radius: 999px;
  background: rgba(17, 29, 51, 0.92);
  color: var(--text-primary);
  border: 1px solid var(--border);
  font: 600 13px/1 'Inter', sans-serif;
  cursor: pointer;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.35);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  transition: background 120ms ease, border-color 120ms ease, transform 120ms ease;
}
.contact-pill:hover {
  background: var(--bg-card-hover);
  border-color: var(--accent-dim);
  transform: translateY(-1px);
}
.contact-pill:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.contact-pill i { color: var(--accent); font-size: 14px; }

.contact-modal[hidden] { display: none; }
.contact-modal {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}
.contact-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(5, 10, 20, 0.72);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}
.contact-modal-card {
  position: relative;
  width: 100%;
  max-width: 460px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.55);
  padding: 18px 20px 20px;
  max-height: calc(100vh - 32px);
  overflow: auto;
}
.contact-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}
.contact-modal-header h2 {
  font-size: 16px;
  font-weight: 600;
  color: var(--text-primary);
  letter-spacing: 0.2px;
}
.contact-modal-close {
  background: transparent;
  border: none;
  color: var(--text-secondary);
  cursor: pointer;
  font-size: 16px;
  padding: 4px 8px;
  border-radius: 6px;
}
.contact-modal-close:hover { color: var(--text-primary); background: rgba(255,255,255,0.04); }

.contact-form { display: flex; flex-direction: column; gap: 12px; }
.contact-field { display: flex; flex-direction: column; gap: 4px; }
.contact-field > span {
  font-size: 12px;
  color: var(--text-secondary);
  font-weight: 500;
}
.contact-field > span em {
  font-style: normal;
  color: var(--text-dim);
  font-weight: 400;
}
.contact-field input,
.contact-field textarea {
  background: rgba(0,0,0,0.22);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 9px 11px;
  color: var(--text-primary);
  font: 400 13px/1.4 'Inter', sans-serif;
  resize: vertical;
}
.contact-field input:focus,
.contact-field textarea:focus {
  outline: none;
  border-color: var(--accent);
  background: rgba(0,0,0,0.32);
}
.contact-field textarea { min-height: 110px; }

/* Honeypot — must be invisible to humans AND assistive tech, but present in DOM so bots find and fill it. */
.contact-hp {
  position: absolute;
  left: -10000px;
  top: auto;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.contact-status {
  min-height: 18px;
  font-size: 12px;
  color: var(--text-secondary);
}
.contact-status.is-error { color: var(--danger); }
.contact-status.is-success { color: var(--success); }

.contact-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 4px;
}
.contact-btn {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px 14px;
  font: 600 13px/1 'Inter', sans-serif;
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease;
}
.contact-btn[disabled] { opacity: 0.55; cursor: not-allowed; }
.contact-btn-ghost {
  background: transparent;
  color: var(--text-secondary);
}
.contact-btn-ghost:hover:not([disabled]) { color: var(--text-primary); background: rgba(255,255,255,0.04); }
.contact-btn-primary {
  background: var(--accent);
  color: #0b1426;
  border-color: var(--accent);
}
.contact-btn-primary:hover:not([disabled]) { background: #6cbbff; border-color: #6cbbff; }

@media (max-width: 480px) {
  .contact-pill span { display: none; }
  .contact-pill { padding: 10px; }
}

/* ───────────────────────────── SEO / a11y utilities ───────────────────────────── */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.skip-link {
  position: absolute;
  top: -40px;
  left: 8px;
  z-index: 1000;
  background: var(--accent, #4a90e2);
  color: #0b1426;
  padding: 8px 14px;
  border-radius: 6px;
  font-weight: 700;
  text-decoration: none;
  transition: top 120ms ease;
}
.skip-link:focus { top: 8px; outline: 2px solid #fff; outline-offset: 2px; }

.site-footer {
  margin: 32px auto 120px;
  padding: 20px 18px;
  max-width: 900px;
  color: var(--text-secondary, #9aa6b2);
  font-size: 13px;
  line-height: 1.55;
  text-align: center;
}
.site-footer p { margin: 0 0 10px; }
.site-footer p:last-child { margin-bottom: 0; }
.site-footer strong { color: var(--text-primary, #e6edf3); }
.site-footer a { color: var(--text-secondary, #9aa6b2); text-decoration: underline; text-underline-offset: 2px; }
.site-footer a:hover { color: var(--text-primary, #e6edf3); }
.site-footer .footer-sep { margin: 0 8px; opacity: 0.6; }
.site-footer .footer-contact-link { cursor: pointer; }
@media (max-width: 480px) {
  .site-footer { margin-bottom: 110px; font-size: 12px; }
}

/* Mobile: shrink the footer statement + push footer to the bottom of the
   viewport when all widgets are hidden. flex-column on .app + margin-top:auto
   on the footer pins it down so the Windy background shows through between. */
@media (max-width: 768px) {
  .app {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    min-height: 100svh; /* iOS Safari: stable viewport height when URL bar expands */
    padding-bottom: 0; /* override base .app 80px pad; footer owns the bottom */
  }
  /* #main must flex-grow so the footer is actually pushed to the bottom of
     the viewport when all widgets are hidden. margin-top: auto on the footer
     alone was not reliably placing it at the bottom — seen as "tagline floats
     mid-screen" on Android Chrome. */
  #main { flex: 1; }
  .site-footer {
    margin-top: auto;
    padding: 12px 18px 0;
    margin-bottom: 78px; /* clear fixed wind-legend (bottom:12px + ~50px height) + breathing room */
  }
  .site-footer .footer-about { font-size: 10px; line-height: 1.45; }
  .site-footer .footer-sources { font-size: 10px; line-height: 1.4; }
  .site-footer .footer-meta { font-size: 11px; }
}

/* ============================================================================
   SEO STATIC BLOCK (#seoStatic)  — Phase 2 / #116
   Prerendered, crawlable tide content baked into /<slug>/ and /<slug>/<date>/
   pages by frontend/build-seo.mjs. It is the visible content for crawlers and
   no-JS visitors. For JS users the SPA boots and supersedes it, so we hide it
   with the `html.js` flag set synchronously in <head> (no flash). Progressive
   enhancement — same NOAA data, no cloaking.
   ============================================================================ */
html.js #seoStatic { display: none; }

.seo-static {
  max-width: 900px;
  margin: 0 auto 24px;
  padding: 18px 18px 24px;
  color: var(--text-primary);
  font-size: 15px;
  line-height: 1.6;
}
.seo-static h1 { font-size: 26px; line-height: 1.25; margin: 4px 0 12px; color: var(--text-primary); }
.seo-static h2 { font-size: 19px; margin: 24px 0 10px; color: var(--text-primary); }
.seo-static h3 { font-size: 16px; margin: 14px 0 4px; color: var(--text-primary); }
.seo-static .seo-lede { color: var(--text-secondary); margin: 0 0 16px; }
.seo-static .seo-sun { color: var(--accent); font-weight: 600; margin: 10px 0 0; }
.seo-static .seo-disclaimer { color: var(--text-dim); font-size: 12px; margin-top: 20px; }

.seo-breadcrumb { font-size: 13px; color: var(--text-secondary); margin-bottom: 10px; }
.seo-breadcrumb a { color: var(--accent); text-decoration: none; }
.seo-breadcrumb a:hover { text-decoration: underline; }
.seo-date-nav { margin: 14px 0; font-size: 14px; }
.seo-date-nav a { color: var(--accent); text-decoration: none; }
.seo-date-nav a:hover { text-decoration: underline; }

.seo-static table {
  width: 100%;
  border-collapse: collapse;
  margin: 6px 0 4px;
  font-size: 14px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
}
.seo-static th, .seo-static td {
  padding: 9px 12px;
  text-align: left;
  border-bottom: 1px solid var(--border);
}
.seo-static thead th { background: rgba(255,255,255,0.04); color: var(--text-secondary); font-weight: 600; }
.seo-static tbody tr:last-child td,
.seo-static tbody tr:last-child th { border-bottom: none; }
.seo-static .seo-week-table th[scope="row"] { color: var(--text-secondary); font-weight: 600; white-space: nowrap; }

.seo-faq { margin-top: 26px; }
.seo-faq-item { margin-bottom: 14px; }
.seo-faq-item p { color: var(--text-secondary); margin: 2px 0 0; }

.seo-other-stations { margin-top: 26px; }
.seo-other-stations ul {
  list-style: none; padding: 0; margin: 8px 0 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 6px 16px;
}
.seo-other-stations a { color: var(--accent); text-decoration: none; font-size: 14px; }
.seo-other-stations a:hover { text-decoration: underline; }

/* Footer hub-and-spoke station nav — ships on home + every prerendered page. */
.footer-stations { max-width: 900px; margin: 18px auto 0; text-align: left; }
.footer-stations-title { font-size: 13px; font-weight: 600; color: var(--text-secondary); margin: 0 0 8px; }
.footer-stations ul {
  list-style: none; padding: 0; margin: 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 4px 14px;
}
.footer-stations a { color: var(--text-secondary); text-decoration: none; font-size: 12px; }
.footer-stations a:hover { color: var(--accent); text-decoration: underline; }

@media (max-width: 480px) {
  .seo-static { font-size: 14px; padding: 14px; }
  .seo-static h1 { font-size: 22px; }
  .seo-static h2 { font-size: 17px; }
}

/* === 7-day tide outlook (below the 48h schedule table) === */
.tide-week { margin-top: 14px; border-top: 1px solid var(--border); padding-top: 10px; }
.tide-week-title {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  color: var(--text-secondary);
  margin-bottom: 8px;
}
.tide-week-grid { display: flex; flex-direction: column; gap: 5px; }
.tide-week-row { display: flex; align-items: baseline; gap: 10px; }
.tide-week-day {
  flex: 0 0 64px;
  font-size: 11px;
  font-weight: 600;
  color: var(--text-secondary);
}
.tide-week-events { display: flex; flex-wrap: wrap; gap: 4px 10px; }
.tide-week-evt { font-size: 11px; font-variant-numeric: tabular-nums; color: var(--text-primary); white-space: nowrap; }
.tide-week-evt.tide-week-high::first-letter { color: var(--accent); font-weight: 700; }
.tide-week-evt.tide-week-low::first-letter { color: #ffb84d; font-weight: 700; }
/* Natural 3-tide day (4th event drifted past midnight) — dim placeholder so
   the short row doesn't read as missing data. */
.tide-week-evt.tide-week-empty { color: var(--text-dim); opacity: 0.5; }
/* === Water-temp trend (under the My Area "Water" value) === */
.cond-trend {
  margin-top: 2px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.2px;
  color: var(--text-dim);
}
.cond-trend-up { color: #ffb84d; }   /* warming */
.cond-trend-down { color: var(--accent); } /* cooling */
/* === BITE WINDOWS — moving-water periods (no scores, no solunar) === */
.bw-day-toggle { display: inline-flex; gap: 4px; margin-left: auto; margin-right: 8px; }
.bw-day-btn {
  background: none;
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: 6px;
  color: rgba(255,255,255,0.45);
  font-size: 10px;
  font-weight: 600;
  padding: 2px 7px;
  cursor: pointer;
  letter-spacing: 0.3px;
  transition: color 0.15s, border-color 0.15s;
}
.bw-day-btn:hover { color: var(--accent); border-color: var(--accent); }
.bw-day-btn.active { color: var(--accent); border-color: var(--accent); background: var(--accent-dim); }

.bw-timeline {
  position: relative;
  height: 30px;
  margin: 2px 0 18px;
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: visible;
}
.bw-bar {
  position: absolute;
  top: 4px;
  bottom: 4px;
  border-radius: 4px;
  min-width: 3px;
}
.bw-bar.bw-incoming { background: linear-gradient(180deg, rgba(77,171,247,0.85), rgba(77,171,247,0.55)); }
.bw-bar.bw-outgoing { background: linear-gradient(180deg, rgba(255,184,77,0.85), rgba(255,184,77,0.5)); }
.bw-bar.bw-moderate { opacity: 0.72; }
.bw-bar.bw-soft { opacity: 0.45; }
.bw-sun {
  position: absolute;
  top: -4px;
  bottom: -4px;
  width: 2px;
  background: var(--warning);
  opacity: 0.85;
}
.bw-sun::after {
  content: '';
  position: absolute;
  top: -5px;
  left: -3px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--warning);
}
.bw-now {
  position: absolute;
  top: -2px;
  bottom: -2px;
  width: 2px;
  background: var(--success);
  box-shadow: 0 0 6px rgba(81,207,102,0.7);
}
.bw-hour-label {
  position: absolute;
  top: 100%;
  transform: translateX(-50%);
  margin-top: 3px;
  font-size: 9px;
  color: var(--text-dim);
  letter-spacing: 0.3px;
}

.bw-list { display: flex; flex-direction: column; gap: 8px; }
.bw-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 12px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: rgba(255,255,255,0.02);
}
.bw-row.bw-active {
  border-color: rgba(81,207,102,0.45);
  background: rgba(81,207,102,0.07);
}
.bw-dir { font-size: 12px; font-weight: 600; min-width: 88px; }
.bw-dir i { margin-right: 4px; }
.bw-dir-incoming { color: var(--accent); }
.bw-dir-outgoing { color: #ffb84d; }
.bw-time { font-size: 13px; font-variant-numeric: tabular-nums; color: var(--text-primary); }
.bw-chips { display: inline-flex; flex-wrap: wrap; gap: 5px; margin-left: auto; }
.bw-chip {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.3px;
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid var(--border);
  color: var(--text-secondary);
  cursor: default;
}
.bw-chip-now { color: var(--success); border-color: rgba(81,207,102,0.5); background: rgba(81,207,102,0.12); }
.bw-chip-strong { color: var(--text-primary); border-color: rgba(255,255,255,0.25); }
.bw-chip-soft { color: var(--text-dim); }
.bw-chip-light { color: var(--warning); border-color: rgba(255,212,59,0.35); background: rgba(255,212,59,0.08); }
.bw-footnote { margin-top: 12px; font-size: 10.5px; line-height: 1.45; color: var(--text-dim); }
.bw-empty { font-size: 12px; color: var(--text-secondary); padding: 4px 0; }

@media (max-width: 480px) {
  .bw-dir { min-width: 0; }
  .bw-chips { margin-left: 0; width: 100%; }
}

/* ============================================
   STATION FINDER — trigger buttons + modal (map + list)
   ============================================ */
.station-nav {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.station-finder-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  flex: 0 0 auto;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--accent);
  font-size: 15px;
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}
.station-finder-btn:hover { color: var(--text-primary); border-color: var(--accent); }

.sf-settings-link {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  width: 100%;
  justify-content: center;
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 9px 12px;
  color: var(--text-primary);
  font: 600 13px/1 'Inter', sans-serif;
  cursor: pointer;
}
.sf-settings-link:hover { border-color: var(--accent); color: var(--accent); }

.station-finder-modal[hidden] { display: none; }
.station-finder-modal {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}
.sf-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(5, 10, 20, 0.72);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}
.sf-card {
  position: relative;
  width: 100%;
  max-width: 880px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.55);
  padding: 16px 18px 18px;
  max-height: calc(100vh - 32px);
  display: flex;
  flex-direction: column;
}
.sf-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}
.sf-header h2 {
  font-size: 16px;
  font-weight: 600;
  color: var(--text-primary);
  letter-spacing: 0.2px;
}
.sf-close {
  background: transparent;
  border: none;
  color: var(--text-secondary);
  cursor: pointer;
  font-size: 16px;
  padding: 4px 8px;
  border-radius: 6px;
}
.sf-close:hover { color: var(--text-primary); background: rgba(255,255,255,0.04); }

.sf-toolbar {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
}
.sf-gps {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  background: var(--accent);
  border: 1px solid var(--accent);
  border-radius: 8px;
  padding: 8px 14px;
  color: #07101f;
  font: 600 13px/1 'Inter', sans-serif;
  cursor: pointer;
}
.sf-gps[disabled] { opacity: 0.6; cursor: progress; }
.sf-gps.is-loading i { animation: sf-spin 0.8s linear infinite; }
@keyframes sf-spin { to { transform: rotate(360deg); } }
.sf-toolbar-hint { font-size: 12px; color: var(--text-dim); }

.sf-banner[hidden] { display: none; }
.sf-banner {
  background: rgba(255, 212, 59, 0.10);
  border: 1px solid rgba(255, 212, 59, 0.35);
  border-radius: 8px;
  padding: 9px 12px;
  margin-bottom: 10px;
  font-size: 13px;
  color: var(--text-primary);
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.sf-switch {
  background: #ffd43b;
  border: none;
  border-radius: 6px;
  padding: 6px 12px;
  font: 600 12px/1 'Inter', sans-serif;
  color: #07101f;
  cursor: pointer;
}

.sf-body {
  display: flex;
  min-height: 0;
  flex: 1;
}
.sf-map {
  flex: 1 1 auto;
  width: 100%;
  min-height: 340px;
  height: 60vh;
  max-height: 620px;
  border-radius: 10px;
  overflow: hidden;
  border: 1px solid var(--border);
  background: #02060f;
}

@media (max-width: 640px) {
  .sf-card { max-width: 100%; padding: 12px 12px 14px; }
  .sf-map { height: 56vh; min-height: 260px; }
}

/* ============================================
   STATION COMBO — custom dropdown (action buttons pinned on top)
   ============================================ */
.station-select-native { display: none !important; }

.station-combo { position: relative; display: inline-block; }
.station-combo-trigger {
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  min-width: 220px;
  width: 100%;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 9px 12px;
  color: var(--text-primary);
  font: 600 14px/1.1 'Inter', sans-serif;
  cursor: pointer;
}
.station-combo-trigger:hover { border-color: var(--accent); }
.station-combo-current { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.station-combo-caret { font-size: 12px; color: var(--text-secondary); transition: transform 150ms ease; }
.station-combo.is-open .station-combo-caret { transform: rotate(180deg); }

.station-combo-panel {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  width: 300px;
  max-width: 88vw;
  max-height: 72vh;
  overflow-y: auto;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 20px 50px rgba(0, 0, 0, 0.55);
  z-index: 1100;
}
.station-combo-panel[hidden] { display: none; }

/* The two action buttons stay pinned to the top while the list scrolls. */
.station-combo-actions {
  display: grid;
  gap: 6px;
  padding: 10px;
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  background: var(--bg-card);
  z-index: 1;
}
.station-combo-action {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  border-radius: 8px;
  padding: 10px 12px;
  font: 700 13px/1 'Inter', sans-serif;
  cursor: pointer;
  text-align: left;
}
.station-combo-action i { font-size: 14px; width: 16px; text-align: center; }
/* GPS = accent-filled; Map = blue-tinted secondary */
#comboGpsBtn { background: var(--accent); border: 1px solid var(--accent); color: #07101f; }
#comboMapBtn { background: rgba(77, 171, 247, 0.14); border: 1px solid rgba(77, 171, 247, 0.5); color: var(--text-primary); }
.station-combo-action:hover { filter: brightness(1.07); }

.station-combo-list { padding: 6px 10px 10px; }
.station-combo-group {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-dim);
  padding: 10px 4px 4px;
}
.station-combo-option {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 7px;
  padding: 8px 10px;
  color: var(--text-primary);
  font: 500 13px/1.2 'Inter', sans-serif;
  cursor: pointer;
}
.station-combo-option:hover { background: rgba(255, 255, 255, 0.06); }
.station-combo-option.is-active {
  background: rgba(77, 171, 247, 0.18);
  border-color: rgba(77, 171, 247, 0.4);
  color: #fff;
}
@media (max-width: 640px) {
  .station-combo-panel { width: min(92vw, 340px); }
}
